博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
以太坊系列之十七: 使用web3进行合约部署调用以及监听
阅读量:5758 次
发布时间:2019-06-18

本文共 7896 字,大约阅读时间需要 26 分钟。

以太坊系列之十七: 使用web3进行智能合约的部署调用以及监听事件(Event)

上一篇介绍了使用golang进行智能合约的部署以及调用,但是使用go语言最大的一个问题是没法持续监听事件的发生.

比如我的后台程序需要监控谁给我转账了,如果使用go语言,目前就只能是轮询数据,而使用web3就简单许多,geth会把我关心的事件
主动通知给我.

token合约

token合约是官方提供的一个样例,这里给出我修改过的版本,方便演示.

contract MyToken {    /* Public variables of the token */    string public name;    string public symbol;    uint8 public decimals;    /* This creates an array with all balances */    mapping (address => uint256) public balanceOf;    mapping (address => mapping (address => uint)) public allowance;    mapping (address => mapping (address => uint)) public spentAllowance;    /* This generates a public event on the blockchain that will notify clients */    event Transfer(address indexed from, address indexed to, uint256 value);    event ReceiveApproval(address _from, uint256 _value, address _token, bytes _extraData);    /* Initializes contract with initial supply tokens to the creator of the contract */    function MyToken(uint256 initialSupply, string tokenName, uint8 decimalUnits, string tokenSymbol) {        balanceOf[msg.sender] = initialSupply;              // Give the creator all initial tokens        name = tokenName;                                   // Set the name for display purposes        symbol = tokenSymbol;                               // Set the symbol for display purposes        decimals = decimalUnits;                            // Amount of decimals for display purposes    }    /* Send coins */    function transfer(address _to, uint256 _value) {        if (balanceOf[msg.sender] < _value) throw;           // Check if the sender has enough        if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows        balanceOf[msg.sender] -= _value;                     // Subtract from the sender        balanceOf[_to] += _value;                            // Add the same to the recipient        Transfer(msg.sender, _to, _value);                   // Notify anyone listening that this transfer took place    }    /* Allow another contract to spend some tokens in your behalf */    function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success) {        allowance[msg.sender][_spender] = _value;        ReceiveApproval(msg.sender, _value, this, _extraData);    }    /* A contract attempts to get the coins */    function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {        if (balanceOf[_from] < _value) throw;                 // Check if the sender has enough        if (balanceOf[_to] + _value < balanceOf[_to]) throw;  // Check for overflows        if (spentAllowance[_from][msg.sender] + _value > allowance[_from][msg.sender]) throw;   // Check allowance        balanceOf[_from] -= _value;                          // Subtract from the sender        balanceOf[_to] += _value;                            // Add the same to the recipient        spentAllowance[_from][msg.sender] += _value;        Transfer(msg.sender, _to, _value);    }    /* This unnamed function is called whenever someone tries to send ether to it */    function () {        throw;     // Prevents accidental sending of ether    }}

编译token

通过solc编译得到的json abi以及hex编码的code,由于太长,太占地方就不放上来了.

这些会在部署以及调用的时候用到.

下面来通过web3进行合约的部署,读取数据,发起事务以及监听事件的发生.

部署合约

部署合约需要创建事务,话费gas,因此相关账户必须事先解锁,web3目前没有api可以解锁账户,需要自己在控制台事先解锁才行.

首先创建合约,需要制定abi.
然后就可以部署合约了,这时候需要合约的code,
部署合约的结果可以通过异步函数来获取,例子已经给出.

var Web3 = require('web3');var web3 = new Web3(new Web3.providers.IpcProvider("\\\\.\\pipe\\geth.ipc",net));var eth=web3.eth;var tokenContract = new web3.eth.Contract(MyTokenABI, null, {    from: '0x1a9ec3b0b807464e6d3398a59d6b0a369bf422fa' // 目前web3没有api来解锁账户,只能自己事先解锁});tokenContract.deploy({    data: MyTokenBin,    arguments: [32222, 'token on web3',0,'web3']}).send({    from: '0x1a9ec3b0b807464e6d3398a59d6b0a369bf422fa',    gas: 1500000,    gasPrice: '30000000000000'}, function(error, transactionHash){    console.log("deploy tx hash:"+transactionHash)}).on('error', function(error){ console.error(error) }).on('transactionHash', function(transactionHash){ console.log("hash:",transactionHash)}).on('receipt', function(receipt){   console.log(receipt.contractAddress) // contains the new contract address}).on('confirmation', function(confirmationNumber, receipt){console.log("receipt,",receipt)}).then(function(newContractInstance){    console.log(newContractInstance.options.address) // instance with the new contract address});

查询合约

合约部署成功以后,有了地址就可以根据地址来查询合约的状态.

查询合约状态并不需要发起事务,也不需要花费gas,因此比较简单.

var tokenContract = new web3.eth.Contract(MyTokenABI, '0x6a0dF9E94a41fCd89d8236a8C03f9D678df5Acf9');tokenContract.methods.name().call(null,function(error,result){        console.log("contract name "+result);    })

调用合约函数

合约的函数除了指明返回值是constant的以外,都需要发起事务,这时候就需要指定调用者,因为要花费该账户的gas.

这里调用一下transfer函数.

tokenContract.methods.transfer("0x8c1b2e9e838e2bf510ec7ff49cc607b718ce8401",387).send({from: '0x1a9ec3b0b807464e6d3398a59d6b0a369bf422fa'}).on('transactionHash', function(hash){}).on('confirmation', function(confirmationNumber, receipt){}).on('receipt', function(receipt){    // receipt example    console.log(receipt); //查询这里可以得到结果}).on('error', console.error); // If a out of gas error, the second parameter is the receipt.

监听事件

刚刚调用transfer的时候还会触发合约的事件Transfer,如果程序关注谁给谁进行了转账,那么就可以通过监听该事件.

通过指定fromBlock,toBlock可以限制事件发生的范围,除了这个还有一个filter参数可以进行更详细的限制,
如有兴趣可以查询文档

tokenContract.events.Transfer({    fromBlock: 0,    toBlock:'latest'}, function(error, event){ /*console.log("result:\n"+JSON.stringify(event)); */}).on('data', function(event){    console.log(event); // same results as the optional callback above}).on('changed', function(event){    // remove event from local database}).on('error', console.error);

需要说明的是,这个监听不仅传送历史事件,未来所有事件也会传送.

下面的结果是首先运行程序,会先打印出来刚刚进行的转账.

然后我在通过其他途径进行转账操作,这时候终端会把新的转账也打印出来.

历史转账:{ address: '0x6a0dF9E94a41fCd89d8236a8C03f9D678df5Acf9',  blockNumber: 10680,  transactionHash: '0x27d5ab9277df504a436b1068697a444d30228584094632f10ab7ba5213a4eccc',  transactionIndex: 0,  blockHash: '0xcde734882b0d8cb7a5bf1f7e6d1ccfac5365308de2d7391ce286b45c5546f40b',  logIndex: 0,  removed: false,  id: 'log_2588a961',  returnValues:   Result {     '0': '0x1a9eC3b0b807464e6D3398a59d6b0a369Bf422fA',     '1': '0x8c1b2E9e838e2Bf510eC7Ff49CC607b718Ce8401',     '2': '387',     from: '0x1a9eC3b0b807464e6D3398a59d6b0a369Bf422fA',     to: '0x8c1b2E9e838e2Bf510eC7Ff49CC607b718Ce8401',     value: '387' },  event: 'Transfer',  signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',  raw:   { data: '0x0000000000000000000000000000000000000000000000000000000000000183',     topics:      [ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',        '0x0000000000000000000000001a9ec3b0b807464e6d3398a59d6b0a369bf422fa',        '0x0000000000000000000000008c1b2e9e838e2bf510ec7ff49cc607b718ce8401' ] } }实时监控到的转账{ address: '0x6a0dF9E94a41fCd89d8236a8C03f9D678df5Acf9',  blockNumber: 10740,  transactionHash: '0xb42651720e8b8b64283cbd245aebaa7ad7e3dda58b9887f645ad6957bd7771b8',  transactionIndex: 0,  blockHash: '0xcdca97ba5a277e402a93188df03a758c916c37eea0f7498365d227ebd7cb2ee2',  logIndex: 0,  removed: false,  id: 'log_edc5dc68',  returnValues:   Result {     '0': '0x1a9eC3b0b807464e6D3398a59d6b0a369Bf422fA',     '1': '0x0000000000000000000000000000000000000001',     '2': '32',     from: '0x1a9eC3b0b807464e6D3398a59d6b0a369Bf422fA',     to: '0x0000000000000000000000000000000000000001',     value: '32' },  event: 'Transfer',  signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',  raw:   { data: '0x0000000000000000000000000000000000000000000000000000000000000020',     topics:      [ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',        '0x0000000000000000000000001a9ec3b0b807464e6d3398a59d6b0a369bf422fa',        '0x0000000000000000000000000000000000000000000000000000000000000001' ] } }

转载地址:http://bktkx.baihongyu.com/

你可能感兴趣的文章
如何通过解决精益问题提高敏捷团队生产力
查看>>
阿里云数据库产品总监何云飞:云服务是影响未来10~20年的事
查看>>
Comment2Wechat —— Typecho 插件
查看>>
Apache下.htaccess文件配置及功能介绍
查看>>
Magento XML cheatsheet
查看>>
Egg 2.19.0 发布,阿里开源的企业级 Node.js 框架
查看>>
Kubernetes 弹性伸缩全场景解析 (四)- 让核心组件充满弹性 ...
查看>>
使用MySQLTuner-perl对MySQL进行优化
查看>>
SAP S/4HANA extensibility扩展原理介绍
查看>>
Swoole 4.1.0 正式版发布,支持原生 Redis/PDO/MySQLi 协程化 ...
查看>>
开发网络视频直播系统需要注意的地方
查看>>
haproxy mysql实例配置
查看>>
强化学习的未来— 第一部分
查看>>
掌握Python系统管理-调试和分析脚本1-debugging
查看>>
TableStore:用户画像数据的存储和查询利器
查看>>
2019 DockerCon 大会即将召开,快来制定您的专属议程吧!
查看>>
15分钟构建超低成本数据大屏:DataV + DLA
查看>>
当下一对一直播源码市场空间
查看>>
1月9日云栖精选夜读 | Mars 算法实践——人脸识别
查看>>
.NET快速开发平台核心优势
查看>>