Event事件监听使用方法

Event事件监听使用方法

环境: solidity 0.8.0, fisco节点 V3.2,  java SDK V3.2, WeBASE V3.0.2
JavaSDK文档–接口说明: 已过时,代码不可用
https://fisco-bcos-doc.readthedocs.io/zh_CN/latest/docs/sdk/java_sdk/event_sub.html
参考代码:https://github.com/FISCO-BCOS/java-sdk-demo/blob/main/src/main/java/org/fisco/bcos/sdk/demo/eventsub/EventSub.java

1 监听工作流程介绍

客户端向节点发送注册请求,在请求中携带客户端关注的合约事件的参数,节点根据请求参数对请求区块范围的Event Log进行过滤,将结果分次推送给客户端。核心代码如下:

// 参数设置
EventSubParams params = new EventSubParams();
// 定义事件回调函数
EventSubCallback callback = new SubscribeCallback();
// 注册事件
EventSubscribe eventSubscribe = EventSubscribe.build(client);
String registerId = eventSubscribe.subscribeEvent(params, callback);

//停止监听事件
eventSubscribe.unsubscribeEvent( registerId );

eventSubscribe.subscribeEvent()是个非阻塞型函数,调用后返回注册id,之后才源源不断地接收到事件消息。

2 事件参数介绍

2.1 定义监听区块范围

参数params设置起始区块高度,
toBlock默认是BigInteger.valueOf(-1),表示latest,一直等待最新区块。

//监听1~300区块的事件
params.setFromBlock(BigInteger.valueOf(1));
params.setToBlock(BigInteger.valueOf(300));
2.2 定义监听事件

参数params设置监听主题topics,是双层数组形式, 第一层最多4个,第二层数量不限
[
[“topic1”,“topic2”,“topic3”,…],
[“topic1”,“topic2”,“topic3”,…],
[“topic1”,“topic2”,“topic3”,…],
[“topic1”,“topic2”,“topic3”,…]
]

// topics默认是为空数组,可以匹配所有的Event   
topics =  new ArrayList<>(Arrays.asList(null, null, null, null));

//手动设置为空
List<List<String>> topics = new ArrayList<List<String>>() {
   
   {add(null);add(null);add(null);add(null);}};

//添加事件topic
params.addTopic(0,"0x2e601d02b417e3eebb1bf0305fed4a7196340cae7656e10ec6c8c1c16eb69f6c");
params.addTopic(0,"0x91c95f04198617c60eaf2180fbca88fc192db379657df0e412a9f7dd4ebbe95d");
params.addTopic(1,"0x91c95f04198617c60eaf2180fbca88fc192db379657df0e412a9f7dd4ebbe95d");
2.3 定义监听地址

参数params设置监听地址,是数组形式,允许同时监听多个地址。
默认为空数组,表示监听所有的合约地址。

// addresses默认为空数组,匹配所有的合约地址
params.addAddress("0x3705a5eac4741c6877f3a507468f07aef3394d65");

3 示例代码

场景1 将链上所有/最新的事件回调至客户端

读取所有区块的事件,持续监听最新区块。 会显示出所有的事件信息。

public void callAllEvents() throws JniException {    
    // 参数设置    
    EventSubParams params = new EventSubParams();    
    
    // 全部Event fromBlock设置为1    
    params.setFromBlock(BigInteger.valueOf(1));    
    // toBlock默认是-1,表示"latest",处理至最新区块继续等待新的区块    
    //params.setToBlock(BigInteger.valueOf(300));    
    
    // addresses默认为空数组,匹配所有的合约地址    
    //params.addAddress("0x3705a5eac4741c6877f3a507468f07aef3394d65");    
    
    // topics默认为空数组,匹配所有的Event    
    //params.addTopic(0, "0x2e601d02b417e3eebb1bf0305fed4a7196340cae7656e10ec6c8c1c16eb69f6c"); 
    //params.addTopic(0, "0x91c95f04198617c60eaf2180fbca88fc192db379657df0e412a9f7dd4ebbe95d"); 

    // 定义事件回调函数    
    EventSubCallback callback = new SubscribeCallback();    

    // 注册事件    
    EventSubscribe eventSubscribe = EventSubscribe.build(client);    
    String registerId = eventSubscribe.subscribeEvent(params, callback);    
    System.out.println("registerId="+registerId);    
    
    //停止监听事件    
    eventSubscribe.unsubscribeEvent( registerId );
}

