Consolidate address rendering view function and partials

pull/688/head
Stamates 6 years ago
parent 849306a95b
commit a514f3f5b9
  1. 2
      apps/block_scout_web/lib/block_scout_web/templates/address/_link.html.eex
  2. 8
      apps/block_scout_web/lib/block_scout_web/templates/transaction/_tile.html.eex
  3. 4
      apps/block_scout_web/lib/block_scout_web/templates/transaction/_token_transfer.html.eex
  4. 4
      apps/block_scout_web/lib/block_scout_web/templates/transaction/overview.html.eex
  5. 78
      apps/block_scout_web/lib/block_scout_web/views/address_view.ex
  6. 92
      apps/block_scout_web/lib/block_scout_web/views/transaction_view.ex
  7. 45
      apps/block_scout_web/test/block_scout_web/views/address_view_test.exs

@ -1,5 +1,3 @@
<%= if @address_hash do %>
<%= link to: address_path(BlockScoutWeb.Endpoint, :show, @address_hash), "data-test": "address_hash_link" do %> <%= link to: address_path(BlockScoutWeb.Endpoint, :show, @address_hash), "data-test": "address_hash_link" do %>
<%= render BlockScoutWeb.AddressView, "_responsive_hash.html", address_hash: @address_hash, contract: @contract, truncate: assigns[:truncate] %> <%= render BlockScoutWeb.AddressView, "_responsive_hash.html", address_hash: @address_hash, contract: @contract, truncate: assigns[:truncate] %>
<% end %> <% end %>
<% end %>

@ -11,13 +11,9 @@
<div class="col-md-7 col-lg-8 d-flex flex-column pr-2 pr-sm-2 pr-md-0"> <div class="col-md-7 col-lg-8 d-flex flex-column pr-2 pr-sm-2 pr-md-0">
<%= render "_link.html", transaction_hash: @transaction.hash %> <%= render "_link.html", transaction_hash: @transaction.hash %>
<span class="text-nowrap"> <span class="text-nowrap">
<%= BlockScoutWeb.AddressView.display_address_hash(assigns[:current_address], @transaction.from_address) %> <%= BlockScoutWeb.AddressView.display_address_hash(assigns[:current_address], @transaction, :from) %>
&rarr; &rarr;
<%= if assigns[:current_address] && assigns[:current_address].hash == to_address_hash(@transaction) do %> <%= BlockScoutWeb.AddressView.display_address_hash(assigns[:current_address], @transaction, :to) %>
<%= render BlockScoutWeb.AddressView, "_responsive_hash.html", address_hash: to_address_hash(@transaction), contract: BlockScoutWeb.AddressView.contract?(@transaction.to_address) %>
<% else %>
<%= render BlockScoutWeb.AddressView, "_link.html", address_hash: to_address_hash(@transaction), contract: BlockScoutWeb.AddressView.contract?(@transaction.to_address) %>
<% end %>
</span> </span>
<span class="d-flex flex-md-row flex-column mt-3 mt-md-0"> <span class="d-flex flex-md-row flex-column mt-3 mt-md-0">
<span class="tile-title"> <span class="tile-title">

@ -11,9 +11,9 @@
</span> </span>
<% end %> <% end %>
<% end %> <% end %>
<%= BlockScoutWeb.AddressView.display_address_hash(@address, @token_transfer.from_address, true) %> <%= BlockScoutWeb.AddressView.display_address_hash(@address, @token_transfer, :from, true) %>
&rarr; &rarr;
<%= BlockScoutWeb.AddressView.display_address_hash(@address, @token_transfer.to_address, true) %> <%= BlockScoutWeb.AddressView.display_address_hash(@address, @token_transfer, :to, true) %>
</span> </span>
<span class="col-12 col-md-7 ml-3 ml-sm-0"> <span class="col-12 col-md-7 ml-3 ml-sm-0">
<%= token_transfer_amount(@token_transfer) %> <%= token_transfer_amount(@token_transfer) %>

