OK, let's say you have a smart contract deployed on the address CONTRACT_ADDRESS
which can trigger different type of events
Event definitions:
event GameStarted(bytes32 indexed gameId, address indexed player1, address indexed player2);
event PlayerMoved(bytes32 indexed gameId, address indexed player);
event GameEnded(bytes32 indexed gameId, address indexed player1, address indexed player2);
When an event is triggered from a smart contract during a transaction, this event is added in an event log (part of the blockchain global state). The event log can be queried using one or several filters (smart contract address, block number range, topics).
The keyword indexed
means that the event will be added to a special data structure called topics
in the event logs. Consequently, it is possible to query the event log on those event parameters.
An event definition accept up to three indexed parameters.
An event is internally structured like this:
- address: the address of the contract (intrinsically provided by Ethereum);
- topics[0]: keccak(EVENT_NAME+"("+EVENT_ARGS.map(canonical_type_of).join(",")+")") (canonical_type_of is a function that simply returns the canonical type of a given argument, e.g. for uint indexed foo, it would return uint256). If the event is declared as anonymous the topics[0] is not generated;
- topics[n]: EVENT_INDEXED_ARGS[n - 1] (EVENT_INDEXED_ARGS is the series of EVENT_ARGS that are indexed);
- data: abi_serialise(EVENT_NON_INDEXED_ARGS) (EVENT_NON_INDEXED_ARGS is the series of EVENT_ARGS that are not indexed, abi_serialise is the ABI serialisation function used for returning a series of typed values from a function, as described above).
Source
Let's go back to the Java part, the following code demonstrates how to filter only the events of type GameStarted
where player2=MY_ADDRESS
from the smart contract CONTRACT_ADDRESS
within the block range [BLOCK_n
, BLOCK_m
]:
EthFilter eventFilter = new EthFilter(
BLOCK_n, // filter: from block
BLOCK_m, // filter: to block
CONTRACT_ADDRESS // filter: smart contract address
);
eventFilter.addSingleTopic(EventEncoder.encode(Contract.GameStarted)); // filter: event type (topic[0])
eventFilter.addOptionalTopics(null, null, MY_ADDRESS); // filter: event parameters (gameId: no filter, player1: no filter, player2: filter)
mContract.getContractAddress()
is the specific address filter! Basically you querying the node to return all events for this given account address