Merge pull request #204 from poanetwork/show-contract-bytecode

Show contract bytecode
pull/223/head
Igor Florian 7 years ago committed by GitHub
commit 2c0ea545c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      apps/explorer/lib/explorer/chain.ex
  2. 10
      apps/explorer/lib/explorer/chain/address.ex
  3. 2
      apps/explorer/lib/explorer/chain/internal_transaction.ex
  4. 44
      apps/explorer/lib/explorer/indexer/block_fetcher/address_extraction.ex
  5. 1
      apps/explorer/priv/repo/migrations/20180117221921_create_address.exs
  6. 28
      apps/explorer/test/explorer/chain_test.exs
  7. 60
      apps/explorer/test/explorer/indexer/block_fetcher/address_extraction_test.exs
  8. 27
      apps/explorer_web/lib/explorer_web/controllers/address_contract_controller.ex
  9. 7
      apps/explorer_web/lib/explorer_web/router.ex
  10. 2
      apps/explorer_web/lib/explorer_web/templates/address/overview.html.eex
  11. 41
      apps/explorer_web/lib/explorer_web/templates/address_contract/index.html.eex
  12. 9
      apps/explorer_web/lib/explorer_web/templates/address_internal_transaction/index.html.eex
  13. 9
      apps/explorer_web/lib/explorer_web/templates/address_transaction/index.html.eex
  14. 3
      apps/explorer_web/lib/explorer_web/views/address_contract_view.ex
  15. 2
      apps/explorer_web/lib/explorer_web/views/address_internal_transaction_view.ex
  16. 2
      apps/explorer_web/lib/explorer_web/views/address_transaction_view.ex
  17. 11
      apps/explorer_web/lib/explorer_web/views/address_view.ex
  18. 76
      apps/explorer_web/priv/gettext/default.pot
  19. 76
      apps/explorer_web/priv/gettext/en/LC_MESSAGES/default.po
  20. 46
      apps/explorer_web/test/explorer_web/controllers/address_contract_controller_test.exs

@ -429,6 +429,22 @@ defmodule Explorer.Chain do
end
end
def find_contract_address(%Hash{byte_count: unquote(Hash.Truncated.byte_count())} = hash) do
address =
Repo.one(
from(
address in Address,
where: address.hash == ^hash and not is_nil(address.contract_code)
)
)
if address do
{:ok, address}
else
{:error, :not_found}
end
end
@doc """
Converts the `Explorer.Chain.Hash.t:t/0` to `iodata` representation that can be written efficiently to users.

@ -5,10 +5,11 @@ defmodule Explorer.Chain.Address do
use Explorer.Schema
alias Explorer.Chain.{Hash, Wei}
alias Explorer.Chain.{Data, Hash, Wei}
@optional_attrs ~w()a
@optional_attrs ~w(contract_code)a
@required_attrs ~w(hash)a
@allowed_attrs @optional_attrs ++ @required_attrs
@typedoc """
Hash of the public key for this address.
@ -19,6 +20,7 @@ defmodule Explorer.Chain.Address do
* `fetched_balance` - The last fetched balance from Parity
* `balance_fetched_at` - the last time `balance` was fetched
* `hash` - the hash of the address's public key
* `contract_code` - the code of the contract when an Address is a contract
* `inserted_at` - when this address was inserted
* `updated_at` when this address was last updated
"""
@ -26,6 +28,7 @@ defmodule Explorer.Chain.Address do
fetched_balance: Wei.t(),
balance_fetched_at: DateTime.t(),
hash: Hash.Truncated.t(),
contract_code: Data.t() | nil,
inserted_at: DateTime.t(),
updated_at: DateTime.t()
}
@ -34,6 +37,7 @@ defmodule Explorer.Chain.Address do
schema "addresses" do
field(:fetched_balance, Wei)
field(:balance_fetched_at, Timex.Ecto.DateTime)
field(:contract_code, Data)
timestamps()
end
@ -47,7 +51,7 @@ defmodule Explorer.Chain.Address do
def changeset(%__MODULE__{} = address, attrs) do
address
|> cast(attrs, @required_attrs, @optional_attrs)
|> cast(attrs, @allowed_attrs)
|> validate_required(@required_attrs)
|> unique_constraint(:hash)
end

@ -8,7 +8,7 @@ defmodule Explorer.Chain.InternalTransaction do
@typedoc """
* `call_type` - the type of call. `nil` when `type` is not `:call`.
* `created_contract_code` - the code of the contract that was crarted when `type` is `:create`.
* `created_contract_code` - the code of the contract that was created when `type` is `:create`.
* `error` - error message when `:call` `type` errors
* `from_address` - the source of the `value`
* `from_address_hash` - hash of the source of the `value`