@ -15,9 +15,9 @@
<h1 class="card-title"><%= gettext "Transaction Details" %> </h1> <h1 class="card-title"><%= gettext "Transaction Details" %> </h1>
<h3 data-test="transaction_detail_hash"><%= @transaction %> </h3> <h3 data-test="transaction_detail_hash"><%= @transaction %> </h3>
<span class="d-block mb-2 text-muted"> <span class="d-block mb-2 text-muted">
<%= BlockScoutWeb.AddressView.display_address_hash(assigns[:current_address], @transaction.from_address) %> <%= BlockScoutWeb.AddressView.display_address_hash(nil, @transaction, :from) %>
<span class="text-muted"> &rarr; </span> <span class="text-muted"> &rarr; </span>
<%= BlockScoutWeb.AddressView.display_address_hash(assigns[:current_address], @transaction.to_address) %> <%= BlockScoutWeb.AddressView.display_address_hash(nil, @transaction, :to) %>
</span> </span>
<div class="d-flex flex-row justify-content-start text-muted"> <div class="d-flex flex-row justify-content-start text-muted">
<span class="mr-4 text-<%= BlockScoutWeb.TransactionView.type_suffix(@transaction) %>"><%= BlockScoutWeb.TransactionView.transaction_display_type(@transaction) %></span> <span class="mr-4 text-<%= BlockScoutWeb.TransactionView.type_suffix(@transaction) %>"><%= BlockScoutWeb.TransactionView.transaction_display_type(@transaction) %></span>

@ -1,7 +1,7 @@
defmodule BlockScoutWeb.AddressView do defmodule BlockScoutWeb.AddressView do
use BlockScoutWeb, :view use BlockScoutWeb, :view
alias Explorer.Chain.{Address, Hash, SmartContract} alias Explorer.Chain.{Address, Hash, SmartContract, TokenTransfer, Transaction}
@dialyzer :no_match @dialyzer :no_match
@ -34,35 +34,30 @@ defmodule BlockScoutWeb.AddressView do
def contract?(nil), do: true def contract?(nil), do: true
def display_address_hash(current_address, target_address, truncate \\ false) def display_address_hash(current_address, struct_to_render_from, direction, truncate \\ false)
def display_address_hash(nil, nil, _truncate), do: gettext("Contract Address Pending") def display_address_hash(current_address, %TokenTransfer{to_address: address}, :to, truncate) do
display_hash(current_address, address.hash, contract?(address), truncate)
end
def display_address_hash(nil, target_address, truncate) do def display_address_hash(current_address, %TokenTransfer{from_address: address}, :from, truncate) do
render( display_hash(current_address, address.hash, contract?(address), truncate)
"_link.html",
address_hash: target_address.hash,
contract: contract?(target_address),
truncate: truncate
)
end end
def display_address_hash(current_address, target_address, truncate) do def display_address_hash(_current_address, %Transaction{to_address_hash: nil, created_contract_address_hash: nil}, :to, _truncate) do
if current_address.hash == target_address.hash do gettext("Contract Address Pending")
render(
"_responsive_hash.html",
address_hash: current_address.hash,
contract: contract?(current_address),
truncate: truncate
)
else
render(
"_link.html",
address_hash: target_address.hash,
contract: contract?(target_address),
truncate: truncate
)
end end
def display_address_hash(current_address, %Transaction{to_address_hash: nil, created_contract_address_hash: hash}, :to, truncate) do
display_hash(current_address, hash, true, truncate)
end
def display_address_hash(current_address, %Transaction{to_address: address}, :to, truncate) do
display_hash(current_address, address.hash, contract?(address), truncate)
end
def display_address_hash(current_address, %Transaction{from_address: address}, :from, truncate) do
display_hash(current_address, address.hash, contract?(address), truncate)
end end
def hash(%Address{hash: hash}) do def hash(%Address{hash: hash}) do
@ -80,6 +75,12 @@ defmodule BlockScoutWeb.AddressView do
def smart_contract_verified?(%Address{smart_contract: nil}), do: false def smart_contract_verified?(%Address{smart_contract: nil}), do: false
def smart_contract_with_read_only_functions?(%Address{smart_contract: %SmartContract{}} = address) do
Enum.any?(address.smart_contract.abi, & &1["constant"])
end
def smart_contract_with_read_only_functions?(%Address{smart_contract: nil}), do: false
def trimmed_hash(%Hash{} = hash) do def trimmed_hash(%Hash{} = hash) do
string_hash = to_string(hash) string_hash = to_string(hash)
"#{String.slice(string_hash, 0..5)}#{String.slice(string_hash, -6..-1)}" "#{String.slice(string_hash, 0..5)}#{String.slice(string_hash, -6..-1)}"
@ -87,9 +88,30 @@ defmodule BlockScoutWeb.AddressView do
def trimmed_hash(_), do: "" def trimmed_hash(_), do: ""
def smart_contract_with_read_only_functions?(%Address{smart_contract: %SmartContract{}} = address) do defp display_hash(nil, hash, contract?, truncate) do
Enum.any?(address.smart_contract.abi, & &1["constant"]) render(
"_link.html",
address_hash: hash,
contract: contract?,
truncate: truncate
)
end end
def smart_contract_with_read_only_functions?(%Address{smart_contract: nil}), do: false defp display_hash(current_address, hash, contract?, truncate) do
if current_address.hash == hash do
render(
"_responsive_hash.html",
address_hash: hash,
contract: contract?,
truncate: truncate
)
else
render(
"_link.html",
address_hash: hash,
contract: contract?,
truncate: truncate
)
end
end
end end

