Merge branch 'master' into verify-link-to-other-explorers

pull/2040/head
Victor Baranov 6 years ago committed by GitHub
commit e7c62d778b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  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. 96
      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

@ -22,6 +22,7 @@
### Fixes
- [#2043](https://github.com/poanetwork/blockscout/pull/2043) - Fixed modal dialog width for 'verify other explorers'
- [#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.
@ -40,6 +41,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:314
@ -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:307
@ -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:309
@ -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:302
@ -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."
@ -1729,4 +1709,14 @@ msgstr ""
#, elixir-format
#: 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 ""
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