@ -26,6 +26,21 @@ defmodule Explorer.Indexer.BlockFetcher.AddressExtraction do
The structure above means any item in `blocks` list that has a `:miner_hash` attribute should
be mapped to a `hash` Address attribute.
Each item in the `List`s relates to a single Address. So, having more than one attribute definition
within an inner `List` means that the attributes are considered part of the same Address.
For example:
%{
internal_transactions: [
...,
[
%{from: :created_contract_address_hash, to: :hash},
%{from: :created_contract_code, to: :contract_code}
]
]
}
"""
@entity_to_address_map %{
@ -33,7 +48,10 @@ defmodule Explorer.Indexer.BlockFetcher.AddressExtraction do
internal_transactions: [
%{from: :from_address_hash, to: :hash},
%{from: :to_address_hash, to: :hash},
%{from: :created_contract_address_hash, to: :hash}
[
%{from: :created_contract_address_hash, to: :hash},
%{from: :created_contract_code, to: :contract_code}
]
],
transactions: [
%{from: :from_address_hash, to: :hash},
@ -50,7 +68,7 @@ defmodule Explorer.Indexer.BlockFetcher.AddressExtraction do
addresses
|> List.flatten()
|> Enum.uniq()
|> merge_addresses()
end
def extract_addresses_from_collection(items, fields),
@ -58,6 +76,18 @@ defmodule Explorer.Indexer.BlockFetcher.AddressExtraction do
def extract_addresses_from_item(item, fields), do: Enum.map(fields, &extract_address(&1, item))
defp extract_address(attrs, item) when is_list(attrs) do
Enum.reduce(attrs, %{}, fn field, acc ->
address = extract_address(field, item)
if is_list(address) do
address
else
Map.merge(address, acc)
end
end)
end
defp extract_address(%{from: from_attribute, to: to_attribute}, item) do
if value = Map.get(item, from_attribute) do
%{to_attribute => value}
@ -65,4 +95,14 @@ defmodule Explorer.Indexer.BlockFetcher.AddressExtraction do
[]
end
end
defp merge_addresses(addresses) do
addresses
|> Enum.group_by(fn address -> address.hash end)
|> Enum.map(fn {_, similar_addresses} ->
Enum.reduce(similar_addresses, %{}, fn address, acc ->
Map.merge(acc, address)
end)
end)
end
end

@ -6,6 +6,7 @@ defmodule Explorer.Repo.Migrations.CreateAddress do
add(:fetched_balance, :numeric, precision: 100)
add(:balance_fetched_at, :utc_datetime)
add(:hash, :bytea, null: false, primary_key: true)
add(:contract_code, :bytea, null: true)
timestamps(null: false)
end

@ -3,7 +3,7 @@ defmodule Explorer.ChainTest do
import Explorer.Factory
alias Explorer.{Chain, Repo}
alias Explorer.{Chain, Repo, Factory}
alias Explorer.Chain.{Address, Block, InternalTransaction, Log, Receipt, Transaction, Wei}
doctest Explorer.Chain
@ -834,4 +834,30 @@ defmodule Explorer.ChainTest do
assert Chain.value(%Transaction{value: %Wei{value: Decimal.new("1e18")}}, :ether) == Decimal.new(1)
end
end
describe "find_contract_address/1" do
test "doesn't find an address that doesn't have a code" do
address = insert(:address, contract_code: nil)
response = Chain.find_contract_address(address.hash)
assert {:error, :not_found} == response
end
test "doesn't find a unexistent address" do
unexistent_address_hash = Factory.address_hash()
response = Chain.find_contract_address(unexistent_address_hash)
assert {:error, :not_found} == response
end
test "finds an contract address" do
address = insert(:address, contract_code: Factory.data("contract_code"))
response = Chain.find_contract_address(address.hash)
assert response == {:ok, address}
end
end
end

@ -10,7 +10,8 @@ defmodule Explorer.Indexer.BlockFetcher.AddressExtractionTest do
internal_transaction = %{
from_address_hash: gen_hash(),
to_address_hash: gen_hash(),
created_contract_address_hash: gen_hash()
created_contract_address_hash: gen_hash(),
created_contract_code: "code"
}
transaction = %{
@ -31,10 +32,13 @@ defmodule Explorer.Indexer.BlockFetcher.AddressExtractionTest do
%{hash: block.miner_hash},
%{hash: internal_transaction.from_address_hash},
%{hash: internal_transaction.to_address_hash},
%{hash: internal_transaction.created_contract_address_hash},
%{hash: log.address_hash},
%{
hash: internal_transaction.created_contract_address_hash,
contract_code: internal_transaction.created_contract_code
},
%{hash: transaction.from_address_hash},
%{hash: transaction.to_address_hash}
%{hash: transaction.to_address_hash},
%{hash: log.address_hash}
]
end
@ -51,20 +55,23 @@ defmodule Explorer.Indexer.BlockFetcher.AddressExtractionTest do
assert Enum.empty?(addresses)
end
test "returns Address hashes without duplication" do
duplicated_hash = "0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca"
different_hash = "0x8bf38d4764929064f2d4d3a56520a76ab3df415b"
test "addresses get merged when they're duplicated by their hash" do
hash = "0xe8ddc5c7a2d2f0d7a9798459c0104fdf5e987aca"
blockchain_data = %{
blocks: [%{miner_hash: duplicated_hash}],
transactions: [%{from_address_hash: duplicated_hash}],
logs: [%{address_hash: different_hash}]
blocks: [%{miner_hash: hash}],
transactions: [%{from_address_hash: hash}],
internal_transactions: [
%{
created_contract_address_hash: hash,
created_contract_code: "code"
}
]
}
assert AddressExtraction.extract_addresses(blockchain_data) ==
[
%{hash: duplicated_hash},
%{hash: different_hash}
%{hash: hash, contract_code: "code"}
]
end
@ -88,7 +95,7 @@ defmodule Explorer.Indexer.BlockFetcher.AddressExtractionTest do
describe "extract_addresses_from_collection/2" do
test "returns all matched addresses" do
fields = [
fields_map = [
%{from: :field_1, to: :hash},
%{from: :field_2, to: :hash}
]
@ -98,7 +105,7 @@ defmodule Explorer.Indexer.BlockFetcher.AddressExtractionTest do
%{field_1: "hash1", field_2: "hash3"}
]
assert AddressExtraction.extract_addresses_from_collection(items, fields) == [
assert AddressExtraction.extract_addresses_from_collection(items, fields_map) == [
%{hash: "hash1"},
%{hash: "hash2"},
%{hash: "hash1"},
@ -120,7 +127,7 @@ defmodule Explorer.Indexer.BlockFetcher.AddressExtractionTest do
assert response == [%{hash: "hash1"}]
end
test "different attributes of the same item becomes different addresses" do
test "attributes of the same item defined separately in the fields map fetches different addresses" do
fields_map = [
%{from: :field_1, to: :hash},
%{from: :field_2, to: :hash}
@ -132,6 +139,29 @@ defmodule Explorer.Indexer.BlockFetcher.AddressExtractionTest do
assert response == [%{hash: "hash1"}, %{hash: "hash2"}]
end
test "a list of attributes in the fields map references the same address" do
fields_map = [
%{from: :field_1, to: :hash},
[
%{from: :field_2, to: :hash},
%{from: :field_2_code, to: :code}
]
]
data = %{field_1: "hash1", field_2: "hash2", field_2_code: "code"}
response =
AddressExtraction.extract_addresses_from_item(
data,
fields_map
)
assert response == [
%{hash: "hash1"},
%{code: "code", hash: "hash2"}
]
end
end
defp gen_hash() do

@ -0,0 +1,27 @@
defmodule ExplorerWeb.AddressContractController do
use ExplorerWeb, :controller
import ExplorerWeb.AddressController, only: [transaction_count: 1]
alias Explorer.{Chain, Market}
alias Explorer.ExchangeRates.Token
def index(conn, %{"address_id" => address_hash_string}) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.find_contract_address(address_hash) do
render(
conn,
"index.html",
address: address,
exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(),
transaction_count: transaction_count(address)
)
else
:error ->
not_found(conn)
{:error, :not_found} ->
not_found(conn)
end
end
end

@ -59,6 +59,13 @@ defmodule ExplorerWeb.Router do
only: [:index],
as: :internal_transaction
)
resources(
"/contracts",
AddressContractController,
only: [:index],
as: :contract
)
end
get("/search", ChainController, :search)

@ -1,5 +1,5 @@
<section>
<h1><%= gettext "Address" %></h1>
<h1><%= address_title(@address) %></h1>
<p data-test="address_detail_hash"><%= @address %></p>
<div class="card mb-3">

@ -0,0 +1,41 @@
<section class="container-fluid">
<%= render ExplorerWeb.AddressView, "overview.html", assigns %>
<div class="card">
<div class="card-header">
<ul class="nav nav-tabs card-header-tabs">
<li class="nav-item">
<%= link(
gettext("Transactions"),
class: "nav-link",
to: address_transaction_path(@conn, :index, @conn.assigns.locale, @conn.params["address_id"])
) %>
</li>
<li class="nav-item">
<%= link(
gettext("Internal Transactions"),
class: "nav-link",
"data-test": "internal_transactions_tab_link",
to: address_internal_transaction_path(@conn, :index, @conn.assigns.locale, @conn.params["address_id"])
) %>
</li>
<li class="nav-item">
<%= link(
gettext("Contract"),
class: "nav-link active",
to: address_contract_path(@conn, :index, @conn.assigns.locale, @conn.params["address_id"])
) %>
</li>
</ul>
</div>
<div class="card-body">
<h2 class="card-title"><%= gettext "Contract bytecode" %></h2>
<pre class="pre-wrap p-2 bg-light mb-0">
<code><%= @address.contract_code %></code>
</pre>
</div>
</div>
</section>

@ -21,6 +21,15 @@
to: address_internal_transaction_path(@conn, :index, @conn.assigns.locale, @conn.params["address_id"])
) %>
</li>
<%= if contract?(@address) do %>
<li class="nav-item">
<%= link(
gettext("Contract"),
class: "nav-link",
to: address_contract_path(@conn, :index, @conn.assigns.locale, @conn.params["address_id"])
) %>
</li>
<% end %>
</ul>
</div>
<div class="card-body">

@ -21,6 +21,15 @@
to: address_internal_transaction_path(@conn, :index, @conn.assigns.locale, @conn.params["address_id"])
) %>
</li>
<%= if contract?(@address) do %>
<li class="nav-item">
<%= link(
gettext("Contract"),
class: "nav-link",
to: address_contract_path(@conn, :index, @conn.assigns.locale, @conn.params["address_id"])
) %>
</li>
<% end %>
</ul>
</div>
<div class="card-body">

@ -0,0 +1,3 @@
defmodule ExplorerWeb.AddressContractView do
use ExplorerWeb, :view
end

@ -1,6 +1,8 @@
defmodule ExplorerWeb.AddressInternalTransactionView do
use ExplorerWeb, :view
import ExplorerWeb.AddressView, only: [contract?: 1]
def format_current_filter(filter) do
case filter do
"to" -> gettext("To")

@ -1,6 +1,8 @@
defmodule ExplorerWeb.AddressTransactionView do
use ExplorerWeb, :view
import ExplorerWeb.AddressView, only: [contract?: 1]
alias ExplorerWeb.TransactionView
def format_current_filter(filter) do

@ -7,6 +7,17 @@ defmodule ExplorerWeb.AddressView do
@dialyzer :no_match
def contract?(%Address{contract_code: nil}), do: false
def contract?(%Address{contract_code: _}), do: true
def address_title(%Address{} = address) do
if contract?(address) do
gettext("Contract Address")
else
gettext("Address")
end
end
def balance(%Address{fetched_balance: nil}), do: ""
@doc """

