Merge pull request #1727 from poanetwork/ab-logs-pagination

add logs pagination in rpc api
pull/1724/head
Ayrat Badykov 6 years ago committed by GitHub
commit a432fb9503
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      CHANGELOG.md
  2. 6
      apps/block_scout_web/lib/block_scout_web/chain.ex
  3. 16
      apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/transaction_controller.ex
  4. 8
      apps/block_scout_web/lib/block_scout_web/etherscan.ex
  5. 14
      apps/block_scout_web/lib/block_scout_web/views/api/rpc/transaction_view.ex
  6. 56
      apps/block_scout_web/test/block_scout_web/controllers/api/rpc/transaction_controller_test.exs

@ -4,6 +4,8 @@
### Fixes
- [#1727](https://github.com/poanetwork/blockscout/pull/1727) - add logs pagination in rpc api
### Chore

@ -115,7 +115,7 @@ defmodule BlockScoutWeb.Chain do
end
end
def paging_options(%{"index" => index_string}) do
def paging_options(%{"index" => index_string}) when is_binary(index_string) do
with {index, ""} <- Integer.parse(index_string) do
[paging_options: %{@default_paging_options | key: {index}}]
else
@ -124,6 +124,10 @@ defmodule BlockScoutWeb.Chain do
end
end
def paging_options(%{"index" => index}) when is_integer(index) do
[paging_options: %{@default_paging_options | key: {index}}]
end
def paging_options(%{"inserted_at" => inserted_at_string, "hash" => hash_string}) do
with {:ok, inserted_at, _} <- DateTime.from_iso8601(inserted_at_string),
{:ok, hash} <- string_to_transaction_hash(hash_string) do

@ -1,14 +1,24 @@
defmodule BlockScoutWeb.API.RPC.TransactionController do
use BlockScoutWeb, :controller
import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1]
alias Explorer.Chain
def gettxinfo(conn, params) do
with {:txhash_param, {:ok, txhash_param}} <- fetch_txhash(params),
{:format, {:ok, transaction_hash}} <- to_transaction_hash(txhash_param),
{:transaction, {:ok, transaction}} <- transaction_from_hash(transaction_hash) do
logs = Chain.transaction_to_logs(transaction)
render(conn, :gettxinfo, %{transaction: transaction, block_height: Chain.block_height(), logs: logs})
{:transaction, {:ok, transaction}} <- transaction_from_hash(transaction_hash),
paging_options <- paging_options(params) do
logs = Chain.transaction_to_logs(transaction, paging_options)
{logs, next_page} = split_list_by_page(logs)
render(conn, :gettxinfo, %{
transaction: transaction,
block_height: Chain.block_height(),
logs: logs,
next_page_params: next_page_params(next_page, logs, params)
})
else
{:transaction, :error} ->
render(conn, :error, error: "Transaction not found")

@ -1995,7 +1995,13 @@ defmodule BlockScoutWeb.Etherscan do
description: "Transaction hash. Hash of contents of the transaction."
}
],
optional_params: [],
optional_params: [
%{
key: "index",
type: "integer",
description: "A nonnegative integer that represents the log index to be used for pagination."
}
],
responses: [
%{
code: "200",

@ -3,8 +3,13 @@ defmodule BlockScoutWeb.API.RPC.TransactionView do
alias BlockScoutWeb.API.RPC.RPCView
def render("gettxinfo.json", %{transaction: transaction, block_height: block_height, logs: logs}) do
data = prepare_transaction(transaction, block_height, logs)
def render("gettxinfo.json", %{
transaction: transaction,
block_height: block_height,
logs: logs,
next_page_params: next_page_params
}) do
data = prepare_transaction(transaction, block_height, logs, next_page_params)
RPCView.render("show.json", data: data)
end
@ -50,7 +55,7 @@ defmodule BlockScoutWeb.API.RPC.TransactionView do
}
end
defp prepare_transaction(transaction, block_height, logs) do
defp prepare_transaction(transaction, block_height, logs, next_page_params) do
%{
"hash" => "#{transaction.hash}",
"timeStamp" => "#{DateTime.to_unix(transaction.block.timestamp)}",
@ -63,7 +68,8 @@ defmodule BlockScoutWeb.API.RPC.TransactionView do
"input" => "#{transaction.input}",
"gasLimit" => "#{transaction.gas}",
"gasUsed" => "#{transaction.gas_used}",
"logs" => Enum.map(logs, &prepare_log/1)
"logs" => Enum.map(logs, &prepare_log/1),
"next_page_params" => next_page_params
}
end

@ -367,6 +367,59 @@ defmodule BlockScoutWeb.API.RPC.TransactionControllerTest do
refute response["result"]
end
test "paginates logs", %{conn: conn} do
block = insert(:block, hash: "0x30d522bcf2d8e0cabc286e6e40623c475c3bc05d0ec484ea239c103b1ac0ded9", number: 99)
transaction =
:transaction
|> insert(hash: "0x13b6bb8e06322096dc83e8d7e6332ca19919ea642212cd259c6b20e7523a0599")
|> with_block(block, status: :ok)
address = insert(:address)
Enum.each(1..100, fn _ ->
insert(:log,
address: address,
transaction: transaction,
first_topic: "first topic",
second_topic: "second topic"
)
end)
params1 = %{
"module" => "transaction",
"action" => "gettxinfo",
"txhash" => "#{transaction.hash}"
}
assert response1 =
conn
|> get("/api", params1)
|> json_response(200)
assert response1["status"] == "1"
assert response1["message"] == "OK"
assert %{
"action" => "gettxinfo",
"index" => _,
"module" => "transaction",
"txhash" => _
} = response1["result"]["next_page_params"]
params2 = response1["result"]["next_page_params"]
assert response2 =
conn
|> get("/api", params2)
|> json_response(200)
assert response2["status"] == "1"
assert response2["message"] == "OK"
assert is_nil(response2["result"]["next_page_params"])
assert response1["result"]["logs"] != response2["result"]["logs"]
end
test "with a txhash with ok status", %{conn: conn} do
block = insert(:block)
@ -409,7 +462,8 @@ defmodule BlockScoutWeb.API.RPC.TransactionControllerTest do
"data" => "#{log.data}",
"topics" => ["first topic", "second topic", nil, nil]
}
]
],
"next_page_params" => nil
}
assert response =

Loading…
Cancel
Save