Ethereum Dapp初心者之路(5): 簡介Web3 Javascript API及常用操作

林瑋宸 Albert Lin
14 min readMay 1, 2018

--

現今有許多Dapp Librarys可以用來跟Ethereum網路溝通,像是由Java撰寫web3J,python的Web3.py和.Net的nethereum。今天要介紹的Web3.js則是由Javascript撰寫的Ethereum JavaScript API。Web3.js提供了一些基本操作,譬如getBalane()、sendTransaction()…等,也可以利用 Web3.js來幫我們佈署smart contract到Ethereum網路上。使用者可以利用Web3.js提供的界面來跟Metamask或Geth Node,甚至是Ganache Testrpc互動。

PS: Ganache Testrpc是專門用來模擬私人Ethereum網路環境的工具,只在本地端的電腦上運行,資料只存放在Memory中。重開後等同於建立另一個全新的私人Ethereum網路。適合前期拿來開發Dapp功能。

Web3.js可以跟後端的Ethereum網路(Metamask或Geth)溝通或模擬的Ethereum網路(Ganache Trestrpc)

Web3.js API Overview

Web3.js Asynchronous

Web3.js的API有分成同步(Synchronous)和非同步(Asynchronous)的呼叫,非同步呼叫採用的是Error-First Callback的方式。

web3.eth.getSyncing(function(error, result) {
if(error) {
// error handle
} else {
// do something
}
});

可以看到在web3.eth.getSyncing()的參數中註冊了一個callback function,而且callback function中的第一個參數是放回傳的error,第二個參數才是放回傳的result。可以在callback function中針對回傳的結果進行處理。

Web3.js API Type

Web3.js的API大約分成幾個種類:

  • eth: Etherum blockchain related methods
  • net: Node’s network status
  • personal: Account functions and sending
  • db: Get/put for local LevelDB
  • shh: P2P messaging using Whisper

Web3.js Big Number

Javascript不能正確的處理big number value,所以Web3.js使用了BigNumber library來處理。但即便使用了BigNumber也無法處理超過20個floating points。建議在處理balance的時候使用Wei來取代Ether會比較好。

Web3.js常用的操作

接下來會提到Web3.js幾個比較常見和重要的操作。每個操作的範例都可以從Web3APIScript下載,範例就放在scripts資料夾中。

Web3 Get Node

判斷目前使用者所連接是那種型態的Ethereum節點,Testrpc、Geth或Metamsak…等。

web3.version.getNode(function(error, result){
if(error){
// error handle
} else {
// do something
};
});

Web3 Syncing

判斷使用者所連接的Ethereum節點是否正在做同步的動作。正在同步為True,否則為False。

web3.eth.getSyncing(function(error, result) {
if(error) {
// error handle
} else {
// do something
}
});

Web3 Coinbase

查看連接Ethereum節點的coinbase address。coinbase是專門存放挖礦所獲得獎勵的read only帳戶。在Geth Node環境下可以使用Geth console下指令web3.miner.setEtherbase()去修改coinbase address。

web3.eth.getCoinbase(function(error, result) {
if(error) {
// error handle
} else {
// do something
}
});

Web3 Default Account

查看目前連接Ethereum節點的deault account address。deault account是read/write only。當我們在進行某些操作例如sendTransaction時,若沒有特別指定要從哪一個帳戶發出,則默認就是使用deault account。因為每個Ethereum節點實作的方式不同,default account不一定有定義,使用前最好檢查一下。

web3.eth.defaultAccount// 為了避免default account undefined的話, 可以改寫成下面的Code
var defaultAccount = web3.eth.defaultAccount;
if(!defaultAccount) {
web3.eth.defaultAccount = web3.eth.accounts[0];
defaultAccont = web3.eth.accounts[0];
}

Web3 Get Balance

取得帳戶裡的餘額。分成同步和非同步兩種。使用web3.eth.getBalance()所獲得餘額的單位是Wei。web3.fromWei()就是把Wei轉成其他單位,下面範例則是轉成Ether。toFixed()是我們只取到小數點後兩位數。getBalance()的第二個參數可以指定要從那個Block讀取資料。web3.eth.defaultBlock默認是latest,意思就是從最新的Block讀取該帳戶的餘額。

/* Get Balance Sync */
var balance = web3.fromWei(web3.eth.getBalance(web3.eth.accounts[0]), 'ether').toFixed(2);
/* Get Balance Async */
web3.eth.getBalance(web3.eth.accounts[0],web3.eth.defaultBlock,
function(error,result){
if(error){
// error handle
} esle {
var balance = web3.fromWei(result,'ether').toFixed(2);
}
}
);

Web3 Lock/Unlock Account

上鎖和解鎖帳戶。對於某些特定的操作必須先把帳戶先unlock才能進行,例如sendTransaction()相關操作。web3.personal.unlockAccount()的第三個參數duration可以設定要解鎖多久。若使用者連接的Etherum節點是Testrpc或Metamask,可以不須作lock/unlock動作。若是在Geth環境下,則在sentd transaction前必須先unlock帳戶。

/* Lock Account */
web3.personal.lockAccount(account, passwd,
function(error, result){
if(error) {
// error handle
} else {
// do something
}
}
);
/* Unlock Account */
web3.personal.unlockAccount(account, passwd, duration
function(error, result){
if(error) {
// error handle
} else {
// do something
}
}
);

