diff --git a/apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex index fe347ee904..e804ec81d9 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex @@ -177,7 +177,7 @@

<%= token_type_name(type)%><%= gettext " Token Transfer" %>

- <%= for transfer <- transaction_with_transfers.token_transfers do %> + <%= for transfer <- aggregate_token_transfers(transaction_with_transfers.token_transfers) do %>

<%= token_transfer_amount(transfer) %> diff --git a/apps/block_scout_web/lib/block_scout_web/views/tokens/helpers.ex b/apps/block_scout_web/lib/block_scout_web/views/tokens/helpers.ex index 1ad70179bf..33569f3a97 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/tokens/helpers.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/tokens/helpers.ex @@ -4,7 +4,7 @@ defmodule BlockScoutWeb.Tokens.Helpers do """ alias BlockScoutWeb.{CurrencyHelpers} - alias Explorer.Chain.{Address, Token, TokenTransfer} + alias Explorer.Chain.{Address, Token} @doc """ Returns the token transfers' amount according to the token's type and decimals. @@ -16,7 +16,7 @@ defmodule BlockScoutWeb.Tokens.Helpers do When the token's type is ERC-721, the function will return a string with the token_id that represents the ERC-721 token since this kind of token doesn't have amount and decimals. """ - def token_transfer_amount(%TokenTransfer{token: token, amount: amount, token_id: token_id}) do + def token_transfer_amount(%{token: token, amount: amount, token_id: token_id}) do do_token_transfer_amount(token, amount, token_id) end diff --git a/apps/block_scout_web/lib/block_scout_web/views/transaction_view.ex b/apps/block_scout_web/lib/block_scout_web/views/transaction_view.ex index 1ed50d28ab..885f0a3f2e 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/transaction_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/transaction_view.ex @@ -39,6 +39,25 @@ defmodule BlockScoutWeb.TransactionView do if type, do: {type, transaction_with_transfers} end + def aggregate_token_transfers(token_transfers) do + token_transfers + |> Enum.reduce(%{}, fn token_transfer, acc -> + new_entry = %{ + token: token_transfer.token, + amount: token_transfer.amount, + token_id: token_transfer.token_id + } + + existing_entry = Map.get(acc, token_transfer.token.contract_address_hash, %{new_entry | amount: Decimal.new(0)}) + + Map.put(acc, token_transfer.token.contract_address_hash, %{ + new_entry + | amount: Decimal.add(new_entry.amount, existing_entry.amount) + }) + end) + |> Enum.map(fn {_key, value} -> value end) + end + def token_type_name(type) do case type do :erc20 -> gettext("ERC-20 ") diff --git a/apps/block_scout_web/test/block_scout_web/views/transaction_view_test.exs b/apps/block_scout_web/test/block_scout_web/views/transaction_view_test.exs index 2a3e5492ed..8598f3826a 100644 --- a/apps/block_scout_web/test/block_scout_web/views/transaction_view_test.exs +++ b/apps/block_scout_web/test/block_scout_web/views/transaction_view_test.exs @@ -253,4 +253,20 @@ defmodule BlockScoutWeb.TransactionViewTest do assert TransactionView.current_tab_name(logs_path) == "Logs" end end + + describe "aggregate_token_transfers/1" do + test "aggregates token transfers" do + transaction = + :transaction + |> insert() + |> with_block() + + token_transfer = insert(:token_transfer, transaction: transaction, amount: Decimal.new(1)) + + result = TransactionView.aggregate_token_transfers([token_transfer, token_transfer, token_transfer]) + + assert Enum.count(result) == 1 + assert List.first(result).amount == Decimal.new(3) + end + end end diff --git a/apps/explorer/test/support/factory.ex b/apps/explorer/test/support/factory.ex index a6e07683a5..8bd8d586b5 100644 --- a/apps/explorer/test/support/factory.ex +++ b/apps/explorer/test/support/factory.ex @@ -413,7 +413,7 @@ defmodule Explorer.Factory do contract_code = Map.fetch!(contract_code_info(), :bytecode) token_address = insert(:contract_address, contract_code: contract_code) - insert(:token, contract_address: token_address) + token = insert(:token, contract_address: token_address) %TokenTransfer{ amount: Decimal.new(1), @@ -422,7 +422,8 @@ defmodule Explorer.Factory do to_address: to_address, token_contract_address: token_address, transaction: log.transaction, - log_index: log.index + log_index: log.index, + token: token } end