diff --git a/README.md b/README.md index 048573e..9756b1e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# EXW3 +# ExW3 -**TODO: Add description** +Ethereum client for Elixir ## Installation diff --git a/lib/exw3.ex b/lib/exw3.ex index 38c6023..759f48a 100644 --- a/lib/exw3.ex +++ b/lib/exw3.ex @@ -34,9 +34,10 @@ defmodule ExW3 do def method(contract_agent, name, args \\ [], options \\ %{}) do if get(contract_agent, :abi)[name]["constant"] do + data = ExW3.encode_inputs(get(contract_agent, :abi), name, args) {:ok, output } = Ethereumex.HttpClient.eth_call(%{ to: get(contract_agent, :address), - data: ExW3.encode_inputs(get(contract_agent, :abi), name, args) + data: data }) [ :ok ] ++ ExW3.decode_output(get(contract_agent, :abi), name, output) |> List.to_tuple else @@ -49,13 +50,6 @@ defmodule ExW3 do end - def accounts do - case Ethereumex.HttpClient.eth_accounts do - {:ok, accounts} -> accounts - err -> err - end - end - def reformat_abi abi do Map.new Enum.map(abi, fn x -> {x["name"], x} end) end @@ -78,6 +72,53 @@ defmodule ExW3 do def encode_inputs abi, name, inputs do input_types = Enum.map abi[name]["inputs"], fn x -> x["type"] end input_signature = Enum.join [name, "(", Enum.join(input_types, ","), ")"] - ABI.encode(input_signature, inputs) |> Hexate.encode + ABI.encode(input_signature, inputs) |> Base.encode16(case: :lower) + end + + def accounts do + case Ethereumex.HttpClient.eth_accounts do + {:ok, accounts} -> accounts + err -> err + end + end + + #Converts ethereum hex string to decimal number + defp to_decimal hex_string do + hex_string + |> String.slice(2..-1) + |> String.to_integer(16) end + + def block_number do + case Ethereumex.HttpClient.eth_block_number do + {:ok, block_number} -> + block_number |> to_decimal + err -> err + end + end + + def balance account do + case Ethereumex.HttpClient.eth_get_balance(account) do + {:ok, balance} -> + balance |> to_decimal + err -> err + end + end + + defp keys_to_decimal map, keys do + Map.new( + Enum.map keys, fn k -> + { k, Map.get(map, k) |> to_decimal } + end + ) + end + + def tx_receipt tx_id do + case Ethereumex.HttpClient.eth_get_transaction_receipt(tx_id) do + {:ok, receipt} -> + Map.merge receipt, keys_to_decimal(receipt, ["blockNumber", "cumulativeGasUsed", "gasUsed"]) + err -> err + end + end + end \ No newline at end of file diff --git a/mix.exs b/mix.exs index 4409ef8..5e648df 100644 --- a/mix.exs +++ b/mix.exs @@ -30,8 +30,7 @@ defmodule ExW3.Mixfile do [ {:ethereumex, "~> 0.3.2"}, {:abi, "~> 0.1.8"}, - {:poison, "~> 3.1"}, - {:hexate, ">= 0.6.0"} + {:poison, "~> 3.1"} ] end end diff --git a/test/examples/contracts/ArrayTester.sol b/test/examples/contracts/ArrayTester.sol index e4aa54c..699a151 100644 --- a/test/examples/contracts/ArrayTester.sol +++ b/test/examples/contracts/ArrayTester.sol @@ -1,11 +1,11 @@ pragma solidity ^0.4.18; contract ArrayTester { - function dynamicUint(uint[] ints) public pure returns (uint[]) { - return ints; - } + function dynamicUint(uint[] ints) public pure returns (uint[]) { + return ints; + } - function staticUint(uint[5] ints) public pure returns (uint[5]) { - return ints; - } + function staticUint(uint[5] ints) public pure returns (uint[5]) { + return ints; + } } \ No newline at end of file diff --git a/test/exw3_test.exs b/test/exw3_test.exs index b71925c..9220d3b 100644 --- a/test/exw3_test.exs +++ b/test/exw3_test.exs @@ -4,16 +4,29 @@ defmodule EXW3Test do setup_all do %{ - simple_storage_abi: ExW3.load_abi("test/examples/build/SimpleStorage.abi"), + simple_storage_abi: ExW3.load_abi("test/examples/build/SimpleStorage.abi"), + array_tester_abi: ExW3.load_abi("test/examples/build/ArrayTester.abi"), accounts: ExW3.accounts } end + test "gets accounts" do + assert ExW3.accounts |> is_list + end + + test "gets balance", context do + assert ExW3.balance(Enum.at context[:accounts], 0 ) |> is_integer + end + + test "gets block number" do + assert ExW3.block_number |> is_integer + end + test "loads abi", context do assert context[:simple_storage_abi] |> is_map end - test "deploys contract and uses it", context do + test "deploys simple storage and uses it", context do contract_address = ExW3.Contract.deploy( "test/examples/build/SimpleStorage.bin", %{ @@ -28,7 +41,9 @@ defmodule EXW3Test do assert result == 0 - ExW3.Contract.method(storage, "set", [1], %{from: Enum.at(context[:accounts], 0)}) + {:ok, tx_id} = ExW3.Contract.method(storage, "set", [1], %{from: Enum.at(context[:accounts], 0)}) + + IO.inspect ExW3.tx_receipt tx_id {:ok, result} = ExW3.Contract.method(storage, "get") @@ -36,8 +51,28 @@ defmodule EXW3Test do end - test "gets accounts" do - assert ExW3.accounts |> is_list + test "deploys array tester and uses it", context do + contract_address = ExW3.Contract.deploy( + "test/examples/build/ArrayTester.bin", + %{ + from: Enum.at(context[:accounts], 0), + gas: 300000 + } + ) + + array_tester = ExW3.Contract.at context[:array_tester_abi], contract_address + + arr = [1, 2, 3, 4, 5] + + {:ok, result} = ExW3.Contract.method(array_tester, "staticUint", [arr]) + + assert result == arr + + #0x5d4e0342 + {:ok, result} = ExW3.Contract.method(array_tester, "dynamicUint", [arr]) + + assert result == arr + end end \ No newline at end of file