API account#txlist filterby=from support

Why:

* For API users to be able to get a list of transactions in which a
given address is the 'sender' (address is the 'from' in transaction).

  Example usage:
    ```
      /api?module=account&action&txlist&address={someAddress}&filterby=from
    ```
* Issue link: https://github.com/poanetwork/blockscout/issues/635

This change addresses the need by:

* Editing `where_address_match/3` in `Explorer.Etherscan` to support
`filter_by: "from"` option.
* Editing `put_filter_by/2` in `API.RPC.AddressController` to support
'from' as an allowed value of the `filterby` parameter.
* Editing API docs page per changes mentioned above.
pull/649/head
Sebastian Abondano 6 years ago
parent 1f26961e59
commit a07998547f
  1. 2
      apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/address_controller.ex
  2. 2
      apps/block_scout_web/lib/block_scout_web/etherscan.ex
  3. 73
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/address_controller_test.exs
  4. 4
      apps/explorer/lib/explorer/etherscan.ex
  5. 33
      apps/explorer/test/explorer/etherscan_test.exs

@ -322,7 +322,7 @@ defmodule BlockScoutWeb.API.RPC.AddressController do
defp put_filter_by(options, params) do
case params do
%{"filterby" => filter_by} when filter_by in ["to"] ->
%{"filterby" => filter_by} when filter_by in ["from", "to"] ->
Map.put(options, :filter_by, filter_by)
_ ->

@ -661,7 +661,7 @@ defmodule BlockScoutWeb.Etherscan do
description: """
A string representing the field to filter by. If none is given
it returns transactions that match to, from, or contract address.
Available values: to
Available values: to, from
"""
}
],

@ -985,6 +985,63 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert response["message"] == "OK"
end
test "with filterby=to option", %{conn: conn} do
block = insert(:block)
address = insert(:address)
insert(:transaction, from_address: address)
|> with_block(block)
insert(:transaction, to_address: address)
|> with_block(block)
params = %{
"module" => "account",
"action" => "txlist",
"address" => "#{address.hash}",
"filterby" => "to"
}
assert response =
conn
|> get("/api", params)
|> json_response(200)
assert length(response["result"]) == 1
assert response["status"] == "1"
assert response["message"] == "OK"
end
test "with filterby=from option", %{conn: conn} do
block = insert(:block)
address = insert(:address)
insert(:transaction, from_address: address)
|> with_block(block)
insert(:transaction, from_address: address)
|> with_block(block)
insert(:transaction, to_address: address)
|> with_block(block)
params = %{
"module" => "account",
"action" => "txlist",
"address" => "#{address.hash}",
"filterby" => "from"
}
assert response =
conn
|> get("/api", params)
|> json_response(200)
assert length(response["result"]) == 2
assert response["status"] == "1"
assert response["message"] == "OK"
end
test "supports GET and POST requests", %{conn: conn} do
address = insert(:address)
@ -1706,16 +1763,22 @@ defmodule BlockScoutWeb.API.RPC.AddressControllerTest do
assert AddressController.optional_params(params3) == %{}
end
test "'filterby' value can only be 'to'" do
test "'filterby' value can be 'to' or 'from'" do
params1 = %{"filterby" => "to"}
optional_params = AddressController.optional_params(params1)
optional_params1 = AddressController.optional_params(params1)
assert optional_params.filter_by == "to"
assert optional_params1.filter_by == "to"
params2 = %{"filterby" => "from"}
params2 = %{"filterby" => "invalid"}
optional_params2 = AddressController.optional_params(params2)
assert AddressController.optional_params(params2) == %{}
assert optional_params2.filter_by == "from"
params3 = %{"filterby" => "invalid"}
assert AddressController.optional_params(params3) == %{}
end
test "only includes optional params when they're given" do

@ -226,6 +226,10 @@ defmodule Explorer.Etherscan do
where(query, [t], t.to_address_hash == ^address_hash)
end
defp where_address_match(query, address_hash, %{filter_by: "from"}) do
where(query, [t], t.from_address_hash == ^address_hash)
end
defp where_address_match(query, address_hash, _) do
query
|> where([t], t.to_address_hash == ^address_hash)

@ -379,6 +379,39 @@ defmodule Explorer.EtherscanTest do
assert length(found_transactions) == 0
end
test "with filter_by: 'from' option with one matching transaction" do
address = insert(:address)
:transaction
|> insert(to_address: address)
|> with_block()
:transaction
|> insert(from_address: address)
|> with_block()
options = %{filter_by: "from"}
found_transactions = Etherscan.list_transactions(address.hash, options)
assert length(found_transactions) == 1
end
test "with filter_by: 'from' option with non-matching transaction" do
address = insert(:address)
other_address = insert(:address)
:transaction
|> insert(from_address: other_address, to_address: nil)
|> with_block()
options = %{filter_by: "from"}
found_transactions = Etherscan.list_transactions(address.hash, options)
assert length(found_transactions) == 0
end
end
describe "list_internal_transactions/1" do

Loading…
Cancel
Save