solidity-5.事件

参考文档
Solidity的event事件(二十一)|入门系列
http://me.tryblockchain.org/blockchain-solidity-event.html

以太坊中的日志和事件:
http://www.8btc.com/ethereum-events-and-logs

事件 event

事件是以太坊EVM提供的一种日志基础设施。
事件可以用来做操作记录,存储为日志。
有了事件DAPP就可以实现一些交互功能,比如通过监控事件并定义回调函数,获取事件触发的日志。

event定义

event关键字定义一个事件,事件可以被继承。

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

indexed属性:可以在事件参数上增加indexed属性,最多可以对三个参数增加这样的属性。属性作用是允许你在web3.js中通过对加了这个属性的参数进行值过滤,比如:

var event = myContract.transfer({value: "100"});
var event = myContract.transfer({value: ["99","100","101"]});

增加了indexed的参数值会存到日志结构的Topic部分,便于快速查找。
而未加indexed的参数值会存在data部分,成为原始日志。

event 触发

类似调用函数的方式,触发事件,比如:

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

event监听

在web3.js中,提供了响应事件的方法,如下2:

var event = myContract.transfer();

    // 监听
    event.watch(function(error, result){
    console.log("Event are as following:-------");
    
    for(let key in result){
     console.log(key + " : " + result[key]);
    }
    
    console.log("Event ending-------");
});

另外一种简便写法是直接加入事件回调,这样就不用再写watch的部分:

var event = myContract.transfer(function(error, result){
    console.log("Event are as following:-------");
    
    for(let key in result){
     console.log(key + " : " + result[key]);
    }
    
    console.log("Event ending-------");
});

event.stopWatching();来终止监听

过滤参数

除了indexed属性,事件还支持传入fromBlocktoBlock等过滤条件。

var event = myContract.transfer({value: "100"}, {fromBlock: 0, toBlock: 'latest'});

底层的日志接口

可以通过底层的日志接口来访问底层的日志机制。通过函数log0,log1,log2,log3,log4。logi支持i + 1个类型为bytes32的参数。其中第一个参数是日志的data部分,其它参数为topic。所以下述事件:

log3(
    msg.value, 0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20,
    msg.sender,
    _id
);

第一个参数为非indexeddata部分值。第二个参数为默认主题,即事件签名的哈希值keccak256("Deposit(address,hash256,uint256)"),后面两个是按顺序的indexed主题。

使用web3.js读取事件的完整例子

例子展示了很多内容,包括:

  • 编译合约
  • 部署合约
  • 合约部署后的回调函数
  • 合约事件监控

    let Web3 = require('web3');
    let web3;
    
    if (typeof web3 !== 'undefined') {
        web3 = new Web3(web3.currentProvider);
    } else {
        // set the provider you want from Web3.providers
        web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
    }
    
    let from = web3.eth.accounts[0];
    
    //编译合约
    let source = "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(){}}";
    let transferCompiled = web3.eth.compile.solidity(source);
    
    console.log(transferCompiled);
    console.log("ABI definition:");
    console.log(transferCompiled["info"]["abiDefinition"]);
    
    //得到合约对象
    let abiDefinition = transferCompiled["info"]["abiDefinition"];
    let transferContract = web3.eth.contract(abiDefinition);
    
    //2. 部署合约
    
    //2.1 获取合约的代码,部署时传递的就是合约编译后的二进制码
    let deployCode = transferCompiled["code"];
    
    //2.2 部署者的地址,当前取默认账户的第一个地址。
    let deployeAddr = web3.eth.accounts[0];
    
    //2.3 异步方式,部署合约
    //警告,你不应该每次都部署合约,这里只是为了提供一个可以完全跑通的例子!!!
    transferContract.new({
        data: deployCode,
        from: deployeAddr,
        gas: 1000000
    }, function(err, myContract) {
        if (!err) {
            // 注意:这个回调会触发两次
            //一次是合约的交易哈希属性完成
            //另一次是在某个地址上完成部署
    
            // 通过判断是否有地址,来确认是第一次调用,还是第二次调用。
            if (!myContract.address) {
                console.log("contract deploy transaction hash: " + myContract.transactionHash) //部署合约的交易哈希值
    
                // 合约发布成功后,才能调用后续的方法
            } else {
                console.log("contract deploy address: " + myContract.address) // 合约的部署地址
    
                console.log("Current balance: " + myContract.getBanlance());
    
                var event = myContract.transfer();
    
                // 监听
                event.watch(function(error, result){
                  console.log("Event are as following:-------");
    
                  for(let key in result){
                    console.log(key + " : " + result[key]);
                  }
    
                  console.log("Event ending-------");
                });
    
                //使用transaction方式调用,写入到区块链上
                myContract.deposit.sendTransaction({
                    from: deployeAddr,
                    value: 100,
                    gas: 1000000
                }, function(err, result){
                  console.log("Deposit status: " + err + " result: " + result);
                  console.log("After deposit balance: " + myContract.getBanlance());
    
                  //终止监听,注意这里要在回调里面,因为是异步执行的。
                  event.stopWatching();
                });
            }
        }
    });

你可能感兴趣的:(solidity-5.事件)