监听Solidity合约事件

31 篇文章 1 订阅
17 篇文章 2 订阅

    在ethers.js里,使用contractWithSigner.on()的方式,监听合约的某个事件或者地址上的交易。合约的事件,会通过emit event的方式发出,使用contractWithSigner.on() 注册了该事件,就可以实现监听了。下面以监听EventValue.sol里的ValueChanged事件为例,进行说明。

1、部署合约

    a) 参考这篇文章 [用ethers.js部署合约],来部署EventValue.sol合约,得到合约地址为:0x850A0D21Da477Ea95D44d00f2B534CB0DF8eef92
    //EventValue.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

contract EventValue {
    event ValueChanged(address indexed author,uint oldValue,uint newValue);
    uint _value;

    constructor(uint value) public {
        uint tmp = _value;
        _value = value;
        emit ValueChanged(msg.sender, tmp, value);
    }
    function getValue() view public returns (uint) {
        return _value;
    }
    function setValue(uint value) public {
        uint tmp = _value;
        _value = value;
        emit ValueChanged(msg.sender, tmp, value);
    }
}

    b) 创建文件夹和文件

mkdir -p test/ethers
cd test/ethers

## 3个脚本
touch 7.er_listenEvent.js
touch 8.any_setValue.js
touch 9.owner_setValue.js

2、编写监听脚本和测试脚本

2.1 监听脚本

    监听合约事件的脚本为7.er_listenEvent.js
    // 7.er_listenEvent.js

const {ethers} = require("ethers")
const fs = require('fs')

let provider = new ethers.providers.JsonRpcProvider('http://localhost:8545')

function getHexString(prikeyPath) {
    const privKeyFile = fs.readFileSync(prikeyPath).toString().trim();
    const privKey = new Buffer.from(privKeyFile, 'hex');    
    return privKey
}

async function listenEvent(){
    var privKey  = getHexString(".secret")
    let wallet = new ethers.Wallet(privKey,provider)
    
    var contractAddr = '0x850A0D21Da477Ea95D44d00f2B534CB0DF8eef92'
    //var contractAddr = '0x305Dd19C5FBAd6b24649A030681C7c494b5481e2'
    var jsonStr = fs.readFileSync('./build/contracts/EventValue.json')
    var jsonInfo = JSON.parse(jsonStr)
    var jsonAbi  = jsonInfo.abi    
    let contract = new ethers.Contract(contractAddr,jsonAbi,provider)
    let contractSign = contract.connect(wallet)

    let curValue = await contractSign.getValue()
    console.log('curValue=',ethers.BigNumber.from(curValue).toNumber())

    let tx = await contractSign.setValue(300)
    console.log('txHash=',tx.hash)
    await tx.wait()

    //1) 监听ValueChanged事件(不区分合约创建者与普通用户)
    contractSign.on("ValueChanged",(author,oldValue,newValue,event) => {
        console.log('---- anyUser ---')
        console.log('user=',author)
        console.log('oldValue=',ethers.BigNumber.from(oldValue).toNumber())
        console.log('newValue=',ethers.BigNumber.from(newValue).toNumber())
        console.log('eventNumber=',event.blockNumber)
    });

    //2) 在这些事件中,找出是合约创建者发起的调用交易
    let filter = contractSign.filters.ValueChanged(wallet.address)
    contractSign.on(filter,(author,oldValue,newValue,event) => {
        console.log('--- the Ower ----')
        console.log('ower=',author)
        console.log('oldValue=',ethers.BigNumber.from(oldValue).toNumber())
        console.log('newValue=',ethers.BigNumber.from(newValue).toNumber())
        console.log('eventNumber=',event.blockNumber)
    })
}

listenEvent()

2.2 普通用户测试脚本

    普通用户的测试脚本为8.any_setValue.js
    // 8.any_setValue.js

const {ethers} = require("ethers")
const fs = require('fs')

let provider = new ethers.providers.JsonRpcProvider('http://localhost:8545')

function getHexString(prikeyPath) {
    const privKeyFile = fs.readFileSync(prikeyPath).toString().trim();
    const privKey = new Buffer.from(privKeyFile, 'hex');    
    return privKey
}

function isNumber(val) {
    return !isNaN(val);
}