@ -10,6 +10,8 @@ defmodule BlockScoutWeb.TransactionView do
defguardp is_transaction_type(mod) when mod in [InternalTransaction, Transaction] defguardp is_transaction_type(mod) when mod in [InternalTransaction, Transaction]
defdelegate formatted_timestamp(block), to: BlockView
def confirmations(%Transaction{block: block}, named_arguments) when is_list(named_arguments) do def confirmations(%Transaction{block: block}, named_arguments) when is_list(named_arguments) do
case block do case block do
nil -> 0 nil -> 0
@ -17,22 +19,19 @@ defmodule BlockScoutWeb.TransactionView do
end end
end end
def from_or_to_address?(_token_transfer, nil), do: false def contract_creation?(%Transaction{to_address: nil}), do: true
def from_or_to_address?(%{from_address_hash: from_hash, to_address_hash: to_hash}, %Address{hash: hash}) do
from_hash == hash || to_hash == hash
end
# This is the address to be shown in the to field
def to_address_hash(%Transaction{to_address_hash: nil, created_contract_address_hash: address_hash}), do: address_hash
def to_address_hash(%Transaction{to_address: %Address{hash: address_hash}}), do: address_hash def contract_creation?(_), do: false
def fee(%Transaction{} = transaction) do def fee(%Transaction{} = transaction) do
{_, value} = Chain.fee(transaction, :wei) {_, value} = Chain.fee(transaction, :wei)
value value
end end
def format_gas_limit(gas) do
Number.to_string!(gas)
end
def formatted_fee(%Transaction{} = transaction, opts) do def formatted_fee(%Transaction{} = transaction, opts) do
transaction transaction
|> Chain.fee(:wei) |> Chain.fee(:wei)
@ -43,34 +42,6 @@ defmodule BlockScoutWeb.TransactionView do
end end
end end
def gas_used(%Transaction{gas_used: nil}), do: gettext("Pending")
def gas_used(%Transaction{gas_used: gas_used}) do
Number.to_string!(gas_used)
end
def involves_contract?(%Transaction{from_address: from_address, to_address: to_address}) do
AddressView.contract?(from_address) || AddressView.contract?(to_address)
end
def involves_token_transfers?(%Transaction{token_transfers: []}), do: false
def involves_token_transfers?(%Transaction{token_transfers: transfers}) when is_list(transfers), do: true
def contract_creation?(%Transaction{to_address: nil}), do: true
def contract_creation?(_), do: false
def qr_code(%Transaction{hash: hash}) do
hash
|> to_string()
|> QRCode.to_png()
|> Base.encode64()
end
def format_gas_limit(gas) do
Number.to_string!(gas)
end
def formatted_status(transaction) do def formatted_status(transaction) do
transaction transaction
|> Chain.transaction_to_status() |> Chain.transaction_to_status()
@ -82,7 +53,11 @@ defmodule BlockScoutWeb.TransactionView do
end end
end end
defdelegate formatted_timestamp(block), to: BlockView def from_or_to_address?(_token_transfer, nil), do: false
def from_or_to_address?(%{from_address_hash: from_hash, to_address_hash: to_hash}, %Address{hash: hash}) do
from_hash == hash || to_hash == hash
end
def gas(%type{gas: gas}) when is_transaction_type(type) do def gas(%type{gas: gas}) when is_transaction_type(type) do
Cldr.Number.to_string!(gas) Cldr.Number.to_string!(gas)
@ -95,23 +70,39 @@ defmodule BlockScoutWeb.TransactionView do
format_wei_value(gas_price, unit) format_wei_value(gas_price, unit)
end end
def gas_used(%Transaction{gas_used: nil}), do: gettext("Pending")
def gas_used(%Transaction{gas_used: gas_used}) do
Number.to_string!(gas_used)
end
def hash(%Transaction{hash: hash}) do def hash(%Transaction{hash: hash}) do
to_string(hash) to_string(hash)
end end
def status(transaction) do def involves_contract?(%Transaction{from_address: from_address, to_address: to_address}) do
Chain.transaction_to_status(transaction) AddressView.contract?(from_address) || AddressView.contract?(to_address)
end end
def type_suffix(%Transaction{} = transaction) do def involves_token_transfers?(%Transaction{token_transfers: []}), do: false
cond do def involves_token_transfers?(%Transaction{token_transfers: transfers}) when is_list(transfers), do: true
involves_token_transfers?(transaction) -> "token-transfer"
contract_creation?(transaction) -> "contract-creation" def qr_code(%Transaction{hash: hash}) do
involves_contract?(transaction) -> "contract-call" hash
true -> "transaction" |> to_string()
|> QRCode.to_png()
|> Base.encode64()
end end
def status(transaction) do
Chain.transaction_to_status(transaction)
end end
# This is the address to be shown in the to field
def to_address_hash(%Transaction{to_address_hash: nil, created_contract_address_hash: address_hash}), do: address_hash |> IO.inspect
def to_address_hash(%Transaction{to_address: %Address{hash: address_hash}}), do: address_hash
def transaction_display_type(%Transaction{} = transaction) do def transaction_display_type(%Transaction{} = transaction) do
cond do cond do
involves_token_transfers?(transaction) -> gettext("Token Transfer") involves_token_transfers?(transaction) -> gettext("Token Transfer")
@ -121,6 +112,15 @@ defmodule BlockScoutWeb.TransactionView do
end end
end end
def type_suffix(%Transaction{} = transaction) do
cond do
involves_token_transfers?(transaction) -> "token-transfer"
contract_creation?(transaction) -> "contract-creation"
involves_contract?(transaction) -> "contract-call"
true -> "transaction"
end
end
@doc """ @doc """
Converts a transaction's Wei value to Ether and returns a formatted display value. Converts a transaction's Wei value to Ether and returns a formatted display value.