@ -1,5 +1,5 @@
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:72
#: lib/explorer_web/templates/address_transaction/index.html.eex:74
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:81
#: lib/explorer_web/templates/address_transaction/index.html.eex:83
#: lib/explorer_web/templates/block/index.html.eex:18
#: lib/explorer_web/templates/block_transaction/index.html.eex:140
#: lib/explorer_web/templates/chain/_blocks.html.eex:8
@ -9,8 +9,8 @@
msgid "Age"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:71
#: lib/explorer_web/templates/address_transaction/index.html.eex:73
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:80
#: lib/explorer_web/templates/address_transaction/index.html.eex:82
#: lib/explorer_web/templates/block_transaction/index.html.eex:139
#: lib/explorer_web/templates/chain/show.html.eex:7
#: lib/explorer_web/templates/transaction/index.html.eex:35
@ -33,7 +33,7 @@ msgstr ""
msgid "Gas Used"
msgstr ""
#: lib/explorer_web/templates/address_transaction/index.html.eex:72
#: lib/explorer_web/templates/address_transaction/index.html.eex:81
#: lib/explorer_web/templates/block_transaction/index.html.eex:30
#: lib/explorer_web/templates/block_transaction/index.html.eex:138
#: lib/explorer_web/templates/pending_transaction/index.html.eex:35
@ -50,6 +50,7 @@ msgstr ""
msgid "POA Network Explorer"
msgstr ""
#: lib/explorer_web/templates/address_contract/index.html.eex:10
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:11
#: lib/explorer_web/templates/address_transaction/index.html.eex:11
#: lib/explorer_web/templates/block/index.html.eex:19
@ -60,8 +61,8 @@ msgstr ""
msgid "Transactions"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:75
#: lib/explorer_web/templates/address_transaction/index.html.eex:78
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:84
#: lib/explorer_web/templates/address_transaction/index.html.eex:87
#: lib/explorer_web/templates/block_transaction/index.html.eex:144
#: lib/explorer_web/templates/chain/_transactions.html.eex:10
#: lib/explorer_web/templates/pending_transaction/index.html.eex:39
@ -151,23 +152,23 @@ msgstr ""
msgid "%{count} transactions in this block"
msgstr ""
#: lib/explorer_web/templates/address/overview.html.eex:2
#: lib/explorer_web/templates/transaction_log/index.html.eex:29
#: lib/explorer_web/views/address_view.ex:17
msgid "Address"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:54
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:73
#: lib/explorer_web/templates/address_transaction/index.html.eex:52
#: lib/explorer_web/templates/address_transaction/index.html.eex:75
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:63
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:82
#: lib/explorer_web/templates/address_transaction/index.html.eex:61
#: lib/explorer_web/templates/address_transaction/index.html.eex:84
#: lib/explorer_web/templates/block_transaction/index.html.eex:141
#: lib/explorer_web/templates/chain/_transactions.html.eex:8
#: lib/explorer_web/templates/pending_transaction/index.html.eex:37
#: lib/explorer_web/templates/transaction/index.html.eex:37
#: lib/explorer_web/templates/transaction/overview.html.eex:55
#: lib/explorer_web/templates/transaction_internal_transaction/index.html.eex:31
#: lib/explorer_web/views/address_internal_transaction_view.ex:7
#: lib/explorer_web/views/address_transaction_view.ex:9
#: lib/explorer_web/views/address_internal_transaction_view.ex:9
#: lib/explorer_web/views/address_transaction_view.ex:11
msgid "From"
msgstr ""
@ -180,18 +181,18 @@ msgstr ""
msgid "Success"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:42
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:74
#: lib/explorer_web/templates/address_transaction/index.html.eex:40
#: lib/explorer_web/templates/address_transaction/index.html.eex:77
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:51
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:83
#: lib/explorer_web/templates/address_transaction/index.html.eex:49
#: lib/explorer_web/templates/address_transaction/index.html.eex:86
#: lib/explorer_web/templates/block_transaction/index.html.eex:143
#: lib/explorer_web/templates/chain/_transactions.html.eex:9
#: lib/explorer_web/templates/pending_transaction/index.html.eex:38
#: lib/explorer_web/templates/transaction/index.html.eex:38
#: lib/explorer_web/templates/transaction/overview.html.eex:71
#: lib/explorer_web/templates/transaction_internal_transaction/index.html.eex:32
#: lib/explorer_web/views/address_internal_transaction_view.ex:6
#: lib/explorer_web/views/address_transaction_view.ex:8
#: lib/explorer_web/views/address_internal_transaction_view.ex:8
#: lib/explorer_web/views/address_transaction_view.ex:10
msgid "To"
msgstr ""
@ -310,7 +311,7 @@ msgstr ""
msgid "Out of Gas"
msgstr ""
#: lib/explorer_web/templates/address_transaction/index.html.eex:70
#: lib/explorer_web/templates/address_transaction/index.html.eex:79
#: lib/explorer_web/templates/block_transaction/index.html.eex:136
#: lib/explorer_web/templates/pending_transaction/index.html.eex:33
#: lib/explorer_web/templates/transaction/index.html.eex:33
@ -325,8 +326,8 @@ msgstr ""
msgid "Showing #%{number}"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:75
#: lib/explorer_web/templates/address_transaction/index.html.eex:78
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:84
#: lib/explorer_web/templates/address_transaction/index.html.eex:87
#: lib/explorer_web/templates/chain/_transactions.html.eex:10
#: lib/explorer_web/templates/pending_transaction/index.html.eex:39
#: lib/explorer_web/templates/transaction/index.html.eex:39
@ -340,6 +341,7 @@ msgstr ""
msgid "Gwei"
msgstr ""
#: lib/explorer_web/templates/address_contract/index.html.eex:17
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:18
#: lib/explorer_web/templates/address_transaction/index.html.eex:18
#: lib/explorer_web/templates/transaction_internal_transaction/index.html.eex:11
@ -351,7 +353,7 @@ msgstr ""
msgid "Search by address, transaction hash, or block number"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:101
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:110
#: lib/explorer_web/templates/transaction_internal_transaction/index.html.eex:53
msgid "There are no Internal Transactions"
msgstr ""
@ -380,14 +382,14 @@ msgstr ""
msgid "Wei"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:36
#: lib/explorer_web/templates/address_transaction/index.html.eex:34
#: lib/explorer_web/views/address_internal_transaction_view.ex:8
#: lib/explorer_web/views/address_transaction_view.ex:10
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:45
#: lib/explorer_web/templates/address_transaction/index.html.eex:43
#: lib/explorer_web/views/address_internal_transaction_view.ex:10
#: lib/explorer_web/views/address_transaction_view.ex:12
msgid "All"
msgstr ""
#: lib/explorer_web/templates/address_transaction/index.html.eex:79
#: lib/explorer_web/templates/address_transaction/index.html.eex:88
msgid "Fee"
msgstr ""
@ -402,7 +404,7 @@ msgstr ""
msgid "Block Details"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:70
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:79
msgid "Parent Tx Hash"
msgstr ""
@ -478,3 +480,17 @@ msgstr ""
#: lib/explorer_web/templates/transaction/overview.html.eex:136
msgid "TX Fee"
msgstr ""
#: lib/explorer_web/templates/address_contract/index.html.eex:25
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:27
#: lib/explorer_web/templates/address_transaction/index.html.eex:27
msgid "Contract"
msgstr ""
#: lib/explorer_web/views/address_view.ex:15
msgid "Contract Address"
msgstr ""
#: lib/explorer_web/templates/address_contract/index.html.eex:34
msgid "Contract bytecode"
msgstr ""

