Refactor 'Read Smart Contract' functionality to be via AJAX

pull/557/head
Amanda Sposito 6 years ago
parent 7f2efcfe34
commit 52845654df
  1. 2
      apps/block_scout_web/assets/js/app.js
  2. 26
      apps/block_scout_web/assets/js/lib/smart_contract/read_only_functions.js
  3. 33
      apps/block_scout_web/lib/block_scout_web/controllers/address_read_contract_controller.ex
  4. 67
      apps/block_scout_web/lib/block_scout_web/controllers/smart_contract_controller.ex
  5. 58
      apps/block_scout_web/lib/block_scout_web/templates/address_read_contract/index.html.eex
  6. 8
      apps/block_scout_web/lib/block_scout_web/templates/smart_contract/_function_response.html.eex
  7. 50
      apps/block_scout_web/lib/block_scout_web/templates/smart_contract/_functions.html.eex
  8. 7
      apps/block_scout_web/lib/block_scout_web/views/smart_contract_view.ex
  9. 49
      apps/block_scout_web/priv/gettext/default.pot
  10. 49
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  11. 55
      apps/block_scout_web/test/block_scout_web/controllers/address_read_contract_controller_test.exs
  12. 97
      apps/block_scout_web/test/block_scout_web/controllers/smart_contract_controller_test.exs
  13. 37
      apps/block_scout_web/test/block_scout_web/controllers/tokens/read_contract_controller_test.exs
  14. 2
      apps/block_scout_web/test/test_helper.exs

@ -24,7 +24,7 @@ import './lib/loading_element'
import './lib/market_history_chart'
import './lib/reload_button'
import './lib/tooltip'
import './lib/smart_contract/read_function'
import './lib/smart_contract/read_only_functions'
import './lib/pretty_json'
import './lib/try_api'

@ -1,5 +1,25 @@
import $ from 'jquery'
const loadFunctions = (element) => {
const $element = $(element)
const url = $element.data('url')
const hash = $element.data('hash')
$.get(
url,
{ hash: hash },
response => $element.html(response)
)
.done(function () {
$('[data-function]').each((_, element) => {
readFunction(element)
})
})
.fail(function (response) {
$element.html(response.statusText)
})
}
const readFunction = (element) => {
const $element = $(element)
const $form = $element.find('[data-function-form]')
@ -26,6 +46,6 @@ const readFunction = (element) => {
})
}
$('[data-function]').each((_, element) => {
readFunction(element)
})
const container = $('[data-smart-contract-functions]')
loadFunctions(container)

@ -3,19 +3,15 @@ defmodule BlockScoutWeb.AddressReadContractController do
alias Explorer.{Chain, Market}
alias Explorer.ExchangeRates.Token
alias Explorer.SmartContract.Reader
import BlockScoutWeb.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)
@ -28,33 +24,4 @@ defmodule BlockScoutWeb.AddressReadContractController do
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

