diff --git a/lib/exw3.ex b/lib/exw3.ex index 46c0f4a..38c6023 100644 --- a/lib/exw3.ex +++ b/lib/exw3.ex @@ -1,4 +1,4 @@ -defmodule EXW3 do +defmodule ExW3 do defmodule Contract do use Agent @@ -20,27 +20,30 @@ defmodule EXW3 do end def deploy(bin_filename, options) do - { :ok, bin} = File.read(Path.join(System.cwd(), bin_filename)) + {:ok, bin} = File.read(Path.join(System.cwd(), bin_filename)) tx = %{ from: options[:from], data: bin, gas: options[:gas] } - { :ok, tx_receipt_id} = Ethereumex.HttpClient.eth_send_transaction(tx) - { :ok, tx_receipt} = Ethereumex.HttpClient.eth_get_transaction_receipt(tx_receipt_id) + {:ok, tx_receipt_id} = Ethereumex.HttpClient.eth_send_transaction(tx) + {:ok, tx_receipt} = Ethereumex.HttpClient.eth_get_transaction_receipt(tx_receipt_id) tx_receipt["contractAddress"] end - def method(contract_agent, name) do + def method(contract_agent, name, args \\ [], options \\ %{}) do if get(contract_agent, :abi)[name]["constant"] do - Ethereumex.HttpClient.eth_call(%{ + {:ok, output } = Ethereumex.HttpClient.eth_call(%{ to: get(contract_agent, :address), - data: EXW3.encode(get(contract_agent, :abi), name, []) + data: ExW3.encode_inputs(get(contract_agent, :abi), name, args) }) + [ :ok ] ++ ExW3.decode_output(get(contract_agent, :abi), name, output) |> List.to_tuple else - - "foobar" + Ethereumex.HttpClient.eth_send_transaction(Map.merge(%{ + to: get(contract_agent, :address), + data: ExW3.encode_inputs(get(contract_agent, :abi), name, args) + }, options)) end end @@ -65,9 +68,16 @@ defmodule EXW3 do end end - def encode abi, name, args do - inputs = Enum.map abi[name]["inputs"], fn x -> x["type"] end - fn_signature = Enum.join [name, "(", Enum.join(inputs, ","), ")"] - ABI.encode(fn_signature, args) |> :binary.decode_unsigned + def decode_output abi, name, output do + {:ok, trim_output} = String.slice(output, 2..String.length(output)) |> Base.decode16(case: :lower) + output_types = Enum.map abi[name]["outputs"], fn x -> x["type"] end + output_signature = Enum.join [name, "(", Enum.join(output_types, ")"), ")"] + ABI.decode(output_signature, trim_output) + end + + 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 end end \ No newline at end of file diff --git a/mix.exs b/mix.exs index e3fc266..4409ef8 100644 --- a/mix.exs +++ b/mix.exs @@ -1,4 +1,4 @@ -defmodule EXW3.Mixfile do +defmodule ExW3.Mixfile do use Mix.Project def project do @@ -30,7 +30,8 @@ defmodule EXW3.Mixfile do [ {:ethereumex, "~> 0.3.2"}, {:abi, "~> 0.1.8"}, - {:poison, "~> 3.1"} + {:poison, "~> 3.1"}, + {:hexate, ">= 0.6.0"} ] end end diff --git a/mix.lock b/mix.lock index e36da30..dcb3eaf 100644 --- a/mix.lock +++ b/mix.lock @@ -5,6 +5,7 @@ "ethereumex": {:hex, :ethereumex, "0.3.2", "ee01a49c781c9751317b2918f799e84185203c81c8314ebebb1f1e22b754db3e", [:mix], [{:httpoison, "~> 1.0.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:poison, "~> 3.1.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"}, "exth_crypto": {:hex, :exth_crypto, "0.1.4", "11f9084dfd70d4f9e96f2710a472f4e6b23044b97530c719550c2b0450ffeb61", [:mix], [{:binary, "~> 0.0.4", [hex: :binary, repo: "hexpm", optional: false]}, {:keccakf1600, "~> 2.0.0", [hex: :keccakf1600_orig, repo: "hexpm", optional: false]}, {:libsecp256k1, "~> 0.1.3", [hex: :libsecp256k1, repo: "hexpm", optional: false]}], "hexpm"}, "hackney": {:hex, :hackney, "1.11.0", "4951ee019df102492dabba66a09e305f61919a8a183a7860236c0fde586134b6", [:rebar3], [{:certifi, "2.0.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, + "hexate": {:hex, :hexate, "0.6.1", "1cea42e462c1daa32223127d4752e71016c3d933d492b9bb7fa4709a4a0fd50d", [:mix], [], "hexpm"}, "httpoison": {:hex, :httpoison, "1.0.0", "1f02f827148d945d40b24f0b0a89afe40bfe037171a6cf70f2486976d86921cd", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, "idna": {:hex, :idna, "5.1.0", "d72b4effeb324ad5da3cab1767cb16b17939004e789d8c0ad5b70f3cea20c89a", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, "keccakf1600": {:hex, :keccakf1600_orig, "2.0.0", "0a7217ddb3ee8220d449bbf7575ec39d4e967099f220a91e3dfca4dbaef91963", [:rebar3], [], "hexpm"}, diff --git a/test/exw3_test.exs b/test/exw3_test.exs index 049b70d..b71925c 100644 --- a/test/exw3_test.exs +++ b/test/exw3_test.exs @@ -1,11 +1,11 @@ defmodule EXW3Test do use ExUnit.Case - doctest EXW3 + doctest ExW3 setup_all do %{ - simple_storage_abi: EXW3.load_abi("test/examples/build/SimpleStorage.abi"), - accounts: EXW3.accounts + simple_storage_abi: ExW3.load_abi("test/examples/build/SimpleStorage.abi"), + accounts: ExW3.accounts } end @@ -14,27 +14,30 @@ defmodule EXW3Test do end test "deploys contract and uses it", context do - contract_address = EXW3.Contract.deploy( + contract_address = ExW3.Contract.deploy( "test/examples/build/SimpleStorage.bin", %{ - from: Enum.at(context[:accounts], 0), - gas: 150000 + from: Enum.at(context[:accounts], 0), + gas: 150000 } ) - contract_agent = EXW3.Contract.at context[:simple_storage_abi], contract_address + storage = ExW3.Contract.at context[:simple_storage_abi], contract_address - EXW3.Contract.get contract_agent, :abi - |> Kernel.inspect - |> IO.puts + {:ok, result} = ExW3.Contract.method(storage, "get") + + assert result == 0 + + ExW3.Contract.method(storage, "set", [1], %{from: Enum.at(context[:accounts], 0)}) + + {:ok, result} = ExW3.Contract.method(storage, "get") + + assert result == 1 - EXW3.Contract.method(contract_agent, "get") - |> Kernel.inspect - |> IO.puts end test "gets accounts" do - assert EXW3.accounts |> is_list + assert ExW3.accounts |> is_list end end \ No newline at end of file diff --git a/test/test_helper.exs b/test/test_helper.exs index 869559e..4fbd00f 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -1 +1,9 @@ -ExUnit.start() +defmodule Log do + def p input do + input + |> Kernel.inspect + |> IO.puts + end +end + +ExUnit.start() \ No newline at end of file