web3J solidity event

1655362915056.png

我们需要监听某个事件 需要根据event 的topic[0] 来筛选。所以当我们要去监听一个 日志时就需要知道topic[0]的值

List<EthLog.LogResult> logs = web3j.ethGetLogs(new EthFilter(DefaultBlockParameter.valueOf(new BigInteger(start.toString())), DefaultBlockParameter.valueOf(new BigInteger(end.toString()))
                , contract).addOptionalTopics(transferTopic)).send().getLogs();

然后这个topic[0] 可以使用

        List<TypeReference<?>> parameters = new ArrayList<>();
        parameters.add(new TypeReference<Address>(true) {
        });
        parameters.add(new TypeReference<Address>(true) {
        });

        Event event = new Event("name", parameters);
        topic[0] =  EventEncoder.encode(event);

正常情况都是正常的 但是当日志里面有一个我们自己定义的结构体 就发现不对了

public static String encode(Event event) {

        String methodSignature = buildMethodSignature(event.getName(), event.getParameters());

        return buildEventSignature(methodSignature);
    }

    static <T extends Type> String buildMethodSignature(
            String methodName, List<TypeReference<T>> parameters) {

        StringBuilder result = new StringBuilder();
        result.append(methodName);
        result.append("(");
        String params =
                parameters.stream().map(p -> Utils.getTypeName(p)).collect(Collectors.joining(","));
        result.append(params);
        result.append(")");
        return result.toString();
    }

    public static String buildEventSignature(String methodSignature) {
        byte[] input = methodSignature.getBytes();
        byte[] hash = Hash.sha3(input);
        return Numeric.toHexString(hash);
    }

看上面代码发现 以event Transfer(address indexed from, address indexed to,uint256 indexed id ); 其实这个topic[0] = keccak256("Transfer(address, address,uint256)") 如果有自己定义的机构体怎么表示?
如果我们用 EventEncoder.encode(event) 方法 ; Utils.getTypeName(p) 它会找到我们再代码里面定义的类名 然后拼接去 keccak256,这是不对的 。

因为 event的topic[0] 和方法签名有点类似 就去看看方法签名时怎么处理的 (DefaultFunctionEncoder)

 public String encodeFunction(final Function function) {
        final List<Type> parameters = function.getInputParameters();

        final String methodSignature = buildMethodSignature(function.getName(), parameters);
        final String methodId = buildMethodId(methodSignature);

        final StringBuilder result = new StringBuilder();
        result.append(methodId);

        return encodeParameters(parameters, result);
    }

    protected static String buildMethodSignature(
            final String methodName, final List<Type> parameters) {

        final StringBuilder result = new StringBuilder();
        result.append(methodName);
        result.append("(");
        final String params =
                parameters.stream().map(Type::getTypeAsString).collect(Collectors.joining(","));
        result.append(params);
        result.append(")");
        return result.toString();
    }

这里拿的是 Type::getTypeAsString 方法

struct NFT {
    address collection;
    uint256 tokenId;
}

那 NFT 的getTypeAsString 的结果就是 (address,uint256) 如果是 NFT [] 那就是 (address,uint256)[] 如果是结构体套结构体就是一次递归。

event Name(address user,NFT[] nfts);

那么 Name 的 topic[0] 就是 keccak256("Name(address,(address,uint256)[])");

其实文档有写 但是写的不太明白 我没有看懂!

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一.ABI ABI是和Ethereum生态系统的合约进行交互的标准方式,所有合约的调用都是通过ABI.一个函数调用...
    mingmingz阅读 982评论 0 1
  • 带宽 每天每个账号5000带宽 抵扣手续费 在波场,除查询之外的任何交易都需要消耗带宽,系统每天给每个激活账户赠送...
    a437e8f87a81阅读 976评论 0 0
  • https://segmentfault.com/a/1190000015295148 流程 合约代码编写(Sol...
    JARVIS_STUDIO阅读 2,302评论 0 0
  • 参考文档Solidity的event事件(二十一)|入门系列http://me.tryblockchain.org...
    jection阅读 1,101评论 0 1
  • 待字闺中开发了一门区块链方面的课程:《深入浅出ETH原理与智能合约开发》,马良老师讲授。此简书文集记录我的学习笔记...
    吉祥在成长阅读 1,664评论 0 1