//回调类
class SubscribeCallback implements EventSubCallback {    
    SubscribeCallback() {  
    }    
    @Override    public void onReceiveLog(String eventSubId, int status, List<EventLog> logs) {
        System.out.println("event sub id: " + eventSubId);        
        System.out.println(" \t status: " + status);        
        System.out.println(" \t logs: " + logs);    
    }
}

运行结果:

registerId=b5e8113bbdd5481381632c1dcf66fd17
event sub id: b5e8113bbdd5481381632c1dcf66fd17
 	 status: 0
 	 logs: null
event sub id: b5e8113bbdd5481381632c1dcf66fd17
 	 status: 0
 	 logs: [EventLog{logIndex='0', transactionIndex='0', transactionHash='0xd1860249407a464d4fe5a6a3a4e5b3388649f6512a5941b99be5f2d266d4b6c8', blockNumber='5', address='6849f21d1e455e9f0712b1e99fa4fcd23758e8f1', data='0x000000000000000000000000a0b0d1cd6a783c0cd2f06613de0795356f4bb85800000000000000000000000000000000000000000000000000000000000000800000000000000000000000001c7a618fa0388aa34bb19081819ea2723b671a96000000000000000000000000437bc19334f027fd90fd39d08fc138962f51d00200000000000000000000000000000000000000000000000000000000000000056170706c65000000000000000000000000000000000000000000000000000000', topics=[0x03b9f246c94041ffa51bb187f9dbb224690a033d125054ccbcb1c17ef6c9b68b]}]
 
 省略若干消息。。。。
 
 event sub id: b5e8113bbdd5481381632c1dcf66fd17
event sub id: b5e8113bbdd5481381632c1dcf66fd17
 	 status: 0
 	 status: 0
 	 logs: [EventLog{logIndex='0', transactionIndex='0', transactionHash='0xc5ebcba146269a0f0e133e33e2bf9935be595efb0a96eb7531c39a61307a3240', blockNumber='308', address='4035a74c5f0daead4ae48a9be0415cfaa8a69d34', data='0x000000000000000000000000a0b0d1cd6a783c0cd2f06613de0795356f4bb8580000000000000000000000000000000000000000000000000000000000000060000000000000000000000000e8aed5848f12dee58599df4f95e7a584ca895d7500000000000000000000000000000000000000000000000000000000000000056170706c65000000000000000000000000000000000000000000000000000000', topics=[0xa2d66134357ca61a7cfe28b780322e6451179110b2348db711cc2ce737c1e6b7]}]
 	 logs: [EventLog{logIndex='0', transactionIndex='0', transactionHash='0x65f14efc743b227b131da2b881d751f77a6b644baafce145b0255692d132e86f', blockNumber='307', address='4035a74c5f0daead4ae48a9be0415cfaa8a69d34', data='0x000000000000000000000000a0b0d1cd6a783c0cd2f06613de0795356f4bb85800000000000000000000000000000000000000000000000000000000000000600000000000000000000000005eae4c2eb8049c8f8f1d35c8164c20684ee2933600000000000000000000000000000000000000000000000000000000000000056170706c65000000000000000000000000000000000000000000000000000000', topics=[0xa2d66134357ca61a7cfe28b780322e6451179110b2348db711cc2ce737c1e6b7]}]
场景2 读取指定地址的所有/最新的事件

我们一般只需要监听使用的合约地址触发的事件,监听参数中填写合约地址,事件消息简化了许多。

