Merge branch 'master' into feature/#2038-new-network-selector

* master: (21 commits)
  (update) changelog
  (fix) added style for more types of errors
  make token inventory async
  fix transaction internal transaction controller tests
  fix gettext
  make transacion internal transaction async
  (update) changelog
  (fix) txs errors color
  fix block transaction tests
  fix gettext
  make block transaction async
  fix gettext
  fix transaction token transfer tests
  add transaction token transfer tab async
  fix credo, gettext
  fix transaction log tests
  make transaction logs tab async
  fix: fix to/from filters on tx list pages
  fix address_token_controller tests
  make logs loading async
  ...
pull/2263/head
Gabriel Rodriguez Alsina 6 years ago
commit 493a46c7be
  1. 2
      CHANGELOG.md
  2. 56
      apps/block_scout_web/assets/css/components/_tile.scss
  3. 38
      apps/block_scout_web/lib/block_scout_web/controllers/address_logs_controller.ex
  4. 56
      apps/block_scout_web/lib/block_scout_web/controllers/address_token_controller.ex
  5. 80
      apps/block_scout_web/lib/block_scout_web/controllers/block_transaction_controller.ex
  6. 52
      apps/block_scout_web/lib/block_scout_web/controllers/tokens/inventory_controller.ex
  7. 68
      apps/block_scout_web/lib/block_scout_web/controllers/transaction_internal_transaction_controller.ex
  8. 77
      apps/block_scout_web/lib/block_scout_web/controllers/transaction_log_controller.ex
  9. 76
      apps/block_scout_web/lib/block_scout_web/controllers/transaction_token_transfer_controller.ex
  10. 54
      apps/block_scout_web/lib/block_scout_web/templates/address_logs/_logs.html.eex
  11. 82
      apps/block_scout_web/lib/block_scout_web/templates/address_logs/index.html.eex
  12. 47
      apps/block_scout_web/lib/block_scout_web/templates/address_token/index.html.eex
  13. 40
      apps/block_scout_web/lib/block_scout_web/templates/block_transaction/index.html.eex
  14. 31
      apps/block_scout_web/lib/block_scout_web/templates/tokens/inventory/index.html.eex
  15. 50
      apps/block_scout_web/lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex
  16. 123
      apps/block_scout_web/lib/block_scout_web/templates/transaction_log/_logs.html.eex
  17. 167
      apps/block_scout_web/lib/block_scout_web/templates/transaction_log/index.html.eex
  18. 32
      apps/block_scout_web/lib/block_scout_web/templates/transaction_token_transfer/index.html.eex
  19. 94
      apps/block_scout_web/priv/gettext/default.pot
  20. 94
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  21. 44
      apps/block_scout_web/test/block_scout_web/controllers/address_token_controller_test.exs
  22. 75
      apps/block_scout_web/test/block_scout_web/controllers/block_transaction_controller_test.exs
  23. 34
      apps/block_scout_web/test/block_scout_web/controllers/tokens/inventory_controller_test.exs
  24. 55
      apps/block_scout_web/test/block_scout_web/controllers/transaction_internal_transaction_controller_test.exs
  25. 43
      apps/block_scout_web/test/block_scout_web/controllers/transaction_log_controller_test.exs
  26. 42
      apps/block_scout_web/test/block_scout_web/controllers/transaction_token_transfer_controller_test.exs
  27. 4
      apps/explorer/lib/explorer/chain/token_transfer.ex
  28. 8
      apps/explorer/test/explorer/chain/token_transfer_test.exs

