# Ethereum adapter for Yggdrasil
[![Build Status](https://travis-ci.org/etherharvest/yggdrasil_ethereum.svg?branch=master)](https://travis-ci.org/etherharvest/yggdrasil_ethereum) [![Hex pm](http://img.shields.io/hexpm/v/yggdrasil_ethereum.svg?style=flat)](https://hex.pm/packages/yggdrasil_ethereum) [![hex.pm downloads](https://img.shields.io/hexpm/dt/yggdrasil_ethereum.svg?style=flat)](https://hex.pm/packages/yggdrasil_ethereum)
This project is an Ethereum adapter for `Yggdrasil` publisher/subscriber.
## Small example
The following example uses Ethereum adapter to distribute messages:
We need to configure [EthEvent](https://github.com/etherharvest/eth_event)
which is the library use to request the events from contracts:
```elixir
config :eth_event,
node_url: "https://mainnet.infura.io/v3", # Can be a custom URL
node_key: "" # Infura key or empty for custom URL
```
And then we declare the event using `EthEvent` library. In this example,
we will declare a `Transfer(address,address,uint256)` _event_. These events are
declared in ERC20 tokens and they are _emitted_ when a successfull token
transfers has occurred between wallets. In Solidity, we would have:
```solidity
contract SomeToken is ERC20 {
event Trasfer(
address indexed from,
address indexed to,
uint256 value
);
(...)
}
```
Using `EthEvent` library, we can create an equivalent of the previous
event in Elixir as follows:
```elixir
iex(1)> defmodule Transfer do
iex(1)> use EthEvent.Schema
iex(1)>
iex(1)> event "Transfer" do
iex(1)> address :from, indexed: true
iex(1)> address :to, indexed: true
iex(1)> uint256 :value
iex(1)> end
iex(1)> end
```
We can now subscribe to any contract that has that type of event. For this
example, we are going to subscribe to the `Transfer` events from OmiseGo
contract. First we declare the channel:
```elixir
iex(2)> contract = "0xd26114cd6EE289AccF82350c8d8487fedB8A0C07" # OmiseGo
iex(3)> channel = %Yggdrasil.Channel{
iex(3)> name: {Transfer, [address: contract]},
iex(3)> adapter: :ethereum
iex(3)> }
```
And then we subscribe to it:
```elixir
iex(4)> Yggdrasil.subscribe(channel)
iex(5)> flush()
{:Y_CONNECTED, %Yggdrasil.Channel{(...)}}
```
If we wait enough, we should receive a message as follows:
```elixir
iex(6)> flush()
{:Y_EVENT, %Yggdrasil.Channel{(...)}, %Transfer{(...)}}
```
Where the struct `%Transfer{}` contains the information of a token
transfer between two wallet addresses.
When we want to stop receiving messages, then we can unsubscribe
from the channel as follows:
```elixir
iex(7)> Yggdrasil.unsubscribe(channel)
iex(8)> flush()
{:Y_DISCONNECTED, %Yggdrasil.Channel{(...)}}
```
## Ethereum adapter
The Ethereum adapter has the following rules:
* The `adapter` name is identified by the atom `:ethereum`.
* The channel `name` must be a tuple with the module name of the event and
the `Keyword` list of options e.g: `:address`, `:from`, `:to`, etc (depends
on the event).
* The `transformer` should be always `:default`.
* Any `backend` can be used (by default is `:default`).
The following is an example of a valid channel for the subscribers:
```elixir
%Yggdrasil.Channel{
name: {Balance, [address: "0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE"]},
adapter: :ethereum
}
```
It will subscribe to the balance of that address.
## Ethereum configuration
This adapter uses long-polling to get the information from the Ethereum node
and the frequency of the requests can be configured with the `:timeout`
parameter.
The following shows a configuration with and without namespace:
```elixir
# Without namespace
config :yggdrasil,
ethereum: [timeout: 5_000]
# With namespace
config :yggdrasil, EthereumOne,
ethereum: [timeout: 15_000]
```
Additionally, we can configure `EthEvent` options:
* `node_url` - The Ethereum node URL.
* `node_key` - It'll be appended to the URL at the end.
```elixir
config :eth_event,
node_url: "https://mainnet.infura.io/v3", # Can be a custom URL
node_key: "some_key" # Empty for custom URL
```
All the options can be provided as OS environment variables. The available
variables are:
* `YGGDRASIL_ETHEREUM_TIMEOUT` or `<NAMESPACE>_YGGDRASIL_ETHEREUM_TIMEOUT`.
* `ETH_EVENT_NODE_URL`.
* `ETH_EVENT_NODE_KEY`.
where `<NAMESPACE>` is the snakecase of the namespace chosen e.g. for the
namespace `EthereumTwo`, you would use `ETHEREUM_TWO` as namespace in the OS
environment variable.
## Installation
Using this Ethereum adapter with `Yggdrasil` is a matter of adding the available
hex package to your `mix.exs` file e.g:
```elixir
def deps do
[{:yggdrasil_ethereum, "~> 0.1"}]
end
```
## Relevant projects used
* [`EthEvent`](https://github.com/etherharvest/eth_event): Library for
Solidity events.
## Author
Alexander de Sousa.
## License
`Yggdrasil` is released under the MIT License. See the LICENSE file for further
details.