EthEvent
is a library to declare and request Solidity events easily.
This project provides a simple way of querying events and other information from the Ethereum blockchain.
Solidity events are no more than encoded block logs. They are usually used to
record that something changed in the contract's state. The following contract
declares and emit
s an event every time someone sends some tokens to other
address:
contract SomeToken is ERC20 {
Transfer(address indexed from, address indexed to, uint value);
...
function transfer(address to, uint value) {
...
emit Transfer(msg.sender, to, value)
}
}
Using the EthEvent.Schema
behaviour you can query the events in the form of
Elixir structs. The Transfer
event defined in the previous contract, could be
defined as follows:
defmodule Transfer do
use EthEvent.Schema
event "Transfer" do
address :from, indexed: true
address :to, indexed: true
uint :value
end
end
The previously defined module includes the functions Transfer.query/1
,
Transfer.query/2
and a struct definition for the Transfer
event e.g:
Let's say we want to look for:
- The
Transfer
event in the contract of address0xd09de8b6b510aecd508a22811398f468e75c8c4d
. - Where the tokens where transferred
from
the wallet address0x93ecb3962981e1ba2928297cb09c1932aa2c9c51
. - And only between the blocks
0
and100
.
We would do the following:
> contract_address = "0xd09de8b6b510aecd508a22811398f468e75c8c4d"
> from = "0x93ecb3962981e1ba2928297cb09c1932aa2c9c51"
> query = %Transfer{address: contract_address, from: from}
> options = [from_block: 0, to_block: 100]
> Transfer.query(query, options)
{:ok,
[
%Transfer{
...
address: "0xd09de8b6b510aecd508a22811398f468e75c8c4d",
block_number: 42,
from: "0x93ecb3962981e1ba2928297cb09c1932aa2c9c51",
to: "0x1e529de18f95ad5a4f41ac5e159fa307d5a85967",
value: 100
}
]
}
The result is the list of events that match the query.
It is possible to query the block number as well using the function
Block.query/1
e.g:
> use EthEvent
> Block.query(%Block{block_number: "latest"})
{:ok,
%Block{
...
block_number: 42,
timestamp: #DateTime<...>
}
}
Similarly to the two previous sections, balances are available as well using
the function query/1
e.g:
> use EthEvent
> address = "0xd09de8b6b510aecd508a22811398f468e75c8c4d"
> Balance.query(%Balance{address: address, block_number: "latest"})
{:ok,
%Balance{
address: "0xd09de8b6b510aecd508a22811398f468e75c8c4d"
balance: 100
}
}
The balance
field is in wei.
One important thing is that events are composable, though they only preserve some fields when composed e.g:
To query the balance of the wallet address
0xd09de8b6b510aecd508a22811398f468e75c8c4d
for the block 42 there are two
ways of doing it:
Without block hash or block_number:
> address = "0xd09de8b6b510aecd508a22811398f468e75c8c4d"
> Balance.query(%Balance{address: address})
{:ok,
%Balance{
address: "0xd09de8b6b510aecd508a22811398f468e75c8c4d"
block_number: nil,
block_hash: nil,
balance: 100
}
}
or with block hash:
> address = "0xd09de8b6b510aecd508a22811398f468e75c8c4d"
> Block.query!(block_number: 42) |> Balance.query(address: address)
{:ok,
%Balance{
address: "0xd09de8b6b510aecd508a22811398f468e75c8c4d"
block_number: 42,
block_hash: "0x15feeab052b4bd65c8e3a2e3efab391debb9d8b5def6ced89ea772...",
balance: 100
}
}
To install just add the following to your dependencies:
def deps do
[
{:eth_event, "~> 0.1"}
]
end