public void callAllEvents() throws JniException {    
    // 参数设置    
    EventSubParams params = new EventSubParams();    
    
    // 全部Event fromBlock设置为1    
    params.setFromBlock(BigInteger.valueOf(1));    
    // toBlock默认是-1,表示"latest",处理至最新区块继续等待新的区块    
    //params.setToBlock(BigInteger.valueOf(300));    
    
    // addresses默认为空数组,匹配所有的合约地址    
    params.addAddress("0x4035a74c5f0daead4ae48a9be0415cfaa8a69d34");    
    
    // topics默认为空数组,匹配所有的Event    
    //params.addTopic(0, "0x2e601d02b417e3eebb1bf0305fed4a7196340cae7656e10ec6c8c1c16eb69f6c"); 
    //params.addTopic(0, "0x91c95f04198617c60eaf2180fbca88fc192db379657df0e412a9f7dd4ebbe95d"); 

    // 定义事件回调函数    
    EventSubCallback callback = new SubscribeCallback();    

    // 注册事件    
    EventSubscribe eventSubscribe = EventSubscribe.build(client);    
    String registerId = eventSubscribe.subscribeEvent(params, callback);    
    System.out.println("registerId="+registerId);    
    
    //停止监听事件    
    eventSubscribe.unsubscribeEvent( registerId );
}

//回调类
class SubscribeCallback implements EventSubCallback {    
    SubscribeCallback() {  
    }    
    @Override    public void onReceiveLog(String eventSubId, int status, List<EventLog> logs) {
        System.out.println("event sub id: " + eventSubId);        
        System.out.println(" \t status: " + status);        
        System.out.println(" \t logs: " + logs);    
    }
}

运行结果只返回了一条记录:

registerId=81916727704349a2ab11f1b2d39ba936
event sub id: 81916727704349a2ab11f1b2d39ba936
 	 status: 0
 	 logs: null
event sub id: 81916727704349a2ab11f1b2d39ba936
event sub id: 81916727704349a2ab11f1b2d39ba936
 	 status: 0
 	 status: 0
 	 logs: [EventLog{logIndex='0', transactionIndex='0', transactionHash='0x65f14efc743b227b131da2b881d751f77a6b644baafce145b0255692d132e86f', blockNumber='307', address='4035a74c5f0daead4ae48a9be0415cfaa8a69d34', data='0x000000000000000000000000a0b0d1cd6a783c0cd2f06613de0795356f4bb85800000000000000000000000000000000000000000000000000000000000000600000000000000000000000005eae4c2eb8049c8f8f1d35c8164c20684ee2933600000000000000000000000000000000000000000000000000000000000000056170706c65000000000000000000000000000000000000000000000000000000', topics=[0xa2d66134357ca61a7cfe28b780322e6451179110b2348db711cc2ce737c1e6b7]}]
 	 logs: [EventLog{logIndex='0', transactionIndex='0', transactionHash='0xc5ebcba146269a0f0e133e33e2bf9935be595efb0a96eb7531c39a61307a3240', blockNumber='308', address='4035a74c5f0daead4ae48a9be0415cfaa8a69d34', data='0x000000000000000000000000a0b0d1cd6a783c0cd2f06613de0795356f4bb8580000000000000000000000000000000000000000000000000000000000000060000000000000000000000000e8aed5848f12dee58599df4f95e7a584ca895d7500000000000000000000000000000000000000000000000000000000000000056170706c65000000000000000000000000000000000000000000000000000000', topics=[0xa2d66134357ca61a7cfe28b780322e6451179110b2348db711cc2ce737c1e6b7]}]
场景3 读取指定地址的某些事件

用于监听特定事件,一般用于立即通知用户或客户端,例如充值、NFT转移、到账。
代码填写topic即可。

场景4 从最新区块开始持续监听事件

fromBlock、toBlock都保持默认值BigInteger.valueOf(-1)即可,不用设置。
会收到到最新区块中的事件消息。

4 启动停止

EventSubscribe接口类中存在 start()、stop()、subscribeEvent()、unsubscribeEvent()方法。我没有深入验证代码,认为层次关系如下, start和stop控制的是注册接口, subscribeEvent()、unsubscribeEvent()控制的是某一类监听。

start()
    subscribeEvent(1)   监听事件1   
    subscribeEvent(2)   监听事件2
    ......
    unsubscribeEvent(1)   取消监听1
    unsubscribeEvent(2)   取消监听2
stop()

猜你喜欢

转载自blog.csdn.net/u012084827/article/details/130366971