diff --git a/lib/archethic_web/live/transaction_details_live.ex b/lib/archethic_web/live/transaction_details_live.ex index 9ab946683f..757e2c0795 100644 --- a/lib/archethic_web/live/transaction_details_live.ex +++ b/lib/archethic_web/live/transaction_details_live.ex @@ -9,6 +9,11 @@ defmodule ArchethicWeb.TransactionDetailsLive do alias Archethic.PubSub alias Archethic.TransactionChain.Transaction + alias Archethic.TransactionChain.TransactionData + alias Archethic.TransactionChain.TransactionData.Ledger + alias Archethic.TransactionChain.TransactionData.TokenLedger + alias Archethic.TransactionChain.Transaction.ValidationStamp + alias Archethic.TransactionChain.Transaction.ValidationStamp.LedgerOperations alias ArchethicWeb.ExplorerView @@ -78,32 +83,86 @@ defmodule ArchethicWeb.TransactionDetailsLive do defp handle_transaction( socket, - tx = %Transaction{address: address} + tx = %Transaction{ + address: address, + data: %TransactionData{ + ledger: %Ledger{token: %TokenLedger{transfers: token_transfers}} + }, + validation_stamp: %ValidationStamp{ + ledger_operations: %LedgerOperations{transaction_movements: transaction_movements} + } + } ) do previous_address = Transaction.previous_address(tx) - with {:ok, balance} <- Archethic.get_balance(address), - inputs <- Archethic.get_transaction_inputs(address) do - ledger_inputs = Enum.reject(inputs, &(&1.type == :call)) - contract_inputs = Enum.filter(inputs, &(&1.type == :call)) - uco_price_at_time = tx.validation_stamp.timestamp |> OracleChain.get_uco_price() - uco_price_now = DateTime.utc_now() |> OracleChain.get_uco_price() + inputs = Archethic.get_transaction_inputs(address) + ledger_inputs = Enum.reject(inputs, &(&1.type == :call)) + contract_inputs = Enum.filter(inputs, &(&1.type == :call)) + uco_price_at_time = tx.validation_stamp.timestamp |> OracleChain.get_uco_price() + uco_price_now = DateTime.utc_now() |> OracleChain.get_uco_price() + + tokens = + Enum.reduce(ledger_inputs, [], fn input, acc -> + case input.type do + {:token, token_address, _} -> [token_address | acc] + _ -> acc + end + end) + + tokens = + Enum.reduce(transaction_movements, tokens, fn movement, acc -> + case movement.type do + {:token, token_address, _} -> [token_address | acc] + _ -> acc + end + end) + + token_properties = + Enum.reduce(token_transfers, tokens, fn transfer, acc -> + [transfer.token_address | acc] + end) + |> Enum.uniq() + |> get_token_properties() - socket - |> assign(:transaction, tx) - |> assign(:previous_address, previous_address) - |> assign(:balance, balance) - |> assign(:inputs, ledger_inputs) - |> assign(:calls, contract_inputs) - |> assign(:address, address) - |> assign(:uco_price_at_time, uco_price_at_time) - |> assign(:uco_price_now, uco_price_now) - else - {:error, :network_issue} -> - socket - |> assign(:error, :network_issue) - |> assign(:address, address) - end + socket + |> assign(:transaction, tx) + |> assign(:previous_address, previous_address) + |> assign(:inputs, ledger_inputs) + |> assign(:calls, contract_inputs) + |> assign(:address, address) + |> assign(:uco_price_at_time, uco_price_at_time) + |> assign(:uco_price_now, uco_price_now) + |> assign(:token_properties, token_properties) + end + + defp get_token_properties(token_addresses) do + Task.async_stream(token_addresses, fn token_address -> + case Archethic.search_transaction(token_address) do + {:ok, %Transaction{data: %TransactionData{content: content}, type: :token}} -> + case Jason.decode(content) do + {:ok, map} -> + properties = %{ + decimals: Map.get(map, "decimals", 8), + symbol: Map.get(map, "symbol") + } + + {token_address, properties} + + _ -> + :error + end + + _ -> + :error + end + end) + |> Enum.reduce(%{}, fn + {:ok, {token_address, properties}}, acc -> + Map.put(acc, token_address, properties) + + _, acc -> + acc + end) end defp handle_not_existing_transaction(socket, address) do diff --git a/lib/archethic_web/templates/explorer/transaction_details.html.leex b/lib/archethic_web/templates/explorer/transaction_details.html.leex index 8a036738fb..c9a002e27f 100644 --- a/lib/archethic_web/templates/explorer/transaction_details.html.leex +++ b/lib/archethic_web/templates/explorer/transaction_details.html.leex @@ -35,7 +35,6 @@ data_section: 'code', operation_section: 'transaction_movements' }" > -

