View Source Ethereumex (ethereumex v0.10.7)
Elixir JSON-RPC client for the Ethereum blockchain.
Check out the documentation here.
Installation
Add :ethereumex to your list of dependencies in mix.exs:
def deps do
  [
    {:ethereumex, "~> 0.10"}
  ]
endEnsure :ethereumex is started before your application:
def application do
  [
    applications: [:ethereumex]
  ]
endConfiguration
In config/config.exs, add Ethereum protocol host params to your config file
config :ethereumex,
  url: "http://localhost:8545"You can also configure the HTTP request timeout for requests sent to the Ethereum JSON-RPC
(you can also overwrite this configuration in opts used when calling the client).
config :ethereumex,
  http_options: [pool_timeout: 5000, receive_timeout: 15_000],
  http_headers: [{"Content-Type", "application/json"}]:pool_timeout - This timeout is applied when we check out a connection from the pool. Default value is 5_000.
:receive_timeout - The maximum time to wait for a response before returning an error. Default value is 15_000
If you want to use IPC you will need to set a few things in your config.
First, specify the :client_type:
config :ethereumex,
  client_type: :ipcThis will resolve to :http by default.
Second, specify the :ipc_path:
config :ethereumex,
  ipc_path: "/path/to/ipc"If you want to count the number of RPC calls per RPC method or overall,
you can attach yourself to executed telemetry events.
There are two events you can attach yourself to:
[:ethereumex] # has RPC method name in metadata
Emitted event: {:event, [:ethereumex], %{counter: 1}, %{method_name: "method_name"}}
or more granular
[:ethereumex, <rpc_method>] # %{} metadata
Emitted event: {:event, [:ethereumex, :method_name_as_atom], %{counter: 1}, %{}}
Each event caries a single ticker that you can pass into your counters (like Statix.increment/2).
Be sure to add :telemetry as project dependency.
The IPC client type mode opens a pool of connection workers (default is 5 and 2, respectively). You can configure the pool size.
config :ethereumex,
  ipc_worker_size: 5,
  ipc_max_worker_overflow: 2,
  ipc_request_timeout: 60_000Test
Download parity and initialize the password file
$ make setup
Run parity
$ make run
Run tests
$ make test
Usage
Available methods:
web3_clientVersionweb3_sha3net_versionnet_peerCountnet_listeningeth_protocolVersioneth_syncingeth_coinbaseeth_chainIdeth_miningeth_hashrateeth_gasPriceeth_accountseth_blockNumbereth_getBalanceeth_getStorageAteth_getTransactionCounteth_getBlockTransactionCountByHasheth_getBlockTransactionCountByNumbereth_getUncleCountByBlockHasheth_getUncleCountByBlockNumbereth_getCodeeth_signeth_sendTransactioneth_sendRawTransactioneth_calleth_estimateGaseth_getBlockByHasheth_getBlockByNumbereth_getTransactionByHasheth_getTransactionByBlockHashAndIndexeth_getTransactionByBlockNumberAndIndexeth_getTransactionReceipteth_getUncleByBlockHashAndIndexeth_getUncleByBlockNumberAndIndexeth_getCompilerseth_compileLLLeth_compileSolidityeth_compileSerpenteth_newFiltereth_newBlockFiltereth_newPendingTransactionFiltereth_uninstallFiltereth_getFilterChangeseth_getFilterLogseth_getLogs- eth_getProof
 eth_getWorketh_submitWorketh_submitHashratedb_putStringdb_getStringdb_putHexdb_getHexshh_postshh_versionshh_newIdentityshh_hasIdentityshh_newGroupshh_addToGroupshh_newFiltershh_uninstallFiltershh_getFilterChangesshh_getMessages
IpcClient
You can follow along with any of these examples using IPC by replacing HttpClient with IpcClient.
Examples
iex> Ethereumex.HttpClient.web3_client_version
{:ok, "Parity//v1.7.2-beta-9f47909-20170918/x86_64-macos/rustc1.19.0"}
# Using the url option will overwrite the configuration
iex> Ethereumex.HttpClient.web3_client_version(url: "http://localhost:8545")
{:ok, "Parity//v1.7.2-beta-9f47909-20170918/x86_64-macos/rustc1.19.0"}
iex> Ethereumex.HttpClient.web3_sha3("wrong_param")
{:error, %{"code" => -32602, "message" => "Invalid params: invalid format."}}
iex> Ethereumex.HttpClient.eth_get_balance("0x407d73d8a49eeb85d32cf465507dd71d507100c1")
{:ok, "0x0"}Note that all method names are snakecases, so, for example, shh_getMessages method has corresponding Ethereumex.HttpClient.shh_get_messages/1 method. Signatures can be found in Ethereumex.Client.Behaviour. There are more examples in tests.
eth_call example - Read only smart contract calls
In order to call a smart contract using the JSON-RPC interface you need to properly hash the data attribute (this will need to include the contract method signature along with arguments if any). You can do this manually or use a hex package like ABI to parse your smart contract interface or encode individual calls.
defp deps do
  [
    ...
    {:ethereumex, "~> 0.9"},
    {:ex_abi, "~> 0.5"}
    ...
  ]
endNow load the ABI and pass the method signature. Note that the address needs to be converted to bytes:
address           = "0xF742d4cE7713c54dD701AA9e92101aC42D63F895" |> String.slice(2..-1) |> Base.decode16!(case: :mixed)
contract_address  = "0xC28980830dD8b9c68a45384f5489ccdAF19D53cC"
abi_encoded_data  = ABI.encode("balanceOf(address)", [address]) |> Base.encode16(case: :lower)Now you can use eth_call to execute this smart contract command:
balance_bytes = Ethereumex.HttpClient.eth_call(%{
  data: "0x" <> abi_encoded_data,
  to: contract_address
})To convert the balance into an integer:
balance_bytes
|> String.slice(2..-1)
|> Base.decode16!(case: :lower)
|> TypeDecoder.decode_raw([{:uint, 256}])
|> List.firstCustom requests
Many Ethereum protocol implementations support additional JSON-RPC API methods. To use them, you should call Ethereumex.HttpClient.request/3 method.
For example, let's call parity's personal_listAccounts method.
iex> Ethereumex.HttpClient.request("personal_listAccounts", [], [])
{:ok,
 ["0x71cf0b576a95c347078ec2339303d13024a26910",
  "0x7c12323a4fff6df1a25d38319d5692982f48ec2e"]}Batch requests
To send batch requests use Ethereumex.HttpClient.batch_request/1 or Ethereumex.HttpClient.batch_request/2 method.
requests = [
   {:web3_client_version, []},
   {:net_version, []},
   {:web3_sha3, ["0x68656c6c6f20776f726c64"]}
 ]
 Ethereumex.HttpClient.batch_request(requests)
 {
   :ok,
   [
     {:ok, "Parity//v1.7.2-beta-9f47909-20170918/x86_64-macos/rustc1.19.0"},
     {:ok, "42"},
     {:ok, "0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad"}
   ]
 }