feat: Add DELETE /api/v2/import/token-info method (#10580)

* feat: Add DELETE /api/v2/import/token-info method

* Process review comments

* Unify params case

* Fix test

* Fix test
pull/10407/head
nikitosing 3 months ago committed by GitHub
parent af88ab547f
commit ebc99bfff9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 47
      apps/block_scout_web/lib/block_scout_web/controllers/api/v2/import_controller.ex
  2. 2
      apps/block_scout_web/lib/block_scout_web/routers/api_router.ex
  3. 92
      apps/block_scout_web/test/block_scout_web/controllers/api/v2/import_controller_test.exs
  4. 12
      apps/explorer/lib/explorer/chain/token.ex

@ -3,9 +3,10 @@ defmodule BlockScoutWeb.API.V2.ImportController do
alias BlockScoutWeb.API.V2.ApiView
alias Explorer.Chain
alias Explorer.Chain.{Data, SmartContract}
alias Explorer.Chain.{Data, SmartContract, Token}
alias Explorer.Chain.Fetcher.LookUpSmartContractSourcesOnDemand
alias Explorer.SmartContract.EthBytecodeDBInterface
alias Indexer.Fetcher.TokenUpdater
import Explorer.SmartContract.Helper, only: [prepare_bytecode_for_microservice: 3, contract_creation_input: 1]
@ -23,12 +24,7 @@ defmodule BlockScoutWeb.API.V2.ImportController do
"tokenName" => token_name
} = params
) do
with {:sensitive_endpoints_api_key, api_key} when not is_nil(api_key) <-
{:sensitive_endpoints_api_key, Application.get_env(:block_scout_web, :sensitive_endpoints_api_key)},
{:api_key, ^api_key} <- {:api_key, params["api_key"]},
{:format_address, {:ok, address_hash}} <-
{:format_address, Chain.string_to_address_hash(token_address_hash_string)},
{:not_found, {:ok, token}} <- {:not_found, Chain.token_from_address_hash(address_hash, @api_true)} do
with {:ok, token} <- validate_api_key_address_hash_and_token(token_address_hash_string, params["api_key"]) do
changeset =
%{is_verified_via_admin_panel: true}
|> put_icon_url(icon_url)
@ -96,6 +92,32 @@ defmodule BlockScoutWeb.API.V2.ImportController do
end
end
def delete_token_info(
conn,
%{
"token_address_hash" => token_address_hash_string
} = params
) do
with {:ok, token} <- validate_api_key_address_hash_and_token(token_address_hash_string, params["api_key"]) do
case Token.drop_token_info(token) do
{:ok, _} ->
TokenUpdater.run([token], [])
conn
|> put_view(ApiView)
|> render(:message, %{message: "Success"})
error ->
Logger.warning(fn -> ["Error on deleting token info: ", inspect(error)] end)
conn
|> put_view(ApiView)
|> put_status(:bad_request)
|> render(:message, %{message: "Error"})
end
end
end
defp params_to_contract_search_options(%{"import_from" => "verifier_alliance"}) do
[only_verifier_alliance?: true]
end
@ -142,4 +164,15 @@ defmodule BlockScoutWeb.API.V2.ImportController do
nil
end
end
defp validate_api_key_address_hash_and_token(token_address_hash_string, provided_api_key) do
with {:sensitive_endpoints_api_key, api_key} when not is_nil(api_key) <-
{:sensitive_endpoints_api_key, Application.get_env(:block_scout_web, :sensitive_endpoints_api_key)},
{:api_key, ^api_key} <- {:api_key, provided_api_key},
{:format_address, {:ok, address_hash}} <-
{:format_address, Chain.string_to_address_hash(token_address_hash_string)},
{:not_found, {:ok, token}} <- {:not_found, Chain.token_from_address_hash(address_hash, @api_true)} do
{:ok, token}
end
end
end

@ -93,6 +93,8 @@ defmodule BlockScoutWeb.Routers.ApiRouter do
pipe_through(:api_v2_no_session)
post("/token-info", V2.ImportController, :import_token_info)
delete("/token-info", V2.ImportController, :delete_token_info)
get("/smart-contracts/:address_hash_param", V2.ImportController, :try_to_search_contract)
end

