Giới thiệu
Sau bài lí thuyết về lộ trình tiếp cận public blockchain thì mình sẽ giới thiệu cách xây dựng một ứng dụng phi tập trung (DApp) cũng như xây dựng một bản mẫu kết hợp giữa Contract và Frontend . Bài đầu tiên sẽ xây dựng một based code cho DApp dựa vào framework Reactjs .
Khởi tạo project
Đầu tiên thì phải chuẩn bị các package cần có, về cơ bản thì cũng chỉ tập trung 2 phần gồm phần contract và phía frontend
Contract
Như đã giới thiệu trong phần trước, framework Truffle cũng đã được đề cập đến với mục đích để dễ dàng test unit cho smart contract, trong trường hợp chưa cài truffle thì có dùng command này để install:
1 2 | <span class="token function">npm</span> <span class="token function">install</span> -g truffle |
Sau đó unbox gói cơ bản của truffle : webpack
Đầu tiên sẽ tạo một folder cho toàn bộ DApp:
1 2 | mkdir EthCodeBased && cd EthCodeBased |
Tiếp đó là unbox gói webpack :
1 2 | truffle unbox webpack |
Tiếp đó init npm:
1 2 | npm init |
Thêm các dependencies , khi đó package.json sẽ có dạng :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <span class="token punctuation">{</span> <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"ethcodebased"</span><span class="token punctuation">,</span> <span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"1.0.0"</span><span class="token punctuation">,</span> <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span> <span class="token property">"main"</span><span class="token operator">:</span> <span class="token string">"truffle-config.js"</span><span class="token punctuation">,</span> <span class="token property">"directories"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"test"</span><span class="token operator">:</span> <span class="token string">"test"</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token property">"scripts"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"test"</span><span class="token operator">:</span> <span class="token string">"echo "Error: no test specified" && exit 1"</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token property">"author"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span> <span class="token property">"license"</span><span class="token operator">:</span> <span class="token string">"ISC"</span><span class="token punctuation">,</span> <span class="token property">"dependencies"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"dotenv"</span><span class="token operator">:</span> <span class="token string">"^8.1.0"</span><span class="token punctuation">,</span> <span class="token property">"solidity-coverage"</span><span class="token operator">:</span> <span class="token string">"^0.6.4"</span><span class="token punctuation">,</span> <span class="token property">"truffle"</span><span class="token operator">:</span> <span class="token string">"^5.0.12"</span><span class="token punctuation">,</span> <span class="token property">"truffle-assertions"</span><span class="token operator">:</span> <span class="token string">"^0.9.1"</span><span class="token punctuation">,</span> <span class="token property">"truffle-hdwallet-provider"</span><span class="token operator">:</span> <span class="token string">"^1.0.6"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Cuối cùng dùng yarn để install các package:
1 2 | yarn <span class="token function">install</span> |
Sau khi chạy hoàn thiện câu lệnh và loại bỏ một số file không cần thiết thì cấu trúc folder sẽ dạng như vậy :
Trong box webpack đã mặc định chứa contract MetaCoin, và đây sẽ là contract để chúng ta làm demo cơ bản. Contract này về cơ bản sẽ là một phiên bản siêu rút gọn của ERC20. Contract này sẽ phát hành 10.000 coin, trong đó mỗi coin sẽ tương ứng với giá là 2 ETH
1 2 3 4 5 6 7 8 | <span class="token keyword">function</span> <span class="token function">getBalanceInEth</span><span class="token punctuation">(</span>address addr<span class="token punctuation">)</span> <span class="token keyword">public</span> view <span class="token function">returns</span><span class="token punctuation">(</span>uint<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> ConvertLib<span class="token punctuation">.</span><span class="token function">convert</span><span class="token punctuation">(</span><span class="token function">getBalance</span><span class="token punctuation">(</span>addr<span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">convert</span><span class="token punctuation">(</span>uint amount<span class="token punctuation">,</span>uint conversionRate<span class="token punctuation">)</span> <span class="token keyword">public</span> pure <span class="token function">returns</span> <span class="token punctuation">(</span>uint convertedAmount<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> amount <span class="token operator">*</span> conversionRate<span class="token punctuation">;</span> <span class="token punctuation">}</span> |
Vẫy đã nắm rõ phần Smart contract, tiếp tục sẽ là cách thứ deploy đoạn code này. Để deploy chúng ta sẽ sử dụng mạng ropsten , do đó sẽ cần config lại file truffle-config.js :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | const path = require('path'<span class="token punctuation">)</span><span class="token punctuation">;</span> var HDWalletProvider = require('truffle-hdwallet-provider'<span class="token punctuation">)</span><span class="token punctuation">;</span> MNENOMIC = process.env.MNENOMIC<span class="token punctuation">;</span> INFURA_API_KEY = process.env.INFURA_API_KEY<span class="token punctuation">;</span> require('dotenv'<span class="token punctuation">)</span>.config(<span class="token punctuation">)</span><span class="token punctuation">;</span> module.exports = <span class="token punctuation">{</span> networks<span class="token operator">:</span> <span class="token punctuation">{</span> development<span class="token operator">:</span> <span class="token punctuation">{</span> host<span class="token operator">:</span> '<span class="token number">127.0</span><span class="token number">.0</span><span class="token number">.1</span>'<span class="token punctuation">,</span> // Localhost (default<span class="token operator">:</span> none<span class="token punctuation">)</span> port<span class="token operator">:</span> <span class="token number">8545</span><span class="token punctuation">,</span> // Standard Ethereum port (default<span class="token operator">:</span> none<span class="token punctuation">)</span> network_id<span class="token operator">:</span> '*' // Any network (default<span class="token operator">:</span> none<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> development<span class="token operator">:</span> <span class="token punctuation">{</span> host<span class="token operator">:</span> '<span class="token number">127.0</span><span class="token number">.0</span><span class="token number">.1</span>'<span class="token punctuation">,</span> port<span class="token operator">:</span> <span class="token number">8545</span><span class="token punctuation">,</span> network_id<span class="token operator">:</span> '*' <span class="token punctuation">}</span><span class="token punctuation">,</span> ropsten<span class="token operator">:</span> <span class="token punctuation">{</span> provider<span class="token operator">:</span> (<span class="token punctuation">)</span> => new HDWalletProvider(MNENOMIC<span class="token punctuation">,</span> 'https<span class="token operator">:</span>//ropsten.infura.io/v3/' + INFURA_API_KEY<span class="token punctuation">)</span><span class="token punctuation">,</span> network_id<span class="token operator">:</span> <span class="token number">3</span><span class="token punctuation">,</span> gas<span class="token operator">:</span> <span class="token number">4612388</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> kovan<span class="token operator">:</span> <span class="token punctuation">{</span> provider<span class="token operator">:</span> (<span class="token punctuation">)</span> => new HDWalletProvider(MNENOMIC<span class="token punctuation">,</span> 'https<span class="token operator">:</span>//kovan.infura.io/v3/' + INFURA_API_KEY<span class="token punctuation">)</span><span class="token punctuation">,</span> network_id<span class="token operator">:</span> <span class="token number">42</span><span class="token punctuation">,</span> gas<span class="token operator">:</span> <span class="token number">470000</span><span class="token punctuation">,</span> gasPrice<span class="token operator">:</span> <span class="token number">21</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> rinkeby<span class="token operator">:</span> <span class="token punctuation">{</span> provider<span class="token operator">:</span> (<span class="token punctuation">)</span> => new HDWalletProvider(MNENOMIC<span class="token punctuation">,</span> 'https<span class="token operator">:</span>//rinkeby.infura.io/v3/' + INFURA_API_KEY<span class="token punctuation">)</span><span class="token punctuation">,</span> network_id<span class="token operator">:</span> <span class="token number">4</span><span class="token punctuation">,</span> gas<span class="token operator">:</span> <span class="token number">470000</span><span class="token punctuation">,</span> gasPrice<span class="token operator">:</span> <span class="token number">21</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> |
Sẽ cần đến 2 thứ là Mnemonic và Infura key:
- Mnemonic: Được lấy từ chính Metamask, 12 kí tự seed words, khi lấy thì nhớ lấy tại tài khoản có ETH vì sau này sẽ dùng tài khoản này để deploy
- Infura key: Được lấy đơn giản bằng cách tạo project trên https://infura.io/dashboard khi đó sẽ tự động sinh ra một PROJECT ID . Infura có thể hiểu là một fullnode
Có đầy đủ các thứ trên thì giờ chỉ cần gọi command để deploy lên mạng ropsten:
1 2 | truffle migrate <span class="token operator">--</span>network ropsten |
và thành công sẽ như sau:
Sau khi đã deploy xong thì sẽ xuất hiện một folder mới lưu file đã compile của contract:
File Metacoin sẽ chứa 2 phần quan trọng đó là ABI và Address :
- ABI có thể hiểu rằng nó chứa bản mô tả về các function, các variable của smart contract vừa được deploy
- Address địa chỉ của contract vừa được deploy, tìm kiếm trong file Metacoin với từ khóa networks sẽ thấy xuất hiện object có key là 3 – tương ứng với chainID của ropsten (mỗi network sẽ có một chainID riêng, mainnet của ETH có chainID là 1)
Vậy là về cơ bản đã xong phần contract, thứ quan trọng cần đạt được ở phần này chính là ABI và Address của smart cotnract. Ngoài sử dụng Truffle thì cũng có thể sử dụng Remix (Sử dụng remix sẽ đỡ tốn gas hơn truffle do không phải tốn thêm gas để deploy contract Migration )
Tips: Có một tips để tối ưu nhất đó chính là compile contract bằng truffle và deploy bằng remix để lấy Address và khi đó là sẽ có một file hoàn hảo với chi phí tối thiểu