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. 70
      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. 84
      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. 44
      apps/block_scout_web/lib/block_scout_web/templates/block_transaction/index.html.eex
  14. 39
      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. 169
      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. 67
      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.
### 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
- [#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.
@ -38,6 +39,7 @@
- [#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
- [#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
- [#2009](https://github.com/poanetwork/blockscout/pull/2009) - addresses page improvements

@ -11,22 +11,24 @@ $tile-type-unique-token-image-color: $orange !default;
$tile-type-internal-transaction-color: $teal !default;
$tile-type-api-documentation-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;
@mixin generate-tile-block($prefix, $color, $label-color: false) {
&#{ $prefix } {
border-left: 4px solid $color;
a {
@if ($label-color) {
color: $label-color;
}
@else {
color: $color;
.tile-transaction-type-block {
a {
@if ($label-color) {
color: $label-color;
}
@else {
color: $color;
}
}
}
}
&.tile-type-#{ $prefix } {
border-left: 4px solid $color;
.tile-label {
@if ($label-color) {
@ -182,18 +184,20 @@ $tile-padding: 1rem;
line-height: 1.4rem;
padding: $tile-padding;
@include generate-tile-block('block', $tile-type-block-color, darken($tile-type-block-color, 20%));
@include generate-tile-block('uncle', $tile-type-uncle-color);
@include generate-tile-block('reorg', $tile-type-reorg-color);
@include generate-tile-block('emission-reward', $tile-type-emission-reward-color);
@include generate-tile-block('transaction', $tile-type-transaction-color);
@include generate-tile-block('contract-call', $tile-type-contract-call-color);
@include generate-tile-block('contract-creation', $tile-type-contract-creation-color);
@include generate-tile-block('token-transfer', $tile-type-token-transfer-color);
@include generate-tile-block('unique-token', $tile-type-unique-token-color);
@include generate-tile-block('unique-token-image', $tile-type-unique-token-image-color);
@include generate-tile-block('internal-transaction', $tile-type-internal-transaction-color);
@include generate-tile-block('api-documentation', $tile-type-api-documentation-color);
@include generate-tile-block('.tile-type-block', $tile-type-block-color, darken($tile-type-block-color, 20%));
@include generate-tile-block('.tile-type-uncle', $tile-type-uncle-color);
@include generate-tile-block('.tile-type-reorg', $tile-type-reorg-color);
@include generate-tile-block('.tile-type-emission-reward', $tile-type-emission-reward-color);
@include generate-tile-block('.tile-type-transaction', $tile-type-transaction-color);
@include generate-tile-block('.tile-type-contract-call', $tile-type-contract-call-color);
@include generate-tile-block('.tile-type-contract-creation', $tile-type-contract-creation-color);
@include generate-tile-block('.tile-type-token-transfer', $tile-type-token-transfer-color);
@include generate-tile-block('.tile-type-unique-token', $tile-type-unique-token-color);
@include generate-tile-block('.tile-type-unique-token-image', $tile-type-unique-token-image-color);
@include generate-tile-block('.tile-type-internal-transaction', $tile-type-internal-transaction-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 {
padding: 0;
@ -256,26 +260,6 @@ $tile-padding: 1rem;
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 {
background-color: #f5f6fa;

@ -6,13 +6,15 @@ defmodule BlockScoutWeb.AddressLogsController do
import BlockScoutWeb.AddressController, only: [transaction_count: 1, validation_count: 1]
import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1]
alias BlockScoutWeb.AddressLogsView
alias Explorer.{Chain, Market}
alias Explorer.ExchangeRates.Token
alias Indexer.Fetcher.CoinBalanceOnDemand
alias Phoenix.View
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),
{:ok, address} <- Chain.hash_to_address(address_hash) do
logs_plus_one = Chain.address_to_logs(address, paging_options(params))
@ -24,19 +26,45 @@ defmodule BlockScoutWeb.AddressLogsController do
nil
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
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(
conn,
"index.html",
address: address,
logs: results,
current_path: current_path(conn),
coin_balance_status: CoinBalanceOnDemand.trigger_fetch(address),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
transaction_count: transaction_count(address),
validation_count: validation_count(address),
next_page_url: next_page_url
validation_count: validation_count(address)
)
else
_ ->

@ -1,29 +1,71 @@
defmodule BlockScoutWeb.AddressTokenController do
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.ExchangeRates.Token
alias Indexer.Fetcher.CoinBalanceOnDemand
alias Phoenix.View
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]
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),
{:ok, address} <- Chain.hash_to_address(address_hash) do
tokens_plus_one = Chain.address_tokens_with_balance(address_hash, paging_options(params))
{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(
conn,
"index.html",
address: address,
current_path: current_path(conn),
coin_balance_status: CoinBalanceOnDemand.trigger_fetch(address),
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
transaction_count: transaction_count(address),
validation_count: validation_count(address),
next_page_params: next_page_params(next_page, tokens, params),
tokens: Market.add_price(tokens)
validation_count: validation_count(address)
)
else
:error ->

@ -5,20 +5,14 @@ defmodule BlockScoutWeb.BlockTransactionController do
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]
alias BlockScoutWeb.TransactionView
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} <-
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)
param_block_hash_or_number_to_block(formatted_block_hash_or_number, []) do
full_options =
Keyword.merge(
[
@ -36,13 +30,73 @@ defmodule BlockScoutWeb.BlockTransactionController do
{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(
conn,
"index.html",
block: block,
block_transaction_count: block_transaction_count,
next_page_params: next_page_params(next_page, transactions, params),
transactions: transactions
current_path: current_path(conn)
)
else
{:error, {:invalid, :hash}} ->

@ -1,12 +1,14 @@
defmodule BlockScoutWeb.Tokens.InventoryController do
use BlockScoutWeb, :controller
alias BlockScoutWeb.Tokens.InventoryView
alias Explorer.{Chain, Market}
alias Explorer.Chain.TokenTransfer
alias Phoenix.View
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),
{:ok, token} <- Chain.token_from_address_hash(address_hash) do
unique_tokens =
@ -17,14 +19,56 @@ defmodule BlockScoutWeb.Tokens.InventoryController do
{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(
conn,
"index.html",
current_path: current_path(conn),
token: Market.add_price(token),
unique_tokens: unique_tokens_paginated,
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),
next_page_params: unique_tokens_next_page(next_page, unique_tokens_paginated, params)
total_token_holders: token.holder_count || Chain.count_token_holders_from_token_hash(address_hash)
)
else
: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]
alias BlockScoutWeb.TransactionView
alias BlockScoutWeb.{InternalTransactionView, TransactionView}
alias Explorer.{Chain, Market}
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),
{:ok, 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)
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(
conn,
"index.html",
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
internal_transactions: internal_transactions,
current_path: current_path(conn),
block_height: Chain.block_height(),
show_token_transfers: Chain.transaction_has_token_transfers?(hash),
next_page_params: next_page_params(next_page, internal_transactions, params),
transaction: transaction
)
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]
alias BlockScoutWeb.TransactionView
alias BlockScoutWeb.{TransactionLogView, TransactionView}
alias Explorer.{Chain, Market}
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),
{: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
Chain.hash_to_transaction(transaction_hash) do
full_options =
Keyword.merge(
[
@ -35,13 +26,69 @@ defmodule BlockScoutWeb.TransactionLogController do
{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(
conn,
"index.html",
logs: logs,
block_height: Chain.block_height(),
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,
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]
alias BlockScoutWeb.TransactionView
alias BlockScoutWeb.{TransactionTokenTransferView, TransactionView}
alias Explorer.{Chain, Market}
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),
{: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
Chain.hash_to_transaction(hash) do
full_options =
Keyword.merge(
[
@ -37,13 +28,68 @@ defmodule BlockScoutWeb.TransactionTokenTransferController do
{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(
conn,
"index.html",
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
block_height: Chain.block_height(),
next_page_params: next_page_params(next_page, token_transfers, params),
token_transfers: token_transfers,
current_path: current_path(conn),
show_token_transfers: true,
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">
<%= 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>
<%= if @next_page_url do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, next_page_path: @next_page_url %>
<% end %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<%= if !@next_page_url do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %>
<% 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>
</button>
<%= if Enum.count(@logs) > 0 do %>
<%= for log <- @logs do %>
<div data-test="transaction_log" class="tile tile-muted">
<dl class="row">
<dt class="col-md-2"> <%= gettext "Transaction" %> </dt>
<dd class="col-md-10">
<h3 class="">
<%= link(
log.transaction,
to: transaction_path(@conn, :show, log.transaction),
"data-test": "log_address_link",
"data-address-hash": log.transaction
) %>
</h3>
</dd>
<dt class="col-md-2"><%= gettext "Topics" %></dt>
<dd class="col-md-10">
<div class="raw-transaction-log-topics">
<%= unless is_nil(log.first_topic) do %>
<div class="text-dark">
<span class="text-dark">[0]</span>
<%= log.first_topic %>
</div>
<% end %>
<%= unless is_nil(log.second_topic) do %>
<div class="text-dark">
<span class="">[1] </span>
<%= log.second_topic %>
</div>
<% end %>
<%= unless is_nil(log.third_topic) do %>
<div class="text-dark">
<span>[2]</span>
<%= log.third_topic %>
</div>
<% end %>
<%= unless is_nil(log.fourth_topic) do %>
<div class="text-dark">
<span>[3]</span>
<%= log.fourth_topic %>
</div>
<% end %>
</div>
</dd>
<dt class="col-md-2">
<%= gettext "Data" %>
</dt>
<dd class="col-md-10">
<%= unless is_nil(log.data) do %>
<div class="text-dark raw-transaction-log-data">
<%= log.data %>
</div>
<% end %>
</dd>
</dl>
<div data-empty-response-message style="display: none;">
<div class="tile tile-muted text-center" data-selector="empty-logs-list">
<%= gettext "There are no logs for this address." %>
</div>
<% end %>
<% else %>
<div class="tile tile-muted text-center">
<span><%= gettext "There are no logs for this address." %></span>
</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 %>
</div>
</div>
</section>

@ -4,49 +4,24 @@
<section>
<div class="card">
<%= 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>
<%= if @next_page_params do %>
<%= 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 %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<%= if !@next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %>
<% 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>
</button>
<%= if Enum.any?(@tokens) do %>
<%= for token <- @tokens do %>
<%= render "_tokens.html", conn: @conn, token: token, address: @address %>
<% end %>
<% else %>
<div class="tile tile-muted text-center">
<span><%= gettext "There are no tokens for this address." %></span>
<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 for this address." %>
</div>
<% end %>
</div>
<%= 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 %>
<div data-items></div>
<%= if !@next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<!--
<%= 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 %>
-->
<%= 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>
</div>
</section>

@ -13,38 +13,26 @@
)
%>
</div>
<div class="card-body">
<h2 class="card-title"><%= gettext "Transactions" %></h2>
<%= if @next_page_params do %>
<%= 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 %>
<%= if !@next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<%= if Enum.count(@transactions) > 0 do %>
<span data-selector="transactions-list">
<%= 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 class="card-body" data-async-load data-async-listing="<%= @current_path %>">
<h2 class="card-title"><%= gettext "Transactions" %></h2>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<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>
</button>
<div data-empty-response-message style="display: none;">
<div class="tile tile-muted text-center" data-selector="empty-transactions-list">
<%= gettext "There are no transactions for this block." %>
</div>
<% end %>
</div>
<%= 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_path(@conn, :index, @next_page_params) %>
<% end %>
<div data-items></div>
<%= if !@next_page_params do %>
<%= 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 %>
</div>
</div>
</section>
</section>

@ -12,28 +12,25 @@
<div class="card">
<%= render OverviewView, "_tabs.html", assigns %>
<div class="card-body">
<h2 class="card-title"><%= gettext "Inventory" %></h2>
<%= if Enum.any?(@unique_tokens) do %>
<%= for token_transfer <- @unique_tokens do %>
<%= render "_token.html", token_transfer: token_transfer %>
<% end %>
<% else %>
<div class="tile tile-muted text-center">
<span data-selector="empty-transactions-list">
<%= gettext "There are no tokens." %>
</span>
<div class="card-body" data-async-load data-async-listing="<%= @current_path %>">
<h2 class="card-title"><%= gettext "Inventory" %></h2>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<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>
</button>
<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." %>
</div>
<% end %>
<%= 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 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 %>
</div>
</div>
</section>

@ -2,49 +2,23 @@
<%= render BlockScoutWeb.TransactionView, "overview.html", assigns %>
<div class="card">
<%= render BlockScoutWeb.TransactionView, "_tabs.html", assigns %>
<div class="card-body">
<h2 class="card-title"><%= gettext "Internal Transactions" %></h2>
<div class="card-body" data-async-load data-async-listing="<%= @current_path %>">
<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, next_page_path: transaction_internal_transaction_path(@conn, :index, @transaction, @next_page_params) %>
<% end %>
<%= 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 %>
<%= if !@next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<%= if Enum.count(@internal_transactions) > 0 do %>
<%= for internal_transaction <- @internal_transactions do %>
<%= render BlockScoutWeb.InternalTransactionView, "_tile.html", internal_transaction: internal_transaction %>
<% end %>
<% else %>
<div class="tile tile-muted text-center">
<span><%= gettext "There are no internal transactions for this transaction." %></span>
<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>
</button>
<div data-empty-response-message style="display: none;">
<div class="tile tile-muted text-center" data-selector="empty-logs-list">
<%= gettext "There are no internal transactions for this transaction." %>
</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 %>
</div>
<%= if !@next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true %>
<% end %>
<div data-items></div>
<!--
<%= 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 %>
-->
<%= 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>
</div>
</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">
<%= 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>
<%= if @next_page_params do %>
<%= 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 %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<%= if !@next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %>
<% 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>
</button>
<%= if Enum.count(@logs) > 0 do %>
<%= for log <- @logs do %>
<div data-test="transaction_log" class="tile tile-muted">
<dl class="row">
<dt class="col-md-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 %>
</dd>
<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 data-empty-response-message style="display: none;">
<div class="tile tile-muted text-center" data-selector="empty-logs-list">
<%= gettext "There are no logs for this transaction." %>
</div>
<% end %>
<% else %>
<div class="tile tile-muted text-center">
<span><%= gettext "There are no logs for this transaction." %></span>
</div>
<% end %>
</div>
<%= 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 %>
<div data-items></div>
<%= if !@next_page_params do %>
<%= 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 u-float-right mt-3",
to: transaction_log_path(
@conn,
:index,
@transaction,
@next_page_params
)
) %>
<% end %>
-->
</div>
</div>
</section>

@ -3,34 +3,24 @@
<div class="card">
<%= 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>
<%= if @next_page_params do %>
<%= 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 %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
<%= if !@next_page_params do %>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true %>
<% 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>
</button>
<%= if Enum.any?(@token_transfers) do %>
<%= for token_transfer <- @token_transfers do %>
<%= render "_token_transfer.html", token_transfer: token_transfer, conn: @conn %>
<% end %>
<% else %>
<div class="tile tile-muted text-center">
<span><%= gettext "There are no token transfers for this transaction." %></span>
<div data-empty-response-message style="display: none;">
<div class="tile tile-muted text-center" data-selector="empty-logs-list">
<%= gettext "There are no token transfers for this transaction" %>
</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_token_transfer_path(@conn, :index, @transaction, @next_page_params) %>
<% end %>
<div data-items></div>
<%= if !@next_page_params do %>
<%= 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 %>
</div>
</div>

@ -98,7 +98,7 @@ msgstr ""
#, elixir-format
#: 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
msgid "Address"
msgstr ""
@ -327,10 +327,10 @@ msgid "Curl"
msgstr ""
#, 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_log/index.html.eex:67
#: lib/block_scout_web/templates/transaction_log/index.html.eex:133
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:113
msgid "Data"
msgstr ""
@ -500,7 +500,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:26
#: lib/block_scout_web/templates/address_logs/index.html.eex:8
#: lib/block_scout_web/templates/address_logs/index.html.eex:7
#: 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/views/address_view.ex:301
@ -558,7 +558,7 @@ msgstr ""
#, elixir-format
#: 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_log/index.html.eex:64
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:45
msgid "Name"
msgstr ""
@ -567,23 +567,6 @@ msgstr ""
msgid "New Smart Contract"
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
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:40
msgid "No"
@ -743,12 +726,12 @@ msgstr ""
#, 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."
msgstr ""
#, 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."
msgstr ""
@ -758,17 +741,12 @@ msgid "There are no token transfers for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:23
msgid "There are no token transfers for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token/index.html.eex:24
#: lib/block_scout_web/templates/address_token/index.html.eex:18
msgid "There are no tokens for this address."
msgstr ""
#, 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."
msgstr ""
@ -778,7 +756,7 @@ msgid "There are no transactions for this address."
msgstr ""
#, 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."
msgstr ""
@ -855,8 +833,8 @@ msgid "Top Accounts - %{subnetwork} Explorer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:33
#: lib/block_scout_web/templates/transaction_log/index.html.eex:103
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:14
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:83
msgid "Topics"
msgstr ""
@ -876,7 +854,7 @@ msgid "Total transactions"
msgstr ""
#, 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
msgid "Transaction"
msgstr ""
@ -900,7 +878,7 @@ msgstr ""
#: 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/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/layout/_topnav.html.eex:35
#: lib/block_scout_web/views/address_view.ex:294
@ -1163,18 +1141,18 @@ msgid "Static Call"
msgstr ""
#, 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"
msgstr ""
#, 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?"
msgstr ""
#, elixir-format
#: 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"
msgstr ""
@ -1184,7 +1162,7 @@ msgid "Method Id"
msgstr ""
#, 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."
msgstr ""
@ -1200,13 +1178,13 @@ msgstr ""
#, elixir-format
#: 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 "
msgstr ""
#, elixir-format
#: 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"
msgstr ""
@ -1222,31 +1200,38 @@ msgstr ""
#, elixir-format
#: 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"
msgstr ""
#, 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."
msgstr ""
#, 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"
msgstr ""
#, elixir-format
#: 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_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_transaction/index.html.eex:57
#: 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/pending_transaction/index.html.eex:19
#: 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/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."
msgstr ""
@ -1697,15 +1682,10 @@ msgid "Displaying the init data provided of the creating transaction."
msgstr ""
#, 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."
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/not_found.html.eex:12
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
msgid "It could still be in the TX Pool of a different node, waiting to be broadcasted."
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
#: 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
msgid "Address"
msgstr ""
@ -327,10 +327,10 @@ msgid "Curl"
msgstr ""
#, 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_log/index.html.eex:67
#: lib/block_scout_web/templates/transaction_log/index.html.eex:133
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:48
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:113
msgid "Data"
msgstr ""
@ -500,7 +500,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:26
#: lib/block_scout_web/templates/address_logs/index.html.eex:8
#: lib/block_scout_web/templates/address_logs/index.html.eex:7
#: 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/views/address_view.ex:301
@ -558,7 +558,7 @@ msgstr ""
#, elixir-format
#: 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_log/index.html.eex:64
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:45
msgid "Name"
msgstr ""
@ -567,23 +567,6 @@ msgstr ""
msgid "New Smart Contract"
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
#: lib/block_scout_web/templates/address_contract_verification/new.html.eex:40
msgid "No"
@ -743,12 +726,12 @@ msgstr ""
#, 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."
msgstr ""
#, 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."
msgstr ""
@ -758,17 +741,12 @@ msgid "There are no token transfers for this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:23
msgid "There are no token transfers for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_token/index.html.eex:24
#: lib/block_scout_web/templates/address_token/index.html.eex:18
msgid "There are no tokens for this address."
msgstr ""
#, 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."
msgstr ""
@ -778,7 +756,7 @@ msgid "There are no transactions for this address."
msgstr ""
#, 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."
msgstr ""
@ -855,8 +833,8 @@ msgid "Top Accounts - %{subnetwork} Explorer"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:33
#: lib/block_scout_web/templates/transaction_log/index.html.eex:103
#: lib/block_scout_web/templates/address_logs/_logs.html.eex:14
#: lib/block_scout_web/templates/transaction_log/_logs.html.eex:83
msgid "Topics"
msgstr ""
@ -876,7 +854,7 @@ msgid "Total transactions"
msgstr ""
#, 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
msgid "Transaction"
msgstr ""
@ -900,7 +878,7 @@ msgstr ""
#: 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/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/layout/_topnav.html.eex:35
#: lib/block_scout_web/views/address_view.ex:294
@ -1163,18 +1141,18 @@ msgid "Static Call"
msgstr ""
#, 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"
msgstr ""
#, 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?"
msgstr ""
#, elixir-format
#: 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"
msgstr ""
@ -1184,7 +1162,7 @@ msgid "Method Id"
msgstr ""
#, 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."
msgstr ""
@ -1200,13 +1178,13 @@ msgstr ""
#, elixir-format
#: 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 "
msgstr ""
#, elixir-format
#: 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"
msgstr ""
@ -1222,31 +1200,38 @@ msgstr ""
#, elixir-format
#: 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"
msgstr ""
#, 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."
msgstr ""
#, 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"
msgstr ""
#, elixir-format
#: 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_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_transaction/index.html.eex:57
#: 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/pending_transaction/index.html.eex:19
#: 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/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."
msgstr ""
@ -1697,15 +1682,10 @@ msgid "Displaying the init data provided of the creating transaction."
msgstr ""
#, 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."
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/not_found.html.eex:12
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
msgid "It could still be in the TX Pool of a different node, waiting to be broadcasted."
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
)
conn = get(conn, address_token_path(conn, :index, address))
conn = get(conn, address_token_path(conn, :index, address), type: "JSON")
actual_token_hashes =
conn.assigns.tokens
|> Enum.map(& &1.contract_address_hash)
{:ok, %{"items" => items}} =
conn.resp_body
|> Poison.decode()
assert html_response(conn, 200)
assert Enum.member?(actual_token_hashes, token1.contract_address_hash)
refute Enum.member?(actual_token_hashes, token2.contract_address_hash)
assert json_response(conn, 200)
assert Enum.any?(items, fn item -> String.contains?(item, to_string(token1.contract_address_hash)) end)
refute Enum.any?(items, fn item -> String.contains?(item, to_string(token2.contract_address_hash)) end)
end
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), %{
"token_name" => name,
"token_type" => type,
"token_inserted_at" => inserted_at
"token_inserted_at" => inserted_at,
"type" => "JSON"
})
actual_tokens =
conn.assigns.tokens
|> Enum.map(& &1.name)
|> Enum.sort()
{:ok, %{"items" => items}} =
conn.resp_body
|> Poison.decode()
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
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)
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")
{:ok, %{"next_page_path" => next_page_path}} =
conn.resp_body
|> Poison.decode()
assert conn.assigns.next_page_params
assert next_page_path
end
test "next_page_params are empty if on last page", %{conn: conn} do
@ -139,9 +145,13 @@ defmodule BlockScoutWeb.AddressTokenControllerTest do
token = insert(:token)
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

@ -39,10 +39,15 @@ defmodule BlockScoutWeb.BlockTransactionControllerTest do
|> with_block(block)
|> 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 2 == Enum.count(conn.assigns.transactions)
assert json_response(conn, 200)
{:ok, %{"items" => items}} =
conn.resp_body
|> Poison.decode()
assert Enum.count(items) == 2
end
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()
|> 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)
assert Enum.count(conn.assigns.transactions) == 1
{:ok, %{"items" => items}} =
conn.resp_body
|> Poison.decode()
assert Enum.count(items) == 1
end
test "does not return transactions for non-consensus block hash", %{conn: conn} do
@ -89,10 +99,15 @@ defmodule BlockScoutWeb.BlockTransactionControllerTest do
transaction = insert(:transaction)
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.count(conn.assigns.transactions) == 0
assert Enum.empty?(items)
end
test "does not return transactions for invalid block hash", %{conn: conn} do
@ -111,44 +126,62 @@ defmodule BlockScoutWeb.BlockTransactionControllerTest do
insert(:transaction)
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 Enum.empty?(conn.assigns.transactions)
assert json_response(conn, 200)
{:ok, %{"items" => items}} =
conn.resp_body
|> Poison.decode()
assert Enum.empty?(items)
end
test "does not return related transactions without a block", %{conn: conn} do
block = insert(:block)
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)
assert Enum.empty?(conn.assigns.transactions)
{:ok, %{"items" => items}} =
conn.resp_body
|> Poison.decode()
assert Enum.empty?(items)
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)
60
|> insert_list(:transaction)
|> 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
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)
:transaction
|> insert()
|> 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
test "displays miner primary address name", %{conn: conn} do

@ -62,13 +62,20 @@ defmodule BlockScoutWeb.Tokens.InventoryControllerTest do
conn =
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
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")
transaction =
@ -87,17 +94,16 @@ defmodule BlockScoutWeb.Tokens.InventoryControllerTest do
)
)
expected_next_page_params = %{
"token_id" => to_string(token.contract_address_hash),
"unique_token" => 1050
}
conn = get(conn, token_inventory_path(conn, :index, token.contract_address_hash), %{type: "JSON"})
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
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")
transaction =
@ -113,9 +119,13 @@ defmodule BlockScoutWeb.Tokens.InventoryControllerTest do
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

