From 78f4a8e2dbd657618bf82ba8b29125bf40e5ab26 Mon Sep 17 00:00:00 2001 From: Izel Nakri Date: Sun, 28 Jan 2018 17:05:45 +0100 Subject: [PATCH] transaction queries complete with tests --- README.md | 14 +- lib/eth.ex | 10 +- lib/eth/query.ex | 29 +- lib/eth/transaction/builder.ex | 5 +- lib/eth/transaction/signer.ex | 4 +- lib/eth/transaction_queries.ex | 41 +- test.sh | 3 - test/eth/eth_test.exs | 6 + test/eth/transaction_queries_test.exs | 526 +++++++++++++++++++++----- 9 files changed, 497 insertions(+), 141 deletions(-) delete mode 100644 test.sh diff --git a/README.md b/README.md index 486d71a..fe5f739 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ Additionally this library wouldnt exist without the libraries below: - libsecp256k1 ### TODO: -contract creation via +Ethereum Smart Contracts, small enhancements ## Installation @@ -84,6 +84,12 @@ def deps do end ``` -Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) -and published on [HexDocs](https://hexdocs.pm). Once published, the docs can -be found at [https://hexdocs.pm/eth](https://hexdocs.pm/eth). +### Running the tests + +Install a testrpc(now renamed to ganache-cli) to run ethereum locally: +```npm install -g ganache-cli``` + +Elixir tests automatically spawns and kills the ganache-cli process. All you need to do now is to run the tests in sequence thus --seed 0: +```mix test --seed 0``` + +The docs can be found at [https://hexdocs.pm/eth](https://hexdocs.pm/eth). diff --git a/lib/eth.ex b/lib/eth.ex index af9b265..2ce3045 100644 --- a/lib/eth.ex +++ b/lib/eth.ex @@ -24,15 +24,19 @@ defmodule ETH do defdelegate gas_price, to: ETH.Query defdelegate gas_price!, to: ETH.Query defdelegate call(call_params), to: ETH.Query + defdelegate call(call_params, state), to: ETH.Query defdelegate call!(call_params), to: ETH.Query + defdelegate call!(call_params, state), to: ETH.Query defdelegate get_block, to: ETH.Query defdelegate get_block(identifier), to: ETH.Query defdelegate get_block!, to: ETH.Query defdelegate get_block!(identifier), to: ETH.Query defdelegate get_balance(wallet_or_address), to: ETH.Query - defdelegate get_balance(wallet_or_address, denomination), to: ETH.Query + defdelegate get_balance(wallet_or_address, state), to: ETH.Query + defdelegate get_balance(wallet_or_address, denomination, state), to: ETH.Query defdelegate get_balance!(wallet_or_address), to: ETH.Query - defdelegate get_balance!(wallet_or_address, denomination), to: ETH.Query + defdelegate get_balance!(wallet_or_address, state), to: ETH.Query + defdelegate get_balance!(wallet_or_address, denomination, state), to: ETH.Query defdelegate estimate_gas(transaction), to: ETH.Query defdelegate estimate_gas!(transaction), to: ETH.Query defdelegate estimate_gas(transaction, denomination), to: ETH.Query @@ -49,7 +53,9 @@ defmodule ETH do defdelegate get_transaction_receipt(transaction_hash), to: ETH.TransactionQueries defdelegate get_transaction_receipt!(transaction_hash), to: ETH.TransactionQueries defdelegate get_transaction_count(wallet_or_address), to: ETH.TransactionQueries + defdelegate get_transaction_count(wallet_or_address, state), to: ETH.TransactionQueries defdelegate get_transaction_count!(wallet_or_address), to: ETH.TransactionQueries + defdelegate get_transaction_count!(wallet_or_address, state), to: ETH.TransactionQueries defdelegate parse(data), to: ETH.Transaction.Parser defdelegate to_list(data), to: ETH.Transaction.Parser diff --git a/lib/eth/query.ex b/lib/eth/query.ex index 4af4f93..0afc72d 100644 --- a/lib/eth/query.ex +++ b/lib/eth/query.ex @@ -45,10 +45,10 @@ defmodule ETH.Query do end # TODO: test this one - def call(call_params), do: HttpClient.eth_call(call_params) + def call(call_params, state \\ "latest"), do: HttpClient.eth_call(call_params, state) - def call!(call_params) do - {:ok, result} = HttpClient.eth_call(call_params) + def call!(call_params, state \\ "latest") do + {:ok, result} = HttpClient.eth_call(call_params, state) result end @@ -99,10 +99,10 @@ defmodule ETH.Query do convert_block_details(raw_block_details) end - def get_balance(param, denomination \\ :ether) + def get_balance(param, denomination \\ :ether, state \\ "latest") - def get_balance(wallet, denomination) when is_map(wallet) do - case HttpClient.eth_get_balance(wallet.eth_address) do + def get_balance(wallet, denomination, state) when is_map(wallet) do + case HttpClient.eth_get_balance(wallet.eth_address, state) do {:ok, hex_balance} -> balance = hex_balance @@ -116,8 +116,8 @@ defmodule ETH.Query do end end - def get_balance(eth_address, denomination) do - case HttpClient.eth_get_balance(eth_address) do + def get_balance(eth_address, denomination, state) do + case HttpClient.eth_get_balance(eth_address, state) do {:ok, hex_balance} -> balance = hex_balance @@ -131,18 +131,18 @@ defmodule ETH.Query do end end - def get_balance!(param, denomination \\ :ether) + def get_balance!(param, denomination \\ :ether, state \\ "latest") - def get_balance!(wallet, denomination) when is_map(wallet) do - {:ok, hex_balance} = HttpClient.eth_get_balance(wallet.eth_address) + def get_balance!(wallet, denomination, state) when is_map(wallet) do + {:ok, hex_balance} = HttpClient.eth_get_balance(wallet.eth_address, state) hex_balance |> convert_to_number |> convert(denomination) end - def get_balance!(eth_address, denomination) do - {:ok, hex_balance} = HttpClient.eth_get_balance(eth_address) + def get_balance!(eth_address, denomination, state) do + {:ok, hex_balance} = HttpClient.eth_get_balance(eth_address, state) hex_balance |> convert_to_number @@ -169,9 +169,6 @@ defmodule ETH.Query do hex_gas_estimate |> convert_to_number |> convert(denomination) |> round end - defp get_result({:ok, eth_result}), do: Map.get(eth_result, "result") - defp get_result(error), do: raise(error) - def convert_transaction_log(log) do Enum.reduce(log, %{}, fn tuple, acc -> {key, value} = tuple diff --git a/lib/eth/transaction/builder.ex b/lib/eth/transaction/builder.ex index 91c3e35..3415750 100644 --- a/lib/eth/transaction/builder.ex +++ b/lib/eth/transaction/builder.ex @@ -67,7 +67,8 @@ defmodule ETH.Transaction.Builder do value = Keyword.get(params, :value, 0) gas_price = Keyword.get(params, :gas_price, ETH.gas_price!()) data = Keyword.get(params, :data, "") - nonce = Keyword.get(params, :nonce, ETH.get_transaction_count!(params[:from])) + # NOTE: this probably causes bug + nonce = Keyword.get(params, :nonce, ETH.get_transaction_count!(params[:from], "pending")) chain_id = Keyword.get(params, :chain_id, 3) gas_limit = @@ -91,7 +92,7 @@ defmodule ETH.Transaction.Builder do value = Map.get(params, :value, 0) gas_price = Map.get(params, :gas_price, ETH.gas_price!()) data = Map.get(params, :data, "") - nonce = Map.get(params, :nonce, ETH.get_transaction_count!(params.from)) + nonce = Map.get(params, :nonce, ETH.get_transaction_count!(params.from, "pending")) chain_id = Map.get(params, :chain_id, 3) gas_limit = diff --git a/lib/eth/transaction/signer.ex b/lib/eth/transaction/signer.ex index 62cc6b8..c1ad469 100644 --- a/lib/eth/transaction/signer.ex +++ b/lib/eth/transaction/signer.ex @@ -109,8 +109,8 @@ defmodule ETH.Transaction.Signer do value, data, v, - r, - s + _r, + _s ], <> ) do diff --git a/lib/eth/transaction_queries.ex b/lib/eth/transaction_queries.ex index 974eaa8..bd1ad17 100644 --- a/lib/eth/transaction_queries.ex +++ b/lib/eth/transaction_queries.ex @@ -6,11 +6,7 @@ defmodule ETH.TransactionQueries do def get_block_transactions(identifier) do case get_block(identifier) do {:ok, block} -> - {:ok, - (block.transactions || []) - |> Enum.map(fn transaction -> - convert_transaction_details(transaction) - end)} + {:ok, Map.get(block, :transactions, [])} error -> error @@ -19,9 +15,6 @@ defmodule ETH.TransactionQueries do def get_block_transactions!(identifier) do get_block!(identifier) |> Map.get(:transactions, []) - |> Enum.map(fn transaction -> - convert_transaction_details(transaction) - end) end def get_block_transaction_count(block_number) when is_number(block_number) do @@ -52,14 +45,14 @@ defmodule ETH.TransactionQueries do def get_transaction_from_block(block_number, index) when is_number(block_number) do case HttpClient.eth_get_transaction_by_block_number_and_index(block_number, index) do - {:ok, transaction} -> {:ok, transaction} + {:ok, transaction} -> {:ok, convert_transaction_details(transaction)} error -> error end end def get_transaction_from_block(block_hash, index) do case HttpClient.eth_get_transaction_by_block_hash_and_index(block_hash, index) do - {:ok, transaction} -> {:ok, transaction} + {:ok, transaction} -> {:ok, convert_transaction_details(transaction)} error -> error end end @@ -68,13 +61,13 @@ defmodule ETH.TransactionQueries do {:ok, transaction} = HttpClient.eth_get_transaction_by_block_number_and_index(block_number, index) - transaction + convert_transaction_details(transaction) end def get_transaction_from_block!(block_hash, index) do {:ok, transaction} = HttpClient.eth_get_transaction_by_block_hash_and_index(block_hash, index) - transaction + convert_transaction_details(transaction) end def get_transaction(transaction_hash) do @@ -105,39 +98,43 @@ defmodule ETH.TransactionQueries do convert_transaction_receipt(raw_transaction_receipt) end - def get_transaction_count(wallet) when is_map(wallet) do - case HttpClient.eth_get_transaction_count(wallet.eth_address) do + def get_transaction_count(target_wallet, state \\ "latest") + + def get_transaction_count(wallet, state) when is_map(wallet) do + case HttpClient.eth_get_transaction_count(wallet.eth_address, state) do {:ok, hex_transaction_count} -> {:ok, convert_to_number(hex_transaction_count)} error -> error end end - def get_transaction_count(eth_address) do - case HttpClient.eth_get_transaction_count(eth_address) do + def get_transaction_count(eth_address, state) do + case HttpClient.eth_get_transaction_count(eth_address, state) do {:ok, hex_transaction_count} -> {:ok, convert_to_number(hex_transaction_count)} error -> error end end - def get_transaction_count!(wallet) when is_map(wallet) do - {:ok, hex_transaction_count} = HttpClient.eth_get_transaction_count(wallet.eth_address) + def get_transaction_count!(target_wallet, state \\ "latest") + + def get_transaction_count!(wallet, state) when is_map(wallet) do + {:ok, hex_transaction_count} = HttpClient.eth_get_transaction_count(wallet.eth_address, state) convert_to_number(hex_transaction_count) end - def get_transaction_count!(eth_address) do - {:ok, hex_transaction_count} = HttpClient.eth_get_transaction_count(eth_address) + def get_transaction_count!(eth_address, state) do + {:ok, hex_transaction_count} = HttpClient.eth_get_transaction_count(eth_address, state) convert_to_number(hex_transaction_count) end - defp convert_to_number(result) do + def convert_to_number(result) do result |> String.slice(2..-1) |> Hexate.to_integer() end - def convert_transaction_receipt(result) do + defp convert_transaction_receipt(result) do result |> Enum.reduce(%{}, fn tuple, acc -> {key, value} = tuple diff --git a/test.sh b/test.sh deleted file mode 100644 index e610448..0000000 --- a/test.sh +++ /dev/null @@ -1,3 +0,0 @@ -testrpc & -mix test -pkill -f testrpc diff --git a/test/eth/eth_test.exs b/test/eth/eth_test.exs index 6fcffaa..0cf59bd 100644 --- a/test/eth/eth_test.exs +++ b/test/eth/eth_test.exs @@ -10,7 +10,9 @@ defmodule ETH.Test do build: 2, build: 3, call: 1, + call: 2, call!: 1, + call!: 2, convert: 2, decode: 1, decode16: 1, @@ -27,8 +29,10 @@ defmodule ETH.Test do get_address: 1, get_balance: 1, get_balance: 2, + get_balance: 3, get_balance!: 1, get_balance!: 2, + get_balance!: 3, get_block: 0, get_block: 1, get_block!: 0, @@ -45,7 +49,9 @@ defmodule ETH.Test do get_transaction: 1, get_transaction!: 1, get_transaction_count: 1, + get_transaction_count: 2, get_transaction_count!: 1, + get_transaction_count!: 2, get_transaction_from_block: 2, get_transaction_from_block!: 2, get_transaction_receipt: 1, diff --git a/test/eth/transaction_queries_test.exs b/test/eth/transaction_queries_test.exs index cc4e7c3..23e83fb 100644 --- a/test/eth/transaction_queries_test.exs +++ b/test/eth/transaction_queries_test.exs @@ -1,4 +1,3 @@ -# TODO: alot of the functions not tested! defmodule ETH.TransactionQueries.Test do use ExUnit.Case @@ -12,132 +11,479 @@ defmodule ETH.TransactionQueries.Test do :ok end - @first_client_account_private_key "a160512c1dc5c33eff6ef89aae083108dcdcabdbe463481949d327fc2ac6ac48" + @first_wallet_in_client %{ + eth_address: "0x051D51BA1E1D58DB72EFEA63549A6792C8F5CB13", + mnemonic_phrase: + "pause action enrich describe found panda world tenant one icon arrange balance soccer field hurdle midnight elite ski inquiry exit section globe raise brass", + private_key: "a160512c1dc5c33eff6ef89aae083108dcdcabdbe463481949d327fc2ac6ac48", + public_key: + "04418C292B1E69D5B49A0F2CA082DF83C361401C8A752C62F1081B6E4935948619779105D12AE05BFD1DE368F66133357FC46F2949899E3BD7F90873384C4F3998" + } + @second_wallet_in_client %{ + eth_address: "0x1800542A82E6DE47CF4D310305F56EE56F63024A", + mnemonic_phrase: + "dignity adapt fat fury require fury federal crystal hero account art link fancy peace infant endless journey crane prepare topple visual walk owner arrive", + private_key: "3e00614daf3b70bcd519aa6b40303341052f439cd24d78664aa7f29f4fed2788", + public_key: + "048D505C1C871C1A04B8970789CAD4EC70BB302470F3EDE2D32A3D27EE25EB4B827CEE264A268A02D9D6153BFDBCF290DA1C5130523B35BF8D964050688A909770" + } + @third_wallet_in_client %{ + eth_address: "0xC8FDF0764E2F783B11B6A2552A78CE14B2CEB484", + mnemonic_phrase: + "loop right hungry only east task humble panel canvas hunt plastic rival page discover omit crisp item when region pencil burden diagram nice nurse", + private_key: "83f739bd4d845bbc1bbcfc21adee985d59ee7de6999d76df46d25151e879e55c", + public_key: + "041D42B37794DA909A9A8C1A2A9EAB6679FE0478383F9FFC212EACDF7B7B844B1E0E7D2F74840DD173141B41AB02B6E01AB0B85D330DBE9D398ECE35C967D230A1" + } + @fourth_wallet_in_client %{ + eth_address: "0x8E4E0A1E2D128EE71EFA14000A9D25A0DFD57426", + mnemonic_phrase: + "whisper organ connect honey demise rose gas bronze soul kangaroo word canvas skate arrange cream broccoli pumpkin post mention aware guilt crane idea stand", + private_key: "fa938cbcb693a5781800e5cfaf33f590dca0188cb8e3adb5162c08267a649c1e", + public_key: + "042F65C8522D43CF527A2CFDA9FD15031B835359EB754D32CFCE7447A4FF4928B39B543571E5286FF564D4C8CDD1F8F3D8F928E505CA3D33D02A6917F09A4FC758" + } + @fifth_wallet_in_client %{ + eth_address: "0xC2AFEFA6B827CD41AC598086BCF45C5AE7061BFE", + mnemonic_phrase: + "lend network mansion huge october bid sister unlock reform husband offer maze inspire frown bitter escape remember talent goat receive capital they choice century", + private_key: "7ff29a1d3759902c326770b44dfe65c4c754bb05b268b5bbad9059c221c10a09", + public_key: + "04F6851EC9A15E389D4D8632DEC890429B9F50038CBECD6013210DD815220826C95D065083810FFE55A32EAF93E4AD79E485C4B334F065A1C759FB76169CABC238" + } + @sixth_wallet_in_client %{ + eth_address: "0xE484D305ED89AAA63FDA68B302547C03F3B479D3", + mnemonic_phrase: + "phrase civil level wine run method tree suspect jeans economy tuition draw safe orchard front message tree cart powder calm term defy fit jazz", + private_key: "a3c53202fdcbd51879fed677a8c7a8a13be13817545fe7e462a4904df67355f3", + public_key: + "04CEA850A30D36321B0F5409219B6D228E98C57297BF8655ADF4AF407D48787224102CE8A4FBD6BA2C6A28E7419158BBCFD5FF1BA8EF05D1FE2B19518F059F3968" + } + + # TODO: add some logs in future + test "get_block_transactions(block_no) works" do + {:ok, first_block_transactions_by_number} = ETH.get_block_transactions(1) - # TODO: ETH.get_block_transactions - test "get_block_transactions/1 works" do - first_block_transactions_by_number = ETH.get_block_transactions(1) + assert first_block_transactions_by_number == [] + + first_tx_hash = ETH.send_transaction!(@first_wallet_in_client, @second_wallet_in_client, 500) + + second_tx_hash = + ETH.send_transaction!(@second_wallet_in_client, @first_wallet_in_client, 2000) - first_block_transactions_by_hash = - ETH.get_block!(1) - |> Map.get(:hash) - |> ETH.get_block_transactions() + Process.sleep(2000) - wallet = ETH.Wallet.create() - first_account_in_your_client = ETH.Wallet.create(@first_client_account_private_key) + assert ETH.get_block_transactions(ETH.block_number!() - 1) == + {:ok, + [ + ETH.get_transaction!(first_tx_hash), + ETH.get_transaction!(second_tx_hash) + ]} + end + + test "get_block_transactions(block_hash) works" do + {:ok, first_block_transactions_by_number} = ETH.get_block_transactions(ETH.get_block!(1).hash) - # ETH.send_transaction(%{ - # from: first_account_in_your_client.eth_address, to: wallet[:eth_address], value: 22 - # }, @first_client_account_private_key) - # ETH.send_transaction(%{ - # from: first_account_in_your_client.eth_address, to: wallet[:eth_address], value: 22 - # }, @first_client_account_private_key) + assert first_block_transactions_by_number == [] - assert first_block_transactions_by_number == {:ok, []} - assert first_block_transactions_by_hash == {:ok, []} + first_tx_hash = ETH.send_transaction!(@first_wallet_in_client, @second_wallet_in_client, 500) - # last_block_transactions_by_number = ETH.block_number |> ETH.get_block_transactions - # last_block_transactions_by_hash = ETH.block_number - # |> ETH.get_block - # |> Map.get(:hash) - # |> ETH.get_block_transactions - # - # assert last_block_transactions_by_number == {:ok, []} - # assert last_block_transactions_by_hash == {:ok, []} + second_tx_hash = + ETH.send_transaction!(@second_wallet_in_client, @first_wallet_in_client, 2000) + + Process.sleep(2000) + + target_block = ETH.get_block!(ETH.block_number!() - 1) + + assert ETH.get_block_transactions(target_block.hash) == + {:ok, + [ + ETH.get_transaction!(first_tx_hash), + ETH.get_transaction!(second_tx_hash) + ]} end - test "get_block_transactions!/1 works" do - first_block_transactions_by_number = ETH.get_block_transactions!(1) + test "get_block_transactions!(block_no) works" do + assert ETH.get_block_transactions!(1) == [] - first_block_transactions_by_hash = - ETH.get_block!(1) - |> Map.get(:hash) - |> ETH.get_block_transactions!() + first_tx_hash = ETH.send_transaction!(@first_wallet_in_client, @second_wallet_in_client, 500) - wallet = ETH.Wallet.create() - first_account_in_your_client = ETH.Wallet.create(@first_client_account_private_key) + second_tx_hash = + ETH.send_transaction!(@second_wallet_in_client, @first_wallet_in_client, 2000) - # ETH.send_transaction(%{ - # from: first_account_in_your_client.eth_address, to: wallet[:eth_address], value: 22 - # }, @first_client_account_private_key) - # ETH.send_transaction(%{ - # from: first_account_in_your_client.eth_address, to: wallet[:eth_address], value: 22 - # }, @first_client_account_private_key) + Process.sleep(2000) - assert first_block_transactions_by_number == [] - assert first_block_transactions_by_hash == [] + assert ETH.get_block_transactions!(ETH.block_number!() - 1) == [ + ETH.get_transaction!(first_tx_hash), + ETH.get_transaction!(second_tx_hash) + ] + end - # last_block_transactions_by_number = ETH.block_number |> ETH.get_block_transactions - # last_block_transactions_by_hash = ETH.block_number - # |> ETH.get_block - # |> Map.get(:hash) - # |> ETH.get_block_transactions - # - # assert last_block_transactions_by_number == {:ok, []} - # assert last_block_transactions_by_hash == {:ok, []} + test "get_block_transactions!(block_hash) works" do + assert ETH.get_block_transactions!(ETH.get_block!(1).hash) == [] + + first_tx_hash = ETH.send_transaction!(@first_wallet_in_client, @second_wallet_in_client, 500) + + second_tx_hash = + ETH.send_transaction!(@second_wallet_in_client, @first_wallet_in_client, 2000) + + Process.sleep(2000) + + target_block = ETH.get_block!(ETH.block_number!() - 1) + + assert ETH.get_block_transactions!(target_block.hash) == [ + ETH.get_transaction!(first_tx_hash), + ETH.get_transaction!(second_tx_hash) + ] end - test "get_block_transactions_count/1 works" do + test "get_block_transaction_count(block_number)" do assert ETH.get_block_transaction_count(1) == {:ok, 0} - assert ETH.get_block!() |> Map.get(:hash) |> ETH.get_transaction_count() == {:ok, 0} - # wallet = ETH.Wallet.create() - # first_account_in_your_client = ETH.Wallet.create(@first_client_account_private_key) + ETH.send_transaction!(@first_wallet_in_client, @second_wallet_in_client, 500) + ETH.send_transaction!(@second_wallet_in_client, @first_wallet_in_client, 2000) - # ETH.send_transaction(%{ - # from: first_account_in_your_client.eth_address, to: wallet[:eth_address], value: 22 - # }, @first_client_account_private_key) - # ETH.send_transaction(%{ - # from: first_account_in_your_client.eth_address, to: wallet[:eth_address], value: 22 - # }, @first_client_account_private_key) + Process.sleep(2000) - # assert ETH.block_number!() |> ETH.get_block_transaction_count() == {:ok, 2} - # assert ETH.block_number!() |> Map.get(:hash) |> ETH.get_transaction_count() == {:ok, 2} + assert ETH.get_block_transaction_count(ETH.block_number!() - 1) == {:ok, 2} end - test "get_block_transactions_count!/1 works" do + test "get_block_transaction_count!(block_number)" do assert ETH.get_block_transaction_count!(1) == 0 - assert ETH.get_block!() |> Map.get(:hash) |> ETH.get_transaction_count!() == 0 - # wallet = ETH.Wallet.create() - # first_account_in_your_client = ETH.Wallet.create(@first_client_account_private_key) + ETH.send_transaction!(@first_wallet_in_client, @second_wallet_in_client, 500) + ETH.send_transaction!(@second_wallet_in_client, @first_wallet_in_client, 2000) + + Process.sleep(2000) + + assert ETH.get_block_transaction_count!(ETH.block_number!() - 1) == 2 + end + + test "get_block_transaction_count(block_hash) works" do + assert ETH.get_block_transaction_count(ETH.get_block!(1).hash) == {:ok, 0} + + ETH.send_transaction!(@first_wallet_in_client, @second_wallet_in_client, 500) + ETH.send_transaction!(@second_wallet_in_client, @first_wallet_in_client, 2000) - # ETH.send_transaction(%{ - # from: first_account_in_your_client.eth_address, to: wallet[:eth_address], value: 22 - # }, @first_client_account_private_key) - # ETH.send_transaction(%{ - # from: first_account_in_your_client.eth_address, to: wallet[:eth_address], value: 22 - # }, @first_client_account_private_key) + Process.sleep(2000) - # assert ETH.block_number!() |> ETH.get_block_transaction_count() == 2 - # assert ETH.block_number!() |> Map.get(:hash) |> ETH.get_transaction_count() == 2 + target_block = ETH.get_block!(ETH.block_number!() - 1) + + assert ETH.get_block_transaction_count(target_block.hash) == {:ok, 2} end - # TODO: get_transaction_from_block!(identifier, index), to: ETH.Query + test "get_block_transaction_count!(block_hash) works" do + assert ETH.get_block_transaction_count!(ETH.get_block!(1).hash) == 0 + + ETH.send_transaction!(@first_wallet_in_client, @second_wallet_in_client, 500) + ETH.send_transaction!(@second_wallet_in_client, @first_wallet_in_client, 2000) + + Process.sleep(2000) + + target_block = ETH.get_block!(ETH.block_number!() - 1) + + assert ETH.get_block_transaction_count!(target_block.hash) == 2 + end - # TODO: get_transaction + test "get_transaction_from_block(block_number, index) works" do + assert ETH.get_transaction_from_block(0, 0) |> elem(0) == :error - # TODO: get_transaction_receipt + first_tx_hash = ETH.send_transaction!(@first_wallet_in_client, @second_wallet_in_client, 500) - test "transaction_count/1 works" do - # TODO: have one with transactions - address_with_balance = ETH.get_accounts!() |> List.last() + second_tx_hash = + ETH.send_transaction!(@second_wallet_in_client, @first_wallet_in_client, 2000) - assert ETH.get_transaction_count(address_with_balance) == {:ok, 0} + Process.sleep(2000) - wallet_with_balance = @first_client_account_private_key |> ETH.Wallet.create() + block_no = ETH.block_number!() - 1 - assert ETH.get_transaction_count(wallet_with_balance) == {:ok, 0} + assert ETH.get_transaction_from_block(block_no, 0) == + {:ok, ETH.get_transaction!(first_tx_hash)} + + assert ETH.get_transaction_from_block(block_no, 1) == + {:ok, ETH.get_transaction!(second_tx_hash)} + + assert ETH.get_transaction_from_block(block_no, 2) |> elem(0) == :error end - test "transaction_count!/1 works" do - # TODO: have one with transactions - address_with_balance = ETH.get_accounts!() |> List.last() + test "get_transaction_from_block!(block_number, index) works" do + assert_raise MatchError, fn -> ETH.get_transaction_from_block!(0, 0) end + + first_tx_hash = ETH.send_transaction!(@first_wallet_in_client, @second_wallet_in_client, 500) + + second_tx_hash = + ETH.send_transaction!(@second_wallet_in_client, @first_wallet_in_client, 2000) + + Process.sleep(2000) + + block_no = ETH.block_number!() - 1 + + assert ETH.get_transaction_from_block!(block_no, 0) == ETH.get_transaction!(first_tx_hash) + assert ETH.get_transaction_from_block!(block_no, 1) == ETH.get_transaction!(second_tx_hash) + assert_raise MatchError, fn -> ETH.get_transaction_from_block!(block_no, 2) |> elem(0) end + end + + test "get_transaction_from_block(block_hash, index) works" do + first_block_hash = ETH.get_block!(0).hash + assert ETH.get_transaction_from_block(first_block_hash, 0) |> elem(0) == :error + + first_tx_hash = ETH.send_transaction!(@first_wallet_in_client, @second_wallet_in_client, 500) + second_tx_hash = + ETH.send_transaction!(@second_wallet_in_client, @first_wallet_in_client, 2000) + + Process.sleep(2000) + + block_hash = ETH.get_block!(ETH.block_number!() - 1).hash + + assert ETH.get_transaction_from_block(block_hash, 0) == + {:ok, ETH.get_transaction!(first_tx_hash)} + + assert ETH.get_transaction_from_block(block_hash, 1) == + {:ok, ETH.get_transaction!(second_tx_hash)} + + assert ETH.get_transaction_from_block(block_hash, 2) |> elem(0) == :error + end + + test "get_transaction_from_block!(block_hash, index) works" do + first_block_hash = ETH.get_block!(0).hash + + assert_raise MatchError, fn -> ETH.get_transaction_from_block!(first_block_hash, 0) end + + first_tx_hash = ETH.send_transaction!(@first_wallet_in_client, @second_wallet_in_client, 500) + + second_tx_hash = + ETH.send_transaction!(@second_wallet_in_client, @first_wallet_in_client, 2000) + + Process.sleep(2000) + + block_hash = ETH.get_block!(ETH.block_number!() - 1).hash + + assert ETH.get_transaction_from_block!(block_hash, 0) == ETH.get_transaction!(first_tx_hash) + assert ETH.get_transaction_from_block!(block_hash, 1) == ETH.get_transaction!(second_tx_hash) + assert_raise MatchError, fn -> ETH.get_transaction_from_block!(block_hash, 2) |> elem(0) end + end + + test "get_transaction(transaction_hash) works" do + first_tx_hash = ETH.send_transaction!(@first_wallet_in_client, @second_wallet_in_client, 500) + + second_tx_hash = + ETH.send_transaction!(@second_wallet_in_client, @first_wallet_in_client, 2000) + + Process.sleep(2000) + + {:ok, first_transaction} = ETH.get_transaction(first_tx_hash) + {:ok, second_transaction} = ETH.get_transaction(second_tx_hash) + + assert Map.keys(first_transaction) == [ + :block_hash, + :block_number, + :from, + :gas, + :gas_price, + :hash, + :input, + :nonce, + :to, + :transaction_index, + :value + ] + + assert first_transaction.hash == first_tx_hash + + assert Map.keys(second_transaction) == [ + :block_hash, + :block_number, + :from, + :gas, + :gas_price, + :hash, + :input, + :nonce, + :to, + :transaction_index, + :value + ] + + assert second_transaction.hash == second_tx_hash + end + + test "get_transaction!(transaction_hash) works" do + first_tx_hash = ETH.send_transaction!(@first_wallet_in_client, @second_wallet_in_client, 500) + + second_tx_hash = + ETH.send_transaction!(@second_wallet_in_client, @first_wallet_in_client, 2000) + + Process.sleep(2000) + + first_transaction = ETH.get_transaction!(first_tx_hash) + second_transaction = ETH.get_transaction!(second_tx_hash) + + assert Map.keys(first_transaction) == [ + :block_hash, + :block_number, + :from, + :gas, + :gas_price, + :hash, + :input, + :nonce, + :to, + :transaction_index, + :value + ] + + assert first_transaction.hash == first_tx_hash + + assert Map.keys(second_transaction) == [ + :block_hash, + :block_number, + :from, + :gas, + :gas_price, + :hash, + :input, + :nonce, + :to, + :transaction_index, + :value + ] + + assert second_transaction.hash == second_tx_hash + end + + test "get_transaction_receipt(transaction_hash) works" do + first_tx_hash = ETH.send_transaction!(@first_wallet_in_client, @second_wallet_in_client, 500) + + second_tx_hash = + ETH.send_transaction!(@second_wallet_in_client, @first_wallet_in_client, 2000) + + Process.sleep(2000) + + {:ok, first_transaction_receipt} = ETH.get_transaction_receipt(first_tx_hash) + {:ok, second_transaction_receipt} = ETH.get_transaction_receipt(second_tx_hash) + + assert Map.keys(first_transaction_receipt) == [ + :block_hash, + :block_number, + :contract_address, + :cumulative_gas_used, + :gas_used, + :logs, + :status, + :transaction_hash, + :transaction_index + ] + + assert first_transaction_receipt.transaction_hash == first_tx_hash + + assert Map.keys(second_transaction_receipt) == [ + :block_hash, + :block_number, + :contract_address, + :cumulative_gas_used, + :gas_used, + :logs, + :status, + :transaction_hash, + :transaction_index + ] + + assert second_transaction_receipt.transaction_hash == second_tx_hash + end + + test "get_transaction_receipt!(transaction_hash) works" do + first_tx_hash = ETH.send_transaction!(@first_wallet_in_client, @second_wallet_in_client, 500) + + second_tx_hash = + ETH.send_transaction!(@second_wallet_in_client, @first_wallet_in_client, 2000) + + Process.sleep(2000) + + first_transaction_receipt = ETH.get_transaction_receipt!(first_tx_hash) + second_transaction_receipt = ETH.get_transaction_receipt!(second_tx_hash) + + assert Map.keys(first_transaction_receipt) == [ + :block_hash, + :block_number, + :contract_address, + :cumulative_gas_used, + :gas_used, + :logs, + :status, + :transaction_hash, + :transaction_index + ] + + assert first_transaction_receipt.transaction_hash == first_tx_hash + + assert Map.keys(second_transaction_receipt) == [ + :block_hash, + :block_number, + :contract_address, + :cumulative_gas_used, + :gas_used, + :logs, + :status, + :transaction_hash, + :transaction_index + ] + + assert second_transaction_receipt.transaction_hash == second_tx_hash + end + + test "get_transaction_count(wallet) works" do + assert ETH.get_transaction_count(@third_wallet_in_client) == {:ok, 0} + + ETH.send_transaction!(@third_wallet_in_client, @second_wallet_in_client, 500) + + Process.sleep(2000) + + ETH.send_transaction!(@third_wallet_in_client, @first_wallet_in_client, 2000) + + Process.sleep(2000) + + assert ETH.get_transaction_count(@third_wallet_in_client, "latest") == {:ok, 2} + end + + test "get_transaction_count!(wallet) works" do + assert ETH.get_transaction_count!(@fourth_wallet_in_client) == 0 + + ETH.send_transaction!(@fourth_wallet_in_client, @second_wallet_in_client, 500) + + Process.sleep(2000) + + ETH.send_transaction!(@fourth_wallet_in_client, @first_wallet_in_client, 2000) + + Process.sleep(2000) + + assert ETH.get_transaction_count!(@fourth_wallet_in_client, "latest") == 2 + end + + test "get_transaction_count(eth_address) works" do + assert ETH.get_transaction_count(@fifth_wallet_in_client.eth_address, "latest") == {:ok, 0} + + ETH.send_transaction!(@fifth_wallet_in_client, @second_wallet_in_client, 500) + + Process.sleep(2000) + + ETH.send_transaction!(@fifth_wallet_in_client, @third_wallet_in_client, 2000) + + Process.sleep(2000) + + assert ETH.get_transaction_count(@fifth_wallet_in_client.eth_address) == {:ok, 2} + end + + test "get_transaction_count!(eth_address) works" do + assert ETH.get_transaction_count!(@sixth_wallet_in_client.eth_address) == 0 + + ETH.send_transaction!(@sixth_wallet_in_client, @second_wallet_in_client, 500) + + Process.sleep(2000) - assert ETH.get_transaction_count!(address_with_balance) == 0 + ETH.send_transaction!(@sixth_wallet_in_client, @third_wallet_in_client, 2000) - wallet_with_balance = @first_client_account_private_key |> ETH.Wallet.create() + Process.sleep(2000) - assert ETH.get_transaction_count!(wallet_with_balance) == 0 + assert ETH.get_transaction_count!(@sixth_wallet_in_client.eth_address) == 2 end end