Add contract creator on Account details page

Now the user will be able to see the contract creator and the
transaction references to it on the Account details page when the
address is a contract.

In order to this work we had to make a query that returns the internal
transaction that has the contract creation. This way we can get the
`from_address` that represents the contract creator and the transaction
from the internal transaction.
pull/362/head
Felipe Renan 6 years ago committed by Felipe Renan
parent 45499cbb4c
commit ceb971b285
  1. 4
      apps/explorer/lib/explorer/chain.ex
  2. 8
      apps/explorer/lib/explorer/chain/address.ex
  3. 4
      apps/explorer/test/explorer/chain_test.exs
  4. 1
      apps/explorer_web/lib/explorer_web/controllers/address_transaction_controller.ex
  5. 30
      apps/explorer_web/lib/explorer_web/templates/address/overview.html.eex
  6. 10
      apps/explorer_web/priv/gettext/default.pot
  7. 10
      apps/explorer_web/priv/gettext/en/LC_MESSAGES/default.po
  8. 15
      apps/explorer_web/test/explorer_web/controllers/address_contract_controller_test.exs
  9. 4
      apps/explorer_web/test/explorer_web/features/pages/address_page.ex
  10. 57
      apps/explorer_web/test/explorer_web/features/viewing_addresses_test.exs

@ -622,7 +622,7 @@ defmodule Explorer.Chain do
query =
from(
address in Address,
preload: [:smart_contract],
preload: [:smart_contract, :contracts_creation_internal_transaction],
where: address.hash == ^hash
)
@ -638,7 +638,7 @@ defmodule Explorer.Chain do
query =
from(
address in Address,
preload: [:smart_contract],
preload: [:smart_contract, :contracts_creation_internal_transaction],
where: address.hash == ^hash and not is_nil(address.contract_code)
)

@ -6,7 +6,7 @@ defmodule Explorer.Chain.Address do
use Explorer.Schema
alias Ecto.Changeset
alias Explorer.Chain.{Block, Data, Hash, Wei, SmartContract}
alias Explorer.Chain.{Block, Data, Hash, Wei, SmartContract, InternalTransaction}
@optional_attrs ~w(contract_code)a
@required_attrs ~w(hash)a
@ -43,6 +43,12 @@ defmodule Explorer.Chain.Address do
has_one(:smart_contract, SmartContract)
has_one(
:contracts_creation_internal_transaction,
InternalTransaction,
foreign_key: :created_contract_address_hash
)
timestamps()
end

@ -832,7 +832,9 @@ defmodule Explorer.ChainTest do
end
test "finds an contract address" do
address = insert(:address, contract_code: Factory.data("contract_code"), smart_contract: nil)
address =
insert(:address, contract_code: Factory.data("contract_code"), smart_contract: nil)
|> Repo.preload(:contracts_creation_internal_transaction)
response = Chain.find_contract_address(address.hash)