@ -1,7 +1,9 @@
defmodule BlockScoutWeb.API.V2.ImportControllerTest do
use BlockScoutWeb.ConnCase
describe "/import/token-info" do
import Mox
describe "POST /import/token-info" do
test "return error on misconfigured api key", %{conn: conn} do
request =
post(conn, "/api/v2/import/token-info", %{
@ -73,4 +75,92 @@ defmodule BlockScoutWeb.API.V2.ImportControllerTest do
Application.put_env(:block_scout_web, :sensitive_endpoints_api_key, nil)
end
end
describe "DELETE /import/token-info" do
test "return error on misconfigured api key", %{conn: conn} do
request =
delete(conn, "/api/v2/import/token-info", %{
"token_address_hash" => build(:address).hash
})
assert %{"message" => "API key not configured on the server"} = json_response(request, 403)
end
test "return error on wrong api key", %{conn: conn} do
Application.put_env(:block_scout_web, :sensitive_endpoints_api_key, "abc")
body = %{"token_address_hash" => build(:address).hash}
request = delete(conn, "/api/v2/import/token-info", Map.merge(body, %{"api_key" => "123"}))
assert %{"message" => "Wrong API key"} = json_response(request, 401)
Application.put_env(:block_scout_web, :sensitive_endpoints_api_key, nil)
end
test "success delete token info", %{conn: conn} do
insert(:token,
name: "old",
symbol: "OLD",
decimals: 10,
cataloged: true,
updated_at: DateTime.add(DateTime.utc_now(), -:timer.hours(50), :millisecond)
)
expect(
EthereumJSONRPC.Mox,
:json_rpc,
1,
fn requests, _opts ->
{:ok,
Enum.map(requests, fn
%{id: id, method: "eth_call", params: [%{data: "0x313ce567", to: _}, "latest"]} ->
%{
id: id,
result: "0x0000000000000000000000000000000000000000000000000000000000000012"
}
%{id: id, method: "eth_call", params: [%{data: "0x06fdde03", to: _}, "latest"]} ->
%{
id: id,
result:
"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000096e657720746f6b656e0000000000000000000000000000000000000000000000"
}
%{id: id, method: "eth_call", params: [%{data: "0x95d89b41", to: _}, "latest"]} ->
%{
id: id,
result:
"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000034e45570000000000000000000000000000000000000000000000000000000000"
}
%{id: id, method: "eth_call", params: [%{data: "0x18160ddd", to: _}, "latest"]} ->
%{
id: id,
result: "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000"
}
end)}
end
)
api_key = "abc123"
icon_url = nil
token_symbol = "NEW"
token_name = "new token"
Application.put_env(:block_scout_web, :sensitive_endpoints_api_key, api_key)
token_address = to_string(insert(:token).contract_address_hash)
body = %{
"token_address_hash" => token_address
}
request = delete(conn, "/api/v2/import/token-info", Map.merge(body, %{"api_key" => api_key}))
assert %{"message" => "Success"} = json_response(request, 200)
request = get(conn, "/api/v2/tokens/#{token_address}")
assert %{"icon_url" => ^icon_url, "name" => ^token_name, "symbol" => ^token_symbol} = json_response(request, 200)
Application.put_env(:block_scout_web, :sensitive_endpoints_api_key, nil)
end
end
end

@ -278,4 +278,16 @@ defmodule Explorer.Chain.Token do
timeout: @timeout
)
end
@doc """
Drops token info for the given token:
Sets is_verified_via_admin_panel to false, icon_url to nil, symbol to nil, name to nil.
Don't forget to set/update token's symbol and name after this function.
"""
@spec drop_token_info(t()) :: {:ok, t()} | {:error, Changeset.t()}
def drop_token_info(token) do
token
|> Changeset.change(%{is_verified_via_admin_panel: false, icon_url: nil, symbol: nil, name: nil})
|> Repo.update()
end
end

Loading…
Cancel
Save