@ -20,6 +20,7 @@
- [#1807](https://github.com/poanetwork/blockscout/pull/1807) - New theming capabilites. - [#1807](https://github.com/poanetwork/blockscout/pull/1807) - New theming capabilites.
### Fixes ### Fixes
- [#2025](https://github.com/poanetwork/blockscout/pull/2025) - Added a new color to display transactions' errors.
- [#2033](https://github.com/poanetwork/blockscout/pull/2033) - Header nav. dropdown active element color issue - [#2033](https://github.com/poanetwork/blockscout/pull/2033) - Header nav. dropdown active element color issue
- [#2019](https://github.com/poanetwork/blockscout/pull/2019) - Fixed the missing tx hashes. - [#2019](https://github.com/poanetwork/blockscout/pull/2019) - Fixed the missing tx hashes.
- [#2020](https://github.com/poanetwork/blockscout/pull/2020) - Fixed a bug triggered when a second click to a selected tab caused the other tabs to hide. - [#2020](https://github.com/poanetwork/blockscout/pull/2020) - Fixed a bug triggered when a second click to a selected tab caused the other tabs to hide.
@ -38,6 +39,7 @@
- [#1960](https://github.com/poanetwork/blockscout/pull/1960) - do not remove bold text in decompiled contacts - [#1960](https://github.com/poanetwork/blockscout/pull/1960) - do not remove bold text in decompiled contacts
- [#1992](https://github.com/poanetwork/blockscout/pull/1992) - fix: support https for wobserver polling - [#1992](https://github.com/poanetwork/blockscout/pull/1992) - fix: support https for wobserver polling
- [#1966](https://github.com/poanetwork/blockscout/pull/1966) - fix: add fields for contract filter performance - [#1966](https://github.com/poanetwork/blockscout/pull/1966) - fix: add fields for contract filter performance
- [#2017](https://github.com/poanetwork/blockscout/pull/2017) - fix: fix to/from filters on tx list pages
- [#2008](https://github.com/poanetwork/blockscout/pull/2008) - add new function clause for xDai network beneficiaries - [#2008](https://github.com/poanetwork/blockscout/pull/2008) - add new function clause for xDai network beneficiaries
- [#2009](https://github.com/poanetwork/blockscout/pull/2009) - addresses page improvements - [#2009](https://github.com/poanetwork/blockscout/pull/2009) - addresses page improvements

@ -11,11 +11,15 @@ $tile-type-unique-token-image-color: $orange !default;
$tile-type-internal-transaction-color: $teal !default; $tile-type-internal-transaction-color: $teal !default;
$tile-type-api-documentation-color: $primary !default; $tile-type-api-documentation-color: $primary !default;
$tile-type-progress-bar-color: $primary !default; $tile-type-progress-bar-color: $primary !default;
$tile-status-error-reason: #ff7986 !default;
$tile-status-awaiting-internal-transactions: $warning !default;
$tile-padding: 1rem; $tile-padding: 1rem;
@mixin generate-tile-block($prefix, $color, $label-color: false) { @mixin generate-tile-block($prefix, $color, $label-color: false) {
&#{ $prefix } {
border-left: 4px solid $color;
.tile-transaction-type-block {
a { a {
@if ($label-color) { @if ($label-color) {
color: $label-color; color: $label-color;
@ -24,9 +28,7 @@ $tile-padding: 1rem;
color: $color; color: $color;
} }
} }
}
&.tile-type-#{ $prefix } {
border-left: 4px solid $color;
.tile-label { .tile-label {
@if ($label-color) { @if ($label-color) {
@ -182,18 +184,20 @@ $tile-padding: 1rem;
line-height: 1.4rem; line-height: 1.4rem;
padding: $tile-padding; padding: $tile-padding;
@include generate-tile-block('block', $tile-type-block-color, darken($tile-type-block-color, 20%)); @include generate-tile-block('.tile-type-block', $tile-type-block-color, darken($tile-type-block-color, 20%));
@include generate-tile-block('uncle', $tile-type-uncle-color); @include generate-tile-block('.tile-type-uncle', $tile-type-uncle-color);
@include generate-tile-block('reorg', $tile-type-reorg-color); @include generate-tile-block('.tile-type-reorg', $tile-type-reorg-color);
@include generate-tile-block('emission-reward', $tile-type-emission-reward-color); @include generate-tile-block('.tile-type-emission-reward', $tile-type-emission-reward-color);
@include generate-tile-block('transaction', $tile-type-transaction-color); @include generate-tile-block('.tile-type-transaction', $tile-type-transaction-color);
@include generate-tile-block('contract-call', $tile-type-contract-call-color); @include generate-tile-block('.tile-type-contract-call', $tile-type-contract-call-color);
@include generate-tile-block('contract-creation', $tile-type-contract-creation-color); @include generate-tile-block('.tile-type-contract-creation', $tile-type-contract-creation-color);
@include generate-tile-block('token-transfer', $tile-type-token-transfer-color); @include generate-tile-block('.tile-type-token-transfer', $tile-type-token-transfer-color);
@include generate-tile-block('unique-token', $tile-type-unique-token-color); @include generate-tile-block('.tile-type-unique-token', $tile-type-unique-token-color);
@include generate-tile-block('unique-token-image', $tile-type-unique-token-image-color); @include generate-tile-block('.tile-type-unique-token-image', $tile-type-unique-token-image-color);
@include generate-tile-block('internal-transaction', $tile-type-internal-transaction-color); @include generate-tile-block('.tile-type-internal-transaction', $tile-type-internal-transaction-color);
@include generate-tile-block('api-documentation', $tile-type-api-documentation-color); @include generate-tile-block('.tile-type-api-documentation', $tile-type-api-documentation-color);
@include generate-tile-block('[class*="status--error"]', $tile-status-error-reason);
@include generate-tile-block('.tile-status--awaiting-internal-transactions', $tile-status-awaiting-internal-transactions);
&.n-p { &.n-p {
padding: 0; padding: 0;
@ -256,26 +260,6 @@ $tile-padding: 1rem;
width: 100%; width: 100%;
} }
.tile-status--error--reason {
border-bottom: 2px solid lighten($danger, 10%);
border-right: 2px solid lighten($danger, 10%);
border-top: 2px solid lighten($danger, 10%);
.tile-status-label {
color: $danger;
}
}
.tile-status--awaiting-internal-transactions {
border-bottom: 2px solid lighten($warning, 10%);
border-right: 2px solid lighten($warning, 10%);
border-top: 2px solid lighten($warning, 10%);
.tile-status-label {
color: $warning;
}
}
/* Progress bar */ /* Progress bar */
.progress { .progress {
background-color: #f5f6fa; background-color: #f5f6fa;

@ -6,13 +6,15 @@ defmodule BlockScoutWeb.AddressLogsController do
import BlockScoutWeb.AddressController, only: [transaction_count: 1, validation_count: 1] 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] import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1]
alias BlockScoutWeb.AddressLogsView
alias Explorer.{Chain, Market} alias Explorer.{Chain, Market}
alias Explorer.ExchangeRates.Token alias Explorer.ExchangeRates.Token
alias Indexer.Fetcher.CoinBalanceOnDemand alias Indexer.Fetcher.CoinBalanceOnDemand
alias Phoenix.View
use BlockScoutWeb, :controller use BlockScoutWeb, :controller
def index(conn, %{"address_id" => address_hash_string} = params) do def index(conn, %{"address_id" => address_hash_string, "type" => "JSON"} = params) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.hash_to_address(address_hash) do {:ok, address} <- Chain.hash_to_address(address_hash) do
logs_plus_one = Chain.address_to_logs(address, paging_options(params)) logs_plus_one = Chain.address_to_logs(address, paging_options(params))
@ -24,19 +26,45 @@ defmodule BlockScoutWeb.AddressLogsController do
nil nil
next_page_params -> next_page_params ->
address_logs_path(conn, :index, address, next_page_params) address_logs_path(conn, :index, address, Map.delete(next_page_params, "type"))
end end
items =
results
|> Enum.map(fn log ->
View.render_to_string(
AddressLogsView,
"_logs.html",
log: log,
conn: conn
)
end)
json(
conn,
%{
items: items,
next_page_path: next_page_url
}
)
else
_ ->
not_found(conn)
end
end
def index(conn, %{"address_id" => address_hash_string}) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.hash_to_address(address_hash) do
render( render(
conn, conn,
"index.html", "index.html",
address: address, address: address,
logs: results, current_path: current_path(conn),
coin_balance_status: CoinBalanceOnDemand.trigger_fetch(address), coin_balance_status: CoinBalanceOnDemand.trigger_fetch(address),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
transaction_count: transaction_count(address), transaction_count: transaction_count(address),
validation_count: validation_count(address), validation_count: validation_count(address)
next_page_url: next_page_url
) )
else else
_ -> _ ->

@ -1,29 +1,71 @@
defmodule BlockScoutWeb.AddressTokenController do defmodule BlockScoutWeb.AddressTokenController do
use BlockScoutWeb, :controller use BlockScoutWeb, :controller
import BlockScoutWeb.AddressController, only: [transaction_count: 1, validation_count: 1]
import BlockScoutWeb.Chain, only: [next_page_params: 3, paging_options: 1, split_list_by_page: 1]
alias BlockScoutWeb.AddressTokenView
alias Explorer.{Chain, Market} alias Explorer.{Chain, Market}
alias Explorer.ExchangeRates.Token alias Explorer.ExchangeRates.Token
alias Indexer.Fetcher.CoinBalanceOnDemand alias Indexer.Fetcher.CoinBalanceOnDemand
alias Phoenix.View
import BlockScoutWeb.AddressController, only: [transaction_count: 1, validation_count: 1] def index(conn, %{"address_id" => address_hash_string, "type" => "JSON"} = params) do
import BlockScoutWeb.Chain, only: [next_page_params: 3, paging_options: 1, split_list_by_page: 1]
def index(conn, %{"address_id" => address_hash_string} = params) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.hash_to_address(address_hash) do {:ok, address} <- Chain.hash_to_address(address_hash) do
tokens_plus_one = Chain.address_tokens_with_balance(address_hash, paging_options(params)) tokens_plus_one = Chain.address_tokens_with_balance(address_hash, paging_options(params))
{tokens, next_page} = split_list_by_page(tokens_plus_one) {tokens, next_page} = split_list_by_page(tokens_plus_one)
next_page_path =
case next_page_params(next_page, tokens, params) do
nil ->
nil
next_page_params ->
address_token_path(conn, :index, address, Map.delete(next_page_params, "type"))
end
items =
tokens
|> Market.add_price()
|> Enum.map(fn token ->
View.render_to_string(
AddressTokenView,
"_tokens.html",
token: token,
address: address,
conn: conn
)
end)
json(
conn,
%{
items: items,
next_page_path: next_page_path
}
)
else
:error ->
unprocessable_entity(conn)
{:error, :not_found} ->
not_found(conn)
end
end
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
render( render(
conn, conn,
"index.html", "index.html",
address: address, address: address,
current_path: current_path(conn),
coin_balance_status: CoinBalanceOnDemand.trigger_fetch(address), coin_balance_status: CoinBalanceOnDemand.trigger_fetch(address),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
transaction_count: transaction_count(address), transaction_count: transaction_count(address),
validation_count: validation_count(address), validation_count: validation_count(address)
next_page_params: next_page_params(next_page, tokens, params),
tokens: Market.add_price(tokens)
) )
else else
:error -> :error ->

@ -5,20 +5,14 @@ defmodule BlockScoutWeb.BlockTransactionController do
only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1] only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1]
import Explorer.Chain, only: [hash_to_block: 2, number_to_block: 2, string_to_block_hash: 1] import Explorer.Chain, only: [hash_to_block: 2, number_to_block: 2, string_to_block_hash: 1]
alias BlockScoutWeb.TransactionView
alias Explorer.Chain alias Explorer.Chain
alias Phoenix.View
def index(conn, %{"block_hash_or_number" => formatted_block_hash_or_number} = params) do def index(conn, %{"block_hash_or_number" => formatted_block_hash_or_number, "type" => "JSON"} = params) do
with {:ok, block} <- with {:ok, block} <-
param_block_hash_or_number_to_block(formatted_block_hash_or_number, param_block_hash_or_number_to_block(formatted_block_hash_or_number, []) do
necessity_by_association: %{
[miner: :names] => :required,
:uncles => :optional,
:nephews => :optional,
:rewards => :optional
}
) do
block_transaction_count = Chain.block_to_transaction_count(block)
full_options = full_options =
Keyword.merge( Keyword.merge(
[ [
@ -36,13 +30,73 @@ defmodule BlockScoutWeb.BlockTransactionController do
{transactions, next_page} = split_list_by_page(transactions_plus_one) {transactions, next_page} = split_list_by_page(transactions_plus_one)
next_page_path =
case next_page_params(next_page, transactions, params) do
nil ->
nil
next_page_params ->
block_transaction_path(
conn,
:index,
block,
Map.delete(next_page_params, "type")
)
end
items =
transactions
|> Enum.map(fn transaction ->
View.render_to_string(
TransactionView,
"_tile.html",
transaction: transaction
)
end)
json(
conn,
%{
items: items,
next_page_path: next_page_path
}
)
else
{:error, {:invalid, :hash}} ->
not_found(conn)
{:error, {:invalid, :number}} ->
not_found(conn)
{:error, :not_found} ->
conn
|> put_status(:not_found)
|> render(
"404.html",
block: nil,
block_above_tip: block_above_tip(formatted_block_hash_or_number)
)
end
end
def index(conn, %{"block_hash_or_number" => formatted_block_hash_or_number}) do
with {:ok, block} <-
param_block_hash_or_number_to_block(formatted_block_hash_or_number,
necessity_by_association: %{
[miner: :names] => :required,
:uncles => :optional,
:nephews => :optional,
:rewards => :optional
}
) do
block_transaction_count = Chain.block_to_transaction_count(block)
render( render(
conn, conn,
"index.html", "index.html",
block: block, block: block,
block_transaction_count: block_transaction_count, block_transaction_count: block_transaction_count,
next_page_params: next_page_params(next_page, transactions, params), current_path: current_path(conn)
transactions: transactions
) )
else else
{:error, {:invalid, :hash}} -> {:error, {:invalid, :hash}} ->

@ -1,12 +1,14 @@
defmodule BlockScoutWeb.Tokens.InventoryController do defmodule BlockScoutWeb.Tokens.InventoryController do
use BlockScoutWeb, :controller use BlockScoutWeb, :controller
alias BlockScoutWeb.Tokens.InventoryView
alias Explorer.{Chain, Market} alias Explorer.{Chain, Market}
alias Explorer.Chain.TokenTransfer alias Explorer.Chain.TokenTransfer
alias Phoenix.View
import BlockScoutWeb.Chain, only: [split_list_by_page: 1, default_paging_options: 0] import BlockScoutWeb.Chain, only: [split_list_by_page: 1, default_paging_options: 0]
def index(conn, %{"token_id" => address_hash_string} = params) do def index(conn, %{"token_id" => address_hash_string, "type" => "JSON"} = params) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, token} <- Chain.token_from_address_hash(address_hash) do {:ok, token} <- Chain.token_from_address_hash(address_hash) do
unique_tokens = unique_tokens =
@ -17,14 +19,56 @@ defmodule BlockScoutWeb.Tokens.InventoryController do
{unique_tokens_paginated, next_page} = split_list_by_page(unique_tokens) {unique_tokens_paginated, next_page} = split_list_by_page(unique_tokens)
next_page_path =
case unique_tokens_next_page(next_page, unique_tokens_paginated, params) do
nil ->
nil
next_page_params ->
token_inventory_path(
conn,
:index,
address_hash_string,
Map.delete(next_page_params, "type")
)
end
items =
unique_tokens_paginated
|> Enum.map(fn token_transfer ->
View.render_to_string(
InventoryView,
"_token.html",
token_transfer: token_transfer
)
end)
json(
conn,
%{
items: items,
next_page_path: next_page_path
}
)
else
:error ->
not_found(conn)
{:error, :not_found} ->
not_found(conn)
end
end
def index(conn, %{"token_id" => address_hash_string}) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, token} <- Chain.token_from_address_hash(address_hash) do
render( render(
conn, conn,
"index.html", "index.html",
current_path: current_path(conn),
token: Market.add_price(token), token: Market.add_price(token),
unique_tokens: unique_tokens_paginated,
total_token_transfers: Chain.count_token_transfers_from_token_hash(address_hash), total_token_transfers: Chain.count_token_transfers_from_token_hash(address_hash),
total_token_holders: token.holder_count || Chain.count_token_holders_from_token_hash(address_hash), total_token_holders: token.holder_count || Chain.count_token_holders_from_token_hash(address_hash)
next_page_params: unique_tokens_next_page(next_page, unique_tokens_paginated, params)
) )
else else
:error -> :error ->

@ -3,11 +3,12 @@ defmodule BlockScoutWeb.TransactionInternalTransactionController do
import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1] import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1]
alias BlockScoutWeb.TransactionView alias BlockScoutWeb.{InternalTransactionView, TransactionView}
alias Explorer.{Chain, Market} alias Explorer.{Chain, Market}
alias Explorer.ExchangeRates.Token alias Explorer.ExchangeRates.Token
alias Phoenix.View
def index(conn, %{"transaction_id" => hash_string} = params) do def index(conn, %{"transaction_id" => hash_string, "type" => "JSON"} = params) do
with {:ok, hash} <- Chain.string_to_transaction_hash(hash_string), with {:ok, hash} <- Chain.string_to_transaction_hash(hash_string),
{:ok, transaction} <- {:ok, transaction} <-
Chain.hash_to_transaction( Chain.hash_to_transaction(
@ -37,14 +38,73 @@ defmodule BlockScoutWeb.TransactionInternalTransactionController do
{internal_transactions, next_page} = split_list_by_page(internal_transactions_plus_one) {internal_transactions, next_page} = split_list_by_page(internal_transactions_plus_one)
next_page_path =
case next_page_params(next_page, internal_transactions, params) do
nil ->
nil
next_page_params ->
transaction_internal_transaction_path(
conn,
:index,
transaction,
Map.delete(next_page_params, "type")
)
end
items =
internal_transactions
|> Enum.map(fn internal_transaction ->
View.render_to_string(
InternalTransactionView,
"_tile.html",
internal_transaction: internal_transaction
)
end)
json(
conn,
%{
items: items,
next_page_path: next_page_path
}
)
else
:error ->
conn
|> put_status(422)
|> put_view(TransactionView)
|> render("invalid.html", transaction_hash: hash_string)
{:error, :not_found} ->
conn
|> put_status(404)
|> put_view(TransactionView)
|> render("not_found.html", transaction_hash: hash_string)
end
end
def index(conn, %{"transaction_id" => hash_string}) do
with {:ok, hash} <- Chain.string_to_transaction_hash(hash_string),
{:ok, transaction} <-
Chain.hash_to_transaction(
hash,
necessity_by_association: %{
:block => :optional,
[created_contract_address: :names] => :optional,
[from_address: :names] => :optional,
[to_address: :names] => :optional,
[to_address: :smart_contract] => :optional,
:token_transfers => :optional
}
) do
render( render(
conn, conn,
"index.html", "index.html",
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
internal_transactions: internal_transactions, current_path: current_path(conn),
block_height: Chain.block_height(), block_height: Chain.block_height(),
show_token_transfers: Chain.transaction_has_token_transfers?(hash), show_token_transfers: Chain.transaction_has_token_transfers?(hash),
next_page_params: next_page_params(next_page, internal_transactions, params),
transaction: transaction transaction: transaction
) )
else else

@ -3,24 +3,15 @@ defmodule BlockScoutWeb.TransactionLogController do
import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1] import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1]
alias BlockScoutWeb.TransactionView alias BlockScoutWeb.{TransactionLogView, TransactionView}
alias Explorer.{Chain, Market} alias Explorer.{Chain, Market}
alias Explorer.ExchangeRates.Token alias Explorer.ExchangeRates.Token
alias Phoenix.View
def index(conn, %{"transaction_id" => transaction_hash_string} = params) do def index(conn, %{"transaction_id" => transaction_hash_string, "type" => "JSON"} = params) do
with {:ok, transaction_hash} <- Chain.string_to_transaction_hash(transaction_hash_string), with {:ok, transaction_hash} <- Chain.string_to_transaction_hash(transaction_hash_string),
{:ok, transaction} <- {:ok, transaction} <-
Chain.hash_to_transaction( Chain.hash_to_transaction(transaction_hash) do
transaction_hash,
necessity_by_association: %{
:block => :optional,
[created_contract_address: :names] => :optional,
[from_address: :names] => :required,
[to_address: :names] => :optional,
[to_address: :smart_contract] => :optional,
:token_transfers => :optional
}
) do
full_options = full_options =
Keyword.merge( Keyword.merge(
[ [
@ -35,13 +26,69 @@ defmodule BlockScoutWeb.TransactionLogController do
{logs, next_page} = split_list_by_page(logs_plus_one) {logs, next_page} = split_list_by_page(logs_plus_one)
next_page_url =
case next_page_params(next_page, logs, params) do
nil ->
nil
next_page_params ->
transaction_log_path(conn, :index, transaction, Map.delete(next_page_params, "type"))
end
items =
logs
|> Enum.map(fn log ->
View.render_to_string(
TransactionLogView,
"_logs.html",
log: log,
conn: conn,
transaction: transaction
)
end)
json(
conn,
%{
items: items,
next_page_path: next_page_url
}
)
else
:error ->
conn
|> put_status(422)
|> put_view(TransactionView)
|> render("invalid.html", transaction_hash: transaction_hash_string)
{:error, :not_found} ->
conn
|> put_status(404)
|> put_view(TransactionView)
|> render("not_found.html", transaction_hash: transaction_hash_string)
end
end
def index(conn, %{"transaction_id" => transaction_hash_string}) do
with {:ok, transaction_hash} <- Chain.string_to_transaction_hash(transaction_hash_string),
{:ok, transaction} <-
Chain.hash_to_transaction(
transaction_hash,
necessity_by_association: %{
:block => :optional,
[created_contract_address: :names] => :optional,
[from_address: :names] => :required,
[to_address: :names] => :optional,
[to_address: :smart_contract] => :optional,
:token_transfers => :optional
}
) do
render( render(
conn, conn,
"index.html", "index.html",
logs: logs,
block_height: Chain.block_height(), block_height: Chain.block_height(),
show_token_transfers: Chain.transaction_has_token_transfers?(transaction_hash), show_token_transfers: Chain.transaction_has_token_transfers?(transaction_hash),
next_page_params: next_page_params(next_page, logs, params), current_path: current_path(conn),
transaction: transaction, transaction: transaction,
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null() exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null()
) )

@ -3,24 +3,15 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do
import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1] import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1]
alias BlockScoutWeb.TransactionView alias BlockScoutWeb.{TransactionTokenTransferView, TransactionView}
alias Explorer.{Chain, Market} alias Explorer.{Chain, Market}
alias Explorer.ExchangeRates.Token alias Explorer.ExchangeRates.Token
alias Phoenix.View
def index(conn, %{"transaction_id" => hash_string} = params) do def index(conn, %{"transaction_id" => hash_string, "type" => "JSON"} = params) do
with {:ok, hash} <- Chain.string_to_transaction_hash(hash_string), with {:ok, hash} <- Chain.string_to_transaction_hash(hash_string),
{:ok, transaction} <- {:ok, transaction} <-
Chain.hash_to_transaction( Chain.hash_to_transaction(hash) do
hash,
necessity_by_association: %{
:block => :optional,
[created_contract_address: :names] => :optional,
[from_address: :names] => :optional,
[to_address: :names] => :optional,
[to_address: :smart_contract] => :optional,
:token_transfers => :optional
}
) do
full_options = full_options =
Keyword.merge( Keyword.merge(
[ [
@ -37,13 +28,68 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do
{token_transfers, next_page} = split_list_by_page(token_transfers_plus_one) {token_transfers, next_page} = split_list_by_page(token_transfers_plus_one)
next_page_url =
case next_page_params(next_page, token_transfers, params) do
nil ->
nil
next_page_params ->
transaction_token_transfer_path(conn, :index, transaction, Map.delete(next_page_params, "type"))
end
items =
token_transfers
|> Enum.map(fn transfer ->
View.render_to_string(
TransactionTokenTransferView,
"_token_transfer.html",
token_transfer: transfer,
conn: conn
)
end)
json(
conn,
%{
items: items,
next_page_path: next_page_url
}
)
else
:error ->
conn
|> put_status(422)
|> put_view(TransactionView)
|> render("invalid.html", transaction_hash: hash_string)
{:error, :not_found} ->
conn
|> put_status(404)
|> put_view(TransactionView)
|> render("not_found.html", transaction_hash: hash_string)
end
end
def index(conn, %{"transaction_id" => hash_string}) do
with {:ok, hash} <- Chain.string_to_transaction_hash(hash_string),
{:ok, transaction} <-
Chain.hash_to_transaction(
hash,
necessity_by_association: %{
:block => :optional,
[created_contract_address: :names] => :optional,
[from_address: :names] => :optional,
[to_address: :names] => :optional,
[to_address: :smart_contract] => :optional,
:token_transfers => :optional
}
) do
render( render(
conn, conn,
"index.html", "index.html",
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
block_height: Chain.block_height(), block_height: Chain.block_height(),
next_page_params: next_page_params(next_page, token_transfers, params), current_path: current_path(conn),
token_transfers: token_transfers,
show_token_transfers: true, show_token_transfers: true,
transaction: transaction transaction: transaction
) )

@ -0,0 +1,54 @@
<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>

@ -3,80 +3,26 @@
<div class="card"> <div class="card">
<%= render BlockScoutWeb.AddressView, "_tabs.html", assigns %> <%= render BlockScoutWeb.AddressView, "_tabs.html", assigns %>
<div class="card-body"> <div class="card-body" data-async-load data-async-listing="<%= @current_path %>">
<h2 class="card-title"><%= gettext "Logs" %></h2> <h2 class="card-title"><%= gettext "Logs" %></h2>
<%= if @next_page_url do %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<%= 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 %> <button data-error-message class="alert alert-danger col-12 text-left" style="display: none;">
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %> <span href="#" class="alert-link"><%= gettext("Something went wrong, click to reload.") %></span>
<% end %> </button>
<%= if Enum.count(@logs) > 0 do %> <div data-empty-response-message style="display: none;">
<%= for log <- @logs do %> <div class="tile tile-muted text-center" data-selector="empty-logs-list">
<div data-test="transaction_log" class="tile tile-muted"> <%= gettext "There are no logs for this address." %>
<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> </div>
<% end %>
</dd>
</dl>
</div> </div>
<% end %>
<% else %> <div data-items></div>
<div class="tile tile-muted text-center">
<span><%= gettext "There are no logs for this address." %></span> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
</div>
<% end %>
</div> </div>
</div> </div>
</section> </section>

@ -4,49 +4,24 @@
<section> <section>
<div class="card"> <div class="card">
<%= render BlockScoutWeb.AddressView, "_tabs.html", assigns %> <%= render BlockScoutWeb.AddressView, "_tabs.html", assigns %>
<div class="card-body"> <div class="card-body" data-async-load data-async-listing="<%= @current_path %>">
<h2 class="card-title"><%= gettext "Tokens" %></h2> <h2 class="card-title"><%= gettext "Tokens" %></h2>
<%= if @next_page_params do %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, next_page_path: address_token_path(@conn, :index, @address, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %> <button data-error-message class="alert alert-danger col-12 text-left" style="display: none;">
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %> <span href="#" class="alert-link"><%= gettext("Something went wrong, click to reload.") %></span>
<% end %> </button>
<%= if Enum.any?(@tokens) do %> <div data-empty-response-message style="display: none;">
<%= for token <- @tokens do %> <div class="tile tile-muted text-center" data-selector="empty-token-list">
<%= render "_tokens.html", conn: @conn, token: token, address: @address %> <%= gettext "There are no tokens for this address." %>
<% end %> </div>
<% else %>
<div class="tile tile-muted text-center">
<span><%= gettext "There are no tokens for this address." %></span>
</div> </div>
<% end %>
<%= if @next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, next_page_path: address_token_path(@conn, :index, @address, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %> <div data-items></div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<!-- <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<%= if @next_page_params do %>
<%= link(
gettext("Next"),
class: "button button-secondary button-sm float-right mt-3",
to: address_token_path(
@conn,
:index,
@address,
@next_page_params
)
) %>
<% end %>
-->
</div> </div>
</div> </div>
</section> </section>

@ -13,38 +13,26 @@
) )
%> %>
</div> </div>
<div class="card-body">
<div class="card-body" data-async-load data-async-listing="<%= @current_path %>">
<h2 class="card-title"><%= gettext "Transactions" %></h2> <h2 class="card-title"><%= gettext "Transactions" %></h2>
<%= if @next_page_params do %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, next_page_path: transaction_path(@conn, :index, @next_page_params) %>
<% end %> <button data-error-message class="alert alert-danger col-12 text-left" style="display: none;">
<span href="#" class="alert-link"><%= gettext("Something went wrong, click to reload.") %></span>
<%= if !@next_page_params do %> </button>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %>
<% end %> <div data-empty-response-message style="display: none;">
<div class="tile tile-muted text-center" data-selector="empty-transactions-list">
<%= if Enum.count(@transactions) > 0 do %> <%= gettext "There are no transactions for this block." %>
<span data-selector="transactions-list"> </div>
<%= for transaction <- @transactions do %>
<%= render BlockScoutWeb.TransactionView, "_tile.html", transaction: transaction %>
<% end %>
</span>
<% else %>
<div class="tile tile-muted text-center">
<span data-selector="empty-transactions-list"><%= gettext "There are no transactions for this block." %></span>
</div> </div>
<% end %>
<%= if @next_page_params do %> <div data-items></div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, next_page_path: transaction_path(@conn, :index, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
</div> </div>
</div>
</section> </section>
</section> </section>

@ -12,28 +12,25 @@
<div class="card"> <div class="card">
<%= render OverviewView, "_tabs.html", assigns %> <%= render OverviewView, "_tabs.html", assigns %>
<div class="card-body"> <div class="card-body" data-async-load data-async-listing="<%= @current_path %>">
<h2 class="card-title"><%= gettext "Inventory" %></h2> <h2 class="card-title"><%= gettext "Inventory" %></h2>
<%= if Enum.any?(@unique_tokens) do %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<%= for token_transfer <- @unique_tokens do %>
<%= render "_token.html", token_transfer: token_transfer %> <button data-error-message class="alert alert-danger col-12 text-left" style="display: none;">
<% end %> <span href="#" class="alert-link"><%= gettext("Something went wrong, click to reload.") %></span>
<% else %> </button>
<div class="tile tile-muted text-center">
<span data-selector="empty-transactions-list"> <div data-empty-response-message style="display: none;">
<div class="tile tile-muted text-center" data-selector="empty-token-list">
<%= gettext "There are no tokens." %> <%= gettext "There are no tokens." %>
</span>
</div> </div>
<% end %> </div>
<div data-items></div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<%= if @next_page_params do %>
<%= link(
gettext("Next Page"),
class: "button button-secondary button-small float-right mt-4",
to: token_inventory_path(@conn, :index, @token.contract_address_hash, @next_page_params)
) %>
<% end %>
</div> </div>
</div> </div>
</section> </section>

@ -2,49 +2,23 @@
<%= render BlockScoutWeb.TransactionView, "overview.html", assigns %> <%= render BlockScoutWeb.TransactionView, "overview.html", assigns %>
<div class="card"> <div class="card">
<%= render BlockScoutWeb.TransactionView, "_tabs.html", assigns %> <%= render BlockScoutWeb.TransactionView, "_tabs.html", assigns %>
<div class="card-body"> <div class="card-body" data-async-load data-async-listing="<%= @current_path %>">
<h2 class="card-title"><%= gettext "Internal Transactions" %></h2> <h1 class="card-title"><%= gettext "Internal Transactions" %></h1>
<%= if @next_page_params do %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, next_page_path: transaction_internal_transaction_path(@conn, :index, @transaction, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %> <button data-error-message class="alert alert-danger col-12 text-left" style="display: none;">
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %> <span href="#" class="alert-link"><%= gettext("Something went wrong, click to reload.") %></span>
<% end %> </button>
<div data-empty-response-message style="display: none;">
<%= if Enum.count(@internal_transactions) > 0 do %> <div class="tile tile-muted text-center" data-selector="empty-logs-list">
<%= for internal_transaction <- @internal_transactions do %> <%= gettext "There are no internal transactions for this transaction." %>
<%= render BlockScoutWeb.InternalTransactionView, "_tile.html", internal_transaction: internal_transaction %> </div>
<% end %>
<% else %>
<div class="tile tile-muted text-center">
<span><%= gettext "There are no internal transactions for this transaction." %></span>
</div> </div>
<% end %>
<%= if @next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, next_page_path: transaction_internal_transaction_path(@conn, :index, @transaction, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %> <div data-items></div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<!-- <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<%= if @next_page_params do %>
<%= link(
gettext("Newer"),
class: "button button-secondary button-sm float-right mt-3",
to: transaction_internal_transaction_path(
@conn,
:index,
@transaction,
@next_page_params
)
) %>
<% end %>
-->
</div> </div>
</div> </div>
</section> </section>

@ -0,0 +1,123 @@
<div data-test="transaction_log" class="tile tile-muted">
<dl class="row">
<dt class="col-md-1"> <%= gettext "Address" %> </dt>
<dd class="col-md-11">
<h3 class="">
<%= link(
@log.address,
to: address_path(@conn, :show, @log.address),
"data-test": "log_address_link",
"data-address-hash": @log.address
) %>
</h3>
</dd>
<dt class="col-md-1"><%= gettext "Decoded" %></dt>
<dd class="col-md-11">
<%= case decode(@log, @transaction) do %>
<% {:error, :contract_not_verified} -> %>
<div class="alert alert-info">
<%= gettext "To see decoded input data, the contract must be verified." %>
<%= case @transaction do %>
<% %{to_address: %{hash: hash}} -> %>
<%= gettext "Verify the contract " %><a href="<%= address_verify_contract_path(@conn, :new, hash)%>"><%= gettext "here" %></a>
<% _ -> %>
<%= nil %>
<% end %>
</div>
<% {:error, :could_not_decode} -> %>
<div class="alert alert-danger">
<%= gettext "Failed to decode log data." %>
</div>
<% {:ok, method_id, text, mapping} -> %>
<table summary="Transaction Info" class="table thead-light table-bordered transaction-input-table">
<tr>
<td>Method Id</td>
<td colspan="3"><code>0x<%= method_id %></code></td>
</tr>
<tr>
<td>Call</td>
<td colspan="3"><code><%= text %></code></td>
</tr>
</table>
<table style="color: black;" summary="<%= gettext "Log Data" %>" class="table thead-light table-bordered table-responsive">
<tr>
<th scope="col"></th>
<th scope="col"><%= gettext "Name" %></th>
<th scope="col"><%= gettext "Type" %></th>
<th scope="col"><%= gettext "Indexed?" %></th>
<th scope="col"><%= gettext "Data" %></th>
<tr>
<%= for {name, type, indexed?, value} <- mapping do %>
<tr>
<th scope="row">
<%= case BlockScoutWeb.ABIEncodedValueView.copy_text(type, value) do %>
<% :error -> %>
<%= nil %>
<% copy_text -> %>
<span
aria-label='<%= gettext "Copy Value" %>'
class="btn-copy-ico"
data-clipboard-text="<%= copy_text %>"
data-placement="top"
data-toggle="tooltip"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32.5 32.5" width="32" height="32">
<path fill-rule="evenodd" d="M23.5 20.5a1 1 0 0 1-1-1v-9h-9a1 1 0 0 1 0-2h10a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1zm-3-7v10a1 1 0 0 1-1 1h-10a1 1 0 0 1-1-1v-10a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1zm-2 1h-8v8h8v-8z"/>
</svg>
</span>
<% end %>
</th>
<td><%= name %></td>
<td><%= type %></td>
<td><%= indexed? %></td>
<td>
<pre class="transaction-input-text tile"><code><%= BlockScoutWeb.ABIEncodedValueView.value_html(type, value) %></code></pre>
</td>
</tr>
<% end %>
</table>
<% _ -> %>
<%= nil %>
<% end %>
<dt class="col-md-1"><%= gettext "Topics" %></dt>
<dd class="col-md-11">
<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-1">
<%= gettext "Data" %>
</dt>
<dd class="col-md-11">
<%= unless is_nil(@log.data) do %>
<div class="text-dark raw-transaction-log-data">
<%= @log.data %>
</div>
<% end %>
</dd>
</dl>
</div>

@ -4,172 +4,25 @@
<div class="card"> <div class="card">
<%= render BlockScoutWeb.TransactionView, "_tabs.html", assigns %> <%= render BlockScoutWeb.TransactionView, "_tabs.html", assigns %>
<div class="card-body"> <div class="card-body" data-async-load data-async-listing="<%= @current_path %>">
<h2 class="card-title"><%= gettext "Logs" %></h2> <h2 class="card-title"><%= gettext "Logs" %></h2>
<%= if @next_page_params do %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, next_page_path: transaction_log_path(@conn,:index, @transaction, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %> <button data-error-message class="alert alert-danger col-12 text-left" style="display: none;">
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %> <span href="#" class="alert-link"><%= gettext("Something went wrong, click to reload.") %></span>
<% end %> </button>
<%= if Enum.count(@logs) > 0 do %> <div data-empty-response-message style="display: none;">
<%= for log <- @logs do %> <div class="tile tile-muted text-center" data-selector="empty-logs-list">
<div data-test="transaction_log" class="tile tile-muted"> <%= gettext "There are no logs for this transaction." %>
<dl class="row">
<dt class="col-md-1"> <%= gettext "Address" %> </dt>
<dd class="col-md-11">
<h3 class="">
<%= link(
log.address,
to: address_path(@conn, :show, log.address),
"data-test": "log_address_link",
"data-address-hash": log.address
) %>
</h3>
</dd>
<dt class="col-md-1"><%= gettext "Decoded" %></dt>
<dd class="col-md-11">
<%= case decode(log, @transaction) do %>
<% {:error, :contract_not_verified} -> %>
<div class="alert alert-info">
<%= gettext "To see decoded input data, the contract must be verified." %>
<%= case @transaction do %>
<% %{to_address: %{hash: hash}} -> %>
<%= gettext "Verify the contract " %><a href="<%= address_verify_contract_path(@conn, :new, hash)%>"><%= gettext "here" %></a>
<% _ -> %>
<%= nil %>
<% end %>
</div> </div>
<% {:error, :could_not_decode} -> %>
<div class="alert alert-danger">
<%= gettext "Failed to decode log data." %>
</div> </div>
<% {:ok, method_id, text, mapping} -> %>
<table summary="Transaction Info" class="table thead-light table-bordered transaction-input-table">
<tr>
<td>Method Id</td>
<td colspan="3"><code>0x<%= method_id %></code></td>
</tr>
<tr>
<td>Call</td>
<td colspan="3"><code><%= text %></code></td>
</tr>
</table>
<table style="color: black;" summary="<%= gettext "Log Data" %>" class="table thead-light table-bordered table-responsive">
<tr>
<th scope="col"></th>
<th scope="col"><%= gettext "Name" %></th>
<th scope="col"><%= gettext "Type" %></th>
<th scope="col"><%= gettext "Indexed?" %></th>
<th scope="col"><%= gettext "Data" %></th>
<tr>
<%= for {name, type, indexed?, value} <- mapping do %>
<tr>
<th scope="row">
<%= case BlockScoutWeb.ABIEncodedValueView.copy_text(type, value) do %>
<% :error -> %>
<%= nil %>
<% copy_text -> %>
<span
aria-label='<%= gettext "Copy Value" %>'
class="btn-copy-ico"
data-clipboard-text="<%= copy_text %>"
data-placement="top"
data-toggle="tooltip"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32.5 32.5" width="32" height="32">
<path fill-rule="evenodd" d="M23.5 20.5a1 1 0 0 1-1-1v-9h-9a1 1 0 0 1 0-2h10a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1zm-3-7v10a1 1 0 0 1-1 1h-10a1 1 0 0 1-1-1v-10a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1zm-2 1h-8v8h8v-8z"/>
</svg>
</span>
<% end %>
</th>
<td><%= name %></td>
<td><%= type %></td>
<td><%= indexed? %></td>
<td>
<pre class="transaction-input-text tile"><code><%= BlockScoutWeb.ABIEncodedValueView.value_html(type, value) %></code></pre>
</td>
</tr>
<% end %>
</table>
<% _ -> %>
<%= nil %>
<% end %>
</dd> <div data-items></div>
<dt class="col-md-1"><%= gettext "Topics" %></dt>
<dd class="col-md-11">
<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-1">
<%= gettext "Data" %>
</dt>
<dd class="col-md-11">
<%= 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 transaction." %></span>
</div>
<% end %>
<%= if @next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, next_page_path: transaction_log_path(@conn,:index, @transaction, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<!--
<%= if @next_page_params do %>
<%= link(
gettext("Newer"),
class: "button button-secondary button-sm u-float-right mt-3",
to: transaction_log_path(
@conn,
:index,
@transaction,
@next_page_params
)
) %>
<% end %>
-->
</div> </div>
</div> </div>
</section> </section>

@ -3,34 +3,24 @@
<div class="card"> <div class="card">
<%= render BlockScoutWeb.TransactionView, "_tabs.html", assigns %> <%= render BlockScoutWeb.TransactionView, "_tabs.html", assigns %>
<div class="card-body"> <div class="card-body" data-async-load data-async-listing="<%= @current_path %>">
<h2 class="card-title"><%= gettext "Token Transfers" %></h2> <h2 class="card-title"><%= gettext "Token Transfers" %></h2>
<%= if @next_page_params do %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, next_page_path: transaction_token_transfer_path(@conn, :index, @transaction, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %> <button data-error-message class="alert alert-danger col-12 text-left" style="display: none;">
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %> <span href="#" class="alert-link"><%= gettext("Something went wrong, click to reload.") %></span>
<% end %> </button>
<%= if Enum.any?(@token_transfers) do %> <div data-empty-response-message style="display: none;">
<%= for token_transfer <- @token_transfers do %> <div class="tile tile-muted text-center" data-selector="empty-logs-list">
<%= render "_token_transfer.html", token_transfer: token_transfer, conn: @conn %> <%= gettext "There are no token transfers for this transaction" %>
<% end %> </div>
<% else %>
<div class="tile tile-muted text-center">
<span><%= gettext "There are no token transfers for this transaction." %></span>
</div> </div>
<% end %>
<%= if @next_page_params do %> <div data-items></div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, next_page_path: transaction_token_transfer_path(@conn, :index, @transaction, @next_page_params) %>
<% end %>
<%= if !@next_page_params do %> <%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
</div> </div>
</div> </div>

@ -98,7 +98,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:16 #: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:16
#: lib/block_scout_web/templates/transaction_log/index.html.eex:22 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:3
#: lib/block_scout_web/views/address_view.ex:99 #: lib/block_scout_web/views/address_view.ex:99
msgid "Address" msgid "Address"
msgstr "" msgstr ""
@ -327,10 +327,10 @@ msgid "Curl"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:63 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:44
#: 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/_logs.html.eex:48
#: lib/block_scout_web/templates/transaction_log/index.html.eex:133 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:113
msgid "Data" msgid "Data"
msgstr "" msgstr ""
@ -500,7 +500,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:26 #: 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/address_logs/index.html.eex:7
#: 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:301 #: lib/block_scout_web/views/address_view.ex:301
@ -558,7 +558,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16
#: lib/block_scout_web/templates/transaction_log/index.html.eex:64 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:45
msgid "Name" msgid "Name"
msgstr "" msgstr ""
@ -567,23 +567,6 @@ msgstr ""
msgid "New Smart Contract" msgid "New Smart Contract"
msgstr "" msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:37
#: lib/block_scout_web/templates/transaction_log/index.html.eex:162
msgid "Newer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token/index.html.eex:39
msgid "Next"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/inventory/index.html.eex:32
msgid "Next Page"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:40 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:40
msgid "No" msgid "No"
@ -743,12 +726,12 @@ msgstr ""
#, elixir-format #, elixir-format
#: #:
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:22 #: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:15
msgid "There are no internal transactions for this transaction." msgid "There are no internal transactions for this transaction."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:147 #: lib/block_scout_web/templates/transaction_log/index.html.eex:18
msgid "There are no logs for this transaction." msgid "There are no logs for this transaction."
msgstr "" msgstr ""
@ -758,17 +741,12 @@ msgid "There are no token transfers for this address."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:23 #: lib/block_scout_web/templates/address_token/index.html.eex:18
msgid "There are no token transfers for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token/index.html.eex:24
msgid "There are no tokens for this address." msgid "There are no tokens for this address."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/tokens/inventory/index.html.eex:25 #: lib/block_scout_web/templates/tokens/inventory/index.html.eex:26
msgid "There are no tokens." msgid "There are no tokens."
msgstr "" msgstr ""
@ -778,7 +756,7 @@ msgid "There are no transactions for this address."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block_transaction/index.html.eex:35 #: lib/block_scout_web/templates/block_transaction/index.html.eex:28
msgid "There are no transactions for this block." msgid "There are no transactions for this block."
msgstr "" msgstr ""
@ -855,8 +833,8 @@ 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/address_logs/_logs.html.eex:14
#: lib/block_scout_web/templates/transaction_log/index.html.eex:103 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:83
msgid "Topics" msgid "Topics"
msgstr "" msgstr ""
@ -876,7 +854,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/templates/address_logs/_logs.html.eex:3
#: lib/block_scout_web/views/transaction_view.ex:287 #: lib/block_scout_web/views/transaction_view.ex:287
msgid "Transaction" msgid "Transaction"
msgstr "" msgstr ""
@ -900,7 +878,7 @@ msgstr ""
#: lib/block_scout_web/templates/address/_tabs.html.eex:3 #: lib/block_scout_web/templates/address/_tabs.html.eex:3
#: lib/block_scout_web/templates/address_transaction/index.html.eex:15 #: lib/block_scout_web/templates/address_transaction/index.html.eex:15
#: lib/block_scout_web/templates/block_transaction/index.html.eex:10 #: lib/block_scout_web/templates/block_transaction/index.html.eex:10
#: lib/block_scout_web/templates/block_transaction/index.html.eex:17 #: lib/block_scout_web/templates/block_transaction/index.html.eex:18
#: lib/block_scout_web/templates/chain/show.html.eex:108 #: lib/block_scout_web/templates/chain/show.html.eex:108
#: lib/block_scout_web/templates/layout/_topnav.html.eex:35 #: lib/block_scout_web/templates/layout/_topnav.html.eex:35
#: lib/block_scout_web/views/address_view.ex:294 #: lib/block_scout_web/views/address_view.ex:294
@ -1163,18 +1141,18 @@ msgid "Static Call"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:33 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:14
msgid "Decoded" msgid "Decoded"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:66 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47
msgid "Indexed?" msgid "Indexed?"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:17 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:17
#: lib/block_scout_web/templates/transaction_log/index.html.eex:65 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
msgid "Type" msgid "Type"
msgstr "" msgstr ""
@ -1184,7 +1162,7 @@ msgid "Method Id"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:38 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:19
msgid "To see decoded input data, the contract must be verified." msgid "To see decoded input data, the contract must be verified."
msgstr "" msgstr ""
@ -1200,13 +1178,13 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11
#: lib/block_scout_web/templates/transaction_log/index.html.eex:41 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:22
msgid "Verify the contract " msgid "Verify the contract "
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11
#: lib/block_scout_web/templates/transaction_log/index.html.eex:41 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:22
msgid "here" msgid "here"
msgstr "" msgstr ""
@ -1222,31 +1200,38 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:28 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:28
#: lib/block_scout_web/templates/transaction_log/index.html.eex:77 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:58
msgid "Copy Value" msgid "Copy Value"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:48 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29
msgid "Failed to decode log data." msgid "Failed to decode log data."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:61 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:42
msgid "Log Data" msgid "Log Data"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34 #: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:61 #: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:61
#: lib/block_scout_web/templates/address_logs/index.html.eex:12
#: lib/block_scout_web/templates/address_token/index.html.eex:13
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:20 #: lib/block_scout_web/templates/address_token_transfer/index.html.eex:20
#: lib/block_scout_web/templates/address_transaction/index.html.eex:57 #: lib/block_scout_web/templates/address_transaction/index.html.eex:57
#: lib/block_scout_web/templates/address_validation/index.html.eex:22 #: lib/block_scout_web/templates/address_validation/index.html.eex:22
#: lib/block_scout_web/templates/block_transaction/index.html.eex:23
#: lib/block_scout_web/templates/chain/show.html.eex:91 #: lib/block_scout_web/templates/chain/show.html.eex:91
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:19 #: lib/block_scout_web/templates/pending_transaction/index.html.eex:19
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:21 #: lib/block_scout_web/templates/tokens/holder/index.html.eex:21
#: lib/block_scout_web/templates/tokens/inventory/index.html.eex:21
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:20 #: lib/block_scout_web/templates/tokens/transfer/index.html.eex:20
#: lib/block_scout_web/templates/transaction/index.html.eex:20 #: lib/block_scout_web/templates/transaction/index.html.eex:20
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:11
#: lib/block_scout_web/templates/transaction_log/index.html.eex:13
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:12
msgid "Something went wrong, click to reload." msgid "Something went wrong, click to reload."
msgstr "" msgstr ""
@ -1697,15 +1682,10 @@ msgid "Displaying the init data provided of the creating transaction."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:77 #: lib/block_scout_web/templates/address_logs/index.html.eex:17
msgid "There are no logs for this address." msgid "There are no logs for this address."
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/not_found.html.eex:7
msgid "Sorry, We are unable to locate this transaction Hash"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/not_found.html.eex:12 #: lib/block_scout_web/templates/transaction/not_found.html.eex:12
msgid "If you have just submitted this transaction please wait for at least 30 seconds before refreshing this page." msgid "If you have just submitted this transaction please wait for at least 30 seconds before refreshing this page."
@ -1730,3 +1710,13 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/not_found.html.eex:16 #: lib/block_scout_web/templates/transaction/not_found.html.eex:16
msgid "It could still be in the TX Pool of a different node, waiting to be broadcasted." msgid "It could still be in the TX Pool of a different node, waiting to be broadcasted."
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/not_found.html.eex:7
msgid "Sorry, We are unable to locate this transaction Hash"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:17
msgid "There are no token transfers for this transaction"
msgstr ""

@ -98,7 +98,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:16 #: lib/block_scout_web/templates/address/_validator_metadata_modal.html.eex:16
#: lib/block_scout_web/templates/transaction_log/index.html.eex:22 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:3
#: lib/block_scout_web/views/address_view.ex:99 #: lib/block_scout_web/views/address_view.ex:99
msgid "Address" msgid "Address"
msgstr "" msgstr ""
@ -327,10 +327,10 @@ msgid "Curl"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:63 #: lib/block_scout_web/templates/address_logs/_logs.html.eex:44
#: 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/_logs.html.eex:48
#: lib/block_scout_web/templates/transaction_log/index.html.eex:133 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:113
msgid "Data" msgid "Data"
msgstr "" msgstr ""
@ -500,7 +500,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:26 #: 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/address_logs/index.html.eex:7
#: 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:301 #: lib/block_scout_web/views/address_view.ex:301
@ -558,7 +558,7 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52 #: lib/block_scout_web/templates/api_docs/_action_tile.html.eex:52
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:16
#: lib/block_scout_web/templates/transaction_log/index.html.eex:64 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:45
msgid "Name" msgid "Name"
msgstr "" msgstr ""
@ -567,23 +567,6 @@ msgstr ""
msgid "New Smart Contract" msgid "New Smart Contract"
msgstr "" msgstr ""
#, elixir-format
#:
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:37
#: lib/block_scout_web/templates/transaction_log/index.html.eex:162
msgid "Newer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token/index.html.eex:39
msgid "Next"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/inventory/index.html.eex:32
msgid "Next Page"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:40 #: lib/block_scout_web/templates/address_contract_verification/new.html.eex:40
msgid "No" msgid "No"
@ -743,12 +726,12 @@ msgstr ""
#, elixir-format #, elixir-format
#: #:
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:22 #: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:15
msgid "There are no internal transactions for this transaction." msgid "There are no internal transactions for this transaction."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:147 #: lib/block_scout_web/templates/transaction_log/index.html.eex:18
msgid "There are no logs for this transaction." msgid "There are no logs for this transaction."
msgstr "" msgstr ""
@ -758,17 +741,12 @@ msgid "There are no token transfers for this address."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:23 #: lib/block_scout_web/templates/address_token/index.html.eex:18
msgid "There are no token transfers for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token/index.html.eex:24
msgid "There are no tokens for this address." msgid "There are no tokens for this address."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/tokens/inventory/index.html.eex:25 #: lib/block_scout_web/templates/tokens/inventory/index.html.eex:26
msgid "There are no tokens." msgid "There are no tokens."
msgstr "" msgstr ""
@ -778,7 +756,7 @@ msgid "There are no transactions for this address."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/block_transaction/index.html.eex:35 #: lib/block_scout_web/templates/block_transaction/index.html.eex:28
msgid "There are no transactions for this block." msgid "There are no transactions for this block."
msgstr "" msgstr ""
@ -855,8 +833,8 @@ 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/address_logs/_logs.html.eex:14
#: lib/block_scout_web/templates/transaction_log/index.html.eex:103 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:83
msgid "Topics" msgid "Topics"
msgstr "" msgstr ""
@ -876,7 +854,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/templates/address_logs/_logs.html.eex:3
#: lib/block_scout_web/views/transaction_view.ex:287 #: lib/block_scout_web/views/transaction_view.ex:287
msgid "Transaction" msgid "Transaction"
msgstr "" msgstr ""
@ -900,7 +878,7 @@ msgstr ""
#: lib/block_scout_web/templates/address/_tabs.html.eex:3 #: lib/block_scout_web/templates/address/_tabs.html.eex:3
#: lib/block_scout_web/templates/address_transaction/index.html.eex:15 #: lib/block_scout_web/templates/address_transaction/index.html.eex:15
#: lib/block_scout_web/templates/block_transaction/index.html.eex:10 #: lib/block_scout_web/templates/block_transaction/index.html.eex:10
#: lib/block_scout_web/templates/block_transaction/index.html.eex:17 #: lib/block_scout_web/templates/block_transaction/index.html.eex:18
#: lib/block_scout_web/templates/chain/show.html.eex:108 #: lib/block_scout_web/templates/chain/show.html.eex:108
#: lib/block_scout_web/templates/layout/_topnav.html.eex:35 #: lib/block_scout_web/templates/layout/_topnav.html.eex:35
#: lib/block_scout_web/views/address_view.ex:294 #: lib/block_scout_web/views/address_view.ex:294
@ -1163,18 +1141,18 @@ msgid "Static Call"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:33 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:14
msgid "Decoded" msgid "Decoded"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:66 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:47
msgid "Indexed?" msgid "Indexed?"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:17 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:17
#: lib/block_scout_web/templates/transaction_log/index.html.eex:65 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:46
msgid "Type" msgid "Type"
msgstr "" msgstr ""
@ -1184,7 +1162,7 @@ msgid "Method Id"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:38 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:19
msgid "To see decoded input data, the contract must be verified." msgid "To see decoded input data, the contract must be verified."
msgstr "" msgstr ""
@ -1200,13 +1178,13 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11
#: lib/block_scout_web/templates/transaction_log/index.html.eex:41 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:22
msgid "Verify the contract " msgid "Verify the contract "
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11 #: lib/block_scout_web/templates/transaction/_decoded_input.html.eex:11
#: lib/block_scout_web/templates/transaction_log/index.html.eex:41 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:22
msgid "here" msgid "here"
msgstr "" msgstr ""
@ -1222,31 +1200,38 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:28 #: lib/block_scout_web/templates/transaction/_decoded_input_body.html.eex:28
#: lib/block_scout_web/templates/transaction_log/index.html.eex:77 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:58
msgid "Copy Value" msgid "Copy Value"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:48 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:29
msgid "Failed to decode log data." msgid "Failed to decode log data."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction_log/index.html.eex:61 #: lib/block_scout_web/templates/transaction_log/_logs.html.eex:42
msgid "Log Data" msgid "Log Data"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34 #: lib/block_scout_web/templates/address_coin_balance/index.html.eex:34
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:61 #: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:61
#: lib/block_scout_web/templates/address_logs/index.html.eex:12
#: lib/block_scout_web/templates/address_token/index.html.eex:13
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:20 #: lib/block_scout_web/templates/address_token_transfer/index.html.eex:20
#: lib/block_scout_web/templates/address_transaction/index.html.eex:57 #: lib/block_scout_web/templates/address_transaction/index.html.eex:57
#: lib/block_scout_web/templates/address_validation/index.html.eex:22 #: lib/block_scout_web/templates/address_validation/index.html.eex:22
#: lib/block_scout_web/templates/block_transaction/index.html.eex:23
#: lib/block_scout_web/templates/chain/show.html.eex:91 #: lib/block_scout_web/templates/chain/show.html.eex:91
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:19 #: lib/block_scout_web/templates/pending_transaction/index.html.eex:19
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:21 #: lib/block_scout_web/templates/tokens/holder/index.html.eex:21
#: lib/block_scout_web/templates/tokens/inventory/index.html.eex:21
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:20 #: lib/block_scout_web/templates/tokens/transfer/index.html.eex:20
#: lib/block_scout_web/templates/transaction/index.html.eex:20 #: lib/block_scout_web/templates/transaction/index.html.eex:20
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:11
#: lib/block_scout_web/templates/transaction_log/index.html.eex:13
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:12
msgid "Something went wrong, click to reload." msgid "Something went wrong, click to reload."
msgstr "" msgstr ""
@ -1697,15 +1682,10 @@ msgid "Displaying the init data provided of the creating transaction."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:77 #: lib/block_scout_web/templates/address_logs/index.html.eex:17
msgid "There are no logs for this address." msgid "There are no logs for this address."
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/not_found.html.eex:7
msgid "Sorry, We are unable to locate this transaction Hash"
msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/transaction/not_found.html.eex:12 #: lib/block_scout_web/templates/transaction/not_found.html.eex:12
msgid "If you have just submitted this transaction please wait for at least 30 seconds before refreshing this page." msgid "If you have just submitted this transaction please wait for at least 30 seconds before refreshing this page."
@ -1730,3 +1710,13 @@ msgstr ""
#: lib/block_scout_web/templates/transaction/not_found.html.eex:16 #: lib/block_scout_web/templates/transaction/not_found.html.eex:16
msgid "It could still be in the TX Pool of a different node, waiting to be broadcasted." msgid "It could still be in the TX Pool of a different node, waiting to be broadcasted."
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction/not_found.html.eex:7
msgid "Sorry, We are unable to locate this transaction Hash"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:17
msgid "There are no token transfers for this transaction"
msgstr ""

@ -57,15 +57,15 @@ defmodule BlockScoutWeb.AddressTokenControllerTest do
to_address: address to_address: address
) )
conn = get(conn, address_token_path(conn, :index, address)) conn = get(conn, address_token_path(conn, :index, address), type: "JSON")
actual_token_hashes = {:ok, %{"items" => items}} =
conn.assigns.tokens conn.resp_body
|> Enum.map(& &1.contract_address_hash) |> Poison.decode()
assert html_response(conn, 200) assert json_response(conn, 200)
assert Enum.member?(actual_token_hashes, token1.contract_address_hash) assert Enum.any?(items, fn item -> String.contains?(item, to_string(token1.contract_address_hash)) end)
refute Enum.member?(actual_token_hashes, token2.contract_address_hash) refute Enum.any?(items, fn item -> String.contains?(item, to_string(token2.contract_address_hash)) end)
end end
test "returns next page of results based on last seen token", %{conn: conn} do test "returns next page of results based on last seen token", %{conn: conn} do
@ -102,15 +102,17 @@ defmodule BlockScoutWeb.AddressTokenControllerTest do
get(conn, address_token_path(BlockScoutWeb.Endpoint, :index, address.hash), %{ get(conn, address_token_path(BlockScoutWeb.Endpoint, :index, address.hash), %{
"token_name" => name, "token_name" => name,
"token_type" => type, "token_type" => type,
"token_inserted_at" => inserted_at "token_inserted_at" => inserted_at,
"type" => "JSON"
}) })
actual_tokens = {:ok, %{"items" => items}} =
conn.assigns.tokens conn.resp_body
|> Enum.map(& &1.name) |> Poison.decode()
|> Enum.sort()
assert second_page_tokens == actual_tokens assert Enum.any?(items, fn item ->
Enum.any?(second_page_tokens, fn token_name -> String.contains?(item, token_name) end)
end)
end end
test "next_page_params exists if not on last page", %{conn: conn} do test "next_page_params exists if not on last page", %{conn: conn} do
@ -129,9 +131,13 @@ defmodule BlockScoutWeb.AddressTokenControllerTest do
insert(:token_transfer, token_contract_address: token.contract_address, from_address: address) insert(:token_transfer, token_contract_address: token.contract_address, from_address: address)
end) end)
conn = get(conn, address_token_path(BlockScoutWeb.Endpoint, :index, address.hash)) conn = get(conn, address_token_path(BlockScoutWeb.Endpoint, :index, address.hash), type: "JSON")
assert conn.assigns.next_page_params {:ok, %{"next_page_path" => next_page_path}} =
conn.resp_body
|> Poison.decode()
assert next_page_path
end end
test "next_page_params are empty if on last page", %{conn: conn} do test "next_page_params are empty if on last page", %{conn: conn} do
@ -139,9 +145,13 @@ defmodule BlockScoutWeb.AddressTokenControllerTest do
token = insert(:token) token = insert(:token)
insert(:token_transfer, token_contract_address: token.contract_address, from_address: address) insert(:token_transfer, token_contract_address: token.contract_address, from_address: address)
conn = get(conn, address_token_path(BlockScoutWeb.Endpoint, :index, address.hash)) conn = get(conn, address_token_path(BlockScoutWeb.Endpoint, :index, address.hash), type: "JSON")
{:ok, %{"next_page_path" => next_page_path}} =
conn.resp_body
|> Poison.decode()
refute conn.assigns.next_page_params refute next_page_path
end end
end end
end end

@ -39,10 +39,15 @@ defmodule BlockScoutWeb.BlockTransactionControllerTest do
|> with_block(block) |> with_block(block)
|> with_contract_creation(insert(:contract_address)) |> with_contract_creation(insert(:contract_address))
conn = get(conn, block_transaction_path(BlockScoutWeb.Endpoint, :index, block.number)) conn = get(conn, block_transaction_path(BlockScoutWeb.Endpoint, :index, block), %{type: "JSON"})
assert html_response(conn, 200) assert json_response(conn, 200)
assert 2 == Enum.count(conn.assigns.transactions)
{:ok, %{"items" => items}} =
conn.resp_body
|> Poison.decode()
assert Enum.count(items) == 2
end end
test "non-consensus block number without consensus blocks is treated as consensus number above tip", %{conn: conn} do test "non-consensus block number without consensus blocks is treated as consensus number above tip", %{conn: conn} do
@ -77,10 +82,15 @@ defmodule BlockScoutWeb.BlockTransactionControllerTest do
|> insert() |> insert()
|> with_block(block) |> with_block(block)
conn = get(conn, block_transaction_path(conn, :index, block.hash)) conn = get(conn, block_transaction_path(BlockScoutWeb.Endpoint, :index, block), %{type: "JSON"})
assert json_response(conn, 200)
assert html_response(conn, 200) {:ok, %{"items" => items}} =
assert Enum.count(conn.assigns.transactions) == 1 conn.resp_body
|> Poison.decode()
assert Enum.count(items) == 1
end end
test "does not return transactions for non-consensus block hash", %{conn: conn} do test "does not return transactions for non-consensus block hash", %{conn: conn} do
@ -89,10 +99,15 @@ defmodule BlockScoutWeb.BlockTransactionControllerTest do
transaction = insert(:transaction) transaction = insert(:transaction)
insert(:transaction_fork, hash: transaction.hash, uncle_hash: block.hash) insert(:transaction_fork, hash: transaction.hash, uncle_hash: block.hash)
conn = get(conn, block_transaction_path(conn, :index, block.hash)) conn = get(conn, block_transaction_path(BlockScoutWeb.Endpoint, :index, block), %{type: "JSON"})
assert json_response(conn, 200)
{:ok, %{"items" => items}} =
conn.resp_body
|> Poison.decode()
assert html_response(conn, 200) assert Enum.empty?(items)
assert Enum.count(conn.assigns.transactions) == 0
end end
test "does not return transactions for invalid block hash", %{conn: conn} do test "does not return transactions for invalid block hash", %{conn: conn} do
@ -111,44 +126,62 @@ defmodule BlockScoutWeb.BlockTransactionControllerTest do
insert(:transaction) insert(:transaction)
block = insert(:block) block = insert(:block)
conn = get(conn, block_transaction_path(BlockScoutWeb.Endpoint, :index, block)) conn = get(conn, block_transaction_path(BlockScoutWeb.Endpoint, :index, block), %{type: "JSON"})
assert html_response(conn, 200) assert json_response(conn, 200)
assert Enum.empty?(conn.assigns.transactions)
{:ok, %{"items" => items}} =
conn.resp_body
|> Poison.decode()
assert Enum.empty?(items)
end end
test "does not return related transactions without a block", %{conn: conn} do test "does not return related transactions without a block", %{conn: conn} do
block = insert(:block) block = insert(:block)
insert(:transaction) insert(:transaction)
conn = get(conn, block_transaction_path(BlockScoutWeb.Endpoint, :index, block)) conn = get(conn, block_transaction_path(BlockScoutWeb.Endpoint, :index, block), %{type: "JSON"})
assert json_response(conn, 200)
assert html_response(conn, 200) {:ok, %{"items" => items}} =
assert Enum.empty?(conn.assigns.transactions) conn.resp_body
|> Poison.decode()
assert Enum.empty?(items)
end end
test "next_page_params exist if not on last page", %{conn: conn} do test "next_page_path exists if not on last page", %{conn: conn} do
block = %Block{number: number} = insert(:block) block = %Block{number: number} = insert(:block)
60 60
|> insert_list(:transaction) |> insert_list(:transaction)
|> with_block(block) |> with_block(block)
conn = get(conn, block_transaction_path(BlockScoutWeb.Endpoint, :index, block)) conn = get(conn, block_transaction_path(BlockScoutWeb.Endpoint, :index, block), %{type: "JSON"})
{:ok, %{"next_page_path" => next_page_path}} =
conn.resp_body
|> Poison.decode()
assert %{"block_number" => ^number, "index" => 10} = conn.assigns.next_page_params assert next_page_path
end end
test "next_page_params are empty if on last page", %{conn: conn} do test "next_page_path is empty if on last page", %{conn: conn} do
block = insert(:block) block = insert(:block)
:transaction :transaction
|> insert() |> insert()
|> with_block(block) |> with_block(block)
conn = get(conn, block_transaction_path(BlockScoutWeb.Endpoint, :index, block)) conn = get(conn, block_transaction_path(BlockScoutWeb.Endpoint, :index, block), %{type: "JSON"})
{:ok, %{"next_page_path" => next_page_path}} =
conn.resp_body
|> Poison.decode()
refute conn.assigns.next_page_params refute next_page_path
end end
test "displays miner primary address name", %{conn: conn} do test "displays miner primary address name", %{conn: conn} do

@ -62,13 +62,20 @@ defmodule BlockScoutWeb.Tokens.InventoryControllerTest do
conn = conn =
get(conn, token_inventory_path(conn, :index, token.contract_address_hash), %{ get(conn, token_inventory_path(conn, :index, token.contract_address_hash), %{
"token_id" => "999" "token_id" => "999",
"type" => "JSON"
}) })
assert Enum.map(conn.assigns.unique_tokens, & &1.token_id) == Enum.map(second_page_token_balances, & &1.token_id) conn = get(conn, token_inventory_path(conn, :index, token.contract_address_hash), %{type: "JSON"})
{:ok, %{"items" => items}} =
conn.resp_body
|> Poison.decode()
assert Enum.count(items) == Enum.count(second_page_token_balances)
end end
test "next_page_params exists if not on last page", %{conn: conn} do test "next_page_path exists if not on last page", %{conn: conn} do
token = insert(:token, type: "ERC-721") token = insert(:token, type: "ERC-721")
transaction = transaction =
@ -87,17 +94,16 @@ defmodule BlockScoutWeb.Tokens.InventoryControllerTest do
) )
) )
expected_next_page_params = %{ conn = get(conn, token_inventory_path(conn, :index, token.contract_address_hash), %{type: "JSON"})
"token_id" => to_string(token.contract_address_hash),
"unique_token" => 1050
}
conn = get(conn, token_inventory_path(conn, :index, token.contract_address_hash)) {:ok, %{"next_page_path" => next_page_path}} =
conn.resp_body
|> Poison.decode()
assert conn.assigns.next_page_params == expected_next_page_params assert next_page_path
end end
test "next_page_params are empty if on last page", %{conn: conn} do test "next_page_path is empty if on last page", %{conn: conn} do
token = insert(:token, type: "ERC-721") token = insert(:token, type: "ERC-721")
transaction = transaction =
@ -113,9 +119,13 @@ defmodule BlockScoutWeb.Tokens.InventoryControllerTest do
token_id: 1000 token_id: 1000
) )
conn = get(conn, token_inventory_path(conn, :index, token.contract_address_hash)) conn = get(conn, token_inventory_path(conn, :index, token.contract_address_hash), %{type: "JSON"})
{:ok, %{"next_page_path" => next_page_path}} =
conn.resp_body
|> Poison.decode()
refute conn.assigns.next_page_params refute next_page_path
end end
end end
end end

@ -3,7 +3,7 @@ defmodule BlockScoutWeb.TransactionInternalTransactionControllerTest do
import BlockScoutWeb.Router.Helpers, only: [transaction_internal_transaction_path: 3] import BlockScoutWeb.Router.Helpers, only: [transaction_internal_transaction_path: 3]
alias Explorer.Chain.{Block, InternalTransaction, Transaction} alias Explorer.Chain.InternalTransaction
alias Explorer.ExchangeRates.Token alias Explorer.ExchangeRates.Token
describe "GET index/3" do describe "GET index/3" do
@ -40,7 +40,6 @@ defmodule BlockScoutWeb.TransactionInternalTransactionControllerTest do
|> insert() |> insert()
|> with_block(insert(:block, number: 1)) |> with_block(insert(:block, number: 1))
expected_internal_transaction =
insert(:internal_transaction, insert(:internal_transaction,
transaction: transaction, transaction: transaction,
index: 0, index: 0,
@ -57,14 +56,15 @@ defmodule BlockScoutWeb.TransactionInternalTransactionControllerTest do
path = transaction_internal_transaction_path(BlockScoutWeb.Endpoint, :index, transaction.hash) path = transaction_internal_transaction_path(BlockScoutWeb.Endpoint, :index, transaction.hash)
conn = get(conn, path) conn = get(conn, path, %{type: "JSON"})
actual_internal_transaction_primary_keys = {:ok, %{"items" => items}} =
Enum.map(conn.assigns.internal_transactions, &{&1.transaction_hash, &1.index}) conn.resp_body
|> Poison.decode()
assert html_response(conn, 200) assert json_response(conn, 200)
assert {expected_internal_transaction.transaction_hash, expected_internal_transaction.index} in actual_internal_transaction_primary_keys assert Enum.count(items) == 2
end end
test "includes USD exchange rate value for address in assigns", %{conn: conn} do test "includes USD exchange rate value for address in assigns", %{conn: conn} do
@ -135,21 +135,21 @@ defmodule BlockScoutWeb.TransactionInternalTransactionControllerTest do
conn = conn =
get(conn, transaction_internal_transaction_path(BlockScoutWeb.Endpoint, :index, transaction.hash), %{ get(conn, transaction_internal_transaction_path(BlockScoutWeb.Endpoint, :index, transaction.hash), %{
"index" => Integer.to_string(index) "index" => Integer.to_string(index),
"type" => "JSON"
}) })
actual_indexes = {:ok, %{"items" => items}} =
conn.assigns.internal_transactions conn.resp_body
|> Enum.map(& &1.index) |> Poison.decode()
assert second_page_indexes == actual_indexes assert Enum.count(items) == Enum.count(second_page_indexes)
end end
test "next_page_params exist if not on last page", %{conn: conn} do test "next_page_path exists if not on last page", %{conn: conn} do
block = %Block{number: number} = insert(:block, number: 7000) block = insert(:block, number: 7000)
transaction = transaction =
%Transaction{index: transaction_index} =
:transaction :transaction
|> insert() |> insert()
|> with_block(block) |> with_block(block)
@ -165,13 +165,19 @@ defmodule BlockScoutWeb.TransactionInternalTransactionControllerTest do
) )
end) end)
conn = get(conn, transaction_internal_transaction_path(BlockScoutWeb.Endpoint, :index, transaction.hash)) conn =
get(conn, transaction_internal_transaction_path(BlockScoutWeb.Endpoint, :index, transaction.hash), %{
type: "JSON"
})
assert %{"block_number" => ^number, "index" => 50, "transaction_index" => ^transaction_index} = {:ok, %{"next_page_path" => next_page_path}} =
conn.assigns.next_page_params conn.resp_body
|> Poison.decode()
assert next_page_path
end end
test "next_page_params are empty if on last page", %{conn: conn} do test "next_page_path is empty if on last page", %{conn: conn} do
transaction = transaction =
:transaction :transaction
|> insert() |> insert()
@ -188,9 +194,16 @@ defmodule BlockScoutWeb.TransactionInternalTransactionControllerTest do
) )
end) end)
conn = get(conn, transaction_internal_transaction_path(BlockScoutWeb.Endpoint, :index, transaction.hash)) conn =
get(conn, transaction_internal_transaction_path(BlockScoutWeb.Endpoint, :index, transaction.hash), %{
type: "JSON"
})
{:ok, %{"next_page_path" => next_page_path}} =
conn.resp_body
|> Poison.decode()
refute conn.assigns.next_page_params refute next_page_path
end end
end end
end end

@ -31,11 +31,12 @@ defmodule BlockScoutWeb.TransactionLogControllerTest do
address = insert(:address) address = insert(:address)
insert(:log, address: address, transaction: transaction) insert(:log, address: address, transaction: transaction)
conn = get(conn, transaction_log_path(conn, :index, transaction)) conn = get(conn, transaction_log_path(conn, :index, transaction), %{type: "JSON"})
first_log = List.first(conn.assigns.logs) {:ok, %{"items" => items}} = conn.resp_body |> Poison.decode()
first_log = List.first(items)
assert first_log.transaction_hash == transaction.hash assert String.contains?(first_log, to_string(address.hash))
end end
test "returns logs for the transaction with nil to_address", %{conn: conn} do test "returns logs for the transaction with nil to_address", %{conn: conn} do
@ -47,20 +48,23 @@ defmodule BlockScoutWeb.TransactionLogControllerTest do
address = insert(:address) address = insert(:address)
insert(:log, address: address, transaction: transaction) insert(:log, address: address, transaction: transaction)
conn = get(conn, transaction_log_path(conn, :index, transaction)) conn = get(conn, transaction_log_path(conn, :index, transaction), %{type: "JSON"})
first_log = List.first(conn.assigns.logs) {:ok, %{"items" => items}} = conn.resp_body |> Poison.decode()
first_log = List.first(items)
assert first_log.transaction_hash == transaction.hash assert String.contains?(first_log, to_string(address.hash))
end end
test "assigns no logs when there are none", %{conn: conn} do test "assigns no logs when there are none", %{conn: conn} do
transaction = insert(:transaction) transaction = insert(:transaction)
path = transaction_log_path(conn, :index, transaction) path = transaction_log_path(conn, :index, transaction)
conn = get(conn, path) conn = get(conn, path, %{type: "JSON"})
assert Enum.count(conn.assigns.logs) == 0 {:ok, %{"items" => items}} = conn.resp_body |> Poison.decode()
assert Enum.empty?(items)
end end
test "returns next page of results based on last seen transaction log", %{conn: conn} do test "returns next page of results based on last seen transaction log", %{conn: conn} do
@ -78,15 +82,16 @@ defmodule BlockScoutWeb.TransactionLogControllerTest do
conn = conn =
get(conn, transaction_log_path(conn, :index, transaction), %{ get(conn, transaction_log_path(conn, :index, transaction), %{
"index" => Integer.to_string(log.index) "index" => Integer.to_string(log.index),
"type" => "JSON"
}) })
actual_indexes = Enum.map(conn.assigns.logs, & &1.index) {:ok, %{"items" => items}} = conn.resp_body |> Poison.decode()
assert second_page_indexes == actual_indexes assert Enum.count(items) == Enum.count(second_page_indexes)
end end
test "next_page_params exist if not on last page", %{conn: conn} do test "next_page_path exists if not on last page", %{conn: conn} do
transaction = transaction =
:transaction :transaction
|> insert() |> insert()
@ -95,20 +100,24 @@ defmodule BlockScoutWeb.TransactionLogControllerTest do
1..60 1..60
|> Enum.map(fn index -> insert(:log, transaction: transaction, index: index) end) |> Enum.map(fn index -> insert(:log, transaction: transaction, index: index) end)
conn = get(conn, transaction_log_path(conn, :index, transaction)) conn = get(conn, transaction_log_path(conn, :index, transaction), %{type: "JSON"})
assert %{"index" => 50} = conn.assigns.next_page_params {:ok, %{"next_page_path" => path}} = conn.resp_body |> Poison.decode()
assert path
end end
test "next_page_params are empty if on last page", %{conn: conn} do test "next_page_path is empty if on last page", %{conn: conn} do
transaction = transaction =
:transaction :transaction
|> insert() |> insert()
|> with_block() |> with_block()
conn = get(conn, transaction_log_path(conn, :index, transaction)) conn = get(conn, transaction_log_path(conn, :index, transaction), %{type: "JSON"})
{:ok, %{"next_page_path" => path}} = conn.resp_body |> Poison.decode()
refute conn.assigns.next_page_params refute path
end end
end end

@ -48,24 +48,19 @@ defmodule BlockScoutWeb.TransactionTokenTransferControllerTest do
test "includes token transfers for the transaction", %{conn: conn} do test "includes token transfers for the transaction", %{conn: conn} do
transaction = insert(:transaction) transaction = insert(:transaction)
expected_token_transfer = insert(:token_transfer, transaction: transaction) insert(:token_transfer, transaction: transaction)
insert(:token_transfer, transaction: transaction) insert(:token_transfer, transaction: transaction)
path = transaction_token_transfer_path(BlockScoutWeb.Endpoint, :index, transaction.hash) path = transaction_token_transfer_path(BlockScoutWeb.Endpoint, :index, transaction.hash)
conn = get(conn, path) conn = get(conn, path, %{type: "JSON"})
actual_token_transfer_primary_keys = assert json_response(conn, 200)
conn.assigns.token_transfers
|> Enum.map(&{&1.transaction_hash, &1.log_index})
assert html_response(conn, 200) {:ok, %{"items" => items}} = conn.resp_body |> Poison.decode()
assert Enum.member?( assert Enum.count(items) == 2
actual_token_transfer_primary_keys,
{expected_token_transfer.transaction_hash, expected_token_transfer.log_index}
)
end end
test "includes USD exchange rate value for address in assigns", %{conn: conn} do test "includes USD exchange rate value for address in assigns", %{conn: conn} do
@ -82,7 +77,7 @@ defmodule BlockScoutWeb.TransactionTokenTransferControllerTest do
|> insert() |> insert()
|> with_block() |> with_block()
token_transfer = insert(:token_transfer, transaction: transaction, block_number: 1000, log_index: 1) insert(:token_transfer, transaction: transaction, block_number: 1000, log_index: 1)
Enum.each(2..5, fn item -> Enum.each(2..5, fn item ->
insert(:token_transfer, transaction: transaction, block_number: item + 1001, log_index: item + 1) insert(:token_transfer, transaction: transaction, block_number: item + 1001, log_index: item + 1)
@ -91,15 +86,16 @@ defmodule BlockScoutWeb.TransactionTokenTransferControllerTest do
conn = conn =
get(conn, transaction_token_transfer_path(BlockScoutWeb.Endpoint, :index, transaction.hash), %{ get(conn, transaction_token_transfer_path(BlockScoutWeb.Endpoint, :index, transaction.hash), %{
"block_number" => "1000", "block_number" => "1000",
"index" => "1" "index" => "1",
"type" => "JSON"
}) })
actual_log_indexes = Enum.map(conn.assigns.token_transfers, & &1.log_index) {:ok, %{"items" => items}} = conn.resp_body |> Poison.decode()
refute Enum.any?(actual_log_indexes, fn log_index -> log_index == token_transfer.log_index end) refute Enum.count(items) == 3
end end
test "next_page_params exist if not on last page", %{conn: conn} do test "next_page_path exists if not on last page", %{conn: conn} do
transaction = transaction =
:transaction :transaction
|> insert() |> insert()
@ -114,12 +110,15 @@ defmodule BlockScoutWeb.TransactionTokenTransferControllerTest do
) )
end) end)
conn = get(conn, transaction_token_transfer_path(BlockScoutWeb.Endpoint, :index, transaction.hash)) conn =
get(conn, transaction_token_transfer_path(BlockScoutWeb.Endpoint, :index, transaction.hash), %{type: "JSON"})
assert Enum.any?(conn.assigns.next_page_params) {:ok, %{"next_page_path" => path}} = conn.resp_body |> Poison.decode()
assert path
end end
test "next_page_params are empty if on last page", %{conn: conn} do test "next_page_path is empty if on last page", %{conn: conn} do
transaction = transaction =
:transaction :transaction
|> insert() |> insert()
@ -134,9 +133,12 @@ defmodule BlockScoutWeb.TransactionTokenTransferControllerTest do
) )
end) end)
conn = get(conn, transaction_token_transfer_path(BlockScoutWeb.Endpoint, :index, transaction.hash)) conn =
get(conn, transaction_token_transfer_path(BlockScoutWeb.Endpoint, :index, transaction.hash), %{type: "JSON"})
{:ok, %{"next_page_path" => path}} = conn.resp_body |> Poison.decode()
assert is_nil(conn.assigns.next_page_params) refute path
end end
test "preloads to_address smart contract verified", %{conn: conn} do test "preloads to_address smart contract verified", %{conn: conn} do

@ -175,7 +175,7 @@ defmodule Explorer.Chain.TokenTransfer do
from( from(
tt in TokenTransfer, tt in TokenTransfer,
where: tt.to_address_hash == ^address_hash, where: tt.to_address_hash == ^address_hash,
select: tt.transaction_hash select: type(tt.transaction_hash, :binary)
) )
query query
@ -189,7 +189,7 @@ defmodule Explorer.Chain.TokenTransfer do
from( from(
tt in TokenTransfer, tt in TokenTransfer,
where: tt.from_address_hash == ^address_hash, where: tt.from_address_hash == ^address_hash,
select: tt.transaction_hash select: type(tt.transaction_hash, :binary)
) )
query query

@ -247,9 +247,11 @@ defmodule Explorer.Chain.TokenTransferTest do
amount: 1 amount: 1
) )
{:ok, transaction_bytes} = Explorer.Chain.Hash.Full.dump(transaction.hash)
transactions_hashes = TokenTransfer.where_any_address_fields_match(:to, paul.hash, %PagingOptions{page_size: 1}) transactions_hashes = TokenTransfer.where_any_address_fields_match(:to, paul.hash, %PagingOptions{page_size: 1})
assert Enum.member?(transactions_hashes, transaction.hash) == true assert Enum.member?(transactions_hashes, transaction_bytes) == true
end end
test "when from_address_hash match returns transactions hashes list" do test "when from_address_hash match returns transactions hashes list" do
@ -283,9 +285,11 @@ defmodule Explorer.Chain.TokenTransferTest do
amount: 1 amount: 1
) )
{:ok, transaction_bytes} = Explorer.Chain.Hash.Full.dump(transaction.hash)
transactions_hashes = TokenTransfer.where_any_address_fields_match(:from, john.hash, %PagingOptions{page_size: 1}) transactions_hashes = TokenTransfer.where_any_address_fields_match(:from, john.hash, %PagingOptions{page_size: 1})
assert Enum.member?(transactions_hashes, transaction.hash) == true assert Enum.member?(transactions_hashes, transaction_bytes) == true
end end
test "when to_from_address_hash or from_address_hash match returns transactions hashes list" do test "when to_from_address_hash or from_address_hash match returns transactions hashes list" do

Loading…
Cancel
Save