@ -10,8 +10,8 @@ msgid ""
msgstr ""
"Language: en\n"
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:72
#: lib/explorer_web/templates/address_transaction/index.html.eex:74
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:81
#: lib/explorer_web/templates/address_transaction/index.html.eex:83
#: lib/explorer_web/templates/block/index.html.eex:18
#: lib/explorer_web/templates/block_transaction/index.html.eex:140
#: lib/explorer_web/templates/chain/_blocks.html.eex:8
@ -21,8 +21,8 @@ msgstr ""
msgid "Age"
msgstr "Age"
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:71
#: lib/explorer_web/templates/address_transaction/index.html.eex:73
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:80
#: lib/explorer_web/templates/address_transaction/index.html.eex:82
#: lib/explorer_web/templates/block_transaction/index.html.eex:139
#: lib/explorer_web/templates/chain/show.html.eex:7
#: lib/explorer_web/templates/transaction/index.html.eex:35
@ -45,7 +45,7 @@ msgstr "%{year} POA Network Ltd. All rights reserved"
msgid "Gas Used"
msgstr "Gas Used"
#: lib/explorer_web/templates/address_transaction/index.html.eex:72
#: lib/explorer_web/templates/address_transaction/index.html.eex:81
#: lib/explorer_web/templates/block_transaction/index.html.eex:30
#: lib/explorer_web/templates/block_transaction/index.html.eex:138
#: lib/explorer_web/templates/pending_transaction/index.html.eex:35
@ -62,6 +62,7 @@ msgstr "Height"
msgid "POA Network Explorer"
msgstr "POA Network Explorer"
#: lib/explorer_web/templates/address_contract/index.html.eex:10
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:11
#: lib/explorer_web/templates/address_transaction/index.html.eex:11
#: lib/explorer_web/templates/block/index.html.eex:19
@ -72,8 +73,8 @@ msgstr "POA Network Explorer"
msgid "Transactions"
msgstr "Transactions"
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:75
#: lib/explorer_web/templates/address_transaction/index.html.eex:78
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:84
#: lib/explorer_web/templates/address_transaction/index.html.eex:87
#: lib/explorer_web/templates/block_transaction/index.html.eex:144
#: lib/explorer_web/templates/chain/_transactions.html.eex:10
#: lib/explorer_web/templates/pending_transaction/index.html.eex:39
@ -163,23 +164,23 @@ msgstr "%{confirmations} block confirmations"
msgid "%{count} transactions in this block"
msgstr "%{count} transactions in this block"
#: lib/explorer_web/templates/address/overview.html.eex:2
#: lib/explorer_web/templates/transaction_log/index.html.eex:29
#: lib/explorer_web/views/address_view.ex:17
msgid "Address"
msgstr "Address"
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:54
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:73
#: lib/explorer_web/templates/address_transaction/index.html.eex:52
#: lib/explorer_web/templates/address_transaction/index.html.eex:75
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:63
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:82
#: lib/explorer_web/templates/address_transaction/index.html.eex:61
#: lib/explorer_web/templates/address_transaction/index.html.eex:84
#: lib/explorer_web/templates/block_transaction/index.html.eex:141
#: lib/explorer_web/templates/chain/_transactions.html.eex:8
#: lib/explorer_web/templates/pending_transaction/index.html.eex:37
#: lib/explorer_web/templates/transaction/index.html.eex:37
#: lib/explorer_web/templates/transaction/overview.html.eex:55
#: lib/explorer_web/templates/transaction_internal_transaction/index.html.eex:31
#: lib/explorer_web/views/address_internal_transaction_view.ex:7
#: lib/explorer_web/views/address_transaction_view.ex:9
#: lib/explorer_web/views/address_internal_transaction_view.ex:9
#: lib/explorer_web/views/address_transaction_view.ex:11
msgid "From"
msgstr "From"
@ -192,18 +193,18 @@ msgstr "Overview"
msgid "Success"
msgstr "Success"
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:42
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:74
#: lib/explorer_web/templates/address_transaction/index.html.eex:40
#: lib/explorer_web/templates/address_transaction/index.html.eex:77
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:51
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:83
#: lib/explorer_web/templates/address_transaction/index.html.eex:49
#: lib/explorer_web/templates/address_transaction/index.html.eex:86
#: lib/explorer_web/templates/block_transaction/index.html.eex:143
#: lib/explorer_web/templates/chain/_transactions.html.eex:9
#: lib/explorer_web/templates/pending_transaction/index.html.eex:38
#: lib/explorer_web/templates/transaction/index.html.eex:38
#: lib/explorer_web/templates/transaction/overview.html.eex:71
#: lib/explorer_web/templates/transaction_internal_transaction/index.html.eex:32
#: lib/explorer_web/views/address_internal_transaction_view.ex:6
#: lib/explorer_web/views/address_transaction_view.ex:8
#: lib/explorer_web/views/address_internal_transaction_view.ex:8
#: lib/explorer_web/views/address_transaction_view.ex:10
msgid "To"
msgstr "To"
@ -322,7 +323,7 @@ msgstr ""
msgid "Out of Gas"
msgstr ""
#: lib/explorer_web/templates/address_transaction/index.html.eex:70
#: lib/explorer_web/templates/address_transaction/index.html.eex:79
#: lib/explorer_web/templates/block_transaction/index.html.eex:136
#: lib/explorer_web/templates/pending_transaction/index.html.eex:33
#: lib/explorer_web/templates/transaction/index.html.eex:33
@ -337,8 +338,8 @@ msgstr ""
msgid "Showing #%{number}"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:75
#: lib/explorer_web/templates/address_transaction/index.html.eex:78
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:84
#: lib/explorer_web/templates/address_transaction/index.html.eex:87
#: lib/explorer_web/templates/chain/_transactions.html.eex:10
#: lib/explorer_web/templates/pending_transaction/index.html.eex:39
#: lib/explorer_web/templates/transaction/index.html.eex:39
@ -352,6 +353,7 @@ msgstr "POA"
msgid "Gwei"
msgstr ""
#: lib/explorer_web/templates/address_contract/index.html.eex:17
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:18
#: lib/explorer_web/templates/address_transaction/index.html.eex:18
#: lib/explorer_web/templates/transaction_internal_transaction/index.html.eex:11
@ -363,7 +365,7 @@ msgstr ""
msgid "Search by address, transaction hash, or block number"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:101
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:110
#: lib/explorer_web/templates/transaction_internal_transaction/index.html.eex:53
msgid "There are no Internal Transactions"
msgstr ""
@ -392,14 +394,14 @@ msgstr ""
msgid "Wei"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:36
#: lib/explorer_web/templates/address_transaction/index.html.eex:34
#: lib/explorer_web/views/address_internal_transaction_view.ex:8
#: lib/explorer_web/views/address_transaction_view.ex:10
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:45
#: lib/explorer_web/templates/address_transaction/index.html.eex:43
#: lib/explorer_web/views/address_internal_transaction_view.ex:10
#: lib/explorer_web/views/address_transaction_view.ex:12
msgid "All"
msgstr ""
#: lib/explorer_web/templates/address_transaction/index.html.eex:79
#: lib/explorer_web/templates/address_transaction/index.html.eex:88
msgid "Fee"
msgstr ""
@ -414,7 +416,7 @@ msgstr ""
msgid "Block Details"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:70
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:79
msgid "Parent Tx Hash"
msgstr ""
@ -490,3 +492,17 @@ msgstr ""
#: lib/explorer_web/templates/transaction/overview.html.eex:136
msgid "TX Fee"
msgstr ""
#: lib/explorer_web/templates/address_contract/index.html.eex:25
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:27
#: lib/explorer_web/templates/address_transaction/index.html.eex:27
msgid "Contract"
msgstr ""
#: lib/explorer_web/views/address_view.ex:15
msgid "Contract Address"
msgstr ""
#: lib/explorer_web/templates/address_contract/index.html.eex:34
msgid "Contract bytecode"
msgstr ""