async function preGetValue(contract) {
    let value = await contract.getValue()
    let valone = ethers.BigNumber.from(value).toNumber()
    console.log("curValue=",valone)
}

async function preSetValue(contract,num) {
    let tx = await contract.setValue(num)
    console.log('tx=',tx.hash)
    await tx.wait()
}

async function doValue(num){
    // var privKey  = getHexString(".secret")
    // other user
    let privKey = '0x0272...d322'
    let wallet = new ethers.Wallet(privKey,provider)
    
    var contractAddr = '0x850A0D21Da477Ea95D44d00f2B534CB0DF8eef92'
    var jsonStr = fs.readFileSync('./build/contracts/EventValue.json')
    var jsonInfo = JSON.parse(jsonStr)
    var jsonAbi  = jsonInfo.abi    
    let contract = new ethers.Contract(contractAddr,jsonAbi,wallet)
    
    await preSetValue(contract,num)
    await preGetValue(contract)
}

var count = process.argv[2]
if (isNumber(count)) {
    doValue(count)
} else {
    console.log('please input a number')
}

2.3 owner用户测试脚本

    合约的部署者,也叫owner用户,其测试脚本如下
    // 9.ower_setValue.js

const {ethers} = require("ethers")
const fs = require('fs')

let provider = new ethers.providers.JsonRpcProvider('http://localhost:8545')

function getHexString(prikeyPath) {
    const privKeyFile = fs.readFileSync(prikeyPath).toString().trim();
    const privKey = new Buffer.from(privKeyFile, 'hex');    
    return privKey
}

function isNumber(val) {
    return !isNaN(val);
}

async function preGetValue(contract) {
    let value = await contract.getValue()
    let valone = ethers.BigNumber.from(value).toNumber()
    console.log("curValue=",valone)
}

async function preSetValue(contract,num) {
    let tx = await contract.setValue(num)
    console.log('tx=',tx.hash)
    await tx.wait()
}

async function doValue(num){
    var privKey  = getHexString(".secret")
    let wallet = new ethers.Wallet(privKey,provider)
    
    var contractAddr = '0x850A0D21Da477Ea95D44d00f2B534CB0DF8eef92'
    var jsonStr = fs.readFileSync('./build/contracts/EventValue.json')
    var jsonInfo = JSON.parse(jsonStr)
    var jsonAbi  = jsonInfo.abi    
    let contract = new ethers.Contract(contractAddr,jsonAbi,wallet)

    await preSetValue(contract,num)
    await preGetValue(contract)
}

var count = process.argv[2]
if (isNumber(count)) {
    doValue(count)
} else {
    console.log('please input a number')
}

3、进行测试

3.1 开启事件监听

node test\ethers\7.er_listenEvent.js

3.2 普通用户测试

node test\ethers\8.any_setValue.js 700

    如图(2) 所示:

图(2) 普通用户,设置value

3.3 owner用户测试

node test\ethers\9.owner_setValue.js 702

    如图(3) 所示:

图(3) owner用户,设置value

    由图(2)、图(3)可知普通用户和owner用户,都可以修改value的值,并且7.er_listenEvent.js脚本监听到了这个value值的修改。

