Add 'Read Smart Contract' page

pull/279/head
Amanda Sposito 6 years ago
parent 73856a72df
commit 01472cb353
  1. 40
      apps/explorer/lib/explorer/smart_contract/reader.ex
  2. 1
      apps/explorer_web/assets/css/app.scss
  3. 1
      apps/explorer_web/assets/js/app.js
  4. 31
      apps/explorer_web/assets/js/lib/smart_contract/read_function.js
  5. 2
      apps/explorer_web/assets/package-lock.json
  6. 2
      apps/explorer_web/config/test.exs
  7. 60
      apps/explorer_web/lib/explorer_web/controllers/address_read_contract_controller.ex
  8. 7
      apps/explorer_web/lib/explorer_web/router.ex
  9. 8
      apps/explorer_web/lib/explorer_web/templates/address_contract/index.html.eex
  10. 8
      apps/explorer_web/lib/explorer_web/templates/address_internal_transaction/index.html.eex
  11. 7
      apps/explorer_web/lib/explorer_web/templates/address_read_contract/_function_response.html.eex
  12. 99
      apps/explorer_web/lib/explorer_web/templates/address_read_contract/index.html.eex
  13. 8
      apps/explorer_web/lib/explorer_web/templates/address_transaction/index.html.eex
  14. 2
      apps/explorer_web/lib/explorer_web/views/address_contract_view.ex
  15. 3
      apps/explorer_web/lib/explorer_web/views/address_internal_transaction_view.ex
  16. 9
      apps/explorer_web/lib/explorer_web/views/address_read_contract_view.ex
  17. 3
      apps/explorer_web/lib/explorer_web/views/address_transaction_view.ex
  18. 6
      apps/explorer_web/lib/explorer_web/views/address_view.ex
  19. 3
      apps/explorer_web/package-lock.json
  20. 75
      apps/explorer_web/priv/gettext/default.pot
  21. 77
      apps/explorer_web/priv/gettext/en/LC_MESSAGES/default.po
  22. 24
      apps/explorer_web/test/explorer_web/controllers/address_read_contract_controller_test.exs
  23. 19
      apps/explorer_web/test/explorer_web/views/address_read_contract_view_test.exs
  24. 67
      apps/explorer_web/test/explorer_web/views/address_view_test.exs