@ -0,0 +1,46 @@
defmodule ExplorerWeb.AddressContractControllerTest do
use ExplorerWeb.ConnCase
import ExplorerWeb.Router.Helpers, only: [address_contract_path: 4]
alias Explorer.Factory
alias Explorer.Chain.Hash
alias Explorer.ExchangeRates.Token
describe "GET index/3" do
test "returns not found for unexistent address", %{conn: conn} do
unexistent_address_hash = Hash.to_string(Factory.address_hash())
conn = get(conn, address_contract_path(ExplorerWeb.Endpoint, :index, :en, unexistent_address_hash))
assert html_response(conn, 404)
end
test "returns not found given an invalid address hash ", %{conn: conn} do
invalid_hash = "invalid_hash"
conn = get(conn, address_contract_path(ExplorerWeb.Endpoint, :index, :en, invalid_hash))
assert html_response(conn, 404)
end
test "returns not found when the address doesn't have a contract", %{conn: conn} do
address = insert(:address)
conn = get(conn, address_contract_path(ExplorerWeb.Endpoint, :index, :en, address))
assert html_response(conn, 404)
end
test "suscefully renders the page", %{conn: conn} do
address = insert(:address, contract_code: Factory.data("contract_code"))
conn = get(conn, address_contract_path(ExplorerWeb.Endpoint, :index, :en, address))
assert html_response(conn, 200)
assert address == conn.assigns.address
assert %Token{} = conn.assigns.exchange_rate
assert conn.assigns.transaction_count
end
end
end
Loading…
Cancel
Save