【Ethereum 智能合約開發(fā)筆記】使用 MetaMask, web3 和 EthJS 呼叫合約

使用 web3 應(yīng)該是開發(fā) DApp 必須的舶胀,不管要查詢 Ethereum 區(qū)塊鏈狀態(tài)绒障、發(fā)送交易淹遵、呼叫智能合約都可以透過 web3。使用 web3 必須連結(jié)到 Ethereum 節(jié)點伴网,之前我寫了一篇文章介紹使用 Infura 提供的節(jié)點。其實常用的 Ethereum 瀏覽器錢包?—?MetaMask 也有提供 web3 provider妆棒,用他提供的 provider 初始化 web3澡腾,就可以連上 MetaMask 提供的節(jié)點。參考以下兩篇官方文件糕珊,我實作了簡單的范例动分,并記錄幾個可能碰到的問題。

MetaMask 官方文件:

  1. MetaMask Compatibility Guide
  2. Developing for MetaMask

另外 MetaMask/mascara 提供在不安裝 MetaMask 的環(huán)境下红选,使用 MetaMask 提供的 web3澜公。

使用范例

寫一個簡單的 JavaScript 程式,使用 MetaMask 提供的 web3 provider 來初始化 web3:

var Web3 = require('web3');
// set the provider of web3
if (typeof web3 !== 'undefined') { 
    console.debug(web3.currentProvider);
    web3 = new Web3(web3.currentProvider);
} else {
    alert("No currentProvider for web3");
}

用 browserify 打包:

browserify web3_init.js -o web3_bundle.js

在 HTML file 中執(zhí)行:

<script src="js/web3_bundle.js"></script>

再寫個 HTML file 測試看看喇肋。希望透過 MetaMask 提供的 web3 取得:

  1. web3 的 API version
  2. 我的 MetaMask account
<html>
  <body>
    <h2>Web3 API version</h2>
    <p id="p1"></p>
    <h2>My Account</h2>
    <p id="account"></p>
    <script src="js/web3_bundle.js"></script>
    <script>
      // Get API version
      var p1 = document.getElementById("p1");
      p1.innerHTML = web3.version.api;
      // Get my MetaMask account
      var account = document.getElementById("account");
      account.innerHTML = web3.eth.accounts;
  </body>
</html>

執(zhí)行結(jié)果:


可能碰到的問題

1. 找不到 web3.currentProvider

  • 必須使用 http server坟乾,根據(jù) MetaMask 官方文件

Due to browser security restrictions, we can’t communicate with dapps running on file://. Please use a local server for development.

  • 必須確認(rèn)啟用 MetaMask extension。

2. 無法取得 web3.eth.accounts

必須用密碼解鎖 MetaMask苟蹈,不然會回傳 undefined 糊渊。

3. 沒有使用 callback

MetaMask 官方文件表示所有提供的 web3 API 都是非同步,必須要傳入 callback function慧脱,除了以下例外:

  • eth_accounts (web3.eth.accounts)
  • eth_coinbase (web3.eth.coinbase)
  • eth_uninstallFilter (web3.eth.uninstallFilter)
  • web3.eth.reset (uninstalls all filters)
  • net_version (web3.version.network)

除了以上 API渺绒,我在使用時也有其他 API 不需要 callback。但確實碰到 API 是必需要用 callback菱鸥,不然 MetaMask 會跳出 error宗兼。

4) Web3 API 版本

以上範(fàn)例是使用 官方 wiki 的 API,版本是 0.2x.x氮采。如果直接用 npm install web3 殷绍,根據(jù)我的經(jīng)驗會安裝的版本為 1.0.0,API 使用的方法會有些不同鹊漠,使用方式請看 web3.js Doc主到。

使用 EthJS 呼叫合約

EthJS 是另一個 Ethereum 的 JavaScript API茶行,也是 MetaMask 開發(fā)者推薦的 JavaScript API。根據(jù) EthJS 官方文件的描述:

EthJS is a highly optimised, light-weight JS utility for Ethereum based on web3.js, but lighter, async only and using BN.js.

EthJS 分為多個 module登钥,如果要使用合約要安裝這兩個:

npm install ethjs-query ethjs-contract --save

同樣使用 MetaMask 提供的 web3 provider 來初始化 EthJS:

var Eth = require('ethjs-query');
var EthContract = require('ethjs-contract');
if (typeof web3 !== 'undefined') {
    eth = new Eth(web3.currentProvider);
    contract = new EthContract(eth);
    startApp();
} else {
    alert("No currentProvider for web3");
}