Web3 Send Transaction

傳送交易。web3.eth.sendTransaction()的第一個參數txnObject是一個JSON format的物件。txnObject可以指定這次transaction的資訊。from是指從哪個帳戶送出,若無指定默認是default account。to是送到那個帳戶。value則是要傳送的金額。其他還有像是gasgasPrice、data、nonce…等參數可以指定。傳送完後可以得到transaction hash,使用web3.eth.getTransactionReceipt(hash)去查詢transaction的狀態。

var txnObject = {
"from": fromAccount,
"to": toAccount,
"value": web3.toWei(1, 'ether'),
// "gas": 21000, // (optional)
// "gasPrice": 4500000, // (optional)
// "data": 'For testing', // (optional)
// "nonce": 10 // (optional)
};
web3.eth.sendTransaction(txnObject, function(error, result){
if(error) {
// error handle
} else {
var txn_hash = result; //Get transaction hash
}
});

Web3 Deploy Contract

Deploy contract有兩種方式,一種是使用Web3.js contract的new(),另一種是使用sendTransaction()的方式。這裡只列出contract new()的方式,sendTransaction()方式可以從Web3ApIScript的範例中看到。在deploy contract之前我們需要先complie contract的sol檔來獲得abi和bytecode。利用abiDefinition建立contractInstance並將bytecode放入data欄位中。constructor_param則是contract 初始化所使用的參數。使用contract new()來進行佈署。執行完new()之後,callback function一共會被呼叫兩次。第一次回傳transaction hash,第二次則是contract address。

var contractInstance = web3.eth.contract(abi);
var params = {
from: fromAccount,
data: bytecode,
gas: gas
};
var constructor_param = 10; //contract init param
contractInstance.new(constructor_param, params,
function(error, result){
if(error) {
// error handle
} else {
if(result.address){
var contractAddress = result.address;
} else {
var txhash = result.transactionHash;
}
}
});

Web3 Interact Contract

與smart contract互動的方式主要分成,取得contract資料的call和改變contract資料的send。使用call只是單純取得contarct資料,並不會改變contract的狀態,所以不會花費任何費用。呼叫call()時要有contract abi和contract address。contract.METHOD.call()的METHOD是放contract中所定義的function名稱,以下面的例子就是getNum

var contract = web3.eth.contract(abi);
var contractInstance = contract.at(address);
/* contractInstance.METHOD.call,
METHOD=getNum is the function of contract
*/
contractInstance.getNum.call(function(error, result) {
if (error) {
// error handle
} else {
// result is string
// do something
}
});

若想要改變contract中的資料就必須使用send。這裡的send指的是send transaction。因為會改變contract中的資料,需要繳交手續費給礦工幫忙把資料紀錄在block中。改變的資料一樣會存放在block中,等同於發起了一筆transaction。使用contract.METHOD.sendTransaction()來改變contract資料。回傳該transaction的hash。METHOD一樣是指contract所定義的function名稱,下面例子就是setNum。parameterValue則是要賦予contract的新值。

var contract = web3.eth.contract(abi);
var contractInstance = contract.at(address);
var txnObject = {
from: fromAccount,
gas: estimatedGas
};
// contractInstance.METHOD.sendTransaction, METHOD=setNum is the function of contract
var parameterValue = 5 ;
contractInstance.setNum.sendTransaction(parameterValue, txnObject,
function(error, result){
if(error){
// error handle
} else {
// do something
}
});

結尾

Web3.js是Dapp Library,專門拿來與Ethereum網路溝通。在學習的過程算是比較有趣的部份,對Ethereum網路會有更深一層的理解。這裡只是介紹了Web3.js一些常用的操作,但完全沒有介紹到Event的部份。因為Event的部份東西比較多,我打算另外寫一篇。不然寫完一篇落落長,連我自己看了都眼花。上面的操作都可以在Web3APIScript這裡找到相對應的範例,有興趣的可以去看看。Web3 javascript的Wiki也寫的詳細的,有興趣的也可以點這裡去逛逛。

Web3.js算是目前最多人使用的Dapp Library,所以才特別拿來說明。對於我自己來說,Javascript算一個比較陌生的語言。本身所使用較多的語言是python,希望改天能有時間可以玩一下Web3.py,到時再來寫一篇關於Web3.py的文章,但目前還是先乖乖學習Web3.js吧!以上是我對於Web3.js的一些理解。若觀念或理解有誤,也拜託各位大大不吝嗇給於糾正。若有問題也歡迎留言在下面,我們可以一起討論尋找答案。希望這篇文章可以給各位有一點點的幫助,下篇見囉!

Reference:
[1] https://www.udemy.com/ethereum-dapp/
[2] https://github.com/ethereum/wiki/wiki/JavaScript-API
[3] https://www.udemy.com/blockchain-developer/
[4] https://github.com/ksin751119/Web3APIScript

若您覺得我的文章有所幫助,歡迎按下「拍手」給我支持並轉發給你的朋友們!
若想請小弟喝杯咖啡也非常歡迎喔XD
BTC: 35wkJ1LvrjnqjxaUqfkx3XCnRrmiZv57XJ
ETH: 0xe5206a8d961a2af5d0be28549432db99e22c5be5
LTC: LYQFY4sKU8CWqae8DCQ8NTLcwZMazdHuKB

--

--