web3J solidity event

1655362915056.png

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

List 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> parameters = new ArrayList<>();
        parameters.add(new TypeReference
(true) { }); parameters.add(new TypeReference
(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  String buildMethodSignature(
            String methodName, List> 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 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 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)[])");

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

你可能感兴趣的:(web3J solidity event)