使用 contract 初始化合約畔师,一樣需要合約的 ABI 和 address:

function startApp() {
    const abi = [ { "constant": true, "inputs": [], "name": "data", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view",  "type": "function" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "_from", "type": "address" }, { "indexed": false, "name": "value", "type":    "uint256" } ], "name": "Set", "type": "event" }, { "constant": false, "inputs": [ { "name": "x", "type": "uint256" } ], "name": "set", "outputs": [],  "payable": false, "stateMutability": "nonpayable", "type": "function" } ];
    const addresss = '0x06e1c13546e04514a0cf8d842216a84745ac317a';
    const SimpleStorage = contract(abi);
    const simpleStorage = SimpleStorage.at(addresss);
    // Listen to clicks from a <button> that trigger a function call of contract 

    listenForClicks(simpleStorage);
}

寫一個簡單的 HTML file,有一個 input 欄位可以輸入任意數(shù)值牧牢,和一個 button看锉。

<input id="data-value" type="text" placeholder="Enter a number">
<button class="set">Set Data!</button>

在寫一個 JavaScript function 監(jiān)聽這個 button,按下 button 后會透過 EthJS 呼叫合約的 set(uint256)塔鳍,把合約中的狀態(tài) data 設(shè)為對應(yīng)數(shù)值伯铣。要呼叫合約不需要知道 function signature,也不用自己建 transaction轮纫。就像使用 JavaScript 物件中的 function腔寡,像是: simpleStorage.set(param, {from: myAddr}, callback() {...})

function listenForClicks(simpleStorage) {
    var button = document.querySelector('button.set');
    button.addEventListener('click', function() {
        var value = document.getElementById('data-value').value;
        simpleStorage.set(value, { from: "0x123abc000..." }, function(error, result) {
            if (error) {
                 console.debug(error);
                 return;
            }  
            // will return txHash as result
            console.debug(result);
        })
   })
}

用看看

  1. 任意輸入一個數(shù)字后掌唾,按 Set Data蹬蚁!


    輸入 20
  2. 跳出 MetaMask 的提醒視窗。MetaMask 提供介面讓使用者授權(quán)交易的發(fā)送郑兴,點擊 confirm 就可以發(fā)送這筆交易犀斋。


  3. 發(fā)送成功,取得 Transaction Hash情连。


  4. 等 transaction confirm 后叽粹,再去呼叫合約的 data(),就會得到更新后的值却舀。一樣可以透過 EthJS虫几,像是這段簡單的 code:

simpleStorage.data(function(error, result) {
    // result[0] is a object of bn.js
    console.debug(result[0].toNumber());
})

// Return value
20

References

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市挽拔,隨后出現(xiàn)的幾起案子辆脸,更是在濱河造成了極大的恐慌,老刑警劉巖螃诅,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啡氢,死亡現(xiàn)場離奇詭異,居然都是意外死亡术裸,警方通過查閱死者的電腦和手機倘是,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來袭艺,“玉大人搀崭,你說我怎么就攤上這事』啵” “怎么了瘤睹?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵升敲,是天一觀的道長。 經(jīng)常有香客問我轰传,道長冻晤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任绸吸,我火速辦了婚禮,結(jié)果婚禮上设江,老公的妹妹穿的比我還像新娘锦茁。我一直安慰自己,他們只是感情好叉存,可當(dāng)我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布码俩。 她就那樣靜靜地躺著,像睡著了一般歼捏。 火紅的嫁衣襯著肌膚如雪稿存。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天瞳秽,我揣著相機與錄音瓣履,去河邊找鬼。 笑死练俐,一個胖子當(dāng)著我的面吹牛袖迎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播腺晾,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼燕锥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了悯蝉?” 一聲冷哼從身側(cè)響起归形,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鼻由,沒想到半個月后暇榴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡蕉世,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年跺撼,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片讨彼。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡歉井,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出哈误,到底是詐尸還是另有隱情哩至,我是刑警寧澤躏嚎,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站菩貌,受9級特大地震影響卢佣,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜箭阶,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一虚茶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧仇参,春花似錦嘹叫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至怕磨,卻和暖如春喂饥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背肠鲫。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工员帮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人导饲。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓集侯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親帜消。 傳聞我的和親對象是個殘疾皇子聪黎,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容