added hiding long output, env var MAX_SIZE_UNLESS_HIDE_ARRAY

pull/4218/head
Viktor Baranov 4 years ago committed by nikitosing
parent 8009234013
commit 75463d78fd
  1. 1
      CHANGELOG.md
  2. 3
      apps/block_scout_web/config/config.exs
  3. 40
      apps/block_scout_web/lib/block_scout_web/templates/smart_contract/_functions.html.eex
  4. 37
      apps/block_scout_web/lib/block_scout_web/views/smart_contract_view.ex
  5. 48
      apps/block_scout_web/test/block_scout_web/views/tokens/smart_contract_view_test.exs

@ -1,6 +1,7 @@
## Current
### Features
- [#4218](https://github.com/blockscout/blockscout/pull/4218) - Hide long arrays in smart-contract's
- [#4205](https://github.com/blockscout/blockscout/pull/4205) - Total transactions fees per day API endpoint
- [#4158](https://github.com/blockscout/blockscout/pull/4158) - Calculate total fee per day
- [#4067](https://github.com/blockscout/blockscout/pull/4067) - Display LP tokens USD value and custom metadata in tokens dropdown at address page

@ -48,7 +48,8 @@ config :block_scout_web,
dark_forest_addresses: System.get_env("CUSTOM_CONTRACT_ADDRESSES_DARK_FOREST"),
dark_forest_addresses_v_0_5: System.get_env("CUSTOM_CONTRACT_ADDRESSES_DARK_FOREST_V_0_5"),
circles_addresses: System.get_env("CUSTOM_CONTRACT_ADDRESSES_CIRCLES"),
test_tokens_addresses: System.get_env("CUSTOM_CONTRACT_ADDRESSES_TEST_TOKEN")
test_tokens_addresses: System.get_env("CUSTOM_CONTRACT_ADDRESSES_TEST_TOKEN"),
max_size_to_show_array_as_is: Integer.parse(System.get_env("MAX_SIZE_UNLESS_HIDE_ARRAY", "50"))
config :block_scout_web, BlockScoutWeb.Counters.BlocksIndexedCounter, enabled: true

@ -98,35 +98,35 @@
<% end %>
</div>
<% end %>
<div data-function-response></div>
</div>
<% else %>
<span class="py-2 word-break-all">
<%= if outputs?(function["outputs"]) do %>
<%= for output <- function["outputs"] do %>
<%= if address?(output["type"]) do %>
<%= if outputs?(function["outputs"]) do %>
<%= for output <- function["outputs"] do %>
<%= if address?(output["type"]) do %>
<div class="py-2 word-break-all">
<%= link(
output["value"],
to: address_path(@conn, :show, output["value"])
) %>
to: address_path(@conn, :show, output["value"])) %>
</div>
<% else %>
<%= if output["type"] == "uint256" do %>
<div class="py-2 word-break-all">
<div data-wei-ether-converter>
<span data-conversion-unit data-original-value="<%= output["value"] %>"><%= output["value"] %></span>
<span class="py-2 px-2">
<input class="wei-ether" type="checkbox" autocomplete="off">
<span class="d-inline-block" data-conversion-text-wei><%= gettext("WEI")%></span>
<span class="d-none" data-conversion-text-eth><%= gettext("ETH")%></span>
</span>
</div>
</div>
<% else %>
<%= if output["type"] == "uint256" do %>
<div data-wei-ether-converter>
<span data-conversion-unit data-original-value="<%= output["value"] %>"><%= output["value"] %></span>
<span class="py-2 px-2">
<input class="wei-ether" type="checkbox" autocomplete="off">
<span class="d-inline-block" data-conversion-text-wei><%= gettext("WEI")%></span>
<span class="d-none" data-conversion-text-eth><%= gettext("ETH")%></span>
</span>
</div>
<% else %>
<%= raw(values_only(output["value"], output["type"], output["components"])) %>
<% end %>
<%= raw(values_only(output["value"], output["type"], output["components"])) %>
<% end %>
<% end %>
<% end %>
</span>
<% end %>
<% end %>
</div>
<% end %>

@ -105,6 +105,9 @@ defmodule BlockScoutWeb.SmartContractView do
end
def values_only(value, type, components) when is_list(value) do
max_size = Enum.at(Tuple.to_list(Application.get_env(:block_scout_web, :max_size_to_show_array_as_is)), 0)
is_too_long = length(value) > max_size
cond do
String.starts_with?(type, "tuple") ->
tuple_types =
@ -117,7 +120,7 @@ defmodule BlockScoutWeb.SmartContractView do
|> tuple_array_to_array(tuple_types)
|> Enum.join(", ")
render_array_value(values)
wrap_output(render_array_value(values), is_too_long)
String.starts_with?(type, "address") ->
values =
@ -125,7 +128,7 @@ defmodule BlockScoutWeb.SmartContractView do
|> Enum.map(&binary_to_utf_string(&1))
|> Enum.join(", ")
render_array_value(values)
wrap_output(render_array_value(values), is_too_long)
String.starts_with?(type, "bytes") ->
values =
@ -133,14 +136,14 @@ defmodule BlockScoutWeb.SmartContractView do
|> Enum.map(&binary_to_utf_string(&1))
|> Enum.join(", ")
render_array_value(values)
wrap_output(render_array_value(values), is_too_long)
true ->
values =
value
|> Enum.join(", ")
render_array_value(values)
wrap_output(render_array_value(values), is_too_long)
end
end
@ -150,26 +153,36 @@ defmodule BlockScoutWeb.SmartContractView do
|> tuple_to_array(type)
|> Enum.join(", ")
values
max_size = Enum.at(Tuple.to_list(Application.get_env(:block_scout_web, :max_size_to_show_array_as_is)), 0)
wrap_output(values, tuple_size(value) > max_size)
end
def values_only(value, type, _components) when type in [:address, "address", "address payable"] do
{:ok, address} = HashAddress.cast(value)
to_string(address)
wrap_output(to_string(address))
end
def values_only(value, "string", _components), do: value
def values_only(value, "string", _components), do: wrap_output(value)
def values_only(value, :string, _components), do: value
def values_only(value, :string, _components), do: wrap_output(value)
def values_only(value, :bytes, _components), do: value
def values_only(value, :bytes, _components), do: wrap_output(value)
def values_only(value, "bool", _components), do: to_string(value)
def values_only(value, "bool", _components), do: wrap_output(to_string(value))
def values_only(value, :bool, _components), do: to_string(value)
def values_only(value, :bool, _components), do: wrap_output(to_string(value))
def values_only(value, _type, _components) do
binary_to_utf_string(value)
wrap_output(binary_to_utf_string(value))
end
def wrap_output(value, is_too_long \\ false) do
if is_too_long do
"<details class=\"py-2 word-break-all\"><summary>Click to view</summary>#{value}</details>"
else
"<div class=\"py-2 word-break-all\">#{value}</div>"
end
end
defp tuple_array_to_array(value, type) do

@ -1,6 +1,8 @@
defmodule BlockScoutWeb.SmartContractViewTest do
use BlockScoutWeb.ConnCase, async: true
@max_size Enum.at(Tuple.to_list(Application.get_env(:block_scout_web, :max_size_to_show_array_as_is)), 0)
alias BlockScoutWeb.SmartContractView
describe "queryable?" do
@ -129,28 +131,39 @@ defmodule BlockScoutWeb.SmartContractViewTest do
end
end
defp wrap_it(output, length \\ -1) do
if length > @max_size do
"<details class=\"py-2 word-break-all\"><summary>Click to view</summary>#{output}</details>"
else
"<div class=\"py-2 word-break-all\">#{output}</div>"
end
end
describe "values_only/2" do
test "joins the values when it is a list of a given type" do
values = [8, 6, 9, 2, 2, 37]
assert SmartContractView.values_only(values, "type", nil) == "[8, 6, 9, 2, 2, 37]"
assert SmartContractView.values_only(values, "type", nil) == wrap_it("[8, 6, 9, 2, 2, 37]", length(values))
end
test "convert the value to string receiving a value and the 'address' type" do
value = <<95, 38, 9, 115, 52, 182, 163, 43, 121, 81, 223, 97, 253, 12, 88, 3, 236, 93, 131, 84>>
assert SmartContractView.values_only(value, "address", nil) == "0x5f26097334b6a32b7951df61fd0c5803ec5d8354"
assert SmartContractView.values_only(value, "address", nil) ==
wrap_it("0x5f26097334b6a32b7951df61fd0c5803ec5d8354")
end
test "convert the value to string receiving a value and the :address type" do
value = <<95, 38, 9, 115, 52, 182, 163, 43, 121, 81, 223, 97, 253, 12, 88, 3, 236, 93, 131, 84>>
assert SmartContractView.values_only(value, :address, nil) == "0x5f26097334b6a32b7951df61fd0c5803ec5d8354"
assert SmartContractView.values_only(value, :address, nil) ==
wrap_it("0x5f26097334b6a32b7951df61fd0c5803ec5d8354")
end
test "convert the value to string receiving a value and the 'address payable' type" do
value = <<95, 38, 9, 115, 52, 182, 163, 43, 121, 81, 223, 97, 253, 12, 88, 3, 236, 93, 131, 84>>
assert SmartContractView.values_only(value, "address payable", nil) ==
"0x5f26097334b6a32b7951df61fd0c5803ec5d8354"
wrap_it("0x5f26097334b6a32b7951df61fd0c5803ec5d8354")
end
test "convert each value to string and join them when receiving 'address[]' as the type" do
@ -160,19 +173,22 @@ defmodule BlockScoutWeb.SmartContractViewTest do
]
assert SmartContractView.values_only(value, "address[]", nil) ==
"[0x5f26097334b6a32b7951df61fd0c5803ec5d8354, 0xcf260ea317555637c55f70e55dba8d5ad8414cb0]"
wrap_it(
"[0x5f26097334b6a32b7951df61fd0c5803ec5d8354, 0xcf260ea317555637c55f70e55dba8d5ad8414cb0]",
length(value)
)
end
test "returns the value when the type is neither 'address' nor 'address payable'" do
value = "POA"
assert SmartContractView.values_only(value, "string", nil) == "POA"
assert SmartContractView.values_only(value, "string", nil) == wrap_it("POA")
end
test "returns the value when the type is :string" do
value = "POA"
assert SmartContractView.values_only(value, :string, nil) == "POA"
assert SmartContractView.values_only(value, :string, nil) == wrap_it("POA")
end
test "returns the value when the type is :bytes" do
@ -180,25 +196,27 @@ defmodule BlockScoutWeb.SmartContractViewTest do
"0x00050000a7823d6f1e31569f51861e345b30c6bebf70ebe700000000000019f2f6a78083ca3e2a662d6dd1703c939c8ace2e268d88ad09518695c6c3712ac10a214be5109a65567100061a800101806401125e4cfb0000000000000000000000000ae055097c6d159879521c384f1d2123d1f195e60000000000000000000000004c26ca0dc82a6e7bb00b8815a65985b67c0d30d3000000000000000000000000000000000000000000000002b5598f488fb733c9"
assert SmartContractView.values_only(value, :bytes, nil) ==
"0x00050000a7823d6f1e31569f51861e345b30c6bebf70ebe700000000000019f2f6a78083ca3e2a662d6dd1703c939c8ace2e268d88ad09518695c6c3712ac10a214be5109a65567100061a800101806401125e4cfb0000000000000000000000000ae055097c6d159879521c384f1d2123d1f195e60000000000000000000000004c26ca0dc82a6e7bb00b8815a65985b67c0d30d3000000000000000000000000000000000000000000000002b5598f488fb733c9"
wrap_it(
"0x00050000a7823d6f1e31569f51861e345b30c6bebf70ebe700000000000019f2f6a78083ca3e2a662d6dd1703c939c8ace2e268d88ad09518695c6c3712ac10a214be5109a65567100061a800101806401125e4cfb0000000000000000000000000ae055097c6d159879521c384f1d2123d1f195e60000000000000000000000004c26ca0dc82a6e7bb00b8815a65985b67c0d30d3000000000000000000000000000000000000000000000002b5598f488fb733c9"
)
end
test "returns the value when the type is boolean" do
value = "true"
assert SmartContractView.values_only(value, "bool", nil) == "true"
assert SmartContractView.values_only(value, "bool", nil) == wrap_it("true")
end
test "returns the value when the type is :bool" do
value = "true"
assert SmartContractView.values_only(value, :bool, nil) == "true"
assert SmartContractView.values_only(value, :bool, nil) == wrap_it("true")
end
test "returns the value when the type is bytes4" do
value = <<228, 184, 12, 77>>
assert SmartContractView.values_only(value, "bytes4", nil) == "0xe4b80c4d"
assert SmartContractView.values_only(value, "bytes4", nil) == wrap_it("0xe4b80c4d")
end
test "returns the value when the type is bytes32" do
@ -207,19 +225,19 @@ defmodule BlockScoutWeb.SmartContractViewTest do
211, 212, 230, 127, 179, 214, 249, 38>>
assert SmartContractView.values_only(value, "bytes32", nil) ==
"0x9cd14677f9aa5569b3bbb351fcd67d1115aa563ae1624276d3d4e67fb3d6f926"
wrap_it("0x9cd14677f9aa5569b3bbb351fcd67d1115aa563ae1624276d3d4e67fb3d6f926")
end
test "returns the value when the type is uint(n) and value is 0" do
value = "0"
assert SmartContractView.values_only(value, "uint64", nil) == "0"
assert SmartContractView.values_only(value, "uint64", nil) == wrap_it("0")
end
test "returns the value when the type is int(n) and value is 0" do
value = "0"
assert SmartContractView.values_only(value, "int64", nil) == "0"
assert SmartContractView.values_only(value, "int64", nil) == wrap_it("0")
end
end
end

Loading…
Cancel
Save