Alright, let's start from scratch.
Let's say you have a very simple contract which increments and decrements a counter deployed to the address 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);
}
}
i. Event definition hash
First you have to define each event (definition) in order to calculate the unique hash that represent this event on the network.
// 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) {}}));
Then to calculate the hash of the event, you only need to do:
private static final String INCREMENT_EVENT_HASH = EventEncoder.encode(INCREMENT_EVENT);
private static final String DECREMENT_EVENT_HASH = EventEncoder.encode(DECREMENT_EVENT);
ii. Filter
Before subscribing to event, it is possible apply filters because by definition, the Ethereum events log (all events of all smart contracts of the network) can be query.
- Filter by Block range and Smart Contract
Return all the events of different types for the smart contract CONTRACT_X
. In our case, we will get CounterIncremented
and CounterDecremented
events.
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 means you will pull the events coming in during the subscription.
If you want to filter by event type, for example to only get the CounterIncremented
event, you can use the property addSingleTopic
EthFilter filter = new EthFilter(
DefaultBlockParameterName.EARLIEST, // From block 0
DefaultBlockParameterName.LATEST, // To latest
CONTRACT_X) // Unique Smart Contract
.addSingleTopic(INCREMENT_EVENT_HASH);
- Filter by event parameters
Finally, you might want to filter by event parameters, for instance all the CounterIncremented
events triggered by a given address (filter by parameter _by
of the CounterIncremented
event)
EthFilter filter = new EthFilter(
DefaultBlockParameterName.EARLIEST, // From block 0
DefaultBlockParameterName.LATEST, // To latest
CONTRACT_X) // Unique Smart Contract
.addSingleTopic(INCREMENT_EVENT_HASH)
.addOptionalTopic("0xdDd6427Aaf3766DC97A9cA9deDD3e7911b085B6B");
Event parameter filter only applied for 'indexed' parameters.
iii. Subscribe to the events
Finally, the last step consists in subscribing for events to the node:
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
});