合约事件推送
标签:go-sdk
事件订阅
Event
正好最近在研究fisco go sdk的合约推送如何使用,官方又没有文档,折腾了半天最后用起来了就顺便写了了文档还提了pr也被官方合入了还挺快乐的,合约事件推送 — FISCO BCOS v2.9.0 文档所以要快乐的记录一下成为一个水货的fisco开源贡献者。
1. 功能简介
合约事件推送功能提供了合约事件的异步推送机制,客户端向节点发送注册请求,在请求中携带客户端关注的合约事件的参数,节点根据请求参数对请求区块范围的Event Log
进行过滤,将结果分次推送给客户端。
2. 交互协议
客户端与节点的交互基于Channel
协议。交互分为三个阶段:注册请求,节点回复,Event Log
数据推送。
注册请求
客户端向节点发送事件推送的注册请求:
1 | // request sample: |
- filerID:字符串类型,每次请求唯一,标记一次注册任务
- groupID:字符串类型,群组ID
- fromBlock:整形字符串,初始区块。“latest” 当前块高
- toBlock:整形字符串,最终区块。“latest” 处理至当前块高时,继续等待新区块
- addresses:字符串或者字符串数组:字符串表示单个合约地址,数组为多个合约地址,数组可以为空
- topics:字符串类型或者数组类型:字符串表示单个topic,数组为多个topic,数组可以为空
节点回复
节点接受客户端注册请求时,会对请求参数进行校验,将是否成功接受该注册请求结果回复给客户端。
1 | // response sample: |
- filterID:字符串类型,每次请求唯一,标记一次注册任务
- result:整形,返回结果。0成功,其余为失败状态码
Event Log数据推送
节点验证客户端注册请求成功之后,根据客户端请求参数条件,向客户端推送Event Log
数据。
1 | // event log push sample: |
- filterID:字符串类型,每次请求唯一,标记一次注册任务
- result:整形 0:
Event Log
数据推送 1:推送完成。客户端一次注册请求对应节点的数据推送会有多次(请求区块范围比较大或者等待新的区块),result
字段为1时说明节点推送已经结束 - logs:Log对象数组,result为0时有效
3. Go SDK教程
注册接口
在FISCO-BCOS Go SDK中client.Client
类提供合约事件的注册接口,用户可以调用SubscribeEventLogs
向节点发送注册请求,并设置回调函数。
1 | func (c *Client) SubscribeEventLogs(eventLogParams types.EventLogParams, handler func(int, []types.Log)) error { |
types.EventLogParams
注册参数
事件回调请求注册的参数:
1 | type EventLogParams struct { |
topic计算
Go语言可以使用github.com/ethereum/go-ethereum/common
包根据合约中定义的事件进行Topic的计算:
1 | topic = common.BytesToHash(crypto.Keccak256([]byte("testEventLog(address,string,uint256)"))).Hex() |
需要注意的是uint及int为uint256及int256的别名,即使合约中使用的类型为uint及int,在topic的计算中仍需使用uint256与int256
4. 示例
此处以一个进行数值更改并计算更改次数的eventDemo.sol
合约进行事件订阅举例:
1 | pragma solidity >=0.4.24; |
该合约提供了setNumber
及getNumber
方法,其中调用前者将获得一个抛出事件。
在Fisco Go SDK中有两种事件订阅方式,分别为使用client
直接进行事件订阅与调用Abigen工具生成的代码中函数进行订阅两种,其中后者须建立session
。
4.1 使用client进行事件订阅
事件推送订阅
在Go SDK中给出了subscriber.go合约事件订阅样例
需要注意的是Topic及Address不可置空,置空将无法接收到相应事件。
1 | func main() { |
Log数据解析
在使用sdk提供的客户端订阅事件的方式中,获取到的数据需要abi
进行解析,
首先需要根据事件包含的变量类型构建一个用于解析的结构体:
1 | type setNum struct { |
此后可采用abi
工具进行解析:
1 | err = c.SubscribeEventLogs(eventLogParams, func(status int, logs []types.Log) { |
此处abi.Json
所使用到的数据需要使用abigen
工具生成对应的go文件后获得:
1 | // EventDemoABI is the input ABI used to generate the binding from. |
4.2 使用Abigen工具生成后的函数进行事件订阅
该方式进行事件订阅需先构建与合约的session
连接,后直接调用abigen
生成的go文件中函数即可进行事件的订阅与解析:
1 | // 根据配置文件构建eventDemoSession |
关于Session的构建请参考合约开发样例部分中例程。