From b9ade785d21a391544d708c868084a4af917d47e Mon Sep 17 00:00:00 2001 From: zachdaniel Date: Thu, 28 Feb 2019 16:53:33 -0500 Subject: [PATCH] feat: add an admin method to import contract methods. --- apps/block_scout_web/assets/js/app.js | 2 + .../assets/js/pages/admin/tasks.js | 26 +++++++++++++ .../lib/block_scout_web/admin_router.ex | 4 ++ .../controllers/admin/tasks_controller.ex | 22 +++++++++++ .../templates/admin/dashboard/index.html.eex | 37 ++++++++++++++++++- apps/block_scout_web/priv/gettext/default.pot | 10 +++++ .../priv/gettext/en/LC_MESSAGES/default.po | 10 +++++ .../lib/explorer/chain/contract_method.ex | 19 +++++++++- 8 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 apps/block_scout_web/assets/js/pages/admin/tasks.js create mode 100644 apps/block_scout_web/lib/block_scout_web/controllers/admin/tasks_controller.ex diff --git a/apps/block_scout_web/assets/js/app.js b/apps/block_scout_web/assets/js/app.js index e01a7fcd7f..4c9ac868d9 100644 --- a/apps/block_scout_web/assets/js/app.js +++ b/apps/block_scout_web/assets/js/app.js @@ -31,6 +31,8 @@ import './pages/pending_transactions' import './pages/transaction' import './pages/transactions' +import './pages/admin/tasks.js' + import './lib/clipboard_buttons' import './lib/currency' import './lib/from_now' diff --git a/apps/block_scout_web/assets/js/pages/admin/tasks.js b/apps/block_scout_web/assets/js/pages/admin/tasks.js new file mode 100644 index 0000000000..7eb7cf1801 --- /dev/null +++ b/apps/block_scout_web/assets/js/pages/admin/tasks.js @@ -0,0 +1,26 @@ +import $ from 'jquery' + +const runTask = (event) => { + const element = event.currentTarget + const $element = $(element) + const $loading = $element.find('[data-loading-message]') + const $errorMessage = $element.find('[data-error-message]') + const $successMessage = $element.find('[data-success-message]') + const apiPath = element.dataset.api_path + + $errorMessage.hide() + $successMessage.hide() + $loading.show() + + $.get(apiPath) + .done(response => { + $successMessage.show() + $loading.hide() + }) + .fail(() => { + $loading.hide() + $errorMessage.show() + }) +} + +$('#run-create-contract-methods').click(runTask) diff --git a/apps/block_scout_web/lib/block_scout_web/admin_router.ex b/apps/block_scout_web/lib/block_scout_web/admin_router.ex index 8a07881c1c..7a1c328ba3 100644 --- a/apps/block_scout_web/lib/block_scout_web/admin_router.ex +++ b/apps/block_scout_web/lib/block_scout_web/admin_router.ex @@ -43,5 +43,9 @@ defmodule BlockScoutWeb.AdminRouter do pipe_through([:browser, :check_configured, :ensure_admin]) get("/", DashboardController, :index) + + scope "/tasks" do + get("/create_contract_methods", TaskController, :create_contract_methods, as: :create_contract_methods) + end end end diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/admin/tasks_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/admin/tasks_controller.ex new file mode 100644 index 0000000000..1e94fc50c4 --- /dev/null +++ b/apps/block_scout_web/lib/block_scout_web/controllers/admin/tasks_controller.ex @@ -0,0 +1,22 @@ +defmodule BlockScoutWeb.Admin.TaskController do + use BlockScoutWeb, :controller + + require Logger + + alias Explorer.Chain.ContractMethod + + @ok_resp Poison.encode!(%{status: "success"}) + @not_ok_resp Poison.encode!(%{status: "failure"}) + + def create_contract_methods(conn, _) do + case ContractMethod.import_all() do + :ok -> + send_resp(conn, 200, Poison.encode!(@ok_resp)) + + {:error, error} -> + Logger.error(fn -> ["Something went wrong while creating contract methods: ", inspect(error)] end) + + send_resp(conn, 500, Poison.encode!(@not_ok_resp)) + end + end +end diff --git a/apps/block_scout_web/lib/block_scout_web/templates/admin/dashboard/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/admin/dashboard/index.html.eex index 5b67246fa6..40fb11a06a 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/admin/dashboard/index.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/admin/dashboard/index.html.eex @@ -1 +1,36 @@ -
+
+
+
+

Tasks

+
+ +
+
+
+
+
+

Create Contract Methods

+
+
+

+ <%= gettext("For any existing contracts in the database, insert all ABI entries into the contract_methods table. Use this in case you have verified smart contracts before early March 2019 and you want other contracts with the same functions to show those ABI's as candidate matches.") %> +

+
+ + +
+
+
+
+
+
diff --git a/apps/block_scout_web/priv/gettext/default.pot b/apps/block_scout_web/priv/gettext/default.pot index 0617fe58ee..05331a389e 100644 --- a/apps/block_scout_web/priv/gettext/default.pot +++ b/apps/block_scout_web/priv/gettext/default.pot @@ -1671,3 +1671,13 @@ msgstr "" #: lib/block_scout_web/templates/transaction/overview.html.eex:131 msgid "UTF-8" msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/admin/dashboard/index.html.eex:16 +msgid "For any existing contracts in the database, insert all ABI entries into the contract_methods table. Use this in case you have verified smart contracts before early March 2019 and you want other contracts with the same functions to show those ABI's as candidate matches." +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/admin/dashboard/index.html.eex:21 +msgid "Run" +msgstr "" diff --git a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po index c04f2a61c7..28c4e6455f 100644 --- a/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po +++ b/apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po @@ -1671,3 +1671,13 @@ msgstr "" #: lib/block_scout_web/templates/transaction/overview.html.eex:131 msgid "UTF-8" msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/admin/dashboard/index.html.eex:16 +msgid "For any existing contracts in the database, insert all ABI entries into the contract_methods table. Use this in case you have verified smart contracts before early March 2019 and you want other contracts with the same functions to show those ABI's as candidate matches." +msgstr "" + +#, elixir-format +#: lib/block_scout_web/templates/admin/dashboard/index.html.eex:21 +msgid "Run" +msgstr "" diff --git a/apps/explorer/lib/explorer/chain/contract_method.ex b/apps/explorer/lib/explorer/chain/contract_method.ex index 135208ccbf..5e2caa99c5 100644 --- a/apps/explorer/lib/explorer/chain/contract_method.ex +++ b/apps/explorer/lib/explorer/chain/contract_method.ex @@ -7,7 +7,7 @@ defmodule Explorer.Chain.ContractMethod do use Explorer.Schema - alias Explorer.Chain.{Hash, MethodIdentifier} + alias Explorer.Chain.{Hash, MethodIdentifier, SmartContract} alias Explorer.Repo @type t :: %__MODULE__{ @@ -49,6 +49,23 @@ defmodule Explorer.Chain.ContractMethod do Repo.insert_all(__MODULE__, successes, on_conflict: :nothing, conflict_target: [:identifier, :abi]) end + def import_all do + result = + Repo.transaction(fn -> + SmartContract + |> Repo.stream() + |> Task.async_stream(fn contract -> + upsert_from_abi(contract.abi, contract.address_hash) + end) + |> Stream.run() + end) + + case result do + {:ok, _} -> :ok + {:error, error} -> {:error, error} + end + end + defp abi_element_to_contract_method(element) do case ABI.parse_specification([element], include_events?: true) do [selector] ->