事件
事件在交易执行期间发出。每个 Move 模块都可定义自己的事件,并决定在模块执行时何时发出事件。Aptos Move 支持两种事件:模块事件和 EventHandle 事件。模块事件是现代事件机制,随 framework 1.7 版本发布;EventHandle 事件已弃用,随最初的 framework 一同发布。受区块链的工作方式影响,EventHandle 事件很可能永远无法从 Aptos 中彻底移除。
模块事件是通过结构体类型标识的全局事件流。要定义事件结构体,请为拥有 drop 和 store 能力的普通 Move 结构体添加 #[event] 属性。例如:
/// 0xcafe::my_module_name/// An example module event struct denotes a coin transfer.#[event]struct TransferEvent has drop, store { sender: address, receiver: address, amount: u64}然后创建并发出该事件:
// Define an event.let event = TransferEvent { sender: 0xcafe, receiver: 0xface, amount: 100};// Emit the event just defined.0x1::event::emit(event);可在此处查看示例模块事件。索引 0、1、2 是类型为 0x66c34778730acbb120cefa57a3d98fd21e0c8b3a51e9baee530088b2e444e94c::event::MyEvent 的三个模块事件。为保持 API 兼容性,模块事件包含 Account Address、Creation Number 和 Sequence Number 字段,且它们均为 0。

在测试中访问
Section titled “在测试中访问”每笔交易的事件都存储在称为事件累加器的独立 Merkle 树中。由于它是临时的且独立于状态树,MoveVM 在生产环境执行交易时无法读取事件。但在测试中,Aptos Move 支持两个原生函数,可读取已发出的事件以进行测试和调试:
/// Return all emitted module events with type T as a vector.# [test_only]public native fun emitted_events<T: drop + store>(): vector<T>;
/// Return true iff `msg` was emitted.# [test_only]public fun was_event_emitted<T: drop + store>(msg: & T): boolAPI 访问
Section titled “API 访问”可通过 GraphQL API 查询模块事件和 EventHandle 事件。
Event-Handle 事件(已弃用)
Section titled “Event-Handle 事件(已弃用)”作为遗留机制,Aptos 继承了源自 EventHandle 的 Libra/Diem 事件流。每个 EventHandle 通过全局唯一值 GUID 和每事件序列号进行标识,并存储在资源中。事件流中的每个事件都拥有从 EventHandle 序列号派生的唯一序列号。
例如,在进行代币转账时,发送方和接收方账户都会分别发出 SentEvent 和 ReceivedEvent。这些数据存储在账本中,可通过 REST 接口的按事件句柄获取事件查询。
假设账户 0xc40f1c9b9fdc204cf77f68c9bb7029b0abbe8ad9e5561f7794964076a4fbdcfd 已向另一账户发送代币,可对 REST 接口发出以下查询:https://api.devnet.aptoslabs.com/v1/accounts/c40f1c9b9fdc204cf77f68c9bb7029b0abbe8ad9e5561f7794964076a4fbdcfd/events/0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>/withdraw_events。输出为该账户存储的所有 WithdrawEvent,如下所示:
[ { "key": "0x0000000000000000caa60eb4a01756955ab9b2d1caca52ed", "sequence_number": "0", "type": "0x1::coin::WithdrawEvent", "data": { "amount": "1000" } }]每个已注册事件都有唯一 key。键 0x0000000000000000caa60eb4a01756955ab9b2d1caca52ed 映射到账户 0xc40f1c9b9fdc204cf77f68c9bb7029b0abbe8ad9e5561f7794964076a4fbdcfd 上注册的事件 0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>/sent_events。随后可用此键直接发出事件查询,例如 https://api.devnet.aptoslabs.com/v1/events/0x0000000000000000caa60eb4a01756955ab9b2d1caca52ed。
这些是事件流,即由事件组成的列表;每个条目包含从 0 开始顺序递增的 sequence_number、type 和 data。每个事件都必须由某种 type 定义;尤其在使用泛型时,可能有多个事件由相同或相似的 type 定义。事件关联 data。一般原则是:应包含在改变数据并发出事件的交易执行前后,理解底层资源变化所需的全部数据。
迁移至模块事件
Section titled “迁移至模块事件”随着模块事件发布,EventHandle 事件已弃用。为支持迁移到模块事件,项目应在当前发出 EventHandle 事件的每个位置同时发出模块事件。当外部系统充分采用模块事件后,可能不再需要发出旧事件。
注意,EventHandle 事件无法也不会被删除;因此无法升级的项目仍可继续使用它们。