参考文献

    [1] ethers.js V5 事件监听
    [2] ethers.js Provider使用
    [3] ethers.js合约详解
    [4] hardhat里的合约监听

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以太坊是一个平台,它上面提供各种模块让用户来搭建应用,如果将搭建应用比作造房子,那么以太坊就提供了墙面、屋顶、地板等模块,用户只需像搭积木一样把房子搭起来,因此在以太坊上建立应用的成本和速度都大大改善。具体来说,以太坊通过一套图灵完备的脚本语言(Ethereum Virtual Machinecode,简称EVM语言)来建立应用,它类似于汇编语言。我们知道,直接用汇编语言编程是非常痛苦的,但以太坊里的编程并不需要直接使用EVM语言,而是类似C语言、python、Lisp等高级语言,再通过编译器转成Evm语言。上面所说的平台之上的应用,其实就是合约,这是以太坊的核心。合约是一个活在以太坊系统里的自动代理人,他有一个自己的以太币地址,当用户向合约的地址里发送一笔交易后,该合约就被激活,然后根据交易中的额外信息,合约会运行自身的代码,最后返回一个结果,这个结果可能是从合约的地址发出另外一笔交易。需要指出的是,以太坊中的交易,不单只是发送以太币而已,它还可以嵌入相当多的额外信息。如果一笔交易是发送给合约的,那么这些信息就非常重要,因为合约将根据这些信息来完成自身的业务逻辑。合约所能提供的业务,几乎是无穷无尽的,它的边界就是你的想象力,因为图灵完备的语言提供了完整的自由度,让用户搭建各种应用。白皮书举了几个例子,如储蓄账户、用户自定义的子货币等。 2013年年末,以太坊创始人Vitalik Buterin发布了以太坊初版白皮书,启动了项目。2014年7月24日起,以太坊进行了为期42天的以太币预售。2016年初,以太坊的技术得到市场认可,价格开始暴涨,吸引了大量开发者以外的人进入以太坊的世界。中国三大比特币交易所之二的火币网及OKCoin币行都于2017年5月31日正式上线以太坊。 [1] 自从进入2016年以来,那些密切关注数字货币产业的人都急切地观察着第二代加密货币平台以太坊的发展动向。作为一种比较新的利用比特币技术的开发项目,以太坊致力于实施全球去中心化且无所有权的的数字技术计算机来执行点对点合约。简单来说就是,以太坊是一个你无法关闭的世界计算机。加密架构与图灵完整性的创新型结合可以促进大量的新产业的出现。反过来,传统行业的创新压力越来越大,甚至面临淘汰的风险。比特币网络事实上是一套分布式的数据库,而以太坊则更进一步,她可以看作是一台分布式的计算机:区块链是计算机的ROM,合约是程序,而以太坊的矿工们则负责计算,担任CPU的角色。这台计算机不是、也不可能是免费使用的,不然任何人都可以往里面存储各种垃圾信息和执行各种鸡毛蒜皮的计算,使用它至少需要支付计算费和存储费,当然还有其它一些费用。最为知名的是2017年初以摩根大通、芝加哥交易所集团、纽约梅隆银行、汤森路透、微软、英特尔、埃森哲等20多家全球top金融机构和科技公司成立的企业以太坊联盟。而以太坊催生的加密货币以太币近期又成了继比特币之后受追捧的资产。  智能合约的潜在应用很多。彭博社商业周刊称它是“所有人共享但无法篡改的软件”。更高级的软件有可能用以太坊创建网络商店。  以太坊是一个平台,它上面提供各种模块让用户来搭建应用,如果将搭建应用比作造房子,那么以太坊就提供了墙面、屋顶、地板等模块,用户只需像搭积木一样把房子搭起来,因此在以太坊上建立应用的成本和速度都大大改善。具体来说,以太坊通过一套图灵完备的脚本语言(Ethereum Virtual Machinecode,简称EVM语言)来建立应用,它类似于汇编语言。我们知道,直接用汇编语言编程是非常痛苦的,但以太坊里的编程并不需要直接使用EVM语言,而是类似C语言、python、Lisp等高级语言,再通过编译器转成Evm语言。上面所说的平台之上的应用,其实就是合约,这是以太坊的核心。合约是一个活在以太坊系统里的自动代理人,他有一个自己的以太币地址,当用户向合约的地址里发送一笔交易后,该合约就被激活,然后根据交易中的额外信息,合约会运行自身的代码,最后返回一个结果,这个结果可能是从合约的地址发出另外一笔交易。需要指出的是,以太坊中的交易,不单只是发送以太币而已,它还可以嵌入相当多的额外信息。如果一笔交易是发送给合约的,那么这些信息就非常重要,因为合约将根据这些信息来完成自身的业务逻辑。合约所能提供的业务,几乎是无穷无尽的,它的边界就是你的想象力,因为图灵完备的语言提供了完整的自由度,让用户搭建各种应用。白皮书举了几个例子,如储蓄账户、用户自定义的子货币等。 2013年年末,以太坊创始人Vitalik Buterin发布了以太坊初版白皮书,启动了项目。2014年7月24日起,以太坊进行了为期42天的以太币预售。2016年初,以太坊的技术得到市场认可,价格开始暴涨,吸引了大量开发者以外的人进入以太坊的世界。中国三大比特币交易所之二的火币网及OKCoin币行都于2017年5月31日正式上线以太坊。 [1] 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值