@ -3,7 +3,7 @@ defmodule BlockScoutWeb.TransactionInternalTransactionControllerTest do
import BlockScoutWeb.Router.Helpers, only: [transaction_internal_transaction_path: 3]
alias Explorer.Chain.{Block, InternalTransaction, Transaction}
alias Explorer.Chain.InternalTransaction
alias Explorer.ExchangeRates.Token
describe "GET index/3" do
@ -40,13 +40,12 @@ defmodule BlockScoutWeb.TransactionInternalTransactionControllerTest do
|> insert()
|> with_block(insert(:block, number: 1))
expected_internal_transaction =
insert(:internal_transaction,
transaction: transaction,
index: 0,
block_number: transaction.block_number,
transaction_index: transaction.index
)
insert(:internal_transaction,
transaction: transaction,
index: 0,
block_number: transaction.block_number,
transaction_index: transaction.index
)
insert(:internal_transaction,
transaction: transaction,
@ -57,14 +56,15 @@ defmodule BlockScoutWeb.TransactionInternalTransactionControllerTest do
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 =
Enum.map(conn.assigns.internal_transactions, &{&1.transaction_hash, &1.index})
{:ok, %{"items" => items}} =
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
test "includes USD exchange rate value for address in assigns", %{conn: conn} do
@ -135,21 +135,21 @@ defmodule BlockScoutWeb.TransactionInternalTransactionControllerTest do
conn =
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 =
conn.assigns.internal_transactions
|> Enum.map(& &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
test "next_page_params exist if not on last page", %{conn: conn} do
block = %Block{number: number} = insert(:block, number: 7000)
test "next_page_path exists if not on last page", %{conn: conn} do
block = insert(:block, number: 7000)
transaction =
%Transaction{index: transaction_index} =
:transaction
|> insert()
|> with_block(block)
@ -165,13 +165,19 @@ defmodule BlockScoutWeb.TransactionInternalTransactionControllerTest do
)
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()
assert %{"block_number" => ^number, "index" => 50, "transaction_index" => ^transaction_index} =
conn.assigns.next_page_params
assert next_page_path
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
|> insert()
@ -188,9 +194,16 @@ defmodule BlockScoutWeb.TransactionInternalTransactionControllerTest do
)
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