@ -65,25 +65,25 @@ defmodule Explorer.SmartContract.Reader do
$ Explorer.SmartContract.Reader.read_only_functions("0x798465571ae21a184a272f044f991ad1d5f87a3f")
=> [
%{
"constant" => true,
"inputs" => [],
"name" => "get",
"outputs" => [%{"name" => "", "type" => "uint256", "value" => 0}],
"payable" => false,
"stateMutability" => "view",
"type" => "function"
},
%{
"constant" => true,
"inputs" => [%{"name" => "x", "type" => "uint256"}],
"name" => "with_arguments",
"outputs" => [%{"name" => "", "type" => "bool", "value" => ""}],
"payable" => false,
"stateMutability" => "view",
"type" => "function"
}
]
%{
"constant" => true,
"inputs" => [],
"name" => "get",
"outputs" => [%{"name" => "", "type" => "uint256", "value" => 0}],
"payable" => false,
"stateMutability" => "view",
"type" => "function"
},
%{
"constant" => true,
"inputs" => [%{"name" => "x", "type" => "uint256"}],
"name" => "with_arguments",
"outputs" => [%{"name" => "", "type" => "bool", "value" => ""}],
"payable" => false,
"stateMutability" => "view",
"type" => "function"
}
]
"""
@spec read_only_functions(%Explorer.Chain.Hash{}) :: [%{}]
def read_only_functions(contract_address_hash) do
@ -140,7 +140,7 @@ defmodule Explorer.SmartContract.Reader do
defp fetch_from_blockchain(contract_address_hash, %{name: name, args: args, outputs: outputs}) do
contract_address_hash
|> query_contract(%{name => args})
|> query_contract(%{name => normalize_args(args)})
|> link_outputs_and_values(outputs, name)
end

@ -32,6 +32,7 @@ $fa-font-path: "~@fortawesome/fontawesome-free/webfonts";
@import "node_modules/bootstrap/scss/utilities/text";
@import "node_modules/bootstrap/scss/utilities/background";
@import "node_modules/bootstrap/scss/utilities/position";
@import "node_modules/bootstrap/scss/utilities/borders";
// Bootstrap Components
@import "node_modules/bootstrap/scss/dropdown";

@ -23,6 +23,7 @@ import './lib/from_now'
import './lib/market_history_chart'
import './lib/reload_button'
import './lib/tooltip'
import './lib/smart_contract/read_function'
import './pages/address'
import './pages/transaction'

@ -0,0 +1,31 @@
import $ from 'jquery'
const readFunction = (element) => {
const $element = $(element)
const $form = $element.find('[data-function-form]')
const $responseContainer = $element.find('[data-function-response]')
$form.on('submit', (event) => {
event.preventDefault()
const url = $form.data('url')
const $functionName = $form.find('input[name=function_name]')
const $functionInputs = $form.find('input[name=function_input]')
const args = $.map($functionInputs, element => {
return $(element).val()
})
const data = {
function_name: $functionName.val(),
args
}
$.get(url, data, response => $responseContainer.html(response))
})
}
$('[data-function]').each((_, element) => {
readFunction(element)
})

@ -11468,7 +11468,7 @@
"cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
"integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
"integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=",
"dev": true,
"requires": {
"nice-try": "^1.0.4",

@ -10,4 +10,4 @@ config :explorer_web, ExplorerWeb.Endpoint,
server: true
# Configure wallaby
config :wallaby, screenshot_on_failure: true
config :wallaby, screenshot_on_failure: true, js_errors: false

@ -0,0 +1,60 @@
defmodule ExplorerWeb.AddressReadContractController do
use ExplorerWeb, :controller
alias Explorer.{Chain, Market}
alias Explorer.ExchangeRates.Token
alias Explorer.SmartContract.Reader
import ExplorerWeb.AddressController, only: [transaction_count: 1]
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
read_only_functions = Reader.read_only_functions(address_hash)
render(
conn,
"index.html",
read_only_functions: read_only_functions,
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
def show(conn, params) do
with true <- ajax?(conn),
{:ok, address_hash} <- Chain.string_to_address_hash(params["address_id"]),
outputs =
Reader.query_function(
address_hash,
%{name: params["function_name"], args: params["args"]}
) do
conn
|> put_status(200)
|> put_layout(false)
|> render(
"_function_response.html",
function_name: params["function_name"],
outputs: outputs
)
else
_ ->
not_found(conn)
end
end
defp ajax?(conn) do
case get_req_header(conn, "x-requested-with") do
[value] -> value in ["XMLHttpRequest", "xmlhttprequest"]
[] -> false
end
end
end

@ -85,6 +85,13 @@ defmodule ExplorerWeb.Router do
only: [:new, :create],
as: :verify_contract
)
resources(
"/read_contract",
AddressReadContractController,
only: [:index, :show],
as: :read_contract
)
end
get("/search", ChainController, :search)

@ -31,6 +31,14 @@
<% end %>
<% end %>
</li>
<%= if smart_contract_with_read_only_functions?(@address) do %>
<li class="nav-item">
<%= link(
gettext("Read Contract"),
to: address_read_contract_path(@conn, :index, @conn.assigns.locale, @conn.params["address_id"]),
class: "nav-link")%>
</li>
<% end %>
</ul>
</div>

@ -36,6 +36,14 @@
<% end %>
</li>
<% end %>
<%= if smart_contract_with_read_only_functions?(@address) do %>
<li class="nav-item">
<%= link(
gettext("Read Contract"),
to: address_read_contract_path(@conn, :index, @conn.assigns.locale, @conn.params["address_id"]),
class: "nav-link")%>
</li>
<% end %>
</ul>
<!-- MOBILE DROPDOWN NAV -->

@ -0,0 +1,7 @@
<span>
[ <%= @function_name %> method Response ] <br />
<%= for item <- @outputs do %>
<i class="fa fa-angle-double-right"></i> <%= item["type"] %> : <%= item["value"] %>
<% end %>
</span>

@ -0,0 +1,99 @@
<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(
to: address_contract_path(@conn, :index, @conn.assigns.locale, @conn.params["address_id"]),
class: "nav-link") do %>
<%= gettext("Code") %>
<%= if smart_contract_verified?(@address) do %>
<i class="far fa-check-circle"></i>
<% end %>
<% end %>
</li>
<li class="nav-item">
<%= link(
gettext("Read Contract"),
to: address_read_contract_path(@conn, :index, @conn.assigns.locale, @conn.params["address_id"]),
class: "nav-link active")%>
</li>
</ul>
</div>
<div class="card-body">
<h2>
<i class="fas fa-book"></i>
<%= gettext("Read Contract Information") %>
</h2>
<%= for {function, counter} <- Enum.with_index(@read_only_functions, 1) do %>
<div class="d-flex py-2 flex-wrap border-bottom" data-function>
<div class="py-2 pr-2">
<%= counter %>.
<%= function["name"] %>
&#8594;
</div>
<%= if queryable?(function["inputs"]) do %>
<form class="form-inline" data-function-form data-url="<%= address_read_contract_path(@conn, :show, :en, @address, @address.hash) %>">
<input type="hidden" name="function_name" value='<%= function["name"] %>' />
<%= for input <- function["inputs"] do %>
<div class="form-group pr-2">
<input type="text" name="function_input" class="form-control form-control-sm mb-1" placeholder='<%= input["name"] %>(<%= input["type"] %>)' />
</div>
<% end %>
<input type="submit" value='<%= gettext("Query")%>' class="button button--secondary button--xsmall py-0" />
</form>
<% else %>
<span class="py-2">
<%= for output <- function["outputs"] do %>
<%= if address?(output["type"]) do %>
<%= link(
output["value"],
to: address_path(@conn, :show, @conn.assigns.locale, output["value"])
) %>
<% else %>
<%= output["value"] %>
<% end %>
<% end %>
</span>
<% end %>
<div class='p-2 text-muted <%= if (queryable?(function["inputs"]) == true), do: "w-100" %>'>
<%= if (queryable?(function["inputs"])), do: raw "&#8627;" %>
<%= for output <- function["outputs"] do %>
<%= output["type"] %>
<% end %>
</div>
<div data-function-response></div>
</div>
<% end %>
</div>
</div>
</section>

@ -36,6 +36,14 @@
<% end %>
</li>
<% end %>
<%= if smart_contract_with_read_only_functions?(@address) do %>
<li class="nav-item">
<%= link(
gettext("Read Contract"),
to: address_read_contract_path(@conn, :index, @conn.assigns.locale, @conn.params["address_id"]),
class: "nav-link")%>
</li>
<% end %>
</ul>
<!-- MOBILE DROPDOWN NAV -->

@ -1,7 +1,7 @@
defmodule ExplorerWeb.AddressContractView do
use ExplorerWeb, :view
import ExplorerWeb.AddressView, only: [smart_contract_verified?: 1]
import ExplorerWeb.AddressView, only: [smart_contract_verified?: 1, smart_contract_with_read_only_functions?: 1]
def format_smart_contract_abi(abi), do: Poison.encode!(abi, pretty: true)

@ -1,7 +1,8 @@
defmodule ExplorerWeb.AddressInternalTransactionView do
use ExplorerWeb, :view
import ExplorerWeb.AddressView, only: [contract?: 1, smart_contract_verified?: 1]
import ExplorerWeb.AddressView,
only: [contract?: 1, smart_contract_verified?: 1, smart_contract_with_read_only_functions?: 1]
def format_current_filter(filter) do
case filter do

@ -0,0 +1,9 @@
defmodule ExplorerWeb.AddressReadContractView do
use ExplorerWeb, :view
import ExplorerWeb.AddressView, only: [smart_contract_verified?: 1]
def queryable?(inputs), do: Enum.any?(inputs)
def address?(type), do: type == "address"
end

@ -1,7 +1,8 @@
defmodule ExplorerWeb.AddressTransactionView do
use ExplorerWeb, :view
import ExplorerWeb.AddressView, only: [contract?: 1, smart_contract_verified?: 1]
import ExplorerWeb.AddressView,
only: [contract?: 1, smart_contract_verified?: 1, smart_contract_with_read_only_functions?: 1]
def format_current_filter(filter) do
case filter do

@ -72,4 +72,10 @@ defmodule ExplorerWeb.AddressView do
end
def trimmed_hash(_), do: ""
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
end

@ -0,0 +1,3 @@
{
"lockfileVersion": 1
}

@ -40,10 +40,11 @@ msgstr ""
#: lib/explorer_web/templates/address/overview.html.eex:21
#: lib/explorer_web/templates/address_contract/index.html.eex:10
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:13
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:47
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:55
#: lib/explorer_web/templates/address_read_contract/index.html.eex:10
#: lib/explorer_web/templates/address_transaction/index.html.eex:13
#: lib/explorer_web/templates/address_transaction/index.html.eex:47
#: lib/explorer_web/templates/address_transaction/index.html.eex:123
#: lib/explorer_web/templates/address_transaction/index.html.eex:55
#: lib/explorer_web/templates/address_transaction/index.html.eex:131
#: lib/explorer_web/templates/block/index.html.eex:19
#: lib/explorer_web/templates/block_transaction/index.html.eex:124
#: lib/explorer_web/templates/chain/_transactions.html.eex:4
@ -142,13 +143,13 @@ msgstr ""
msgid "Address"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:98
#: lib/explorer_web/templates/address_transaction/index.html.eex:109
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:106
#: lib/explorer_web/templates/address_transaction/index.html.eex:117
#: lib/explorer_web/templates/block_transaction/index.html.eex:142
#: lib/explorer_web/templates/transaction/overview.html.eex:79
#: lib/explorer_web/templates/transaction_internal_transaction/index.html.eex:31
#: lib/explorer_web/views/address_internal_transaction_view.ex:9
#: lib/explorer_web/views/address_transaction_view.ex:9
#: lib/explorer_web/views/address_internal_transaction_view.ex:10
#: lib/explorer_web/views/address_transaction_view.ex:10
msgid "From"
msgstr ""
@ -161,13 +162,13 @@ msgstr ""
msgid "Success"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:86
#: lib/explorer_web/templates/address_transaction/index.html.eex:97
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:94
#: lib/explorer_web/templates/address_transaction/index.html.eex:105
#: lib/explorer_web/templates/block_transaction/index.html.eex:144
#: lib/explorer_web/templates/transaction/overview.html.eex:91
#: lib/explorer_web/templates/transaction_internal_transaction/index.html.eex:32
#: lib/explorer_web/views/address_internal_transaction_view.ex:8
#: lib/explorer_web/views/address_transaction_view.ex:8
#: lib/explorer_web/views/address_internal_transaction_view.ex:9
#: lib/explorer_web/views/address_transaction_view.ex:9
msgid "To"
msgstr ""
@ -312,10 +313,11 @@ msgstr ""
#: lib/explorer_web/templates/address_contract/index.html.eex:17
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:20
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:52
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:111
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:60
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:119
#: lib/explorer_web/templates/address_read_contract/index.html.eex:17
#: lib/explorer_web/templates/address_transaction/index.html.eex:20
#: lib/explorer_web/templates/address_transaction/index.html.eex:52
#: lib/explorer_web/templates/address_transaction/index.html.eex:60
#: lib/explorer_web/templates/transaction_internal_transaction/index.html.eex:11
#: lib/explorer_web/templates/transaction_log/index.html.eex:11
msgid "Internal Transactions"
@ -353,10 +355,10 @@ msgstr ""
msgid "Wei"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:80
#: lib/explorer_web/templates/address_transaction/index.html.eex:91
#: lib/explorer_web/views/address_internal_transaction_view.ex:10
#: lib/explorer_web/views/address_transaction_view.ex:10
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:88
#: lib/explorer_web/templates/address_transaction/index.html.eex:99
#: lib/explorer_web/views/address_internal_transaction_view.ex:11
#: lib/explorer_web/views/address_transaction_view.ex:11
msgid "All"
msgstr ""
@ -473,8 +475,8 @@ msgstr ""
msgid "There are no Transactions"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:125
#: lib/explorer_web/templates/address_transaction/index.html.eex:138
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:133
#: lib/explorer_web/templates/address_transaction/index.html.eex:146
#: lib/explorer_web/templates/block/index.html.eex:60
#: lib/explorer_web/templates/block_transaction/index.html.eex:198
#: lib/explorer_web/templates/pending_transaction/index.html.eex:54
@ -486,15 +488,16 @@ msgstr ""
msgid "Contract Source Code"
msgstr ""
#: lib/explorer_web/templates/address_contract/index.html.eex:44
#: lib/explorer_web/templates/address_contract/index.html.eex:52
msgid "Verify and Publish"
msgstr ""
#: lib/explorer_web/templates/address_contract/index.html.eex:27
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:31
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:61
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:69
#: lib/explorer_web/templates/address_read_contract/index.html.eex:27
#: lib/explorer_web/templates/address_transaction/index.html.eex:31
#: lib/explorer_web/templates/address_transaction/index.html.eex:61
#: lib/explorer_web/templates/address_transaction/index.html.eex:69
msgid "Code"
msgstr ""
@ -589,7 +592,7 @@ msgid "block confirmations"
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address_transaction/index.html.eex:81
#: lib/explorer_web/templates/address_transaction/index.html.eex:89
msgid "Connection Lost, click to load newer transactions"
msgstr ""
@ -605,7 +608,7 @@ msgid "Internal Transaction"
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address_transaction/index.html.eex:76
#: lib/explorer_web/templates/address_transaction/index.html.eex:84
msgid "More messages have come in"
msgstr ""
@ -615,12 +618,12 @@ msgid "QR Code"
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:118
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:126
msgid "There are no internal transactions for this address."
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address_transaction/index.html.eex:131
#: lib/explorer_web/templates/address_transaction/index.html.eex:139
msgid "There are no transactions for this address."
msgstr ""
@ -664,3 +667,21 @@ msgstr ""
#: lib/explorer_web/templates/address_transaction/_transaction.html.eex:29
msgid "OUT"
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address_read_contract/index.html.eex:69
msgid "Query"
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address_contract/index.html.eex:37
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:42
#: lib/explorer_web/templates/address_read_contract/index.html.eex:36
#: lib/explorer_web/templates/address_transaction/index.html.eex:42
msgid "Read Contract"
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address_read_contract/index.html.eex:46
msgid "Read Contract Information"
msgstr ""

@ -52,10 +52,11 @@ msgstr "POA Network Explorer"
#: lib/explorer_web/templates/address/overview.html.eex:21
#: lib/explorer_web/templates/address_contract/index.html.eex:10
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:13
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:47
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:55
#: lib/explorer_web/templates/address_read_contract/index.html.eex:10
#: lib/explorer_web/templates/address_transaction/index.html.eex:13
#: lib/explorer_web/templates/address_transaction/index.html.eex:47
#: lib/explorer_web/templates/address_transaction/index.html.eex:123
#: lib/explorer_web/templates/address_transaction/index.html.eex:55
#: lib/explorer_web/templates/address_transaction/index.html.eex:131
#: lib/explorer_web/templates/block/index.html.eex:19
#: lib/explorer_web/templates/block_transaction/index.html.eex:124
#: lib/explorer_web/templates/chain/_transactions.html.eex:4
@ -154,13 +155,13 @@ msgstr "%{count} transactions in this block"
msgid "Address"
msgstr "Address"
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:98
#: lib/explorer_web/templates/address_transaction/index.html.eex:109
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:106
#: lib/explorer_web/templates/address_transaction/index.html.eex:117
#: lib/explorer_web/templates/block_transaction/index.html.eex:142
#: lib/explorer_web/templates/transaction/overview.html.eex:79
#: lib/explorer_web/templates/transaction_internal_transaction/index.html.eex:31
#: lib/explorer_web/views/address_internal_transaction_view.ex:9
#: lib/explorer_web/views/address_transaction_view.ex:9
#: lib/explorer_web/views/address_internal_transaction_view.ex:10
#: lib/explorer_web/views/address_transaction_view.ex:10
msgid "From"
msgstr "From"
@ -173,13 +174,13 @@ msgstr "Overview"
msgid "Success"
msgstr "Success"
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:86
#: lib/explorer_web/templates/address_transaction/index.html.eex:97
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:94
#: lib/explorer_web/templates/address_transaction/index.html.eex:105
#: lib/explorer_web/templates/block_transaction/index.html.eex:144
#: lib/explorer_web/templates/transaction/overview.html.eex:91
#: lib/explorer_web/templates/transaction_internal_transaction/index.html.eex:32
#: lib/explorer_web/views/address_internal_transaction_view.ex:8
#: lib/explorer_web/views/address_transaction_view.ex:8
#: lib/explorer_web/views/address_internal_transaction_view.ex:9
#: lib/explorer_web/views/address_transaction_view.ex:9
msgid "To"
msgstr "To"
@ -324,10 +325,11 @@ msgstr ""
#: lib/explorer_web/templates/address_contract/index.html.eex:17
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:20
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:52
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:111
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:60
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:119
#: lib/explorer_web/templates/address_read_contract/index.html.eex:17
#: lib/explorer_web/templates/address_transaction/index.html.eex:20
#: lib/explorer_web/templates/address_transaction/index.html.eex:52
#: lib/explorer_web/templates/address_transaction/index.html.eex:60
#: lib/explorer_web/templates/transaction_internal_transaction/index.html.eex:11
#: lib/explorer_web/templates/transaction_log/index.html.eex:11
msgid "Internal Transactions"
@ -365,10 +367,10 @@ msgstr ""
msgid "Wei"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:80
#: lib/explorer_web/templates/address_transaction/index.html.eex:91
#: lib/explorer_web/views/address_internal_transaction_view.ex:10
#: lib/explorer_web/views/address_transaction_view.ex:10
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:88
#: lib/explorer_web/templates/address_transaction/index.html.eex:99
#: lib/explorer_web/views/address_internal_transaction_view.ex:11
#: lib/explorer_web/views/address_transaction_view.ex:11
msgid "All"
msgstr ""
@ -485,8 +487,8 @@ msgstr ""
msgid "There are no Transactions"
msgstr ""
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:125
#: lib/explorer_web/templates/address_transaction/index.html.eex:138
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:133
#: lib/explorer_web/templates/address_transaction/index.html.eex:146
#: lib/explorer_web/templates/block/index.html.eex:60
#: lib/explorer_web/templates/block_transaction/index.html.eex:198
#: lib/explorer_web/templates/pending_transaction/index.html.eex:54
@ -498,15 +500,16 @@ msgstr ""
msgid "Contract Source Code"
msgstr "Contract Source Code"
#: lib/explorer_web/templates/address_contract/index.html.eex:44
#: lib/explorer_web/templates/address_contract/index.html.eex:52
msgid "Verify and Publish"
msgstr ""
#: lib/explorer_web/templates/address_contract/index.html.eex:27
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:31
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:61
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:69
#: lib/explorer_web/templates/address_read_contract/index.html.eex:27
#: lib/explorer_web/templates/address_transaction/index.html.eex:31
#: lib/explorer_web/templates/address_transaction/index.html.eex:61
#: lib/explorer_web/templates/address_transaction/index.html.eex:69
msgid "Code"
msgstr ""
@ -601,7 +604,7 @@ msgid "block confirmations"
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address_transaction/index.html.eex:81
#: lib/explorer_web/templates/address_transaction/index.html.eex:89
msgid "Connection Lost, click to load newer transactions"
msgstr ""
@ -617,7 +620,7 @@ msgid "Internal Transaction"
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address_transaction/index.html.eex:76
#: lib/explorer_web/templates/address_transaction/index.html.eex:84
msgid "More messages have come in"
msgstr ""
@ -627,12 +630,12 @@ msgid "QR Code"
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:118
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:126
msgid "There are no internal transactions for this address."
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address_transaction/index.html.eex:131
#: lib/explorer_web/templates/address_transaction/index.html.eex:139
msgid "There are no transactions for this address."
msgstr ""
@ -656,7 +659,7 @@ msgstr ""
msgid "at"
msgstr ""
#, elixir-format, fuzzy
#, elixir-format
#: lib/explorer_web/templates/address_transaction/_transaction.html.eex:36
#: lib/explorer_web/templates/chain/_transactions.html.eex:25
#: lib/explorer_web/templates/transaction/index.html.eex:47
@ -676,3 +679,21 @@ msgstr ""
#: lib/explorer_web/templates/address_transaction/_transaction.html.eex:29
msgid "OUT"
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address_read_contract/index.html.eex:69
msgid "Query"
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address_contract/index.html.eex:37
#: lib/explorer_web/templates/address_internal_transaction/index.html.eex:42
#: lib/explorer_web/templates/address_read_contract/index.html.eex:36
#: lib/explorer_web/templates/address_transaction/index.html.eex:42
msgid "Read Contract"
msgstr ""
#, elixir-format
#: lib/explorer_web/templates/address_read_contract/index.html.eex:46
msgid "Read Contract Information"
msgstr ""

@ -0,0 +1,24 @@
defmodule ExplorerWeb.AddressReadContractControllerTest do
use ExplorerWeb.ConnCase
describe "GET show/3" do
test "only responds to ajax requests", %{conn: conn} do
smart_contract = insert(:smart_contract)
path =
address_read_contract_path(
ExplorerWeb.Endpoint,
:show,
:en,
smart_contract.address_hash,
smart_contract.address_hash,
function_name: "get",
args: []
)
conn = get(conn, path)
assert conn.status == 404
end
end
end

@ -0,0 +1,19 @@
defmodule ExplorerWeb.AddressReadContractViewTest do
use ExplorerWeb.ConnCase, async: true
alias ExplorerWeb.AddressReadContractView
describe "queryable?/1" do
test "returns true if list of inputs is not empty" do
assert AddressReadContractView.queryable?([%{"name" => "argument_name", "type" => "uint256"}]) == true
assert AddressReadContractView.queryable?([]) == false
end
end
describe "address?/1" do
test "returns true if type equals `address`" do
assert AddressReadContractView.address?("address") == true
assert AddressReadContractView.address?("uint256") == false
end
end
end

@ -44,4 +44,71 @@ defmodule ExplorerWeb.AddressViewTest do
assert {:ok, _} = Base.decode64(AddressView.qr_code(address))
end
end
describe "smart_contract_verified?/1" do
test "returns true when smart contract is verified" do
smart_contract = insert(:smart_contract)
address = insert(:address, smart_contract: smart_contract)
assert AddressView.smart_contract_verified?(address)
end
test "returns false when smart contract is not verified" do
address = insert(:address, smart_contract: nil)
refute AddressView.smart_contract_verified?(address)
end
end
describe "smart_contract_with_read_only_functions?/1" do
test "returns true when abi has read only functions" do
smart_contract =
insert(
:smart_contract,
abi: [
%{
"constant" => true,
"inputs" => [],
"name" => "get",
"outputs" => [%{"name" => "", "type" => "uint256"}],
"payable" => false,
"stateMutability" => "view",
"type" => "function"
}
]
)
address = insert(:address, smart_contract: smart_contract)
assert AddressView.smart_contract_with_read_only_functions?(address)
end
test "returns false when there is no read only functions" do
smart_contract =
insert(
:smart_contract,
abi: [
%{
"constant" => false,
"inputs" => [%{"name" => "x", "type" => "uint256"}],
"name" => "set",
"outputs" => [],
"payable" => false,
"stateMutability" => "nonpayable",
"type" => "function"
}
]
)
address = insert(:address, smart_contract: smart_contract)
refute AddressView.smart_contract_with_read_only_functions?(address)
end
test "returns false when smart contract is not verified" do
address = insert(:address, smart_contract: nil)
refute AddressView.smart_contract_with_read_only_functions?(address)
end
end
end

Loading…
Cancel
Save