feat: Xname app proxy (#11010)

* Xname app proxy

* fix specs

* Process reviewer comments
vb-airtable-proxy
Victor Baranov 4 weeks ago committed by GitHub
parent 6dbdb26b35
commit eb94a4230f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 24
      apps/block_scout_web/lib/block_scout_web/controllers/api/v2/proxy/xname_controller.ex
  2. 4
      apps/block_scout_web/lib/block_scout_web/routers/api_router.ex
  3. 20
      apps/explorer/lib/explorer/third_party_integrations/noves_fi.ex
  4. 50
      apps/explorer/lib/explorer/third_party_integrations/xname.ex
  5. 12
      apps/explorer/lib/explorer/third_party_integrations/zerion.ex
  6. 4
      config/runtime.exs
  7. 2
      cspell.json
  8. 2
      docker-compose/envs/common-blockscout.env

@ -0,0 +1,24 @@
defmodule BlockScoutWeb.API.V2.Proxy.XnameController do
use BlockScoutWeb, :controller
alias BlockScoutWeb.API.V2.AddressController
alias Explorer.ThirdPartyIntegrations.Xname
action_fallback(BlockScoutWeb.API.V2.FallbackController)
@doc """
Function to handle GET requests to `/api/v2/proxy/xname/address/:address_hash_param` endpoint.
"""
@spec address(Plug.Conn.t(), map()) :: Plug.Conn.t() | {atom(), any()}
def address(conn, %{"address_hash_param" => address_hash_string} = params) do
with {:ok, _address_hash, _address} <- AddressController.validate_address(address_hash_string, params),
url = Xname.address_url(address_hash_string),
{response, status} <- Xname.api_request(url, conn),
{:is_empty_response, false} <- {:is_empty_response, is_nil(response)} do
conn
|> put_status(status)
|> json(response)
end
end
end

@ -353,6 +353,10 @@ defmodule BlockScoutWeb.Routers.ApiRouter do
get("/wallets/:address_hash_param/portfolio", V2.Proxy.ZerionController, :wallet_portfolio)
end
scope "/xname" do
get("/addresses/:address_hash_param", V2.Proxy.XnameController, :address)
end
scope "/metadata" do
get("/addresses", V2.Proxy.MetadataController, :addresses)
end

@ -3,6 +3,8 @@ defmodule Explorer.ThirdPartyIntegrations.NovesFi do
Module for Noves.Fi API integration https://blockscout.noves.fi/swagger/index.html
"""
require Logger
alias Explorer.Helper
alias Explorer.Utility.Microservice
@ -33,7 +35,11 @@ defmodule Explorer.ThirdPartyIntegrations.NovesFi do
{:ok, %HTTPoison.Response{status_code: status, body: body}} ->
{Helper.decode_json(body), status}
_ ->
{:error, reason} ->
Logger.error(fn ->
["Error while requesting Noves.Fi API endpoint #{url}. The reason is: ", inspect(reason)]
end)
{nil, 500}
end
end
@ -47,13 +53,17 @@ defmodule Explorer.ThirdPartyIntegrations.NovesFi do
{:ok, %HTTPoison.Response{status_code: status, body: body}} ->
{Helper.decode_json(body), status}
_ ->
{:error, reason} ->
Logger.error(fn ->
["Error while requesting Noves.Fi API endpoint #{url}. The reason is: ", inspect(reason)]
end)
{nil, 500}
end
end
@doc """
Noves.fi /evm/{chain}/tx/{txHash} endpoint
Noves.fi /evm/:chain/tx/:transaction_hash endpoint
"""
@spec transaction_url(String.t()) :: String.t()
def transaction_url(transaction_hash_string) do
@ -61,7 +71,7 @@ defmodule Explorer.ThirdPartyIntegrations.NovesFi do
end
@doc """
Noves.fi /evm/{chain}/describeTxs endpoint
Noves.fi /evm/:chain/describeTxs endpoint
"""
@spec describe_transactions_url() :: String.t()
def describe_transactions_url do
@ -69,7 +79,7 @@ defmodule Explorer.ThirdPartyIntegrations.NovesFi do
end
@doc """
Noves.fi /evm/{chain}/transactions/{accountAddress} endpoint
Noves.fi /evm/:chain/transactions/:address_hash endpoint
"""
@spec address_transactions_url(String.t()) :: String.t()
def address_transactions_url(address_hash_string) do

@ -0,0 +1,50 @@
defmodule Explorer.ThirdPartyIntegrations.Xname do
@moduledoc """
Module for proxying xname https://xname.app/ API endpoints
"""
require Logger
alias Explorer.Helper
alias Explorer.Utility.Microservice
@recv_timeout 60_000
@doc """
Proxy request to XName API endpoints
"""
@spec api_request(String.t(), Plug.Conn.t(), atom()) :: {any(), integer()}
def api_request(url, conn, method \\ :get)
def api_request(url, _conn, :get) do
headers = [{"x-api-key", api_key()}]
case HTTPoison.get(url, headers, recv_timeout: @recv_timeout) do
{:ok, %HTTPoison.Response{status_code: status, body: body}} ->
{Helper.decode_json(body), status}
{:error, reason} ->
Logger.error(fn ->
["Error while requesting XName app API endpoint #{url}. The reason is: ", inspect(reason)]
end)
{nil, 500}
end
end
@doc """
https://gateway.xname.app/xhs/level/:address_hash endpoint
"""
@spec address_url(String.t()) :: String.t()
def address_url(address_hash_string) do
"#{base_url()}/xhs/level/#{address_hash_string}"
end
defp base_url do
Microservice.base_url(__MODULE__)
end
defp api_key do
Application.get_env(:explorer, __MODULE__)[:api_key]
end
end

@ -3,6 +3,8 @@ defmodule Explorer.ThirdPartyIntegrations.Zerion do
Module for Zerion API integration https://developers.zerion.io/reference
"""
require Logger
alias Explorer.Helper
alias Explorer.Utility.Microservice
@ -11,7 +13,7 @@ defmodule Explorer.ThirdPartyIntegrations.Zerion do
@doc """
Proxy request to Zerion API endpoints
"""
@spec api_request(String.t(), Plug.Conn.t(), :get | :post_transactions) :: {any(), integer()}
@spec api_request(String.t(), Plug.Conn.t(), atom()) :: {any(), integer()}
def api_request(url, conn, method \\ :get)
def api_request(url, _conn, :get) do
@ -22,13 +24,17 @@ defmodule Explorer.ThirdPartyIntegrations.Zerion do
{:ok, %HTTPoison.Response{status_code: status, body: body}} ->
{Helper.decode_json(body), status}
_ ->
{:error, reason} ->
Logger.error(fn ->
["Error while requesting Zerion API endpoint #{url}. The reason is: ", inspect(reason)]
end)
{nil, 500}
end
end
@doc """
Zerion /wallets/{accountAddress}/portfolio endpoint
Zerion /wallets/:address_hash/portfolio endpoint
"""
@spec wallet_portfolio_url(String.t()) :: String.t()
def wallet_portfolio_url(address_hash_string) do

@ -499,6 +499,10 @@ config :explorer, Explorer.ThirdPartyIntegrations.Zerion,
service_url: System.get_env("ZERION_BASE_API_URL", "https://api.zerion.io/v1"),
api_key: System.get_env("ZERION_API_TOKEN")
config :explorer, Explorer.ThirdPartyIntegrations.Xname,
service_url: System.get_env("XNAME_BASE_API_URL", "https://gateway.xname.app"),
api_key: System.get_env("XNAME_API_TOKEN")
enabled? = ConfigHelper.parse_bool_env_var("MICROSERVICE_SC_VERIFIER_ENABLED", "true")
# or "eth_bytecode_db"
type = System.get_env("MICROSERVICE_SC_VERIFIER_TYPE", "sc_verifier")

@ -435,6 +435,7 @@
"prederived",
"progressbar",
"proxiable",
"proxying",
"psql",
"pubkey",
"pubkeys",
@ -641,6 +642,7 @@
"xakgj",
"xbaddress",
"xdai",
"Xname",
"xffff",
"xlevel",
"xlink",

@ -447,6 +447,8 @@ TENDERLY_CHAIN_PATH=
# NOVES_FI_API_TOKEN=
# ZERION_BASE_API_URL=
# ZERION_API_TOKEN=
# XNAME_BASE_API_URL=
# XNAME_API_TOKEN=
# BRIDGED_TOKENS_ENABLED=
# BRIDGED_TOKENS_ETH_OMNI_BRIDGE_MEDIATOR=
# BRIDGED_TOKENS_BSC_OMNI_BRIDGE_MEDIATOR=

Loading…
Cancel
Save