@ -0,0 +1,67 @@
defmodule BlockScoutWeb.SmartContractController do
use BlockScoutWeb, :controller
alias Explorer.Chain
alias Explorer.SmartContract.Reader
def index(conn, %{"hash" => address_hash_string}) do
with true <- ajax?(conn),
{: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)
conn
|> put_status(200)
|> put_layout(false)
|> render(
"_functions.html",
read_only_functions: read_only_functions,
address: address
)
else
:error ->
unprocessable_entity(conn)
{:error, :not_found} ->
not_found(conn)
_ ->
not_found(conn)
end
end
def show(conn, params) do
with true <- ajax?(conn),
{:ok, address_hash} <- Chain.string_to_address_hash(params["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
:error ->
unprocessable_entity(conn)
{:error, :not_found} ->
not_found(conn)
_ ->
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

@ -40,61 +40,9 @@
</ul>
</div>
<div class="card-body">
<h2 class="crad-title"> <%= gettext("Read Contract Information") %> </h2>
<%= for {function, counter} <- Enum.with_index(@read_only_functions, 1) do %>
<div class="d-flex py-2 border-bottom" data-function>
<div class="py-2 pr-2 text-nowrap">
<%= counter %>.
<%= function["name"] %>
&#8594;
</div>
<%= if queryable?(function["inputs"]) do %>
<div class="">
<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 address-input-sm mt-2" placeholder='<%= input["name"] %>(<%= input["type"] %>)' />
</div>
<% end %>
<input type="submit" value='<%= gettext("Query")%>' class="button button--secondary button--xsmall py-0 mt-2" />
</form>
<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>
<% 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>
<% end %>
<!-- loaded via AJAX -->
<div class="card-body" data-smart-contract-functions data-hash="<%= to_string(@address.hash) %>" data-url="<%= smart_contract_path(@conn, :index, :en) %>">
<i class="fa fa-spinner fa-spin"></i> <%= gettext("loading...") %>
</div>
</div>
</section>

@ -0,0 +1,8 @@
<div class="tile tile-muted monospace">
[ <%= @function_name %> method Response ]
<%= for item <- @outputs do %>
<i class="fa fa-angle-double-right"></i>
<span class="text-dark"> <%= item["type"] %> : <%= item["value"] %> </span>
<% end %>
</div>

@ -0,0 +1,50 @@
<%= for {function, counter} <- Enum.with_index(@read_only_functions, 1) do %>
<div class="d-flex py-2 border-bottom" data-function>
<div class="py-2 pr-2 text-nowrap">
<%= counter %>.
<%= function["name"] %>
&#8594;
</div>
<%= if queryable?(function["inputs"]) do %>
<div class="">
<form class="form-inline" data-function-form data-url="<%= smart_contract_path(@conn, :show, :en, @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 address-input-sm mt-2" placeholder='<%= input["name"] %>(<%= input["type"] %>)' />
</div>
<% end %>
<input type="submit" value='<%= gettext("Query")%>' class="button button--secondary button--xsmall py-0 mt-2" />
</form>
<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>
<% 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>
<% end %>

@ -0,0 +1,7 @@
defmodule BlockScoutWeb.SmartContractView do
use BlockScoutWeb, :view
def queryable?(inputs), do: Enum.any?(inputs)
def address?(type), do: type == "address"
end

@ -481,7 +481,7 @@ msgstr ""
#: lib/block_scout_web/templates/block/index.html.eex:15
#: lib/block_scout_web/templates/block_transaction/index.html.eex:51
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:78
#: lib/block_scout_web/templates/token/show.html.eex:102
#: lib/block_scout_web/templates/tokens/token/show.html.eex:71
#: lib/block_scout_web/templates/transaction/index.html.eex:66
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:72
msgid "Older"
@ -637,7 +637,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/_transaction.html.eex:41
#: lib/block_scout_web/templates/token/_token_transfer.html.eex:38
#: lib/block_scout_web/templates/tokens/token/_token_transfer.html.eex:38
#: lib/block_scout_web/templates/transaction/_tile.html.eex:28
msgid "Block #%{number}"
msgstr ""
@ -659,7 +659,7 @@ msgid "OUT"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_read_contract/index.html.eex:67
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:22
msgid "Query"
msgstr ""
@ -668,14 +668,13 @@ msgstr ""
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:42
#: lib/block_scout_web/templates/address_read_contract/index.html.eex:36
#: lib/block_scout_web/templates/address_transaction/index.html.eex:42
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:25
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:42
#: lib/block_scout_web/templates/tokens/token/show.html.eex:26
#: lib/block_scout_web/templates/tokens/token/show.html.eex:45
msgid "Read Contract"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_read_contract/index.html.eex:44
msgid "Read Contract Information"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:12
msgid "%{count} Transactions"
@ -723,7 +722,7 @@ msgid "Used"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/token/_token_transfer.html.eex:4
#: lib/block_scout_web/templates/tokens/token/_token_transfer.html.eex:4
#: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:4
#: lib/block_scout_web/views/transaction_view.ex:116
msgid "Token Transfer"
@ -731,7 +730,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/_transaction.html.eex:64
#: lib/block_scout_web/templates/token/show.html.eex:20
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:18
msgid "Transfers"
msgstr ""
@ -759,20 +758,23 @@ msgstr ""
msgid "Validated Transactions"
msgstr ""
#: lib/block_scout_web/templates/token/show.html.eex:95
#: lib/block_scout_web/templates/tokens/token/show.html.eex:64
msgid "There are no transfers for this Token."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/token/show.html.eex:11
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:10
msgid "Token Details"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/token/show.html.eex:63
#: lib/block_scout_web/templates/token/show.html.eex:73
#: lib/block_scout_web/templates/token/show.html.eex:76
#: lib/block_scout_web/templates/token/show.html.eex:86
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:17
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:34
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:37
#: lib/block_scout_web/templates/tokens/token/show.html.eex:17
#: lib/block_scout_web/templates/tokens/token/show.html.eex:36
#: lib/block_scout_web/templates/tokens/token/show.html.eex:39
#: lib/block_scout_web/templates/tokens/token/show.html.eex:55
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:12
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:42
#: lib/block_scout_web/templates/transaction_log/index.html.eex:13
@ -785,17 +787,17 @@ msgid "Token Transfers"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/token/show.html.eex:19
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:17
msgid "addresses"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/token/show.html.eex:22
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:20
msgid "decimals"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/token/show.html.eex:33
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:31
msgid "Total Supply"
msgstr ""
@ -805,11 +807,12 @@ msgid "API"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/token_helpers.ex:38
msgid "ERC-721 TokenID [%{token_id}]"
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:65
msgid "There are no token transfers for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:65
msgid "There are no token transfers for this transaction."
#: lib/block_scout_web/templates/address_read_contract/index.html.eex:45
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:52
msgid "loading..."
msgstr ""

@ -493,7 +493,7 @@ msgstr ""
#: lib/block_scout_web/templates/block/index.html.eex:15
#: lib/block_scout_web/templates/block_transaction/index.html.eex:51
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:78
#: lib/block_scout_web/templates/token/show.html.eex:102
#: lib/block_scout_web/templates/tokens/token/show.html.eex:71
#: lib/block_scout_web/templates/transaction/index.html.eex:66
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:72
msgid "Older"
@ -649,7 +649,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/_transaction.html.eex:41
#: lib/block_scout_web/templates/token/_token_transfer.html.eex:38
#: lib/block_scout_web/templates/tokens/token/_token_transfer.html.eex:38
#: lib/block_scout_web/templates/transaction/_tile.html.eex:28
msgid "Block #%{number}"
msgstr ""
@ -671,7 +671,7 @@ msgid "OUT"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_read_contract/index.html.eex:67
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:22
msgid "Query"
msgstr ""
@ -680,14 +680,13 @@ msgstr ""
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:42
#: lib/block_scout_web/templates/address_read_contract/index.html.eex:36
#: lib/block_scout_web/templates/address_transaction/index.html.eex:42
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:25
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:42
#: lib/block_scout_web/templates/tokens/token/show.html.eex:26
#: lib/block_scout_web/templates/tokens/token/show.html.eex:45
msgid "Read Contract"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_read_contract/index.html.eex:44
msgid "Read Contract Information"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/overview.html.eex:12
msgid "%{count} Transactions"
@ -735,7 +734,7 @@ msgid "Used"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/token/_token_transfer.html.eex:4
#: lib/block_scout_web/templates/tokens/token/_token_transfer.html.eex:4
#: lib/block_scout_web/templates/transaction_token_transfer/_token_transfer.html.eex:4
#: lib/block_scout_web/views/transaction_view.ex:116
msgid "Token Transfer"
@ -743,7 +742,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/_transaction.html.eex:64
#: lib/block_scout_web/templates/token/show.html.eex:20
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:18
msgid "Transfers"
msgstr ""
@ -771,20 +770,23 @@ msgstr ""
msgid "Validated Transactions"
msgstr ""
#: lib/block_scout_web/templates/token/show.html.eex:95
#: lib/block_scout_web/templates/tokens/token/show.html.eex:64
msgid "There are no transfers for this Token."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/token/show.html.eex:11
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:10
msgid "Token Details"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/token/show.html.eex:63
#: lib/block_scout_web/templates/token/show.html.eex:73
#: lib/block_scout_web/templates/token/show.html.eex:76
#: lib/block_scout_web/templates/token/show.html.eex:86
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:17
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:34
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:37
#: lib/block_scout_web/templates/tokens/token/show.html.eex:17
#: lib/block_scout_web/templates/tokens/token/show.html.eex:36
#: lib/block_scout_web/templates/tokens/token/show.html.eex:39
#: lib/block_scout_web/templates/tokens/token/show.html.eex:55
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:12
#: lib/block_scout_web/templates/transaction_internal_transaction/index.html.eex:42
#: lib/block_scout_web/templates/transaction_log/index.html.eex:13
@ -797,17 +799,17 @@ msgid "Token Transfers"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/token/show.html.eex:19
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:17
msgid "addresses"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/token/show.html.eex:22
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:20
msgid "decimals"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/token/show.html.eex:33
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:31
msgid "Total Supply"
msgstr ""
@ -817,11 +819,12 @@ msgid "API"
msgstr ""
#, elixir-format
#: lib/block_scout_web/views/token_helpers.ex:38
msgid "ERC-721 TokenID [%{token_id}]"
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:65
msgid "There are no token transfers for this transaction."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:65
msgid "There are no token transfers for this transaction."
#: lib/block_scout_web/templates/address_read_contract/index.html.eex:45
#: lib/block_scout_web/templates/tokens/read_contract/index.html.eex:52
msgid "loading..."
msgstr ""

@ -1,24 +1,43 @@
defmodule BlockScoutWeb.AddressReadContractControllerTest do
use BlockScoutWeb.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(
BlockScoutWeb.Endpoint,
:show,
:en,
smart_contract.address_hash,
smart_contract.address_hash,
function_name: "get",
args: []
)
conn = get(conn, path)
assert conn.status == 404
alias Explorer.ExchangeRates.Token
describe "GET index/3" do
test "with invalid address hash", %{conn: conn} do
conn = get(conn, address_read_contract_path(BlockScoutWeb.Endpoint, :index, :en, "invalid_address"))
assert html_response(conn, 404)
end
test "with valid address that is not a contract", %{conn: conn} do
address = insert(:address)
conn = get(conn, address_read_contract_path(BlockScoutWeb.Endpoint, :index, :en, address.hash))
assert html_response(conn, 404)
end
test "successfully renders the page when the address is a contract", %{conn: conn} do
contract_address = insert(:contract_address)
transaction = insert(:transaction, from_address: contract_address)
insert(
:internal_transaction_create,
index: 0,
transaction: transaction,
created_contract_address: contract_address
)
insert(:smart_contract, address_hash: contract_address.hash)
conn = get(conn, address_read_contract_path(BlockScoutWeb.Endpoint, :index, :en, contract_address.hash))
assert html_response(conn, 200)
assert contract_address.hash == conn.assigns.address.hash
assert %Token{} = conn.assigns.exchange_rate
assert conn.assigns.transaction_count
end
end
end

@ -0,0 +1,97 @@
defmodule BlockScoutWeb.SmartContractControllerTest do
use BlockScoutWeb.ConnCase
import Mox
setup :verify_on_exit!
describe "GET index/3" do
test "only responds to ajax requests", %{conn: conn} do
smart_contract = insert(:smart_contract)
path = smart_contract_path(BlockScoutWeb.Endpoint, :index, :en, hash: smart_contract.address_hash)
conn = get(conn, path)
assert conn.status == 404
end
test "lists the smart contract read only functions" do
token_contract_address = insert(:contract_address)
insert(:smart_contract, address_hash: token_contract_address.hash)
blockchain_get_function_mock()
path = smart_contract_path(BlockScoutWeb.Endpoint, :index, :en, hash: token_contract_address.hash)
conn =
build_conn()
|> put_req_header("x-requested-with", "xmlhttprequest")
|> get(path)
assert conn.status == 200
refute conn.assigns.read_only_functions == []
end
end
describe "GET show/3" do
test "only responds to ajax requests", %{conn: conn} do
smart_contract = insert(:smart_contract)
path =
smart_contract_path(
BlockScoutWeb.Endpoint,
:show,
:en,
smart_contract.address_hash,
function_name: "get",
args: []
)
conn = get(conn, path)
assert conn.status == 404
end
test "fetch the function value from the blockchain" do
smart_contract = insert(:smart_contract)
blockchain_get_function_mock()
path =
smart_contract_path(
BlockScoutWeb.Endpoint,
:show,
:en,
smart_contract.address_hash,
function_name: "get",
args: []
)
conn =
build_conn()
|> put_req_header("x-requested-with", "xmlhttprequest")
|> get(path)
assert conn.status == 200
assert %{
function_name: "get",
layout: false,
locale: "en",
outputs: [%{"name" => "", "type" => "uint256", "value" => 0}]
} = conn.assigns
end
end
defp blockchain_get_function_mock() do
expect(
EthereumJSONRPC.Mox,
:json_rpc,
fn [%{id: id, method: _, params: [%{data: _, to: _}]}], _options ->
{:ok, [%{id: id, jsonrpc: "2.0", result: "0x0000000000000000000000000000000000000000000000000000000000000000"}]}
end
)
end
end

@ -0,0 +1,37 @@
defmodule BlockScoutWeb.Tokens.ReadContractControllerTest do
use BlockScoutWeb.ConnCase
describe "GET index/3" do
test "with invalid address hash", %{conn: conn} do
conn = get(conn, token_read_contract_path(BlockScoutWeb.Endpoint, :index, :en, "invalid_address"))
assert html_response(conn, 404)
end
test "successfully renders the page when the token is a verified smart contract", %{conn: conn} do
token_contract_address = insert(:contract_address)
token = insert(:token, contract_address: token_contract_address)
transaction =
:transaction
|> insert()
|> with_block()
insert(
:token_transfer,
to_address: build(:address),
transaction: transaction,
token_contract_address: token_contract_address,
token: token
)
conn = get(conn, token_read_contract_path(BlockScoutWeb.Endpoint, :index, :en, token.contract_address_hash))
assert html_response(conn, 200)
assert token.contract_address_hash == conn.assigns.token.contract_address_hash
assert conn.assigns.total_token_transfers
assert conn.assigns.total_address_in_token_transfers
end
end
end

@ -15,3 +15,5 @@ ExUnit.configure(formatters: [JUnitFormatter, ExUnit.CLIFormatter])
ExUnit.start()
Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo, :manual)
Mox.defmock(EthereumJSONRPC.Mox, for: EthereumJSONRPC.Transport)

Loading…
Cancel
Save