@ -26,7 +26,6 @@ defmodule ExplorerWeb.AddressTransactionController do
|> Keyword.merge(current_filter(params))
transactions_plus_one = Chain.address_to_transactions(address, full_options)
{transactions, next_page} = split_list_by_page(transactions_plus_one)
render(

@ -19,6 +19,35 @@
<h3 class="<%= if ExplorerWeb.AddressView.contract?(@address) do %>contract-address<% end %>" data-test="address_detail_hash"><%= @address %></h3>
<div class="d-flex flex-row justify-content-start text-muted">
<span class="mr-4" data-test="transaction_count"><%= Cldr.Number.to_string!(@transaction_count) %> <%= gettext "Transactions" %></span>
<%= if contract?(@address) do %>
<span class="mr-4" data-test="address_contract_creator">
<%= gettext "Contract created by" %>
<%= link(
trimmed_hash(@address.contracts_creation_internal_transaction.from_address_hash),
to: address_path(
ExplorerWeb.Endpoint,
:show,
@locale,
@address.contracts_creation_internal_transaction.from_address_hash
)
) %>
<%= gettext "at" %>
<%= link(
trimmed_hash(@address.contracts_creation_internal_transaction.transaction_hash),
to: transaction_path(
ExplorerWeb.Endpoint,
:show,
@locale,
@address.contracts_creation_internal_transaction.transaction_hash
),
"data-test": "transaction_hash_link",
"class": "tile-title"
) %>
</span>
<% end %>
</div>
</div>
</div>
@ -38,7 +67,6 @@
</div>
</section>
<!-- Modal -->
<div class="modal fade" id="qrModal" tabindex="-1" role="dialog" aria-labelledby="qrModalLabel" aria-hidden="true">
<div class="modal-dialog modal-sm" role="document">

@ -633,3 +633,13 @@ msgstr ""
#: lib/explorer_web/views/transaction_view.ex:112
msgid "Contract Call"
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address/overview.html.eex:25
msgid "Contract created by"
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address/overview.html.eex:36
msgid "at"
msgstr ""

@ -645,3 +645,13 @@ msgstr ""
#: lib/explorer_web/views/transaction_view.ex:112
msgid "Contract Call"
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address/overview.html.eex:25
msgid "Contract created by"
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address/overview.html.eex:36
msgid "at"
msgstr ""

@ -24,7 +24,7 @@ defmodule ExplorerWeb.AddressContractControllerTest do
assert html_response(conn, 404)
end
test "returns not found when the address doesn't have a contract", %{conn: conn} do
test "returns not found when the address isn't a contract", %{conn: conn} do
address = insert(:address)
conn = get(conn, address_contract_path(ExplorerWeb.Endpoint, :index, :en, address))
@ -32,13 +32,22 @@ defmodule ExplorerWeb.AddressContractControllerTest do
assert html_response(conn, 404)
end
test "suscefully renders the page", %{conn: conn} do
test "successfully renders the page when the address is a contract", %{conn: conn} do
address = insert(:address, contract_code: Factory.data("contract_code"), smart_contract: nil)
transaction = insert(:transaction, from_address: address)
insert(
:internal_transaction_create,
index: 0,
transaction: transaction,
created_contract_address: address
)
conn = get(conn, address_contract_path(ExplorerWeb.Endpoint, :index, :en, address))
assert html_response(conn, 200)
assert address == conn.assigns.address
assert address.hash == conn.assigns.address.hash
assert %Token{} = conn.assigns.exchange_rate
assert conn.assigns.transaction_count
end

@ -15,6 +15,10 @@ defmodule ExplorerWeb.AddressPage do
css("[data-test='address_balance']")
end
def contract_creator do
css("[data-test='address_contract_creator']")
end
def click_internal_transactions(session) do
click(session, css("[data-test='internal_transactions_tab_link']"))
end

@ -48,6 +48,63 @@ defmodule ExplorerWeb.ViewingAddressesTest do
|> assert_text(AddressPage.balance(), "0.0000000000000005 POA")
end
describe "viewing contract creator" do
test "see the contract creator and transaction links", %{session: session} do
address = insert(:address)
transaction = insert(:transaction, from_address: address)
contract = insert(:address, contract_code: Explorer.Factory.data("contract_code"))
internal_transaction =
insert(
:internal_transaction_create,
index: 0,
transaction: transaction,
from_address: address,
created_contract_address: contract
)
address_hash = ExplorerWeb.AddressView.trimmed_hash(address.hash)
transaction_hash = ExplorerWeb.AddressView.trimmed_hash(transaction.hash)
session
|> AddressPage.visit_page(internal_transaction.created_contract_address)
|> assert_text(AddressPage.contract_creator(), "#{address_hash} at #{transaction_hash}")
end
test "see the contract creator and transaction links even when the creator is another contract", %{session: session} do
lincoln = insert(:address)
contract = insert(:address, contract_code: Explorer.Factory.data("contract_code"))
transaction = insert(:transaction)
another_contract = insert(:address, contract_code: Explorer.Factory.data("contract_code"))
insert(
:internal_transaction,
index: 0,
transaction: transaction,
from_address: lincoln,
to_address: contract,
created_contract_address: contract,
type: :call
)
internal_transaction =
insert(
:internal_transaction_create,
index: 1,
transaction: transaction,
from_address: contract,
created_contract_address: another_contract
)
contract_hash = ExplorerWeb.AddressView.trimmed_hash(contract.hash)
transaction_hash = ExplorerWeb.AddressView.trimmed_hash(transaction.hash)
session
|> AddressPage.visit_page(internal_transaction.created_contract_address)
|> assert_text(AddressPage.contract_creator(), "#{contract_hash} at #{transaction_hash}")
end
end
describe "viewing transactions" do
test "sees all addresses transactions by default", %{
addresses: addresses,

Loading…
Cancel
Save