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/