1. 程式人生 > >以太坊學習(6)關於web3.js 1.0版本中event事件無法觸發的問題

以太坊學習(6)關於web3.js 1.0版本中event事件無法觸發的問題

關於web3.js 1.0版本中event事件無法觸發的問題

寫在最前:請檢查你的provider連線方式,http provider已不支援event事件的觸發了

具體請看官方源文件

一、問題還原:

(1)先給出智慧合約程式碼

  • 合約內容比較簡單
  • deposit()函式,對合約地址發起交易,可傳送以太幣。。相當於存錢到合約地址
  • event transfer()  事件
pragma solidity ^0.4.0;

contract Transfer{
  event transfer(address indexed _from, address indexed _to, uint indexed value);

  function deposit() payable {
    address current = this;
    uint value = msg.value;
    transfer(msg.sender, current, value);
  }


  function getBanlance() constant returns(uint) {
      return this.balance;
  }

  /* fallback function */
  function(){}
}

(2)在通過web3.js對event事件進行測試時,遇到如下event無法觸發的情況:

let Web3=require('web3');
let fs=require('fs');
let web3;

if(typeof web3 !=='undefined'){ //檢查是否已有web3例項
    web3=new Web3(web3.currentProvider);
}else{
    //否則就連線到給出節點
    web3=new Web3();
    web3.setProvider(new Web3.providers.WebsocketProvider("ws://localhost:8546"));
}
web3.eth.getBlock(0, function(error, result){
    if(!error)
        console.log("connect should be success");
    else
        console.log("something wrong,the connection might be failed");
})

//abi 直接由solc在外部 solcjs --abi mycontract.sol 編譯好,這裡直接引用
var abi=JSON.parse(fs.readFileSync("mycontract_sol_Transfer.abi").toString())
var myContractAddress="0x15a27fb5ea1c3842fac984df488df9325ef60829";
var transferContract =new web3.eth.Contract(abi); 
transferContract.options.address=myContractAddress;

//event
transferContract.events.transfer({},
    function(err,event){
        console.log(event);
    });

//發起交易,試圖觸發event
transferContract.methods.deposit().send({
    from:"0x2EC12C8e3a8a0df6EdD448688e6EE0E0132ED801",
    value:100,
    gas:10000000
});

【執行前,請先確保你的節點已經啟動,並且合約已經部署過了,否則你沒有合約的地址,無法發起交易】

執行步驟:

1.node 形式啟動

 2.看起來是連線上了,但是後面報錯說是沒有解鎖

解鎖賬戶: personal.unlockAccount(eth.accounts[0])

3.再次啟動

左圖是geth客戶端可以看見有一筆交易提交,右圖是啟動後

4.啟動挖礦,確認交易

  miner.start()

 5.已經挖礦確認了,但是node.js執行這邊直接退出了,並沒有輸出事件event

二、解決方案

如果是上述的問題,那麼很可能就是provider的設定問題,我們選擇websocket provider,再嘗試

(1)要修改的部分程式碼:

if(typeof web3 !=='undefined'){ //檢查是否已有web3例項
    web3=new Web3(web3.currentProvider);
}else{
    //否則就連線到給出節點
    web3=new Web3();
    web3.setProvider(new Web3.providers.WebsocketProvider("ws://localhost:8546"));//注意這裡注意埠不用一致,直接預設8546即可(若剛剛啟動節點的rpc埠是8545的情況下)
}

(2)修改完後的全部程式碼:

let Web3=require('web3');
let fs=require('fs');
let web3;

if(typeof web3 !=='undefined'){ //檢查是否已有web3例項
    web3=new Web3(web3.currentProvider);
}else{
    //否則就連線到給出節點
    web3=new Web3();
    web3.setProvider(new Web3.providers.WebsocketProvider("ws://localhost:8546"));
}
web3.eth.getBlock(0, function(error, result){
    if(!error)
        console.log("connect should be success");
    else
        console.log("something wrong,the connection might be failed");
})

//abi 直接由solc在外部 solcjs --abi mycontract.sol 編譯好,這裡直接引用
var abi=JSON.parse(fs.readFileSync("mycontract_sol_Transfer.abi").toString())
var myContractAddress="0x15a27fb5ea1c3842fac984df488df9325ef60829";
var transferContract =new web3.eth.Contract(abi); 
transferContract.options.address=myContractAddress;

//event
transferContract.events.transfer({},
    function(err,event){
        console.log(event);
    });

//發起交易,試圖觸發event
transferContract.methods.deposit().send({
    from:"0x2EC12C8e3a8a0df6EdD448688e6EE0E0132ED801",
    value:100,
    gas:10000000
});

(3)重複之前的啟動步驟 

挖礦確認後:

 可以捕捉到event事件並輸出了

三、另外的問題

問題簡述:web3.js 1.0版本下有好多的beta 版本,不同的beta版本可能會導致一些奇怪的問題。2018-10-17下直接使用npm install web3 ,會下載 web3.js 1.0 beta36

使用 beta36版本,事件可以觸發,但是輸出的時候會報錯如下:

解決方案:

引入指定版本的web3.js

 npm install [email protected]    //指定安裝版本

即可解決問題。