You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Java使用web3j库监听智能合约触发的事件

基于web3j监听智能合约链上事件的实现方案

前置准备

  • 引入web3j核心依赖,Maven配置示例如下:
<dependency>
    <groupId>org.web3j</groupId>
    <artifactId>core</artifactId>
    <version>4.10.0</version> <!-- 可替换为最新稳定版 -->
</dependency>
  • 确认链节点RPC地址可用,长期监听场景优先选择支持WebSocket协议的节点地址。
  • 如果使用合约包装类方案,需提前通过web3j命令行工具,将智能合约编译后的abi、bin文件生成对应的Java包装类。

具体实现

方式1:通过智能合约Java包装类监听(推荐)

web3j自动封装了事件解析逻辑,代码侵入性最低,适合有合约源码的场景,示例为监听ERC20合约的Transfer事件:

// 1. 初始化web3j实例,使用WebSocket适配长期监听场景
Web3j web3j = Web3j.build(new WebSocketService("ws://你的节点RPC地址", false));
// 2. 加载已部署的链上合约
ERC20 erc20 = ERC20.load(
    "0x合约地址", 
    web3j, 
    new DefaultTransactionManager(web3j), 
    DefaultGasProvider.GAS_PRICE, 
    DefaultGasProvider.GAS_LIMIT
);
// 3. 注册事件监听器,参数为监听的起始块、结束块
erc20.transferEventFlowable(DefaultBlockParameterName.LATEST, DefaultBlockParameterName.LATEST)
    .subscribe(event -> {
        // 直接获取解析完成的事件参数
        String from = event.from;
        String to = event.to;
        BigInteger value = event.value;
        // 这里写业务逻辑
        System.out.printf("监听到转账:%s 向 %s 转了 %d 个Token%n", from, to, value);
    }, error -> {
        // 异常处理,可在这里补充节点断开后的重连逻辑
        System.err.println("监听异常:" + error.getMessage());
    });

如果需要拉取历史区块的事件,可将起始块参数替换为对应的区块高度数值。

方式2:手动构造事件过滤器监听

没有合约Java包装类时可以用该方案,自行定义事件结构完成监听和解析:

// 1. 定义和合约一致的事件结构
Event transferEvent = new Event("Transfer",
    Arrays.asList(
        new TypeReference<Address>(true) {}, // 第一个indexed参数
        new TypeReference<Address>(true) {}, // 第二个indexed参数
        new TypeReference<Uint256>(false) {} // 非indexed参数
    )
);
// 2. 构造事件过滤器
EthFilter filter = new EthFilter(
    DefaultBlockParameterName.LATEST, 
    DefaultBlockParameterName.LATEST,
    "0x合约地址" // 不填则监听全网符合条件的事件
);
filter.addSingleTopic(EventEncoder.encode(transferEvent));
// 3. 注册监听器手动解析日志
web3j.ethLogFlowable(filter).subscribe(log -> {
    List<Type> nonIndexedParams = FunctionReturnDecoder.decode(log.getData(), transferEvent.getNonIndexedParameters());
    String from = log.getTopics().get(1);
    String to = log.getTopics().get(2);
    BigInteger value = (BigInteger) nonIndexedParams.get(0).getValue();
    // 这里写业务逻辑
    System.out.printf("监听到转账:%s 向 %s 转了 %d 个Token%n", from, to, value);
}, error -> {
    System.err.println("监听异常:" + error.getMessage());
});

注意事项

  • 生产环境建议添加区块确认数校验,收到事件后等待1~6个区块确认再执行业务逻辑,避免链分叉导致数据失效。
  • 大批量拉取历史事件时建议分块拉取,单次拉取区块范围不要超过1000块,避免节点响应超时。
  • 必须添加异常重连机制,节点连接断开后自动重建监听,避免事件丢失。

内容的提问来源于stack exchange,提问作者shaikh47

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 03:36:04