Transaction - <%= Base.encode16(@address) %>

<% end %> @@ -381,14 +397,20 @@ (<%= format_full_usd_amount(unspent_output.amount, @uco_price_at_time[:usd], @uco_price_now[:usd]) %>) <% end %> <% {:token, token_address, token_id} -> %> - <%= to_float(unspent_output.amount) %> + <%= decimals = Map.get(@token_properties, token_address, %{}) |> Map.get(:decimals, 8) + to_float(unspent_output.amount, decimals) %> Token - <%= if token_id >= 1 do %> - (#<%= token_id %>) - <% end %> + <%= if token_id >= 1 do %> + (#<%= token_id %>) + <% end %> <%= link to: Routes.live_path(@socket, ArchethicWeb.TransactionDetailsLive, Base.encode16(token_address)) do %> - <%= Base.encode16(:binary.part(token_address, 0, 13)) %>... + + <%= case Map.get(@token_properties, token_address, %{}) |> Map.get(:symbol) do + nil -> "#{Base.encode16(:binary.part(token_address, 0, 13))}..." + symbol -> symbol + end %> + <% end %> <% end %> @@ -510,7 +532,16 @@
Amount
-
<%= to_float(input.amount) %>
+
+ <%= case input.type do + {:token, token_address, _} -> + decimals = Map.get(@token_properties, token_address, %{}) |> Map.get(:decimals, 8) + to_float(input.amount, decimals) + + _ -> + to_float(input.amount) + end %> +
@@ -533,10 +564,15 @@ <% end %>
- <%= link to: Routes.live_path(@socket, ArchethicWeb.TransactionDetailsLive, Base.encode16(token_address)) do %> - <%= Base.encode16(:binary.part(token_address, 0, 6)) %>... - <%= Base.encode16(:binary.part(token_address, 0, 12)) %>... - <% end %> + <%= link to: Routes.live_path(@socket, ArchethicWeb.TransactionDetailsLive, Base.encode16(token_address)) do + case Map.get(@token_properties, token_address, %{}) |> Map.get(:symbol) do %> + <% nil -> %> + <%= Base.encode16(:binary.part(token_address, 0, 6)) %>... + <%= Base.encode16(:binary.part(token_address, 0, 12)) %>... + <% symbol -> %> + <%= symbol %> + <% end + end %>
<% end %> diff --git a/lib/archethic_web/views/layout_helpers.ex b/lib/archethic_web/views/layout_helpers.ex index b044816569..9cba0cbc90 100644 --- a/lib/archethic_web/views/layout_helpers.ex +++ b/lib/archethic_web/views/layout_helpers.ex @@ -24,8 +24,8 @@ defmodule ArchethicWeb.LayoutHelpers do Sizeable.filesize(nb_bytes) end - def to_float(number) when is_number(number) do - :erlang.float_to_binary(number / 100_000_000, [:compact, decimals: 8]) + def to_float(number, decimals \\ 8) when is_number(number) do + :erlang.float_to_binary(number / :math.pow(10, decimals), [:compact, decimals: decimals]) end def format_usd_amount(uco_amount, uco_price) do