defmodule EthEvent do @moduledoc """ [![Build Status](https://travis-ci.org/etherharvest/eth_event.svg?branch=master)](https://travis-ci.org/etherharvest/eth_event) [![Hex pm](http://img.shields.io/hexpm/v/eth_event.svg?style=flat)](https://hex.pm/packages/eth_event) [![hex.pm downloads](https://img.shields.io/hexpm/dt/eth_event.svg?style=flat)](https://hex.pm/packages/eth_event) `EthEvent` is a library to declare and request Solidity events easily. ## Queries This project provides a simple way of querying events and other information from the Ethereum blockchain. ### Query Solidity events 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: ```solidity 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 address `0xd09de8b6b510aecd508a22811398f468e75c8c4d`. - Where the tokens where transferred `from` the wallet address `0x93ecb3962981e1ba2928297cb09c1932aa2c9c51`. - And only between the blocks `0` and `100`. 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. ### Query block number 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<...> } } ``` ### Query balance 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_. ### Query composability 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 } } ``` ## Installation To install just add the following to your dependencies: ```elixir def deps do [ {:eth_event, "~> 0.1"} ] end ``` """ defmacro __using__(_) do quote do alias EthEvent.Api.{Block, Balance} end end end