您正在查看: 2021年3月

web3j 监听 Solidity Funcion event

假设您有一个非常简单的合同,可以递增和递减部署到该地址的计数器 CONTRACT_X

pragma solidity ^0.4.20;

contract Counter {
    int counter; // Global state

    event CounterIncremented(address indexed _by, int _newValue);
    event CounterDecremented(address indexed _by, int _newValue);

    function increment(int _value) public {
        counter = counter + _value;
        emit CounterIncremented(msg.sender, counter);
    }

    function deincrement(int _value) public {
        counter = counter - _value;
        emit CounterDecremented(msg.sender, counter);
    }
}

事件定义哈希

首先,您必须定义每个事件(定义),以便计算代表该事件在网络上的唯一哈希。

// Definition of event CounterIncremented(address indexed _by, int _newValue)
public static final Event INCREMENT_EVENT = new Event("CounterIncremented", 
    Arrays.<TypeReference<?>>asList(new TypeReference<Address>(true) {}, new TypeReference<Int>(false) {}}));

// Definition of event CounterDecremented(address indexed _by, int _newValue)
public static final Event DECREMENT_EVENT = new Event("CounterDecremented", 
    Arrays.<TypeReference<?>>asList(new TypeReference<Address>(true) {}, new TypeReference<Int>(false) {}}));

然后,要计算事件的哈希,您只需要执行以下操作:

private static final String INCREMENT_EVENT_HASH = EventEncoder.encode(INCREMENT_EVENT);

private static final String DECREMENT_EVENT_HASH = EventEncoder.encode(DECREMENT_EVENT);

筛选

在订阅事件之前,可以应用过滤器,因为根据定义,可以查询以太坊事件日志(网络所有智能合约的所有事件)。

按区块范围和智能合约过滤

返回智能合约的所有不同类型的事件CONTRACT_X。在我们的情况下,我们将获得CounterIncremented和CounterDecremented事件。

EthFilter filter = new EthFilter(
    DefaultBlockParameterName.EARLIEST, // From block 0
    DefaultBlockParameterName.LATEST,  // To last block
    CONTRACT_X); // Unique Smart Contract

EthFilter filter = new EthFilter(
    DefaultBlockParameterName.LATEST, // only the latest block  
    DefaultBlockParameterName.LATEST,  // 
    CONTRACT_X); // Unique Smart Contract

EthFilter filter = new EthFilter(
    DefaultBlockParameterName.valueOf("2222"), // From block no 2222
    DefaultBlockParameterName.LATEST,  // To latest
    Arrays.asList(address1, address2, address3)); // List of Smart Contracts

LATEST意味着您将提取订阅期间出现的事件。

  • 按事件过滤
    如果要按事件类型过滤,例如仅获取CounterIncremented事件,则可以使用属性addSingleTopic
    EthFilter filter = new EthFilter(
      DefaultBlockParameterName.EARLIEST, // From block 0 
      DefaultBlockParameterName.LATEST,  // To latest
      CONTRACT_X) // Unique Smart Contract
    .addSingleTopic(INCREMENT_EVENT_HASH);
  • 按事件参数过滤
    最后,您可能希望按事件参数进行过滤,例如,CounterIncremented由给定地址触发的所有事件(按事件的参数_by进行过滤CounterIncremented)
    EthFilter filter = new EthFilter(
      DefaultBlockParameterName.EARLIEST, // From block 0
      DefaultBlockParameterName.LATEST,  // To latest
      CONTRACT_X) // Unique Smart Contract
    .addSingleTopic(INCREMENT_EVENT_HASH)
    .addOptionalTopic("0xdDd6427Aaf3766DC97A9cA9deDD3e7911b085B6B");

    事件参数过滤器仅适用于“索引”参数。

    订阅活动

    最后,最后一步是订阅节点的事件:

    web3.ethLogFlowable(filter).subscribe(event -> { 
      event.getAddress(); // Smart contract address
      event.getBlockNumber(); // Block number
      event.getTransactionHash(); // Transaction that emitted the event
      event.getTopics().get(0); // Event hash
      event.getTopics().get(1-n); // Event parameter (1) _by, (2) _value
    }); 

    参考

    https://ethereum.stackexchange.com/questions/66379/recover-solidity-funcion-event-in-web3j
    http://docs.web3j.io/latest/advanced/filters_and_events/

MyEtherWallet 本地部署

编译运行

git clone https://github.com/MyEtherWallet/MyEtherWallet.git
cd MyEtherWallet/
npm i
npm run start:ci

外网访问

https://github.com/MyEtherWallet/MyEtherWallet/blob/1e76e24312d21a447d35f0810c5431dbdb7432ee/vueConfig/mew.js#L10

 devServer: {
    https: true, // 是否默认https
    host: 'localhost', // 访问地址
    hotOnly: true,
    port: 8080,  //端口
    headers: defaultConfigs.headers // 删掉
  },

web3j.ethCall 测试

package com.example.demo.test;

import com.example.demo.util.Constants;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.FunctionReturnDecoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.request.Transaction;
import org.web3j.protocol.core.methods.response.EthCall;
import org.web3j.protocol.http.HttpService;

import java.util.Arrays;
import java.util.List;

public class TransactionGetTest {

    public static void main(String[] args) throws Exception {
        Web3j web3j = Web3j.build(new HttpService()); // defaults to http://localhost:8545/

        /*
         * String name 函数名字
         * List<Type> inputParameters 入口参数
         * List<TypeReference<?>> outputParameters 出口参数
         */
        Function function = new Function("get",
                Arrays.<Type>asList(),
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {
                }));

        // encode the function
        String encodedFunction = FunctionEncoder.encode(function);

        /*
         * String from null(optional)
         * String to 合约地址
         * String data ABI
         */
        EthCall response = web3j.ethCall(Transaction.createEthCallTransaction(null, Constants.ADDRESS, encodedFunction), DefaultBlockParameterName.LATEST).send();

        // get result
        List<Type> result = FunctionReturnDecoder.decode(response.getValue(), function.getOutputParameters());
        int data = Integer.parseInt(result.get(0).getValue().toString());
        System.out.println("data = " + data);
    }
}

https://github.com/zhangbincheng1997/Ethereum/blob/dda4509fca76157b28465b8449d8aae9a1ac9ef6/helloworld/src/main/java/com/example/demo/test/TransactionGetTest.java