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