diff --git a/CHANGELOG.md b/CHANGELOG.md
index d61f364197..705fa4f3e6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
## Current
### Features
+- [#3320](https://github.com/poanetwork/blockscout/pull/3320) - Bridged tokens from AMB extensions support
- [#3311](https://github.com/poanetwork/blockscout/pull/3311) - List of addresses with restricted access option
- [#3293](https://github.com/poanetwork/blockscout/pull/3293) - Composite market cap for xDai: TokenBridge + OmniBridge
- [#3282](https://github.com/poanetwork/blockscout/pull/3282), [#3318](https://github.com/poanetwork/blockscout/pull/3318) - Import bridged tokens custom metadata
diff --git a/apps/block_scout_web/assets/css/app.scss b/apps/block_scout_web/assets/css/app.scss
index e81af0781f..ded845b4b5 100644
--- a/apps/block_scout_web/assets/css/app.scss
+++ b/apps/block_scout_web/assets/css/app.scss
@@ -117,6 +117,7 @@ $fa-font-path: "~@fortawesome/fontawesome-free/webfonts";
@import "components/_erc721_token_image_container";
@import "components/_inventory_token_instance_image_container";
@import "components/_external_link";
+@import "components/_label";
@import "theme/dark-theme";
diff --git a/apps/block_scout_web/assets/css/components/_label.scss b/apps/block_scout_web/assets/css/components/_label.scss
new file mode 100644
index 0000000000..20dd9fa3d5
--- /dev/null
+++ b/apps/block_scout_web/assets/css/components/_label.scss
@@ -0,0 +1,19 @@
+.bridged-token-label {
+ display: inline-block;
+ padding: 5px;
+ background: #f5f6fa;
+ color: #a3a9b5;
+ border-radius: 5px;
+ font-size: 10px;
+ &.right {
+ float: right;
+ }
+ &.omni {
+ background: $primary;
+ color: white;
+ }
+ &.amb {
+ background: $secondary;
+ color: white;
+ }
+}
\ No newline at end of file
diff --git a/apps/block_scout_web/config/config.exs b/apps/block_scout_web/config/config.exs
index 4f696156ea..4d5d3c6fe8 100644
--- a/apps/block_scout_web/config/config.exs
+++ b/apps/block_scout_web/config/config.exs
@@ -36,8 +36,9 @@ config :block_scout_web,
api_url: System.get_env("API_URL"),
apps_menu: if(System.get_env("APPS_MENU", "false") == "true", do: true, else: false),
external_apps: System.get_env("EXTERNAL_APPS"),
- multi_token_bridge_mediator: System.get_env("MULTI_TOKEN_BRIDGE_MEDIATOR"),
- foreign_json_rpc: System.get_env("FOREIGN_JSON_RPC"),
+ omni_bridge_mediator: System.get_env("OMNI_BRIDGE_MEDIATOR"),
+ amb_bridge_mediators: System.get_env("AMB_BRIDGE_MEDIATORS"),
+ foreign_json_rpc: System.get_env("FOREIGN_JSON_RPC", ""),
gas_price: System.get_env("GAS_PRICE", nil),
restricted_list: System.get_env("RESTRICTED_LIST", nil),
restricted_list_key: System.get_env("RESTRICTED_LIST_KEY", nil)
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/bridged_tokens_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/bridged_tokens_controller.ex
index 815077567f..3aeea6602f 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/bridged_tokens_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/bridged_tokens_controller.ex
@@ -31,11 +31,12 @@ defmodule BlockScoutWeb.BridgedTokensController do
items =
tokens_page
|> Enum.with_index(1)
- |> Enum.map(fn {token, index} ->
+ |> Enum.map(fn {[token, bridged_token], index} ->
View.render_to_string(
BridgedTokensView,
"_tile.html",
token: token,
+ bridged_token: bridged_token,
index: index
)
end)
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/bridged_tokens/_tile.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/bridged_tokens/_tile.html.eex
index 094a16442a..49cad1f047 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/bridged_tokens/_tile.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/bridged_tokens/_tile.html.eex
@@ -7,10 +7,33 @@
<% token = token_display_name(@token) %>
- <%= link(token,
- to: token_path(BlockScoutWeb.Endpoint, :show, @token.contract_address_hash),
- "data-test": "token_link",
- class: "text-truncate") %>
+
+ <%= link(token,
+ to: token_path(BlockScoutWeb.Endpoint, :show, @token.contract_address_hash),
+ "data-test": "token_link",
+ class: "text-truncate") %>
+ <%= if @bridged_token.type do %>
+ <%= String.upcase(@bridged_token.type) %>
+ <% end %>
+ <%= if owl_token_amb?(@token.contract_address.hash) do %>
+
+
+
+ <% end %>
+ <%= if owl_token_omni?(@token.contract_address.hash) do %>
+
+
+
+ <% end %>
+
|
<%= render BlockScoutWeb.AddressView,
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/bridged_tokens/index.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/bridged_tokens/index.html.eex
index 5b76450d69..6277ab16cd 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/bridged_tokens/index.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/bridged_tokens/index.html.eex
@@ -2,6 +2,7 @@
<%= gettext "Bridged Tokens" %>
+ List of the tokens bridged through OmniBridge OMNI and Arbitrary Message Bridge AMB extensions
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "top", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex
index c8b4a8f7b5..32e1d4ea9a 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex
@@ -78,7 +78,7 @@
<%= gettext("Accounts") %>
<% end %>
- <%= if Application.get_env(:block_scout_web, :multi_token_bridge_mediator) && Application.get_env(:block_scout_web, :multi_token_bridge_mediator) != "" do %>
+ <%= if Application.get_env(:block_scout_web, :omni_bridge_mediator) && Application.get_env(:block_scout_web, :omni_bridge_mediator) != "" do %>
diff --git a/apps/block_scout_web/lib/block_scout_web/views/bridged_tokens_view.ex b/apps/block_scout_web/lib/block_scout_web/views/bridged_tokens_view.ex
index 4a105aaa40..8b1d3659a5 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/bridged_tokens_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/bridged_tokens_view.ex
@@ -3,10 +3,29 @@ defmodule BlockScoutWeb.BridgedTokensView do
alias Explorer.Chain.Token
+ @owl_token_amb "0x0905Ab807F8FD040255F0cF8fa14756c1D824931"
+ @owl_token_omni "0x750eCf8c11867Ce5Dbc556592c5bb1E0C6d16538"
+
def decimals?(%Token{decimals: nil}), do: false
def decimals?(%Token{decimals: _}), do: true
def token_display_name(%Token{name: nil}), do: ""
def token_display_name(%Token{name: name}), do: name
+
+ def owl_token_amb?(address_hash) do
+ to_string(address_hash) == String.downcase(@owl_token_amb)
+ end
+
+ def owl_token_omni?(address_hash) do
+ to_string(address_hash) == String.downcase(@owl_token_omni)
+ end
+
+ def owl_token_amb_info do
+ ""
+ end
+
+ def owl_token_omni_info do
+ ""
+ end
end
diff --git a/apps/block_scout_web/lib/block_scout_web/views/tokens_view.ex b/apps/block_scout_web/lib/block_scout_web/views/tokens_view.ex
index 7589dc5ef5..bde196fa85 100644
--- a/apps/block_scout_web/lib/block_scout_web/views/tokens_view.ex
+++ b/apps/block_scout_web/lib/block_scout_web/views/tokens_view.ex
@@ -7,9 +7,9 @@ defmodule BlockScoutWeb.TokensView do
def decimals?(%Token{decimals: _}), do: true
def bridged_tokens_enabled? do
- multi_token_bridge_mediator = Application.get_env(:block_scout_web, :multi_token_bridge_mediator)
+ omni_bridge_mediator = Application.get_env(:block_scout_web, :omni_bridge_mediator)
- multi_token_bridge_mediator && multi_token_bridge_mediator !== ""
+ omni_bridge_mediator && omni_bridge_mediator !== ""
end
def token_display_name(%Token{name: nil, symbol: nil}), do: ""
diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex
index 5e8de20254..02073f3505 100644
--- a/apps/explorer/lib/explorer/chain.ex
+++ b/apps/explorer/lib/explorer/chain.ex
@@ -24,6 +24,8 @@ defmodule Explorer.Chain do
import EthereumJSONRPC, only: [integer_to_quantity: 1, json_rpc: 2, fetch_block_internal_transactions: 2]
+ require Logger
+
alias ABI.{TypeDecoder, TypeEncoder}
alias Ecto.Adapters.SQL
alias Ecto.{Changeset, Multi}
@@ -1820,11 +1822,19 @@ defmodule Explorer.Chain do
end
defp fetch_top_bridged_tokens(paging_options) do
+ bridged_tokens_query =
+ from(bt in BridgedToken,
+ select: bt
+ )
+
base_query =
from(t in Token,
+ left_join: bt in subquery(bridged_tokens_query),
+ on: t.contract_address_hash == bt.home_token_contract_address_hash,
where: t.total_supply > ^0,
where: t.bridged,
order_by: [desc: t.holder_count, asc: t.name],
+ select: [t, bt],
preload: [:contract_address]
)
@@ -3581,9 +3591,62 @@ defmodule Explorer.Chain do
end
@doc """
- Fetches bridged tokens metadata.
+ Processes AMB tokens from mediators addresses provided
+ """
+ def process_amb_tokens do
+ amb_bridge_mediators_var = Application.get_env(:block_scout_web, :amb_bridge_mediators)
+ amb_bridge_mediators = (amb_bridge_mediators_var && String.split(amb_bridge_mediators_var, ",")) || []
+
+ json_rpc_named_arguments = Application.get_env(:explorer, :json_rpc_named_arguments)
+
+ foreign_json_rpc = Application.get_env(:block_scout_web, :foreign_json_rpc)
+
+ eth_call_foreign_json_rpc_named_arguments =
+ compose_foreign_json_rpc_named_arguments(json_rpc_named_arguments, foreign_json_rpc)
+
+ amb_bridge_mediators
+ |> Enum.each(fn amb_bridge_mediator_hash ->
+ with {:ok, bridge_contract_hash_resp} <-
+ get_bridge_contract_hash(amb_bridge_mediator_hash, json_rpc_named_arguments),
+ bridge_contract_hash <- decode_contract_address_hash_response(bridge_contract_hash_resp),
+ {:ok, destination_chain_id_resp} <- get_destination_chain_id(bridge_contract_hash, json_rpc_named_arguments),
+ foreign_chain_id <- decode_contract_integer_response(destination_chain_id_resp),
+ {:ok, home_token_contract_hash_resp} <-
+ get_erc677_token_hash(amb_bridge_mediator_hash, json_rpc_named_arguments),
+ home_token_contract_hash_string <- decode_contract_address_hash_response(home_token_contract_hash_resp),
+ {:ok, home_token_contract_hash} <- Chain.string_to_address_hash(home_token_contract_hash_string),
+ {:ok, foreign_mediator_contract_hash_resp} <-
+ get_foreign_mediator_contract_hash(amb_bridge_mediator_hash, json_rpc_named_arguments),
+ foreign_mediator_contract_hash <- decode_contract_address_hash_response(foreign_mediator_contract_hash_resp),
+ {:ok, foreign_token_contract_hash_resp} <-
+ get_erc677_token_hash(foreign_mediator_contract_hash, eth_call_foreign_json_rpc_named_arguments),
+ foreign_token_contract_hash_string <-
+ decode_contract_address_hash_response(foreign_token_contract_hash_resp),
+ {:ok, foreign_token_contract_hash} <- Chain.string_to_address_hash(foreign_token_contract_hash_string) do
+ insert_bridged_token_metadata(home_token_contract_hash, %{
+ foreign_chain_id: foreign_chain_id,
+ foreign_token_address_hash: foreign_token_contract_hash,
+ custom_metadata: nil,
+ type: "amb"
+ })
+
+ set_token_bridged_status(home_token_contract_hash, true)
+ else
+ result ->
+ Logger.debug([
+ "failed to fetch metadata for token bridged with AMB mediator #{amb_bridge_mediator_hash}",
+ inspect(result)
+ ])
+ end
+ end)
+
+ :ok
+ end
+
+ @doc """
+ Fetches bridged tokens metadata from OmniBridge.
"""
- def fetch_bridged_tokens_metadata(token_addresses) do
+ def fetch_omni_bridged_tokens_metadata(token_addresses) do
Enum.each(token_addresses, fn token_address_hash ->
created_from_int_tx_success_query =
from(
@@ -3627,7 +3690,7 @@ defmodule Explorer.Chain do
set_token_bridged_status(token_address_hash, false)
created_from_int_tx && created_from_int_tx_success ->
- extract_bridged_token_metadata_wrapper(token_address_hash, created_from_int_tx_success)
+ extract_omni_bridged_token_metadata_wrapper(token_address_hash, created_from_int_tx_success)
true ->
:ok
@@ -3637,18 +3700,18 @@ defmodule Explorer.Chain do
:ok
end
- defp extract_bridged_token_metadata_wrapper(token_address_hash, created_from_int_tx_success) do
- multi_token_bridge_mediator = Application.get_env(:block_scout_web, :multi_token_bridge_mediator)
+ defp extract_omni_bridged_token_metadata_wrapper(token_address_hash, created_from_int_tx_success) do
+ omni_bridge_mediator = Application.get_env(:block_scout_web, :omni_bridge_mediator)
%{transaction_hash: transaction_hash} = created_from_int_tx_success
- if multi_token_bridge_mediator && multi_token_bridge_mediator !== "" do
- {:ok, multi_token_bridge_mediator_hash} = Chain.string_to_address_hash(multi_token_bridge_mediator)
+ if omni_bridge_mediator && omni_bridge_mediator !== "" do
+ {:ok, omni_bridge_mediator_hash} = Chain.string_to_address_hash(omni_bridge_mediator)
created_by_amb_mediator_query =
from(
it in InternalTransaction,
where: it.transaction_hash == ^transaction_hash,
- where: it.to_address_hash == ^multi_token_bridge_mediator_hash
+ where: it.to_address_hash == ^omni_bridge_mediator_hash
)
created_by_amb_mediator =
@@ -3656,10 +3719,10 @@ defmodule Explorer.Chain do
|> Repo.all()
if Enum.count(created_by_amb_mediator) > 0 do
- extract_bridged_token_metadata(
+ extract_omni_bridged_token_metadata(
token_address_hash,
- multi_token_bridge_mediator,
- multi_token_bridge_mediator_hash
+ omni_bridge_mediator,
+ omni_bridge_mediator_hash
)
else
set_token_bridged_status(token_address_hash, false)
@@ -3667,61 +3730,24 @@ defmodule Explorer.Chain do
end
end
- defp extract_bridged_token_metadata(token_address_hash, multi_token_bridge_mediator, multi_token_bridge_mediator_hash) do
+ defp extract_omni_bridged_token_metadata(token_address_hash, omni_bridge_mediator, omni_bridge_mediator_hash) do
json_rpc_named_arguments = Application.get_env(:explorer, :json_rpc_named_arguments)
- # keccak 256 from getTokenInterfacesVersion()
- get_token_interfaces_version_signature = "0x859ba28c"
- # keccak 256 from foreignTokenAddress(address)
- foreign_token_address_signature = "0x47ac7d6a"
- # keccak 256 from bridgeContract()
- bridge_contract_signature = "0xcd596583"
- # keccak 256 from destinationChainId()
- destination_chain_id_signature = "0xb0750611"
-
- token_address_hash_abi_encoded =
- [token_address_hash.bytes]
- |> TypeEncoder.encode([:address])
- |> Base.encode16()
-
- foreign_token_address_method = foreign_token_address_signature <> token_address_hash_abi_encoded
with {:ok, _} <-
- get_token_interfaces_version_signature
- |> Contract.eth_call_request(token_address_hash, 1, nil, nil)
- |> json_rpc(json_rpc_named_arguments),
+ get_token_interfaces_version_signature(token_address_hash, json_rpc_named_arguments),
{:ok, foreign_token_address_abi_encoded} <-
- foreign_token_address_method
- |> Contract.eth_call_request(
- multi_token_bridge_mediator,
- 1,
- nil,
- nil
- )
- |> json_rpc(json_rpc_named_arguments),
- {:ok, bridge_contract} <-
- bridge_contract_signature
- |> Contract.eth_call_request(multi_token_bridge_mediator_hash, 1, nil, nil)
- |> json_rpc(json_rpc_named_arguments) do
- "0x" <> foreign_token_address_no_prefix = foreign_token_address_abi_encoded
-
- <<_prefix::binary-size(24), foreign_token_address_hash_string_raw::binary()>> = foreign_token_address_no_prefix
-
- foreign_token_address_hash_string = "0x" <> foreign_token_address_hash_string_raw
-
+ get_foreign_token_address(omni_bridge_mediator, token_address_hash, json_rpc_named_arguments),
+ {:ok, bridge_contract_hash_resp} <-
+ get_bridge_contract_hash(omni_bridge_mediator_hash, json_rpc_named_arguments) do
+ foreign_token_address_hash_string = decode_contract_address_hash_response(foreign_token_address_abi_encoded)
{:ok, foreign_token_address_hash} = Chain.string_to_address_hash(foreign_token_address_hash_string)
- "0x" <> bridge_contract_no_prefix = bridge_contract
- <<_prefix::binary-size(24), multi_token_bridge_hash_string_raw::binary()>> = bridge_contract_no_prefix
-
- multi_token_bridge_hash_string = "0x" <> multi_token_bridge_hash_string_raw
+ multi_token_bridge_hash_string = decode_contract_address_hash_response(bridge_contract_hash_resp)
{:ok, foreign_chain_id_abi_encoded} =
- destination_chain_id_signature
- |> Contract.eth_call_request(multi_token_bridge_hash_string, 1, nil, nil)
- |> json_rpc(json_rpc_named_arguments)
+ get_destination_chain_id(multi_token_bridge_hash_string, json_rpc_named_arguments)
- "0x" <> foreign_chain_id_abi_encoded_no_prefix = foreign_chain_id_abi_encoded
- {foreign_chain_id, _} = Integer.parse(foreign_chain_id_abi_encoded_no_prefix, 16)
+ foreign_chain_id = decode_contract_integer_response(foreign_chain_id_abi_encoded)
foreign_json_rpc = Application.get_env(:block_scout_web, :foreign_json_rpc)
@@ -3731,38 +3757,135 @@ defmodule Explorer.Chain do
insert_bridged_token_metadata(token_address_hash, %{
foreign_chain_id: foreign_chain_id,
foreign_token_address_hash: foreign_token_address_hash,
- custom_metadata: custom_metadata
+ custom_metadata: custom_metadata,
+ type: "omni"
})
set_token_bridged_status(token_address_hash, true)
end
end
+ defp get_bridge_contract_hash(mediator_hash, json_rpc_named_arguments) do
+ # keccak 256 from bridgeContract()
+ bridge_contract_signature = "0xcd596583"
+
+ perform_eth_call_request(bridge_contract_signature, mediator_hash, json_rpc_named_arguments)
+ end
+
+ defp get_erc677_token_hash(mediator_hash, json_rpc_named_arguments) do
+ # keccak 256 from erc677token()
+ erc677_token_signature = "0x18d8f9c9"
+
+ perform_eth_call_request(erc677_token_signature, mediator_hash, json_rpc_named_arguments)
+ end
+
+ defp get_foreign_mediator_contract_hash(mediator_hash, json_rpc_named_arguments) do
+ # keccak 256 from mediatorContractOnOtherSide()
+ mediator_contract_on_other_side_signature = "0x871c0760"
+
+ perform_eth_call_request(mediator_contract_on_other_side_signature, mediator_hash, json_rpc_named_arguments)
+ end
+
+ defp get_destination_chain_id(bridge_contract_hash, json_rpc_named_arguments) do
+ # keccak 256 from destinationChainId()
+ destination_chain_id_signature = "0xb0750611"
+
+ perform_eth_call_request(destination_chain_id_signature, bridge_contract_hash, json_rpc_named_arguments)
+ end
+
+ defp get_token_interfaces_version_signature(token_address_hash, json_rpc_named_arguments) do
+ # keccak 256 from getTokenInterfacesVersion()
+ get_token_interfaces_version_signature = "0x859ba28c"
+
+ perform_eth_call_request(get_token_interfaces_version_signature, token_address_hash, json_rpc_named_arguments)
+ end
+
+ defp get_foreign_token_address(omni_bridge_mediator, token_address_hash, json_rpc_named_arguments) do
+ # keccak 256 from foreignTokenAddress(address)
+ foreign_token_address_signature = "0x47ac7d6a"
+
+ token_address_hash_abi_encoded =
+ [token_address_hash.bytes]
+ |> TypeEncoder.encode([:address])
+ |> Base.encode16()
+
+ foreign_token_address_method = foreign_token_address_signature <> token_address_hash_abi_encoded
+
+ perform_eth_call_request(foreign_token_address_method, omni_bridge_mediator, json_rpc_named_arguments)
+ end
+
+ defp perform_eth_call_request(method, destination, json_rpc_named_arguments)
+ when not is_nil(json_rpc_named_arguments) do
+ method
+ |> Contract.eth_call_request(destination, 1, nil, nil)
+ |> json_rpc(json_rpc_named_arguments)
+ end
+
+ defp perform_eth_call_request(_method, _destination, json_rpc_named_arguments)
+ when is_nil(json_rpc_named_arguments) do
+ :error
+ end
+
+ def decode_contract_address_hash_response(resp) do
+ case resp do
+ "0x000000000000000000000000" <> address ->
+ "0x" <> address
+
+ _ ->
+ nil
+ end
+ end
+
+ def decode_contract_integer_response(resp) do
+ case resp do
+ "0x" <> integer_encoded ->
+ {integer_value, _} = Integer.parse(integer_encoded, 16)
+ integer_value
+
+ _ ->
+ nil
+ end
+ end
+
defp set_token_bridged_status(token_address_hash, status) do
- target_token = Repo.get!(Token, token_address_hash)
- token = Changeset.change(target_token, bridged: status)
+ case Repo.get(Token, token_address_hash) do
+ %Explorer.Chain.Token{bridged: bridged} = target_token ->
+ if !bridged do
+ token = Changeset.change(target_token, bridged: status)
- Repo.update(token)
+ Repo.update(token)
+ end
+
+ _ ->
+ :ok
+ end
end
defp insert_bridged_token_metadata(token_address_hash, %{
foreign_chain_id: foreign_chain_id,
foreign_token_address_hash: foreign_token_address_hash,
- custom_metadata: custom_metadata
+ custom_metadata: custom_metadata,
+ type: type
}) do
- {:ok, _} =
- Repo.insert(
- %BridgedToken{
- home_token_contract_address_hash: token_address_hash,
- foreign_chain_id: foreign_chain_id,
- foreign_token_contract_address_hash: foreign_token_address_hash,
- custom_metadata: custom_metadata
- },
- on_conflict: :nothing
- )
+ target_token = Repo.get(Token, token_address_hash)
+
+ if target_token do
+ {:ok, _} =
+ Repo.insert(
+ %BridgedToken{
+ home_token_contract_address_hash: token_address_hash,
+ foreign_chain_id: foreign_chain_id,
+ foreign_token_contract_address_hash: foreign_token_address_hash,
+ custom_metadata: custom_metadata,
+ type: type
+ },
+ on_conflict: :nothing
+ )
+ end
end
- # get_bridged_token_custom_metadata function currently gets Balancer token composite tokens with their weights
+ # Fetches custom metadata for bridged tokens from the node.
+ # Currently, gets Balancer token composite tokens with their weights
# from foreign chain
defp get_bridged_token_custom_metadata(foreign_token_address_hash, json_rpc_named_arguments, foreign_json_rpc)
when not is_nil(foreign_json_rpc) and foreign_json_rpc !== "" do
@@ -3823,7 +3946,8 @@ defmodule Explorer.Chain do
nil
end
- defp compose_foreign_json_rpc_named_arguments(json_rpc_named_arguments, foreign_json_rpc) do
+ defp compose_foreign_json_rpc_named_arguments(json_rpc_named_arguments, foreign_json_rpc)
+ when foreign_json_rpc != "" do
{_, eth_call_foreign_json_rpc_named_arguments} =
Keyword.get_and_update(json_rpc_named_arguments, :transport_options, fn transport_options ->
{_, updated_transport_options} =
@@ -3835,6 +3959,16 @@ defmodule Explorer.Chain do
eth_call_foreign_json_rpc_named_arguments
end
+ defp compose_foreign_json_rpc_named_arguments(_json_rpc_named_arguments, foreign_json_rpc)
+ when foreign_json_rpc == "" do
+ nil
+ end
+
+ defp compose_foreign_json_rpc_named_arguments(json_rpc_named_arguments, _foreign_json_rpc)
+ when is_nil(json_rpc_named_arguments) do
+ nil
+ end
+
defp update_transport_options_set_foreign_json_rpc(transport_options, foreign_json_rpc) do
Keyword.get_and_update(transport_options, :method_to_url, fn method_to_url ->
{_, updated_method_to_url} =
diff --git a/apps/explorer/lib/explorer/chain/bridged_token.ex b/apps/explorer/lib/explorer/chain/bridged_token.ex
index b9d3fae300..8db227606b 100644
--- a/apps/explorer/lib/explorer/chain/bridged_token.ex
+++ b/apps/explorer/lib/explorer/chain/bridged_token.ex
@@ -15,13 +15,16 @@ defmodule Explorer.Chain.BridgedToken do
* `foreign_token_contract_address_hash` - Foreign token's contract hash
* `home_token_contract_address` - The `t:Address.t/0` of the home token's contract
* `home_token_contract_address_hash` - Home token's contract hash foreign key
+ * `custom_metadata` - Arbitrary string with custom metadata. For instance, tokens/weights for Balance tokens
+ * `type` - omni/amb
"""
@type t :: %BridgedToken{
foreign_chain_id: Decimal.t(),
foreign_token_contract_address_hash: Hash.Address.t(),
home_token_contract_address: %Ecto.Association.NotLoaded{} | Address.t(),
home_token_contract_address_hash: Hash.Address.t(),
- custom_metadata: String.t()
+ custom_metadata: String.t(),
+ type: String.t()
}
@derive {Poison.Encoder,
@@ -45,6 +48,7 @@ defmodule Explorer.Chain.BridgedToken do
field(:foreign_chain_id, :decimal)
field(:foreign_token_contract_address_hash, Hash.Address)
field(:custom_metadata, :string)
+ field(:type, :string)
belongs_to(
:home_token_contract_address,
@@ -59,7 +63,7 @@ defmodule Explorer.Chain.BridgedToken do
end
@required_attrs ~w(home_token_contract_address_hash)a
- @optional_attrs ~w(foreign_chain_id foreign_token_contract_address_hash custom_metadata)a
+ @optional_attrs ~w(foreign_chain_id foreign_token_contract_address_hash custom_metadata type)a
@doc false
def changeset(%BridgedToken{} = bridged_token, params \\ %{}) do
diff --git a/apps/explorer/priv/repo/migrations/20200929075625_add_bridged_token_type.exs b/apps/explorer/priv/repo/migrations/20200929075625_add_bridged_token_type.exs
new file mode 100644
index 0000000000..b8a6c30f45
--- /dev/null
+++ b/apps/explorer/priv/repo/migrations/20200929075625_add_bridged_token_type.exs
@@ -0,0 +1,9 @@
+defmodule Explorer.Repo.Migrations.AddBridgedTokenType do
+ use Ecto.Migration
+
+ def change do
+ alter table(:bridged_tokens) do
+ add(:type, :string, null: true)
+ end
+ end
+end
diff --git a/apps/indexer/lib/indexer/set_amb_bridged_metadata_for_tokens.ex b/apps/indexer/lib/indexer/set_amb_bridged_metadata_for_tokens.ex
new file mode 100644
index 0000000000..b12e93872b
--- /dev/null
+++ b/apps/indexer/lib/indexer/set_amb_bridged_metadata_for_tokens.ex
@@ -0,0 +1,39 @@
+defmodule Indexer.SetAmbBridgedMetadataForTokens do
+ @moduledoc """
+ Sets token metadata for bridged tokens from AMB extensions.
+ """
+
+ use GenServer
+
+ require Logger
+
+ alias Explorer.Chain
+
+ def start_link([init_opts, gen_server_opts]) do
+ start_link(init_opts, gen_server_opts)
+ end
+
+ def start_link(init_opts, gen_server_opts) do
+ GenServer.start_link(__MODULE__, init_opts, gen_server_opts)
+ end
+
+ @impl GenServer
+ def init(_opts) do
+ send(self(), :process_amb_tokens)
+
+ {:ok, %{}}
+ end
+
+ @impl GenServer
+ def handle_info(:process_amb_tokens, state) do
+ fetch_amb_bridged_tokens_metadata()
+
+ {:noreply, state}
+ end
+
+ defp fetch_amb_bridged_tokens_metadata do
+ :ok = Chain.process_amb_tokens()
+
+ Logger.debug(fn -> "Bridged status fetched for AMB tokens" end)
+ end
+end
diff --git a/apps/indexer/lib/indexer/set_bridged_metadata_for_tokens.ex b/apps/indexer/lib/indexer/set_omni_bridged_metadata_for_tokens.ex
similarity index 80%
rename from apps/indexer/lib/indexer/set_bridged_metadata_for_tokens.ex
rename to apps/indexer/lib/indexer/set_omni_bridged_metadata_for_tokens.ex
index 9c15939a1c..13a06779d0 100644
--- a/apps/indexer/lib/indexer/set_bridged_metadata_for_tokens.ex
+++ b/apps/indexer/lib/indexer/set_omni_bridged_metadata_for_tokens.ex
@@ -1,4 +1,4 @@
-defmodule Indexer.SetBridgedMetadataForTokens do
+defmodule Indexer.SetOmniBridgedMetadataForTokens do
@moduledoc """
Peiodically checks unprocessed tokens and sets bridged status.
"""
@@ -34,15 +34,15 @@ defmodule Indexer.SetBridgedMetadataForTokens do
{:ok, token_addresses} = Chain.unprocessed_token_addresses_to_reveal_bridged_tokens()
- fetch_bridged_tokens_metadata(token_addresses)
+ fetch_omni_bridged_tokens_metadata(token_addresses)
Process.send_after(self(), :reveal_unprocessed_tokens, interval)
{:noreply, state}
end
- defp fetch_bridged_tokens_metadata(token_addresses) do
- :ok = Chain.fetch_bridged_tokens_metadata(token_addresses)
+ defp fetch_omni_bridged_tokens_metadata(token_addresses) do
+ :ok = Chain.fetch_omni_bridged_tokens_metadata(token_addresses)
Logger.debug(fn -> "Bridged status fetched for tokens" end)
end
diff --git a/apps/indexer/lib/indexer/supervisor.ex b/apps/indexer/lib/indexer/supervisor.ex
index 4c65a93506..f105c0eaec 100644
--- a/apps/indexer/lib/indexer/supervisor.ex
+++ b/apps/indexer/lib/indexer/supervisor.ex
@@ -5,7 +5,7 @@ defmodule Indexer.Supervisor do
use Supervisor
- alias Indexer.{Block, PendingOpsCleaner, SetBridgedMetadataForTokens}
+ alias Indexer.{Block, PendingOpsCleaner, SetAmbBridgedMetadataForTokens, SetOmniBridgedMetadataForTokens}
alias Indexer.Block.{Catchup, Realtime}
alias Indexer.Fetcher.{
@@ -129,15 +129,24 @@ defmodule Indexer.Supervisor do
{PendingOpsCleaner, [[], []]}
]
- multi_token_bridge_mediator = Application.get_env(:block_scout_web, :multi_token_bridge_mediator)
+ omni_bridge_mediator = Application.get_env(:block_scout_web, :omni_bridge_mediator)
- all_fetchers =
- if multi_token_bridge_mediator && multi_token_bridge_mediator !== "" do
- [{SetBridgedMetadataForTokens, [[], []]} | basic_fetchers]
+ extended_fetchers =
+ if omni_bridge_mediator && omni_bridge_mediator !== "" do
+ [{SetOmniBridgedMetadataForTokens, [[], []]} | basic_fetchers]
else
basic_fetchers
end
+ amb_bridge_mediators = Application.get_env(:block_scout_web, :amb_bridge_mediators)
+
+ all_fetchers =
+ if amb_bridge_mediators && amb_bridge_mediators !== "" do
+ [{SetAmbBridgedMetadataForTokens, [[], []]} | extended_fetchers]
+ else
+ extended_fetchers
+ end
+
Supervisor.init(
all_fetchers,
strategy: :one_for_one
|