白天搞智能合约,晚上撸前端代码,只要咖啡还续着,凌晨照样在线!会说 Solidity、PHP、Node.js,还有 Vue 和 HTML 的“方言”,代码不怕我不写,就怕写完跑太快。Bug?那都是小场面,一出手就搞定。我的宗旨是——交付准时,调试无敌,客户满意才是真理!
8. 监听合约事件
监听合约事件
contract.on
在ethersjs中,合约对象有一个contract.on的监听方法,让我们持续监听合约的事件:
contract.on("eventName", function)
contract.on有两个参数,一个是要监听的事件名称"eventName",需要包含在合约abi中;另一个是我们在事件发生时调用的函数。
contract.once
合约对象有一个contract.once的监听方法,让我们只监听一次合约释放事件,它的参数与contract.on一样:
contract.once("eventName", function)
监听USDT合约
- 声明
provider:Alchemy是一个免费的ETH节点提供商。需要先申请一个,后续会用到。
import { ethers } from "ethers";
// 准备 alchemy API
const ALCHEMY_MAINNET_URL = 'https://eth-mainnet.g.alchemy.com/v2/oKmOQKbneVkxgHZfibs-iFhIlIAl6HDN';
// 连接主网 provider
const provider = new ethers.JsonRpcProvider(ALCHEMY_MAINNET_URL);
- 声明合约变量:我们只关心
USDT合约的Transfer事件,把它填入到abi中就可以。如果你关心其他函数和事件的话,可以在etherscan上找到。
// USDT的合约地址
const contractAddress = '0xdac17f958d2ee523a2206206994597c13d831ec7'
// 构建USDT的Transfer的ABI
const abi = [
"event Transfer(address indexed from, address indexed to, uint value)"
];
// 生成USDT合约对象
const contractUSDT = new ethers.Contract(contractAddress, abi, provider);
- 利用
contract.once()函数,监听一次Transfer事件,并打印结果。
// 只监听一次
console.log("\n1. 利用contract.once(),监听一次Transfer事件");
contractUSDT.once('Transfer', (from, to, value)=>{
// 打印结果
console.log(
`${from} -> ${to} ${ethers.formatUnits(ethers.getBigInt(value),6)}`
)
})

- 利用
contract.on()函数,持续监听Transfer事件,并打印结果。
// 持续监听USDT合约
console.log("\n2. 利用contract.on(),持续监听Transfer事件");
contractUSDT.on('Transfer', (from, to, value)=>{
console.log(
// 打印结果
`${from} -> ${to} ${ethers.formatUnits(ethers.getBigInt(value),6)}`
)
})

完整代码
// 监听合约方法:
// 1. 持续监听
// contractUSDT.on("事件名", Listener)
// 2. 只监听一次
// contractUSDT.once("事件名", Listener)
import { ethers } from "ethers";
// 准备 alchemy API
const ALCHEMY_MAINNET_URL = 'https://eth-mainnet.g.alchemy.com/v2/oKmOQKbneVkxgHZfibs-iFhIlIAl6HDN';
// 连接主网 provider
const provider = new ethers.JsonRpcProvider(ALCHEMY_MAINNET_URL);
// USDT的合约地址
const contractAddress = '0xdac17f958d2ee523a2206206994597c13d831ec7'
// 构建USDT的Transfer的ABI
const abi = [
"event Transfer(address indexed from, address indexed to, uint value)"
];
// 生成USDT合约对象
const contractUSDT = new ethers.Contract(contractAddress, abi, provider);
const main = async () => {
// 监听USDT合约的Transfer事件
try{
// 只监听一次
console.log("\n1. 利用contract.once(),监听一次Transfer事件");
contractUSDT.once('Transfer', (from, to, value)=>{
// 打印结果
console.log(
`${from} -> ${to} ${ethers.formatUnits(ethers.getBigInt(value),6)}`
)
})
// 持续监听USDT合约
console.log("\n2. 利用contract.on(),持续监听Transfer事件");
contractUSDT.on('Transfer', (from, to, value)=>{
console.log(
// 打印结果
`${from} -> ${to} ${ethers.formatUnits(ethers.getBigInt(value),6)}`
)
})
}catch(e){
console.log(e);
}
}
main()
