Merge branch 'master' into ab-pagination

pull/1974/head
Ayrat Badykov 6 years ago committed by GitHub
commit 0e82037fb9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 2
      README.md
  3. 8
      apps/block_scout_web/lib/block_scout_web/chain.ex
  4. 46
      apps/block_scout_web/lib/block_scout_web/controllers/address_logs_controller.ex
  5. 7
      apps/block_scout_web/lib/block_scout_web/router.ex
  6. 7
      apps/block_scout_web/lib/block_scout_web/templates/address/_tabs.html.eex
  7. 82
      apps/block_scout_web/lib/block_scout_web/templates/address_logs/index.html.eex
  8. 3
      apps/block_scout_web/lib/block_scout_web/views/address_logs_view.ex
  9. 1
      apps/block_scout_web/lib/block_scout_web/views/address_view.ex
  10. 19
      apps/block_scout_web/priv/gettext/default.pot
  11. 19
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  12. 32
      apps/explorer/lib/explorer/chain.ex
  13. 45
      apps/explorer/test/explorer/chain_test.exs

@ -22,6 +22,7 @@
- [#1920](https://github.com/poanetwork/blockscout/pull/1920) - fix: remove source code fields from list endpoint - [#1920](https://github.com/poanetwork/blockscout/pull/1920) - fix: remove source code fields from list endpoint
- [#1876](https://github.com/poanetwork/blockscout/pull/1876) - async calculate a count of blocks - [#1876](https://github.com/poanetwork/blockscout/pull/1876) - async calculate a count of blocks
- [#1941](https://github.com/poanetwork/blockscout/pull/1941) - feat: add on demand fetching and stale attr to rpc - [#1941](https://github.com/poanetwork/blockscout/pull/1941) - feat: add on demand fetching and stale attr to rpc
- [#1956](https://github.com/poanetwork/blockscout/pull/1956) - add logs tab to address
- [#1933](https://github.com/poanetwork/blockscout/pull/1933) - add eth_BlockNumber json rpc method - [#1933](https://github.com/poanetwork/blockscout/pull/1933) - add eth_BlockNumber json rpc method
- [#1952](https://github.com/poanetwork/blockscout/pull/1952) - feat: exclude empty contracts by default - [#1952](https://github.com/poanetwork/blockscout/pull/1952) - feat: exclude empty contracts by default

@ -64,7 +64,7 @@ Currently available block explorers (i.e. Etherscan and Etherchain) are closed s
* [SafeChain](https://explorer.safechain.io) * [SafeChain](https://explorer.safechain.io)
* [SpringChain](https://explorer.springrole.com/) * [SpringChain](https://explorer.springrole.com/)
* [PIRL](http://pirl.es/) * [PIRL](http://pirl.es/)
* [Petrichor](https://explorer.petrichor-dev.com/) * [Petrichor](https://explorer.petrachor.com/)
* [Ether-1](https://blocks.ether1.wattpool.net/) * [Ether-1](https://blocks.ether1.wattpool.net/)

@ -205,8 +205,12 @@ defmodule BlockScoutWeb.Chain do
%{"block_number" => block_number, "transaction_index" => transaction_index, "index" => index} %{"block_number" => block_number, "transaction_index" => transaction_index, "index" => index}
end end
defp paging_params(%Log{index: index}) do defp paging_params(%Log{index: index} = log) do
%{"index" => index} if Ecto.assoc_loaded?(log.transaction) do
%{"block_number" => log.transaction.block_number, "transaction_index" => log.transaction.index, "index" => index}
else
%{"index" => index}
end
end end
defp paging_params(%Transaction{block_number: nil, inserted_at: inserted_at, hash: hash}) do defp paging_params(%Transaction{block_number: nil, inserted_at: inserted_at, hash: hash}) do

@ -0,0 +1,46 @@
defmodule BlockScoutWeb.AddressLogsController do
@moduledoc """
Manages events logs tab.
"""
import BlockScoutWeb.AddressController, only: [transaction_count: 1, validation_count: 1]
import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1]
alias Explorer.{Chain, Market}
alias Explorer.ExchangeRates.Token
alias Indexer.Fetcher.CoinBalanceOnDemand
use BlockScoutWeb, :controller
def index(conn, %{"address_id" => address_hash_string} = params) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.hash_to_address(address_hash) do
logs_plus_one = Chain.address_to_logs(address, paging_options(params))
{results, next_page} = split_list_by_page(logs_plus_one)
next_page_url =
case next_page_params(next_page, results, params) do
nil ->
nil
next_page_params ->
address_logs_path(conn, :index, address, next_page_params)
end
render(
conn,
"index.html",
address: address,
logs: results,
coin_balance_status: CoinBalanceOnDemand.trigger_fetch(address),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
transaction_count: transaction_count(address),
validation_count: validation_count(address),
next_page_url: next_page_url
)
else
_ ->
not_found(conn)
end
end
end

@ -147,6 +147,13 @@ defmodule BlockScoutWeb.Router do
as: :decompiled_contract as: :decompiled_contract
) )
resources(
"/logs",
AddressLogsController,
only: [:index],
as: :logs
)
resources( resources(
"/contract_verifications", "/contract_verifications",
AddressContractVerificationController, AddressContractVerificationController,

@ -22,6 +22,11 @@
"data-test": "coin_balance_tab_link", "data-test": "coin_balance_tab_link",
to: address_coin_balance_path(@conn, :index, @address.hash) to: address_coin_balance_path(@conn, :index, @address.hash)
) %> ) %>
<%= link(
gettext("Logs"),
class: "card-tab #{tab_status("logs", @conn.request_path)}",
to: address_logs_path(@conn, :index, @address.hash)
) %>
<%= if BlockScoutWeb.AddressView.validator?(@validation_count) do %> <%= if BlockScoutWeb.AddressView.validator?(@validation_count) do %>
<%= link( <%= link(
gettext("Blocks Validated"), gettext("Blocks Validated"),
@ -55,4 +60,4 @@
class: "card-tab #{tab_status("read_contract", @conn.request_path)}") class: "card-tab #{tab_status("read_contract", @conn.request_path)}")
%> %>
<% end %> <% end %>
</div> </div>

@ -0,0 +1,82 @@
<section class="container">
<%= render BlockScoutWeb.AddressView, "overview.html", assigns %>
<div class="card">
<%= render BlockScoutWeb.AddressView, "_tabs.html", assigns %>
<div class="card-body">
<h2 class="card-title"><%= gettext "Logs" %></h2>
<%= if @next_page_url do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, next_page_path: @next_page_url %>
<% end %>
<%= if !@next_page_url do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<%= if Enum.count(@logs) > 0 do %>
<%= for log <- @logs do %>
<div data-test="transaction_log" class="tile tile-muted">
<dl class="row">
<dt class="col-md-2"> <%= gettext "Transaction" %> </dt>
<dd class="col-md-10">
<h3 class="">
<%= link(
log.transaction,
to: transaction_path(@conn, :show, log.transaction),
"data-test": "log_address_link",
"data-address-hash": log.transaction
) %>
</h3>
</dd>
<dt class="col-md-2"><%= gettext "Topics" %></dt>
<dd class="col-md-10">
<div class="raw-transaction-log-topics">
<%= unless is_nil(log.first_topic) do %>
<div class="text-dark">
<span class="text-dark">[0]</span>
<%= log.first_topic %>
</div>
<% end %>
<%= unless is_nil(log.second_topic) do %>
<div class="text-dark">
<span class="">[1] </span>
<%= log.second_topic %>
</div>
<% end %>
<%= unless is_nil(log.third_topic) do %>
<div class="text-dark">
<span>[2]</span>
<%= log.third_topic %>
</div>
<% end %>
<%= unless is_nil(log.fourth_topic) do %>
<div class="text-dark">
<span>[3]</span>
<%= log.fourth_topic %>
</div>
<% end %>
</div>
</dd>
<dt class="col-md-2">
<%= gettext "Data" %>
</dt>
<dd class="col-md-10">
<%= unless is_nil(log.data) do %>
<div class="text-dark raw-transaction-log-data">
<%= log.data %>
</div>
<% end %>
</dd>
</dl>
</div>
<% end %>
<% else %>
<div class="tile tile-muted text-center">
<span><%= gettext "There are no logs for this address." %></span>
</div>
<% end %>
</div>
</div>
</section>

@ -0,0 +1,3 @@
defmodule BlockScoutWeb.AddressLogsView do
use BlockScoutWeb, :view
end

@ -300,6 +300,7 @@ defmodule BlockScoutWeb.AddressView do
defp tab_name(["read_contract"]), do: gettext("Read Contract") defp tab_name(["read_contract"]), do: gettext("Read Contract")
defp tab_name(["coin_balances"]), do: gettext("Coin Balance History") defp tab_name(["coin_balances"]), do: gettext("Coin Balance History")
defp tab_name(["validations"]), do: gettext("Blocks Validated") defp tab_name(["validations"]), do: gettext("Blocks Validated")
defp tab_name(["logs"]), do: gettext("Logs")
def short_hash(%Address{hash: hash}) do def short_hash(%Address{hash: hash}) do
<< <<

@ -187,7 +187,7 @@ msgid "Blocks Indexed"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:27 #: lib/block_scout_web/templates/address/_tabs.html.eex:32
#: lib/block_scout_web/templates/address/overview.html.eex:95 #: lib/block_scout_web/templates/address/overview.html.eex:95
#: lib/block_scout_web/templates/address_validation/index.html.eex:13 #: lib/block_scout_web/templates/address_validation/index.html.eex:13
#: lib/block_scout_web/views/address_view.ex:302 #: lib/block_scout_web/views/address_view.ex:302
@ -215,7 +215,7 @@ msgid "Close"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:37 #: lib/block_scout_web/templates/address/_tabs.html.eex:42
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:165 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:165
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:187 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:187
#: lib/block_scout_web/views/address_view.ex:298 #: lib/block_scout_web/views/address_view.ex:298
@ -334,6 +334,7 @@ msgid "Curl"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:63
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:18 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:18
#: lib/block_scout_web/templates/transaction_log/index.html.eex:67 #: lib/block_scout_web/templates/transaction_log/index.html.eex:67
#: lib/block_scout_web/templates/transaction_log/index.html.eex:133 #: lib/block_scout_web/templates/transaction_log/index.html.eex:133
@ -505,8 +506,11 @@ msgid "Limit"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:26
#: lib/block_scout_web/templates/address_logs/index.html.eex:8
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:17 #: lib/block_scout_web/templates/transaction/_tabs.html.eex:17
#: lib/block_scout_web/templates/transaction_log/index.html.eex:8 #: lib/block_scout_web/templates/transaction_log/index.html.eex:8
#: lib/block_scout_web/views/address_view.ex:303
#: lib/block_scout_web/views/transaction_view.ex:340 #: lib/block_scout_web/views/transaction_view.ex:340
msgid "Logs" msgid "Logs"
msgstr "" msgstr ""
@ -682,7 +686,7 @@ msgid "Query"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:53 #: lib/block_scout_web/templates/address/_tabs.html.eex:58
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:25 #: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:25
#: lib/block_scout_web/views/address_view.ex:300 #: lib/block_scout_web/views/address_view.ex:300
#: lib/block_scout_web/views/tokens/overview_view.ex:37 #: lib/block_scout_web/views/tokens/overview_view.ex:37
@ -874,6 +878,7 @@ msgid "Top Accounts - %{subnetwork} Explorer"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:33
#: lib/block_scout_web/templates/transaction_log/index.html.eex:103 #: lib/block_scout_web/templates/transaction_log/index.html.eex:103
msgid "Topics" msgid "Topics"
msgstr "" msgstr ""
@ -894,6 +899,7 @@ msgid "Total transactions"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:22
#: lib/block_scout_web/views/transaction_view.ex:287 #: lib/block_scout_web/views/transaction_view.ex:287
msgid "Transaction" msgid "Transaction"
msgstr "" msgstr ""
@ -1661,7 +1667,7 @@ msgid "Decompiled Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:47 #: lib/block_scout_web/templates/address/_tabs.html.eex:52
msgid "Decompiled code" msgid "Decompiled code"
msgstr "" msgstr ""
@ -1745,3 +1751,8 @@ msgstr ""
#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:38 #: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:38
msgid "of" msgid "of"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:77
msgid "There are no logs for this address."
msgstr ""

@ -187,7 +187,7 @@ msgid "Blocks Indexed"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:27 #: lib/block_scout_web/templates/address/_tabs.html.eex:32
#: lib/block_scout_web/templates/address/overview.html.eex:95 #: lib/block_scout_web/templates/address/overview.html.eex:95
#: lib/block_scout_web/templates/address_validation/index.html.eex:13 #: lib/block_scout_web/templates/address_validation/index.html.eex:13
#: lib/block_scout_web/views/address_view.ex:302 #: lib/block_scout_web/views/address_view.ex:302
@ -215,7 +215,7 @@ msgid "Close"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:37 #: lib/block_scout_web/templates/address/_tabs.html.eex:42
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:165 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:165
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:187 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:187
#: lib/block_scout_web/views/address_view.ex:298 #: lib/block_scout_web/views/address_view.ex:298
@ -334,6 +334,7 @@ msgid "Curl"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:63
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:18 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:18
#: lib/block_scout_web/templates/transaction_log/index.html.eex:67 #: lib/block_scout_web/templates/transaction_log/index.html.eex:67
#: lib/block_scout_web/templates/transaction_log/index.html.eex:133 #: lib/block_scout_web/templates/transaction_log/index.html.eex:133
@ -505,8 +506,11 @@ msgid "Limit"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:26
#: lib/block_scout_web/templates/address_logs/index.html.eex:8
#: lib/block_scout_web/templates/transaction/_tabs.html.eex:17 #: lib/block_scout_web/templates/transaction/_tabs.html.eex:17
#: lib/block_scout_web/templates/transaction_log/index.html.eex:8 #: lib/block_scout_web/templates/transaction_log/index.html.eex:8
#: lib/block_scout_web/views/address_view.ex:303
#: lib/block_scout_web/views/transaction_view.ex:340 #: lib/block_scout_web/views/transaction_view.ex:340
msgid "Logs" msgid "Logs"
msgstr "" msgstr ""
@ -682,7 +686,7 @@ msgid "Query"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:53 #: lib/block_scout_web/templates/address/_tabs.html.eex:58
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:25 #: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:25
#: lib/block_scout_web/views/address_view.ex:300 #: lib/block_scout_web/views/address_view.ex:300
#: lib/block_scout_web/views/tokens/overview_view.ex:37 #: lib/block_scout_web/views/tokens/overview_view.ex:37
@ -874,6 +878,7 @@ msgid "Top Accounts - %{subnetwork} Explorer"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:33
#: lib/block_scout_web/templates/transaction_log/index.html.eex:103 #: lib/block_scout_web/templates/transaction_log/index.html.eex:103
msgid "Topics" msgid "Topics"
msgstr "" msgstr ""
@ -894,6 +899,7 @@ msgid "Total transactions"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:22
#: lib/block_scout_web/views/transaction_view.ex:287 #: lib/block_scout_web/views/transaction_view.ex:287
msgid "Transaction" msgid "Transaction"
msgstr "" msgstr ""
@ -1661,7 +1667,7 @@ msgid "Decompiled Code"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:47 #: lib/block_scout_web/templates/address/_tabs.html.eex:52
msgid "Decompiled code" msgid "Decompiled code"
msgstr "" msgstr ""
@ -1745,3 +1751,8 @@ msgstr ""
#: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:38 #: lib/block_scout_web/templates/common_components/_pagination_container.html.eex:38
msgid "of" msgid "of"
msgstr "" msgstr ""
#, elixir-format, fuzzy
#: lib/block_scout_web/templates/address_logs/index.html.eex:77
msgid "There are no logs for this address."
msgstr ""

@ -279,6 +279,38 @@ defmodule Explorer.Chain do
|> Enum.take(paging_options.page_size) |> Enum.take(paging_options.page_size)
end end
@spec address_to_logs(Address.t(), [paging_options]) :: [
Log.t()
]
def address_to_logs(
%Address{hash: %Hash{byte_count: unquote(Hash.Address.byte_count())} = address_hash},
options \\ []
)
when is_list(options) do
paging_options = Keyword.get(options, :paging_options) || %PagingOptions{page_size: 50}
{block_number, transaction_index, log_index} = paging_options.key || {BlockNumberCache.max_number(), 0, 0}
query =
from(log in Log,
inner_join: transaction in assoc(log, :transaction),
order_by: [desc: transaction.block_number, desc: transaction.index],
preload: [:transaction],
where:
log.address_hash == ^address_hash and
(transaction.block_number < ^block_number or
(transaction.block_number == ^block_number and transaction.index > ^transaction_index) or
(transaction.block_number == ^block_number and transaction.index == ^transaction_index and
log.index > ^log_index)),
limit: ^paging_options.page_size,
select: log
)
query
|> Repo.all()
|> Enum.take(paging_options.page_size)
end
@doc """ @doc """
Finds all `t:Explorer.Chain.Transaction.t/0`s given the address_hash and the token contract Finds all `t:Explorer.Chain.Transaction.t/0`s given the address_hash and the token contract
address hash. address hash.

@ -50,6 +50,51 @@ defmodule Explorer.ChainTest do
end end
end end
describe "address_to_logs/2" do
test "fetches logs" do
address = insert(:address)
transaction1 =
:transaction
|> insert(to_address: address)
|> with_block()
insert(:log, transaction: transaction1, index: 1, address: address)
transaction2 =
:transaction
|> insert(from_address: address)
|> with_block()
insert(:log, transaction: transaction2, index: 2, address: address)
assert Enum.count(Chain.address_to_logs(address)) == 2
end
test "paginates logs" do
address = insert(:address)
transaction =
:transaction
|> insert(to_address: address)
|> with_block()
log1 = insert(:log, transaction: transaction, index: 1, address: address)
2..51
|> Enum.map(fn index -> insert(:log, transaction: transaction, index: index, address: address) end)
|> Enum.map(& &1.index)
paging_options1 = %PagingOptions{page_size: 1}
[_log] = Chain.address_to_logs(address, paging_options: paging_options1)
paging_options2 = %PagingOptions{page_size: 60, key: {transaction.block_number, transaction.index, log1.index}}
assert Enum.count(Chain.address_to_logs(address, paging_options: paging_options2)) == 50
end
end
describe "address_to_transactions_with_rewards/2" do describe "address_to_transactions_with_rewards/2" do
test "without transactions" do test "without transactions" do
address = insert(:address) address = insert(:address)

Loading…
Cancel
Save