@ -31,11 +31,12 @@ defmodule BlockScoutWeb.TransactionLogControllerTest do
address = insert(:address)
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
test "returns logs for the transaction with nil to_address", %{conn: conn} do
@ -47,20 +48,23 @@ defmodule BlockScoutWeb.TransactionLogControllerTest do
address = insert(:address)
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
test "assigns no logs when there are none", %{conn: conn} do
transaction = insert(: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
test "returns next page of results based on last seen transaction log", %{conn: conn} do
@ -78,15 +82,16 @@ defmodule BlockScoutWeb.TransactionLogControllerTest do
conn =
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
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
|> insert()
@ -95,20 +100,24 @@ defmodule BlockScoutWeb.TransactionLogControllerTest do
1..60
|> 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"})
{:ok, %{"next_page_path" => path}} = conn.resp_body |> Poison.decode()
assert %{"index" => 50} = conn.assigns.next_page_params
assert path
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
|> insert()
|> 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

@ -48,24 +48,19 @@ defmodule BlockScoutWeb.TransactionTokenTransferControllerTest do
test "includes token transfers for the transaction", %{conn: conn} do
transaction = insert(:transaction)
expected_token_transfer = 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)
conn = get(conn, path)
conn = get(conn, path, %{type: "JSON"})
actual_token_transfer_primary_keys =
conn.assigns.token_transfers
|> Enum.map(&{&1.transaction_hash, &1.log_index})
assert json_response(conn, 200)
assert html_response(conn, 200)
{:ok, %{"items" => items}} = conn.resp_body |> Poison.decode()
assert Enum.member?(
actual_token_transfer_primary_keys,
{expected_token_transfer.transaction_hash, expected_token_transfer.log_index}
)
assert Enum.count(items) == 2
end
test "includes USD exchange rate value for address in assigns", %{conn: conn} do
@ -82,7 +77,7 @@ defmodule BlockScoutWeb.TransactionTokenTransferControllerTest do
|> insert()
|> 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 ->
insert(:token_transfer, transaction: transaction, block_number: item + 1001, log_index: item + 1)
@ -91,15 +86,16 @@ defmodule BlockScoutWeb.TransactionTokenTransferControllerTest do
conn =
get(conn, transaction_token_transfer_path(BlockScoutWeb.Endpoint, :index, transaction.hash), %{
"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
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
|> insert()
@ -114,12 +110,15 @@ defmodule BlockScoutWeb.TransactionTokenTransferControllerTest do
)
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
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
|> insert()
@ -134,9 +133,12 @@ defmodule BlockScoutWeb.TransactionTokenTransferControllerTest do
)
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
test "preloads to_address smart contract verified", %{conn: conn} do

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

@ -247,9 +247,11 @@ defmodule Explorer.Chain.TokenTransferTest do
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})
assert Enum.member?(transactions_hashes, transaction.hash) == true
assert Enum.member?(transactions_hashes, transaction_bytes) == true
end
test "when from_address_hash match returns transactions hashes list" do
@ -283,9 +285,11 @@ defmodule Explorer.Chain.TokenTransferTest do
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})
assert Enum.member?(transactions_hashes, transaction.hash) == true
assert Enum.member?(transactions_hashes, transaction_bytes) == true
end
test "when to_from_address_hash or from_address_hash match returns transactions hashes list" do

Loading…
Cancel
Save