【Ethereum 智能合約開發筆記】不用自己跑節點,使用 Infura 和 web3.js 呼叫合約

Anderson Chen
Jan 29, 2018 · 10 min read
Infura Logo from Consensys

Infura 提供公開的 Ethereum 主網和測試網路節點。到 Infura 官網申請,只要輸入一點基本資料和 Email,就可以收到 API-key。

Infura API keys

使用 RPC 查詢合約內儲存的狀態

最常需要查詢的狀態就是 Token 的餘額啦。我就用 EOS Token 合約做為範例試看看。

可以透過 Etherscan,大部分知名的合約可以直接搜尋到。

要呼叫合約,至少需要:

  • 合約地址,例如:0x86Fa049857E0209aa7D9e616F7eb3b3B78ECfdb0
  • 要呼叫的 function signature,例如以 ERC 20 Token 合約來說,查詢餘額要呼叫的 function 是 balanceOf(address),其對應的 function signature 是 70a08231

balanceOf(address) 為例:

i. 把 balanceOf(address) 經過 sha3

ii. 取除了 0x 外,前面的 8 位

以上流程可以用任何工具完成,以 web3.js 為例:

另外也可以把 contract code 貼到 Remix。在合約的 Details 中可以看到完整的合約介面和對應的 function signature。


可以透過一個簡單的 POST 用 Infura 提供的節點呼叫一個 RPC。有哪些 RPC method 可以看 Ethereum RPC doc

如果要呼叫的 function 只是查詢,而沒有要更新合約的狀態,那就用 eth_call 這個 RPC。POST Data 如下:

其中 params 的值包含:

  • "to":合約地址
  • "data":丟給合約的參數。由三個部分組成:0x70a08231和一個 32 bytes 的參數 00000000000000000000000033b8287511ac7F003902e83D642Be46(也就是我要查詢的帳戶)
  • "latest",代表使用最新的區塊鏈資料

0x000000000000000000000000000000000000000000000000b1d16ec625a59d3e 是十六進位,換算成十進位是 12813144212159962430。EOS token 的 decimal18,也就是小弟的帳戶只有少少的 12.8x 個 EOS token。


web3.js(Ethereum JavaScript API)

如果要更新合約的狀態,就需要送 transaction,要送 transaction 就需要錢包中的 private key 來 sign transaction 和提供 Ether 做手續費。因為送 transaction 要手續費,為了省點錢,我就部署一個合約在 Ropsten 測試鏈上做這次的試驗。以上步驟比較麻煩,我用 web3.js 寫兩個簡單的程式,一個查詢合約狀態、一個更新合約狀態。web3.js 的功能和 RPC 差不多,但是個 JavaScript 套件。有哪些 API 可以用請看 JavaScript API doc(v0.2x)。

這次部署一個很簡單的合約。合約只儲存一個狀態 data,並可透過 set() 更新狀態。詳細如何部署合約,可參考我的另一篇文章

合約程式碼:

合約地址:0x5fb30123b9efedcd15094266948fb7c862279ee1

合約的 function signatures:


查詢合約狀態

使用 web3.eth.call

Print 出來結果會是 0,因為還沒更新過狀態。


更新合約狀態

使用 web3.eth.sendRawTransaction

RPC 和 web3.js 提供的 SendTransaction 都是連到一節點,使用節點中的帳戶 sign 過再發送。而如果要用自己的帳戶就要用 sendRawTransaction,也就是說要自己建立 transaction、自己 sign 過,再透過 sendRawTransaction 發送。

rawTx 中包含:

  • nonce:紀錄目前帳戶送出的交易數,用來避免 replay attack,每次送要加 1。可以用 RPC eth_getTransactionCount 查詢目前帳戶的 nonce。也可以用 Etherscan 查,但 Etherscan 顯示的 No Of Transactions 會包含送出去但沒有成功的交易,所以會不準
  • gasPrice:一般用 1 Gwei(= 1000000000 = 0x3B9ACA00)
  • gasLimit:gaslimit 估算可參考 使用ethereum browser計算gas cost
  • to:合約地址
  • value:要送的 Ether 數量,因為只是要呼叫合約所以設 0
  • data:丟給合約的參數。由三個部分組成:0x60fe47b1和一個 32 bytes 的參數 000000000000000000000000000000000000000000000000000000000000000a(也就是我要更新的值,這邊設 10)

要引入另一個套件 ethereumjs-tx。記得先用 npm 安裝。

建立 raw transaction。

用自己的 private key sign。

成功就會回傳一個 transaction hash,像是:

交易成功送出且被收進 block 後,再次查詢合約狀態,Print 出來結果就會是 10

可以透過 Etherscan 確認交易有沒有被收進 block 以及合約執行的結果(可能因為參數錯誤導致執行失敗)。



Originally published at gist.github.com.

Taipei Ethereum Meetup

台北以太坊社群專欄

Anderson Chen

Written by

Founder @ Dapp Pocket

Taipei Ethereum Meetup

台北以太坊社群專欄

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade