From 75463d78fd87acdd2ebc69dd1d20ac499b552d28 Mon Sep 17 00:00:00 2001 From: Viktor Baranov Date: Thu, 27 May 2021 13:16:30 +0300 Subject: [PATCH] added hiding long output, env var MAX_SIZE_UNLESS_HIDE_ARRAY --- CHANGELOG.md | 1 + apps/block_scout_web/config/config.exs | 3 +- .../smart_contract/_functions.html.eex | 42 ++++++++-------- .../views/smart_contract_view.ex | 37 +++++++++----- .../views/tokens/smart_contract_view_test.exs | 48 +++++++++++++------ 5 files changed, 82 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf77d05097..31eedd1f9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/apps/block_scout_web/config/config.exs b/apps/block_scout_web/config/config.exs index d8d6cabd80..dc59bf2c8f 100644 --- a/apps/block_scout_web/config/config.exs +++ b/apps/block_scout_web/config/config.exs @@ -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 diff --git a/apps/block_scout_web/lib/block_scout_web/templates/smart_contract/_functions.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/smart_contract/_functions.html.eex index 3c27d3f8e8..d638cf4205 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/smart_contract/_functions.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/smart_contract/_functions.html.eex @@ -98,35 +98,35 @@ <% end %> <% end %> -
<% else %> - - <%= 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 %> +
<%= link( output["value"], - to: address_path(@conn, :show, output["value"]) - ) %> + to: address_path(@conn, :show, output["value"])) %> +
+ <% else %> + <%= if output["type"] == "uint256" do %> +
+
+ "><%= output["value"] %> + + + <%= gettext("WEI")%> + <%= gettext("ETH")%> + +
+
<% else %> - <%= if output["type"] == "uint256" do %> -
- "><%= output["value"] %> - - - <%= gettext("WEI")%> - <%= gettext("ETH")%> - -
- <% else %> - <%= raw(values_only(output["value"], output["type"], output["components"])) %> - <% end %> + <%= raw(values_only(output["value"], output["type"], output["components"])) %> <% end %> <% end %> <% end %> -
+ <% end %> <% end %> -<% end %> +<% end %> \ No newline at end of file diff --git a/apps/block_scout_web/lib/block_scout_web/views/smart_contract_view.ex b/apps/block_scout_web/lib/block_scout_web/views/smart_contract_view.ex index d9ab656ce9..d75ba3a24e 100644 --- a/apps/block_scout_web/lib/block_scout_web/views/smart_contract_view.ex +++ b/apps/block_scout_web/lib/block_scout_web/views/smart_contract_view.ex @@ -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 + "
Click to view#{value}
" + else + "
#{value}
" + end end defp tuple_array_to_array(value, type) do diff --git a/apps/block_scout_web/test/block_scout_web/views/tokens/smart_contract_view_test.exs b/apps/block_scout_web/test/block_scout_web/views/tokens/smart_contract_view_test.exs index 7e43ce4e10..2a23017b49 100644 --- a/apps/block_scout_web/test/block_scout_web/views/tokens/smart_contract_view_test.exs +++ b/apps/block_scout_web/test/block_scout_web/views/tokens/smart_contract_view_test.exs @@ -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 + "
Click to view#{output}
" + else + "
#{output}
" + 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