Skip to content

Commit

Permalink
Improve explorer UI with decimals and symbol for token
Browse files Browse the repository at this point in the history
  • Loading branch information
Neylix committed Sep 22, 2022
1 parent 010a1d5 commit 8e298cc
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 44 deletions.
109 changes: 87 additions & 22 deletions lib/archethic_web/live/transaction_details_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ defmodule ArchethicWeb.TransactionDetailsLive do
alias Archethic.PubSub

alias Archethic.TransactionChain.Transaction
alias Archethic.TransactionChain.TransactionData
alias Archethic.TransactionChain.TransactionInput
alias Archethic.TransactionChain.TransactionData.Ledger
alias Archethic.TransactionChain.TransactionData.TokenLedger
alias Archethic.TransactionChain.TransactionData.TokenLedger.Transfer, as: TokenTransfer
alias Archethic.TransactionChain.Transaction.ValidationStamp
alias Archethic.TransactionChain.Transaction.ValidationStamp.LedgerOperations

alias Archethic.TransactionChain.Transaction.ValidationStamp.LedgerOperations.TransactionMovement

alias ArchethicWeb.ExplorerView

Expand Down Expand Up @@ -78,32 +87,88 @@ 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()

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
token_properties =
get_token_addresses([], ledger_inputs)
|> get_token_addresses(transaction_movements)
|> get_token_addresses(token_transfers)
|> Enum.uniq()
|> get_token_properties()

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_addresses(acc, [%TransactionMovement{type: {:token, token_address, _}} | rest]) do
get_token_addresses([token_address | acc], rest)
end

defp get_token_addresses(acc, [%TransactionInput{type: {:token, token_address, _}} | rest]) do
get_token_addresses([token_address | acc], rest)
end

defp get_token_addresses(acc, [%TokenTransfer{token_address: token_address} | rest]) do
get_token_addresses([token_address | acc], rest)
end

defp get_token_addresses(acc, [_ | rest]) do
get_token_addresses(acc, rest)
end

defp get_token_addresses(acc, []), do: acc

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}} ->
{token_address, content}

_ ->
:error
end
end)
|> Enum.reduce(%{}, fn
{:ok, {token_address, content}}, acc ->
case Jason.decode(content) do
{:ok, map} ->
properties = %{
decimals: Map.get(map, "decimals", 8),
symbol: Map.get(map, "symbol")
}

Map.put(acc, token_address, properties)

_ ->
acc
end

_, acc ->
acc
end)
end

defp handle_not_existing_transaction(socket, address) do
Expand Down
76 changes: 56 additions & 20 deletions lib/archethic_web/templates/explorer/transaction_details.html.leex
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
data_section: 'code',
operation_section: 'transaction_movements'
}" >
<h1 class="subtitle is-size-4 heading has-text-white">Transaction - <small><%= Base.encode16(@address) %></small></h1>
<div class="tabs is-fullwidth" >
<ul>
<li @click="tab_panel='tx' "
Expand Down Expand Up @@ -191,13 +190,26 @@
</div>
<div class="columns">
<div class="column is-1 heading">Amount</div>
<div class="column"><%= to_float(transfer.amount) %></div>
<div class="column">
<%= decimals = Map.get(@token_properties, transfer.token_address, %{}) |> Map.get(:decimals, 8)
to_float(transfer.amount, decimals) %>
</div>
</div>
<div class="columns">
<div class="column is-1 heading">Token</div>
<div class="column">
<%= link to: Routes.live_path(@socket, ArchethicWeb.TransactionDetailsLive, Base.encode16(transfer.token_address)) do%>
<span class="text_wrap"><%= Base.encode16(transfer.token_address) %></span>
<span class="text_wrap">
<%= case Map.get(@token_properties, transfer.token_address, %{}) |> Map.get(:symbol) do
nil -> Base.encode16(transfer.token_address)
symbol -> symbol
end %>
<%= if transfer.token_id >= 1 do %>
<span class="tag is-success is-light ml-2">
(#<%= transfer.token_id %>)
</span>
<% end %>
</span>
<% end %>
</div>
</div>
Expand Down Expand Up @@ -339,17 +351,21 @@
(<%= format_full_usd_amount(movement.amount, @uco_price_at_time[:usd], @uco_price_now[:usd]) %>)
<% end %>
<% {:token, token_address, token_id} -> %>
<%= to_float(movement.amount) %>
<%= decimals = Map.get(@token_properties, token_address, %{}) |> Map.get(:decimals, 8)
to_float(movement.amount, decimals) %>
<span class="tag is-success is-light ml-2">Token
<%= if token_id >= 1 do %>
(#<%= token_id %>)
<% end %>

<%= if token_id >= 1 do %>
(#<%= token_id %>)
<% end %>
</span>
<%= link to: Routes.live_path(@socket, ArchethicWeb.TransactionDetailsLive, Base.encode16(token_address)) do %>
<span><%= Base.encode16(:binary.part(token_address, 0, 13)) %>...</span>
<span>
<%= case Map.get(@token_properties, token_address, %{}) |> Map.get(:symbol) do
nil -> "#{Base.encode16(:binary.part(token_address, 0, 13))}..."
symbol -> symbol
end %>
</span>
<% end %>
</div>
<% end %>
</div>
</div>
Expand Down Expand Up @@ -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) %>
<span class="tag is-success is-light ml-2">Token
<%= if token_id >= 1 do %>
(#<%= token_id %>)
<% end %>
<%= if token_id >= 1 do %>
(#<%= token_id %>)
<% end %>
</span>
<%= link to: Routes.live_path(@socket, ArchethicWeb.TransactionDetailsLive, Base.encode16(token_address)) do %>
<span><%= Base.encode16(:binary.part(token_address, 0, 13)) %>...</span>
<span>
<%= case Map.get(@token_properties, token_address, %{}) |> Map.get(:symbol) do
nil -> "#{Base.encode16(:binary.part(token_address, 0, 13))}..."
symbol -> symbol
end %>
</span>
<% end %>
<% end %>
</div>
Expand Down Expand Up @@ -510,7 +532,16 @@
<div class="column heading">Amount</div>
</div>
<div class="columns">
<div class="column"><%= to_float(input.amount) %></div>
<div class="column">
<%= 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 %>
</div>
</div>
</div>
<div class="column">
Expand All @@ -533,10 +564,15 @@
<% end %>
</span></div>
<div class="column is-4-desktop">
<%= link to: Routes.live_path(@socket, ArchethicWeb.TransactionDetailsLive, Base.encode16(token_address)) do %>
<span class="is-hidden-mobile"><%= Base.encode16(:binary.part(token_address, 0, 6)) %>...</span>
<span class="is-hidden-desktop"><%= Base.encode16(:binary.part(token_address, 0, 12)) %>...</span>
<% 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 -> %>
<span class="is-hidden-mobile"><%= Base.encode16(:binary.part(token_address, 0, 6)) %>...</span>
<span class="is-hidden-desktop"><%= Base.encode16(:binary.part(token_address, 0, 12)) %>...</span>
<% symbol -> %>
<span><%= symbol %></span>
<% end
end %>
</div>
</div>
<% end %>
Expand Down
4 changes: 2 additions & 2 deletions lib/archethic_web/views/layout_helpers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 8e298cc

Please sign in to comment.