# Ethex
Ethereum json-rpc implementation for multi-chain based on ex_abi.
## Cases I met
### case one
In every elixir backend dapp, you need interact with contract on blockchain. And you need to write or copy get_logs logic and decode_event logic again and again.
### case two
Every time I sync logs from chain, firstly decode indexed topic and decode data, then combine them together. What I need is decoding once and never destroy origin structure of logs.
### case three
In my case, the contract can deployed on ETH, or BSC, or Polygon. So I need to switch between multi-chain, not just one global config for json-rpc client.
## Installation
The package can be installed by adding `ethex` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:ethex, "~> 0.1.3"}
]
end
```
## Usage
You can get eth_block_number directly:
```elixir
iex(1)> Ethex.block_number "https://matic-mumbai.chainstacklabs.com"
{:ok, 30949805}
```
When interact with contract on blockchain, firstly, register abi to let Ethex know about it. Given the abi name and abi path.
```elixir
iex(2)> Ethex.register_abi "erc20", "/path/to/erc20.abi.json"
```
Then you can call function like `balanceOf`:
```elixir
iex(3)> Ethex.call "https://matic-mumbai.chainstacklabs.com", "erc20",
...(3)> "0xf167FcA5b9FeDf4E8baCAf8547225af93832ed6F", "balanceOf",
...(3)> ["8CcF629e123D83112423c283998443829A291334" |> Base.decode16!(case: :mixed)]
{:ok, [9999998000000000000000000000]}
```
And when do sync logs from blockchain by https endpoint:
```elixir
iex(4)> filter = %{fromBlock: "0x1D841AD", toBlock: "0x1D8434C", address: ["0x42F771DC235830077A04EE518472D88671755fF8"]}
%{
address: ["0x42F771DC235830077A04EE518472D88671755fF8"],
fromBlock: "0x1D841AD",
toBlock: "0x1D8434C"
}
iex(5)> Ethex.get_logs_and_decode "https://matic-mumbai.chainstacklabs.com", "erc20", filter
{:ok,
[
%Ethex.Struct.Transaction{
address: "0x42f771dc235830077a04ee518472d88671755ff8",
block_hash: "0xcc827e8fae4271bf91c65ce10b3a590b6d9c2d665cf8ae55224caf1444753b9d",
block_number: 30950172,
event_name: "Transfer",
log_index: "0x10",
removed: false,
returns: [
%{name: "_from", value: "0x8ccf629e123d83112423c283998443829a291334"},
%{name: "_to", value: "0xa2e7d1addb682c3f2ba78d5124433cb8ba2a4f4b"},
%{name: "_value", value: 10000000000000000000000}
],
transaction_hash: "0x48965d02c69f3eae46486d677efd55f06943fda3d8c2acf667ac5980ad569a1c",
transaction_index: "0x5"
}
]}
```
For polling logs, you need to maintaining block range, to avoid `excceed max block` error. So here is a util for generate block range, it need `latest` or the block number you sync last time. The reason why not use `eth_getFilterChanges` is that some chain not implement this method.
```elixir
iex(1)> Ethex.gen_block_range "https://matic-mumbai.chainstacklabs.com", "latest"
{:ok, 31246216, %{fromBlock: "0x1DCC774", toBlock: "0x1DCC788"} }
iex(2)> Ethex.gen_block_range "https://matic-mumbai.chainstacklabs.com", 31246216
{:ok, 31246262, %{fromBlock: "0x1DCC788", toBlock: "0x1DCC7B6"} }
```
## TODO
- add changelog
- add send transaction, this will update minor version to 0.2.0
- add config to initial register_abi and request_id