发出事件
学习如何在 Anchor 程序中使用 emit! 和 emit_cpi! 宏发出事件。
示例
Anchor 提供了两个宏来在你的程序中发出事件:
emit!()
- 直接向程序日志发出事件。这种方法更简单, 但数据提供商有时可能会截断程序日志emit_cpi!()
- 通过跨程序调用 (CPI) 发出事件, 将事件数据包含在指令数据中。
emit_cpi()
方法是作为程序日志的替代方案引入的,因为程序日志有时会被数据提供商截断。
虽然 CPI 指令数据不太可能被截断,但这种方法确实会因为跨程序调用而产生额外的计算成本。
emit
emit!()
宏提供了一种通过程序日志发出事件的方式。当调用时,它会:
- 使用
sol_log_data()
系统调用将数据写入程序日志 - 将事件数据编码为
base64 字符串
并加上
Program Data:
前缀
要在客户端应用程序中接收发出的事件,请使用
addEventListener()
方法。该方法会自动
解析和解码
程序日志中的事件数据。
使用示例:
以下是程序日志的输出。事件数据被 base64 编码为 Zb1eU3aiYdwOAAAASGVsbG8sIFNvbGFuYSE=
。
确保你使用的 RPC 提供商不会从交易数据中截断程序日志。
emit_cpi
emit_cpi!()
宏通过跨程序调用 (CPI) 向程序本身发出事件。事件数据被编码并包含在 CPI 的指令数据中(而不是程序日志中)。
要通过 CPI 发出事件,你需要在程序的 Cargo.toml
中启用 event-cpi
功能:
使用示例:
event_cpi
属性必须添加到使用 emit_cpi!()
宏发出事件的指令的 #[derive(Accounts)]
结构体中。该属性
自动包含所需的额外账户
以支持自我 CPI。
要在客户端应用程序中获取发出的事件数据,你需要使用交易签名获取完整交易数据,并从 CPI 指令数据中解析事件数据。
以下是一个示例交易,展示了事件数据在交易详情中的呈现方式。使用 emit_cpi!()
时,事件数据会被编码并包含在内部指令(CPI)的 data
字段中。
在下面的示例交易中,编码的事件数据为 "data": "6AJcBqZP8afBKheoif1oA6UAiLAcqYr2RaR33pFnEY1taQp"
,位于 innerInstructions
数组中。
目前,通过 CPI 发出的事件数据无法直接订阅。 要访问此数据,你必须获取完整交易数据并手动从 CPI 的指令数据中解码事件信息。