add ERC-721 info to transaction overview page

pull/1789/head
Ayrat Badykov 6 years ago
parent d383c1a2bc
commit 723d683677
No known key found for this signature in database
GPG Key ID: B44668E265E9396F
  1. 28
      apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex
  2. 59
      apps/block_scout_web/lib/block_scout_web/views/transaction_view.ex
  3. 24
      apps/block_scout_web/test/block_scout_web/views/transaction_view_test.exs

@ -138,8 +138,9 @@
</div>
</div>
<% token_transfer = assigns[:token_transfers] && erc20_token_transfer(@transaction, @token_transfers) %>
<%= if token_transfer do %>
<%= cond do %>
<% erc20_token_transfer = assigns[:token_transfers] && erc20_token_transfer(@transaction, @token_transfers) -> %>
<div class="col-md-12 col-lg-4 d-flex flex-column flex-md-row flex-lg-column">
<!-- Value -->
<div class="card card-primary flex-grow-1">
@ -148,14 +149,31 @@
<div class="text-right">
<h3 class="text-white">
<span class="col-12 col-md-7 ml-3 ml-sm-0">
<%= token_transfer_amount(token_transfer) %>
<%= link(token_symbol(token_transfer.token), to: token_path(BlockScoutWeb.Endpoint, :show, token_transfer.token.contract_address_hash)) %>
<%= token_transfer_amount(erc20_token_transfer) %>
<%= link(token_symbol(erc20_token_transfer.token), to: token_path(BlockScoutWeb.Endpoint, :show, erc20_token_transfer.token.contract_address_hash)) %>
</span>
</h3>
</div>
</div>
</div>
<% else %>
<% erc721_token_transfer = assigns[:token_transfers] && erc721_token_transfer(@transaction, @token_transfers) -> %>
<div class="col-md-12 col-lg-4 d-flex flex-column flex-md-row flex-lg-column">
<!-- Value -->
<div class="card card-primary flex-grow-1">
<div class="card-body">
<h2 class="card-title text-white"><%= gettext "ERC-721" %> <%= gettext "Token Transfer" %></h2>
<div class="text-right">
<h3 class="text-white">
<span class="col-12 col-md-7 ml-3 ml-sm-0">
<%= token_transfer_amount(erc721_token_transfer) %>
<%= link(token_symbol(erc721_token_transfer.token), to: token_path(BlockScoutWeb.Endpoint, :show, erc721_token_transfer.token.contract_address_hash)) %>
</span>
</h3>
</div>
</div>
</div>
<% true -> %>
<div class="col-md-12 col-lg-4 d-flex flex-column flex-md-row flex-lg-column">
<!-- Value -->
<div class="card card-primary flex-grow-1">

@ -48,30 +48,67 @@ defmodule BlockScoutWeb.TransactionView do
{unquote(TokenTransfer.transfer_function_signature()) <> params, ^zero_wei} ->
types = [:address, {:uint, 256}]
try do
[address, value] =
params
|> Base.decode16!(case: :mixed)
|> TypeDecoder.decode_raw(types)
[address, value] = decode_params(params, types)
decimal_value = Decimal.new(value)
Enum.find(token_transfers, fn token_transfer ->
token_transfer.to_address_hash.bytes == address && token_transfer.amount == decimal_value
end)
rescue
_ -> nil
end
_ ->
nil
end
rescue
_ -> nil
end
def erc20_token_transfer(_, _) do
nil
end
def erc721_token_transfer(
%Transaction{
status: :ok,
created_contract_address_hash: nil,
input: input,
value: value
},
token_transfers
) do
zero_wei = %Wei{value: Decimal.new(0)}
# https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC721/ERC721.sol#L35
{from_address, to_address} =
case {to_string(input), value} do
{"0x23b872dd" <> params, ^zero_wei} ->
types = [:address, :address, {:uint, 256}]
[from_address, to_address, _value] = decode_params(params, types)
{from_address, to_address}
{"0x42842e0e" <> params, ^zero_wei} ->
types = [:address, :address, {:uint, 256}]
[from_address, to_address, _value] = decode_params(params, types)
{from_address, to_address}
{"0xb88d4fde" <> params, ^zero_wei} ->
types = [:address, :address, {:uint, 256}, :bytes]
[from_address, to_address, _value, _data] = decode_params(params, types)
{from_address, to_address}
_ ->
nil
end
Enum.find(token_transfers, fn token_transfer ->
token_transfer.from_address_hash.bytes == from_address && token_transfer.to_address_hash.bytes == to_address
end)
rescue
_ -> nil
end
def erc721_token_transfer(_, _), do: nil
def processing_time_duration(%Transaction{block: nil}) do
:pending
end
@ -298,4 +335,10 @@ defmodule BlockScoutWeb.TransactionView do
defp tab_name(["token_transfers"]), do: gettext("Token Transfers")
defp tab_name(["internal_transactions"]), do: gettext("Internal Transactions")
defp tab_name(["logs"]), do: gettext("Logs")
defp decode_params(params, types) do
params
|> Base.decode16!(case: :mixed)
|> TypeDecoder.decode_raw(types)
end
end

@ -47,6 +47,30 @@ defmodule BlockScoutWeb.TransactionViewTest do
end
end
describe "erc721_token_transfer/2" do
test "finds token transfer" do
from_address_hash = "0x7a30272c902563b712245696f0a81c5a0e45ddc8"
to_address_hash = "0xb544cead8b660aae9f2e37450f7be2ffbc501793"
from_address = insert(:address, hash: from_address_hash)
to_address = insert(:address, hash: to_address_hash)
block = insert(:block)
transaction =
insert(:transaction,
input:
"0x23b872dd0000000000000000000000007a30272c902563b712245696f0a81c5a0e45ddc8000000000000000000000000b544cead8b660aae9f2e37450f7be2ffbc5017930000000000000000000000000000000000000000000000000000000000000002",
value: Decimal.new(0),
created_contract_address_hash: nil
)
|> with_block(block, status: :ok)
token_transfer =
insert(:token_transfer, from_address: from_address, to_address: to_address, transaction: transaction)
assert TransactionView.erc721_token_transfer(transaction, [token_transfer]) == token_transfer
end
end
describe "processing_time_duration/2" do
test "returns :pending if the transaction has no block" do
transaction = build(:transaction, block: nil)

Loading…
Cancel
Save