@ -15,6 +15,51 @@ defmodule BlockScoutWeb.AddressViewTest do
address = insert(:address, contract_code: nil) address = insert(:address, contract_code: nil)
refute AddressView.contract?(address) refute AddressView.contract?(address)
end end
test "with nil address" do
assert AddressView.contract?(nil)
end
end
describe "display_address_hash/3" do
test "for a pending contract creation to address" do
transaction = insert(:transaction, to_address: nil, created_contract_address_hash: nil)
assert AddressView.display_address_hash(nil, transaction, :to) == "Contract Address Pending"
end
test "for a non-contract to address not on address page" do
transaction = insert(:transaction)
rendered_string =
nil
|> AddressView.display_address_hash(transaction, :to)
|> Phoenix.HTML.safe_to_string()
assert rendered_string =~ "responsive_hash"
assert rendered_string =~ "address_hash_link"
refute rendered_string =~ "contract-address"
end
test "for a non-contract to address non matching address page" do
transaction = insert(:transaction)
rendered_string =
:address
|> insert()
|> AddressView.display_address_hash(transaction, :to)
|> Phoenix.HTML.safe_to_string()
assert rendered_string =~ "responsive_hash"
assert rendered_string =~ "address_hash_link"
refute rendered_string =~ "contract-address"
end
test "for a non-contract to address matching address page" do
transaction = insert(:transaction)
rendered_string =
transaction.to_address
|> AddressView.display_address_hash(transaction, :to)
|> Phoenix.HTML.safe_to_string()
assert rendered_string =~ "responsive_hash"
refute rendered_string =~ "address_hash_link"
refute rendered_string =~ "contract-address"
end
end end
describe "qr_code/1" do describe "qr_code/1" do

Loading…
Cancel
Save