快速學習-以太坊編寫合約的部署腳本

編寫合約的部署腳本

上節課我們已經通過編譯從 solidity 源碼得到了字節碼,接下來我們會試圖完成一個自動化腳本,將合約部署到區塊鏈網絡中。

部署的必要條件

與以太坊節點的通信連接

我們需要啓動一個以太坊節點,連接到想要的網絡,然後開放 HTTP-RPC的 API(默認 8545 端口)給外部調用;或者也可以用第三方提供的可用節點入口,以太坊社區有人專門爲開發者提供了節點服務。目前我們直接用 ganache,不需要考慮這些問題,但如果配置其它網絡,這個配置就是必要的。

餘額大於 0 的賬戶

因爲以太坊上的任何交易都需要賬戶發起,賬戶中必須有足夠的餘額來支付手續費(Transaction Fee),如果餘額爲 0 部署會失敗。當然,我們目前用的是 ganache,裏面默認有 10 個賬戶,每個賬戶 100ETH,不存在這個問題,但如果要部署到其它網絡(私鏈、測試網絡、主網)就必須考慮這個問題。

安裝依賴

搞清楚部署的必要條件之後,我們需要安裝必要的依賴包。首先是 web3.js,web3.js 的 1.0.0 版本尚未發佈,但是相比 0.2x.x 版本變化非常大,1.x 中大量使用了 Promise,可以結合 async/await 使用,而 0.x 版本只支持回調,因爲使用 async/await 能讓代碼可讀性更好,我們這次選擇使用 1.0.0 版本。

npm install web3

編寫部署腳本

做好準備工作之後,我們開始編寫合約部署腳本,在 scripts 目錄下新建腳本文件 deploy.js:

const path = require('path');
const Web3 = require('web3');
const web3 = new Web3(new Web3.providers
	.HttpProvider('http://localhost:8545'));
// 1. 拿到 abi 和 bytecode 
const contractPath = path.resolve(__dirname,
	'../compiled/Car.json');
const {
	interface,
	bytecode
} = require(contractPath);
(async() => {
	// 2. 獲取錢包裏面的賬戶
	const accounts = await web3.eth.getAccounts();
	console.log('部署合約的賬戶:', accounts[0]);
	// 3. 創建合約實例並且部署
	var result = await new
	web3.eth.Contract(JSON.parse(interface))
		.deploy({
			data: bytecode,
			arguments: ['AUDI']
		})
		.send({
			from: accounts[0],
			gas: '1000000'
		});
	console.log('合約部署成功:', result);
})();

我們來熟悉一下 v1.0.0 版本中的部署操作。由於 1.0.0 版本中調用返回全部是 promise,所以我們這裏用到了 ES7 中的 async/await 來處理所有異步調用。

第二步獲取錢包賬戶,存爲本地變量,然後選取 accounts[0] 作爲部署合約的賬戶;我們應該確保這個賬戶中以太餘額充足。

第三步中,我們用 promise 的鏈式調用完成了創建抽象合約對象、創建部署交易對象(deploy)和發送部署交易三個步驟,其中只有 send 一步是真正的異步請求調用。分開寫就是這樣:

const contract = new web3.eth.Contract(JSON.parse(interface)); 
const transaction = contract.deploy({ data: bytecode, arguments: 
['AUDI'] }); 
const result = await transaction.send({ from: accounts[0], gas: 
1000000 });

運行腳本

在根目錄下運行寫好的部署腳本:node scripts/deploy.js
查看結果,可以看到合約已經成功部署。我們發現返回結果有些複雜,所以可以對代碼稍作改進,截取 address 返回,並計算一下部署花了多少時間:

const path = require('path');
const Web3 = require('web3');
const web3 = new Web3(new Web3.providers
	.HttpProvider('http://localhost:8545'));
// 1. 拿到 bytecode
const contractPath = path.resolve(__dirname,
	'../compiled/Car.json');
const {
	interface,
	bytecode
} = require(contractPath);
(async() => {
	// 2. 獲取錢包裏面的賬戶
	const accounts = await web3.eth.getAccounts();
	console.log('部署合約賬戶:', accounts[0]);
	// 3. 創建合約實例並且部署
	console.time('合約部署耗時');
	var result = await new
	web3.eth.Contract(JSON.parse(interface))
		.deploy({
			data: bytecode,
			arguments: ['AUDI']
		})
		.send({
			from: accounts[0],
			gas: '1000000'
		});
	console.timeEnd('合約部署耗時');
	console.log('合約部署成功:', result.options.address);
})();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章