进阶
合约事件
监听和解析合约发出的事件日志
概述
Sophia 语言提供了在函数中发出 Events 的能力。本页将教你如何访问和解码特定交易的事件日志。
示例合约:EventEmitter
以下示例合约用于演示事件发出:
contract EventEmitter =
// 定义事件类型
datatype event =
FirstEvent(int)
| AnotherEvent(indexed address, string)
entrypoint emitEvents(value: int, msg: string) =
Chain.event(FirstEvent(value))
Chain.event(AnotherEvent(Call.caller, msg))
indexed 关键字:
indexed 标记的参数会被索引,便于后续过滤和搜索。
使用 ACI 解码事件
使用源代码初始化合约实例时,SDK 会自动解码事件:
// 调用合约方法时,事件会自动解码
const tx = await contract.emitEvents(1337, '这条消息未被索引');
console.log(tx.decodedEvents);
/*
输出:
[
{
name: 'AnotherEvent',
args: [
'fUq2NesPXcYZ1CcqBcGC3StpdnQw3iVxMA3YSeCNAwfN4myQk',
'这条消息未被索引'
],
contract: {
name: 'EventEmitter',
address: 'ct_6y3N9KqQb74QsvR9NrESyhWeLNiA9aJgJ7ua8CvsTuGot6uzh'
}
},
{
name: 'FirstEvent',
args: [1337n],
contract: {
name: 'EventEmitter',
address: 'ct_6y3N9KqQb74QsvR9NrESyhWeLNiA9aJgJ7ua8CvsTuGot6uzh'
}
}
]
*/
从交易哈希解码事件
也可以从已上链的交易中获取并解码事件日志:
const txHash = 'th_2YV3AmAz2kXdTnQxXtR2uxQi3KuLS9wfvXyqKkQQ2Y6dE6RnET';
// 从节点获取交易详情
const txInfo = await aeSdk.api.getTransactionInfoByHash(txHash);
// 使用合约实例解码事件
const decodedEvents = contract.$decodeEvents(txInfo.callInfo.log);
console.log(decodedEvents);
/*
输出:
[
{
name: 'AnotherEvent',
args: [
'fUq2NesPXcYZ1CcqBcGC3StpdnQw3iVxMA3YSeCNAwfN4myQk',
'this message is not indexed'
],
contract: {
name: 'EventEmitter',
address: 'ct_fKhQBiNQkDfoZcVF1ZzPzY7Lig6FnHDCLyFYBY33ZjfzGYPps'
}
},
{
name: 'FirstEvent',
args: [1337n],
contract: {
name: 'EventEmitter',
address: 'ct_fKhQBiNQkDfoZcVF1ZzPzY7Lig6FnHDCLyFYBY33ZjfzGYPps'
}
}
]
*/
事件数据结构
解码后的事件包含以下字段:
| 字段 | 类型 | 说明 |
|---|---|---|
name |
string | 事件名称(如 FirstEvent) |
args |
Array | 事件参数数组,已解码为 JS 类型 |
contract.name |
string | 发出事件的合约名称 |
contract.address |
string | 合约地址 |
常见应用场景
交易通知
监听转账事件,实时通知用户
数据同步
将链上事件同步到链下数据库
审计日志
记录重要操作的历史
状态变更追踪
跟踪合约状态变化
继续学习