Remove bridged tokens functionality from Blockscout core

pull/5703/head
Viktor Baranov 2 years ago
parent 4f461d818f
commit 678927883f
  1. 4
      .dialyzer-ignore
  2. 1
      CHANGELOG.md
  3. 2
      apps/block_scout_web/assets/js/lib/autocomplete.js
  4. 9
      apps/block_scout_web/assets/js/lib/token_icon.js
  5. 4
      apps/block_scout_web/assets/js/pages/token/overview.js
  6. 4
      apps/block_scout_web/config/config.exs
  7. 2
      apps/block_scout_web/lib/block_scout_web/chain.ex
  8. 63
      apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex
  9. 3
      apps/block_scout_web/lib/block_scout_web/controllers/address_token_controller.ex
  10. 39
      apps/block_scout_web/lib/block_scout_web/controllers/api/rpc/token_controller.ex
  11. 5
      apps/block_scout_web/lib/block_scout_web/controllers/chain_controller.ex
  12. 116
      apps/block_scout_web/lib/block_scout_web/controllers/tokens/bridged_tokens_controller.ex
  13. 112
      apps/block_scout_web/lib/block_scout_web/etherscan.ex
  14. 15
      apps/block_scout_web/lib/block_scout_web/templates/address_token/_tokens.html.eex
  15. 6
      apps/block_scout_web/lib/block_scout_web/templates/address_token_balance/_token_balances.html.eex
  16. 20
      apps/block_scout_web/lib/block_scout_web/templates/address_token_balance/_tokens.html.eex
  17. 97
      apps/block_scout_web/lib/block_scout_web/templates/bridged_tokens/_tile.html.eex
  18. 70
      apps/block_scout_web/lib/block_scout_web/templates/bridged_tokens/index.html.eex
  19. 15
      apps/block_scout_web/lib/block_scout_web/templates/chain/show.html.eex
  20. 74
      apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex
  21. 1
      apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex
  22. 4
      apps/block_scout_web/lib/block_scout_web/templates/search/_tile.html.eex
  23. 15
      apps/block_scout_web/lib/block_scout_web/templates/tokens/overview/_details.html.eex
  24. 4
      apps/block_scout_web/lib/block_scout_web/views/address_token_balance_view.ex
  25. 16
      apps/block_scout_web/lib/block_scout_web/views/address_view.ex
  26. 27
      apps/block_scout_web/lib/block_scout_web/views/api/rpc/token_view.ex
  27. 49
      apps/block_scout_web/lib/block_scout_web/views/bridged_tokens_view.ex
  28. 13
      apps/block_scout_web/lib/block_scout_web/views/chain_view.ex
  29. 56
      apps/block_scout_web/lib/block_scout_web/views/tokens/overview_view.ex
  30. 2
      apps/block_scout_web/lib/block_scout_web/web_router.ex
  31. 119
      apps/block_scout_web/priv/gettext/default.pot
  32. 119
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  33. 3
      apps/block_scout_web/test/block_scout_web/controllers/address_controller_test.exs
  34. 32
      apps/block_scout_web/test/block_scout_web/views/address_token_balance_view_test.exs
  35. 20
      apps/explorer/config/config.exs
  36. 937
      apps/explorer/lib/explorer/chain.ex
  37. 6
      apps/explorer/lib/explorer/chain/address/current_token_balance.ex
  38. 97
      apps/explorer/lib/explorer/chain/bridged_token.ex
  39. 55
      apps/explorer/lib/explorer/chain/cache/token_exchange_rate.ex
  40. 4
      apps/explorer/lib/explorer/chain/import/runner/tokens.ex
  41. 298
      apps/explorer/lib/explorer/chain/supply/token_bridge.ex
  42. 5
      apps/explorer/lib/explorer/chain/token.ex
  43. 194
      apps/explorer/lib/explorer/counters/bridge.ex
  44. 6
      apps/explorer/lib/explorer/exchange_rates/source.ex
  45. 4
      apps/explorer/lib/explorer/exchange_rates/source/coin_gecko.ex
  46. 71
      apps/explorer/lib/explorer/exchange_rates/source/token_bridge.ex
  47. 43
      apps/explorer/lib/explorer/market/market.ex
  48. 11
      apps/explorer/priv/repo/migrations/20220622140604_remove_bridged_tokens.exs
  49. 4
      apps/explorer/test/explorer/chain/address/current_token_balance_test.exs
  50. 67
      apps/explorer/test/explorer/chain/supply/token_bridge_test.exs
  51. 2
      apps/explorer/test/explorer/chain_test.exs
  52. 45
      apps/explorer/test/explorer/exchange_rates/source/token_bridge_test.exs
  53. 52
      apps/indexer/lib/indexer/calc_lp_tokens_total_liquidity.ex
  54. 4
      apps/indexer/lib/indexer/fetcher/token_balance_on_demand.ex
  55. 44
      apps/indexer/lib/indexer/set_amb_bridged_metadata_for_tokens.ex
  56. 54
      apps/indexer/lib/indexer/set_omni_bridged_metadata_for_tokens.ex
  57. 26
      apps/indexer/lib/indexer/supervisor.ex
  58. 7
      docker-compose/envs/common-blockscout.env
  59. 16
      docker/Makefile

@ -20,8 +20,8 @@ lib/block_scout_web/views/layout_view.ex:145: The call 'Elixir.Poison.Parser':'p
lib/block_scout_web/views/layout_view.ex:237: The call 'Elixir.Poison.Parser':'parse!'
lib/explorer/smart_contract/reader.ex:435
lib/indexer/fetcher/token_total_supply_on_demand.ex:16
lib/explorer/exchange_rates/source.ex:120
lib/explorer/exchange_rates/source.ex:123
lib/explorer/exchange_rates/source.ex:116
lib/explorer/exchange_rates/source.ex:119
lib/explorer/smart_contract/solidity/verifier.ex:223
lib/block_scout_web/templates/address_contract/index.html.eex:158
lib/block_scout_web/templates/address_contract/index.html.eex:195

@ -8,6 +8,7 @@
- [#5690](https://github.com/blockscout/blockscout/pull/5690) - Allow special characters for password in DB URL parser
### Chore
- [#5703](https://github.com/blockscout/blockscout/pull/5703) - Remove bridged tokens functionality from Blockscout core
- [#5700](https://github.com/blockscout/blockscout/pull/5700) - Remove Staking dapp logic from Blockscout core
- [#5696](https://github.com/blockscout/blockscout/pull/5696) - Update .tool-versions
- [#5695](https://github.com/blockscout/blockscout/pull/5695) - Decimal hex package update 1.9 -> 2.0

@ -99,7 +99,7 @@ const resultItemElement = async (item, data) => {
const $searchInput = $('#main-search-autocomplete')
const chainID = $searchInput.data('chain-id')
const displayTokenIcons = $searchInput.data('display-token-icons')
appendTokenIcon($tokenIconContainer, chainID, data.value.address_hash, data.value.foreign_chain_id, data.value.foreign_token_hash, displayTokenIcons, 15)
appendTokenIcon($tokenIconContainer, chainID, data.value.address_hash, displayTokenIcons, 15)
}
const config = (id) => {
return {

@ -21,14 +21,9 @@ function getTokenIconUrl (chainID, addressHash) {
}
}
function appendTokenIcon ($tokenIconContainer, chainID, addressHash, foreignChainID, foreignAddressHash, displayTokenIcons, size) {
function appendTokenIcon ($tokenIconContainer, chainID, addressHash, displayTokenIcons, size) {
const iconSize = size || 20
let tokenIconURL = null
if (foreignChainID) {
tokenIconURL = getTokenIconUrl(foreignChainID.toString(), foreignAddressHash)
} else if (chainID) {
tokenIconURL = getTokenIconUrl(chainID.toString(), addressHash)
}
const tokenIconURL = getTokenIconUrl(chainID.toString(), addressHash)
if (displayTokenIcons) {
checkLink(tokenIconURL)
.then(checkTokenIconLink => {

@ -5,9 +5,7 @@ if ($('[data-page="token-details"]').length) {
const $tokenIconContainer = $('#token-icon')
const chainID = $tokenIconContainer.data('chain-id')
const addressHash = $tokenIconContainer.data('address-hash')
const foreignChainID = $tokenIconContainer.data('foreign-chain-id')
const foreignAddressHash = $tokenIconContainer.data('foreign-address-hash')
const displayTokenIcons = $tokenIconContainer.data('display-token-icons')
appendTokenIcon($tokenIconContainer, chainID, addressHash, foreignChainID, foreignAddressHash, displayTokenIcons)
appendTokenIcon($tokenIconContainer, chainID, addressHash, displayTokenIcons)
}

@ -33,10 +33,6 @@ 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"),
eth_omni_bridge_mediator: System.get_env("ETH_OMNI_BRIDGE_MEDIATOR"),
bsc_omni_bridge_mediator: System.get_env("BSC_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),

@ -341,7 +341,7 @@ defmodule BlockScoutWeb.Chain do
%{"address_hash" => to_string(address_hash), "value" => Decimal.to_integer(value)}
end
defp paging_params({%CurrentTokenBalance{value: value}, _, %Token{name: name, type: type}}) do
defp paging_params({%CurrentTokenBalance{value: value}, %Token{name: name, type: type}}) do
%{"token_name" => name, "token_type" => type, "value" => Decimal.to_integer(value)}
end

@ -7,12 +7,11 @@ defmodule BlockScoutWeb.AddressController do
AccessHelpers,
AddressTransactionController,
AddressView,
Controller,
CurrencyHelpers
Controller
}
alias Explorer.Counters.{AddressTokenTransfersCounter, AddressTransactionsCounter, AddressTransactionsGasUsageCounter}
alias Explorer.{Chain, CustomContractsHelpers, Market}
alias Explorer.{Chain, Market}
alias Explorer.Chain.Wei
alias Explorer.ExchangeRates.Token
alias Indexer.Fetcher.CoinBalanceOnDemand
@ -143,7 +142,7 @@ defmodule BlockScoutWeb.AddressController do
def address_counters(conn, %{"id" => address_hash_string}) do
with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string),
{:ok, address} <- Chain.hash_to_address(address_hash) do
{validation_count, crc_total_worth} = address_counters(address)
{validation_count} = address_counters(address)
transactions_from_db = address.transactions_count || 0
token_transfers_from_db = address.token_transfers_count || 0
@ -153,8 +152,7 @@ defmodule BlockScoutWeb.AddressController do
transaction_count: transactions_from_db,
token_transfer_count: token_transfers_from_db,
gas_usage_count: address_gas_usage_from_db,
validation_count: validation_count,
crc_total_worth: crc_total_worth
validation_count: validation_count
})
else
_ ->
@ -162,8 +160,7 @@ defmodule BlockScoutWeb.AddressController do
transaction_count: 0,
token_transfer_count: 0,
gas_usage_count: 0,
validation_count: 0,
crc_total_worth: 0
validation_count: 0
})
end
end
@ -174,11 +171,6 @@ defmodule BlockScoutWeb.AddressController do
validation_count(address)
end)
crc_total_worth_task =
Task.async(fn ->
crc_total_worth(address)
end)
Task.start_link(fn ->
transaction_count(address)
end)
@ -192,8 +184,7 @@ defmodule BlockScoutWeb.AddressController do
end)
[
validation_count_task,
crc_total_worth_task
validation_count_task
]
|> Task.yield_many(:infinity)
|> Enum.map(fn {_task, res} ->
@ -226,46 +217,4 @@ defmodule BlockScoutWeb.AddressController do
defp validation_count(address) do
Chain.address_to_validation_count(address.hash)
end
defp crc_total_worth(address) do
circles_total_balance(address.hash)
end
defp circles_total_balance(address_hash) do
circles_addresses_list = CustomContractsHelpers.get_custom_addresses_list(:circles_addresses)
token_balances =
address_hash
|> Chain.fetch_last_token_balances()
token_balances_except_bridged =
token_balances
|> Enum.filter(fn {_, _, token} -> !token.bridged end)
circles_total_balance_raw =
if Enum.count(circles_addresses_list) > 0 do
token_balances_except_bridged
|> Enum.reduce(Decimal.new(0), fn {token_balance, _, token}, acc_balance ->
{:ok, token_address} = Chain.hash_to_address(token.contract_address_hash)
from_address = AddressView.from_address_hash(token_address)
created_from_address_hash =
if from_address,
do: "0x" <> Base.encode16(from_address.bytes, case: :lower),
else: nil
if Enum.member?(circles_addresses_list, created_from_address_hash) && token.name == "Circles" &&
token.symbol == "CRC" do
Decimal.add(acc_balance, token_balance.value)
else
acc_balance
end
end)
else
Decimal.new(0)
end
CurrencyHelpers.format_according_to_decimals(circles_total_balance_raw, Decimal.new(18))
end
end

@ -33,13 +33,12 @@ defmodule BlockScoutWeb.AddressTokenController do
items =
tokens
|> Market.add_price()
|> Enum.map(fn {token_balance, bridged_token, token} ->
|> Enum.map(fn {token_balance, token} ->
View.render_to_string(
AddressTokenView,
"_tokens.html",
token_balance: token_balance,
token: token,
bridged_token: bridged_token,
address: address,
conn: conn
)

@ -4,8 +4,6 @@ defmodule BlockScoutWeb.API.RPC.TokenController do
alias BlockScoutWeb.API.RPC.Helpers
alias Explorer.{Chain, PagingOptions}
@default_page_size 50
def gettoken(conn, params) do
with {:contractaddress_param, {:ok, contractaddress_param}} <- fetch_contractaddress(params),
{:format, {:ok, address_hash}} <- to_address_hash(contractaddress_param),
@ -52,47 +50,10 @@ defmodule BlockScoutWeb.API.RPC.TokenController do
end
end
def bridgedtokenlist(conn, params) do
chainid = params |> Map.get("chainid")
destination = translate_chain_id_to_destination(chainid)
params_with_paging_options = Helpers.put_pagination_options(%{}, params)
page_number =
if Map.has_key?(params_with_paging_options, :page_number), do: params_with_paging_options.page_number, else: 1
page_size =
if Map.has_key?(params_with_paging_options, :page_size),
do: params_with_paging_options.page_size,
else: @default_page_size
options = [
paging_options: %PagingOptions{
key: nil,
page_number: page_number,
page_size: page_size
}
]
from_api = true
bridged_tokens = Chain.list_top_bridged_tokens(destination, nil, from_api, options)
render(conn, "bridgedtokenlist.json", %{bridged_tokens: bridged_tokens})
end
defp fetch_contractaddress(params) do
{:contractaddress_param, Map.fetch(params, "contractaddress")}
end
defp translate_chain_id_to_destination(destination) do
case destination do
"1" -> :eth
"42" -> :kovan
"56" -> :bsc
"99" -> :poa
wrong_chain_id -> wrong_chain_id
end
end
defp to_address_hash(address_hash_string) do
{:format, Chain.string_to_address_hash(address_hash_string)}
end

@ -9,7 +9,7 @@ defmodule BlockScoutWeb.ChainController do
alias Explorer.Chain.Cache.Block, as: BlockCache
alias Explorer.Chain.Cache.GasUsage
alias Explorer.Chain.Cache.Transaction, as: TransactionCache
alias Explorer.Chain.Supply.{RSK, TokenBridge}
alias Explorer.Chain.Supply.RSK
alias Explorer.Chain.Transaction.History.TransactionStats
alias Explorer.Counters.AverageBlockTime
alias Explorer.ExchangeRates.Token
@ -27,9 +27,6 @@ defmodule BlockScoutWeb.ChainController do
RSK ->
RSK
TokenBridge ->
TokenBridge
_ ->
:standard
end

@ -1,116 +0,0 @@
defmodule BlockScoutWeb.BridgedTokensController do
use BlockScoutWeb, :controller
import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1]
alias BlockScoutWeb.{BridgedTokensView, Controller}
alias Explorer.Chain
alias Phoenix.View
def show(conn, %{"type" => "JSON", "id" => "eth"} = params) do
get_items(conn, params, :eth)
end
def show(conn, %{"type" => "JSON", "id" => "bsc"} = params) do
get_items(conn, params, :bsc)
end
def show(conn, %{"id" => "eth"}) do
render(conn, "index.html",
current_path: Controller.current_full_path(conn),
chain: "Ethereum",
chain_id: 1,
destination: :eth
)
end
def show(conn, %{"id" => "bsc"}) do
render(conn, "index.html",
current_path: Controller.current_full_path(conn),
chain: "Binance Smart Chain",
chain_id: 56,
destination: :bsc
)
end
def show(conn, _params) do
not_found(conn)
end
def index(conn, %{"type" => "JSON"} = params) do
get_items(conn, params, :eth)
end
def index(conn, _params) do
render(conn, "index.html",
current_path: Controller.current_full_path(conn),
chain: "Ethereum",
chain_id: 1,
destination: :eth
)
end
defp get_items(conn, params, destination) do
filter =
if Map.has_key?(params, "filter") do
Map.get(params, "filter")
else
nil
end
paging_params =
params
|> paging_options()
from_api = false
tokens = Chain.list_top_bridged_tokens(destination, filter, from_api, paging_params)
{tokens_page, next_page} = split_list_by_page(tokens)
next_page_path =
case next_page_params(next_page, tokens_page, params) do
nil ->
nil
next_page_params ->
bridged_tokens_path(
conn,
:show,
destination,
Map.delete(next_page_params, "type")
)
end
items_count_str = Map.get(params, "items_count")
items_count =
if items_count_str do
{items_count, _} = Integer.parse(items_count_str)
items_count
else
0
end
items =
tokens_page
|> Enum.with_index(1)
|> Enum.map(fn {[token, bridged_token], index} ->
View.render_to_string(
BridgedTokensView,
"_tile.html",
token: token,
bridged_token: bridged_token,
destination: destination,
index: items_count + index
)
end)
json(
conn,
%{
items: items,
next_page_path: next_page_path
}
)
end
end

@ -293,35 +293,6 @@ defmodule BlockScoutWeb.Etherscan do
"result" => nil
}
@token_bridgedtokenlist_example_value %{
"status" => "1",
"message" => "OK",
"result" => [
%{
"foreignChainId" => "1",
"foreignTokenContractAddressHash" => "0x0ae055097c6d159879521c384f1d2123d1f195e6",
"homeContractAddressHash" => "0xb7d311e2eb55f2f68a9440da38e7989210b9a05e",
"homeDecimals" => "18",
"homeHolderCount" => 393,
"homeName" => "STAKE on xDai",
"homeSymbol" => "STAKE",
"homeTotalSupply" => "1484374.775044204093387391",
"homeUsdValue" => "18807028.39981006586321824397"
},
%{
"foreignChainId" => "1",
"foreignTokenContractAddressHash" => "0xf5581dfefd8fb0e4aec526be659cfab1f8c781da",
"homeContractAddressHash" => "0xd057604a14982fe8d88c5fc25aac3267ea142a08",
"homeDecimals" => "18",
"homeHolderCount" => 73,
"homeName" => "HOPR Token on xDai",
"homeSymbol" => "HOPR",
"homeTotalSupply" => "26600449.86076749062791602",
"homeUsdValue" => "6638727.472651464170990256943"
}
]
}
@stats_tokensupply_example_value %{
"status" => "1",
"message" => "OK",
@ -622,12 +593,6 @@ defmodule BlockScoutWeb.Etherscan do
enum_interpretation: %{"0" => "error", "1" => "ok"}
}
@success_status_type %{
type: "status",
enum: ~s(["1"]),
enum_interpretation: %{"1" => "ok"}
}
@jsonrpc_version_type %{
type: "string",
example: ~s("2.0")
@ -773,37 +738,6 @@ defmodule BlockScoutWeb.Etherscan do
}
}
@bridged_token_details %{
name: "Bridged Token Detail",
fields: %{
foreignChainId: %{
type: "value",
definition: "Chain ID of the chain where original token exists.",
example: ~s("1")
},
foreignTokenContractAddressHash: @address_hash_type,
homeContractAddressHash: @address_hash_type,
homeDecimals: @token_decimal_type,
homeHolderCount: %{
type: "value",
definition: "Token holders count.",
example: ~s("393")
},
homeName: @token_name_type,
homeSymbol: @token_symbol_type,
homeTotalSupply: %{
type: "value",
definition: "Total supply of the token on the home side (where token was bridged).",
example: ~s("1484374.775044204093387391")
},
homeUsdValue: %{
type: "value",
definition: "Total supply of the token on the home side (where token was bridged) in USD.",
example: ~s("6638727.472651464170990256943")
}
}
}
@address_balance %{
name: "AddressBalance",
fields: %{
@ -2055,49 +1989,6 @@ defmodule BlockScoutWeb.Etherscan do
]
}
@token_bridgedtokenlist_action %{
name: "bridgedTokenList",
description: "Get bridged tokens list.",
required_params: [],
optional_params: [
%{
key: "chainid",
type: "integer",
description: "A nonnegative integer that represents the chain id, where original token exists."
},
%{
key: "page",
type: "integer",
description:
"A nonnegative integer that represents the page number to be used for pagination. 'offset' must be provided in conjunction."
},
%{
key: "offset",
type: "integer",
description:
"A nonnegative integer that represents the maximum number of records to return when paginating. 'page' must be provided in conjunction."
}
],
responses: [
%{
code: "200",
description: "successful operation",
example_value: Jason.encode!(@token_bridgedtokenlist_example_value),
model: %{
name: "Result",
fields: %{
status: @success_status_type,
message: @message_type,
result: %{
type: "array",
array_type: @bridged_token_details
}
}
}
}
]
}
@stats_tokensupply_action %{
name: "tokensupply",
description:
@ -3028,8 +2919,7 @@ defmodule BlockScoutWeb.Etherscan do
name: "token",
actions: [
@token_gettoken_action,
@token_gettokenholders_action,
@token_bridgedtokenlist_action
@token_gettokenholders_action
]
}

@ -3,8 +3,8 @@
</td>
<td>
<%= if System.get_env("DISPLAY_TOKEN_ICONS") === "true" do %>
<% chain_id_for_token_icon = if @bridged_token && @bridged_token.foreign_chain_id, do: @bridged_token.foreign_chain_id |> Decimal.to_integer() |> to_string(), else: System.get_env("CHAIN_ID") %>
<% address_hash = if @bridged_token && @bridged_token.foreign_token_contract_address_hash, do: @bridged_token.foreign_token_contract_address_hash, else: @token.contract_address_hash %>
<% chain_id_for_token_icon = System.get_env("CHAIN_ID") %>
<% address_hash = @token.contract_address_hash %>
<%=
render BlockScoutWeb.TokensView,
"_token_icon.html",
@ -38,17 +38,10 @@
</p>
</td>
<td class="stakes-td">
<%= if @bridged_token && @bridged_token.lp_token && @bridged_token.custom_cap do %>
<% lp_token_balance_usd = @token_balance.value |> Decimal.div(@token_balance.token.total_supply) |> Decimal.mult(@bridged_token.custom_cap) |> Decimal.round(4) %>
<%= if @token_balance.token.usd_value do %>
<p class="mb-0 col-md-6 text-right">
<span data-selector="token-balance-usd" data-usd-value="<%= lp_token_balance_usd %>"><%= ChainView.format_usd_value(lp_token_balance_usd) %></span>
<span data-selector="token-balance-usd" data-usd-value="<%= Chain.balance_in_usd(@token_balance) %>"><%= ChainView.format_usd_value(Chain.balance_in_usd(@token_balance)) %></span>
</p>
<% else %>
<%= if @token_balance.token.usd_value do %>
<p class="mb-0 col-md-6 text-right">
<span data-selector="token-balance-usd" data-usd-value="<%= Chain.balance_in_usd(@token_balance) %>"><%= ChainView.format_usd_value(Chain.balance_in_usd(@token_balance)) %></span>
</p>
<% end %>
<% end %>
</td>
<td class="stakes-td">

@ -47,7 +47,7 @@
placeholder: gettext("Search tokens")
) %>
</div>
<%= if Enum.any?(@token_balances, fn {token_balance, _, _} -> token_balance.token.type == "ERC-721" end) do %>
<%= if Enum.any?(@token_balances, fn {token_balance, _} -> token_balance.token.type == "ERC-721" end) do %>
<%= render(
"_tokens.html",
conn: @conn,
@ -56,7 +56,7 @@
) %>
<% end %>
<%= if Enum.any?(@token_balances, fn {token_balance, _, _} -> token_balance.token.type == "ERC-1155" end) do %>
<%= if Enum.any?(@token_balances, fn {token_balance, _} -> token_balance.token.type == "ERC-1155" end) do %>
<%= render(
"_tokens.html",
conn: @conn,
@ -65,7 +65,7 @@
) %>
<% end %>
<%= if Enum.any?(@token_balances, fn {token_balance, _, _} -> token_balance.token.type == "ERC-20" end) do %>
<%= if Enum.any?(@token_balances, fn {token_balance, _} -> token_balance.token.type == "ERC-20" end) do %>
<%= render(
"_tokens.html",
conn: @conn,

@ -3,7 +3,7 @@
<%= @type %> (<span data-number-of-tokens-by-type="<%= @type %>"><%= Enum.count(@token_balances)%></span>)
</h6>
<%= for {token_balance, bridged_token, token} <- sort_by_usd_value_and_name(@token_balances) do %>
<%= for {token_balance, token} <- sort_by_usd_value_and_name(@token_balances) do %>
<div
class="border-bottom"
data-dropdown-token-balance-test
@ -22,8 +22,8 @@
) do %>
<div class="row dropdown-row wh-sp">
<%= if System.get_env("DISPLAY_TOKEN_ICONS") === "true" do %>
<% chain_id_for_token_icon = if bridged_token && bridged_token.foreign_chain_id, do: bridged_token.foreign_chain_id |> Decimal.to_integer() |> to_string(), else: System.get_env("CHAIN_ID") %>
<% address_hash = if bridged_token && bridged_token.foreign_token_contract_address_hash, do: bridged_token.foreign_token_contract_address_hash, else: token.contract_address_hash %>
<% chain_id_for_token_icon = System.get_env("CHAIN_ID") %>
<% address_hash = token.contract_address_hash %>
<%=
render BlockScoutWeb.TokensView,
"_token_icon.html",
@ -33,21 +33,11 @@
%>
<% end %>
<p class="mb-0 col-md-6 pl-0 pr-0 el-1 flex-grow-2"><%= token_name(token) %>
<%= if bridged_token && bridged_token.custom_metadata do %>
<%= "(" <> bridged_token.custom_metadata <> ")" %>
<% end %>
</p>
<%= if bridged_token && bridged_token.lp_token && bridged_token.custom_cap do %>
<% lp_token_balance_usd = token_balance.value |> Decimal.div(token.total_supply) |> Decimal.mult(bridged_token.custom_cap) |> Decimal.round(4) %>
<%= if token_balance.token.usd_value do %>
<p class="mb-0 col-md-6 text-right usd-total">
<span data-selector="token-balance-usd" data-usd-value="<%= lp_token_balance_usd %>"></span>
<span data-selector="token-balance-usd" data-usd-value="<%= Chain.balance_in_usd(token_balance) %>"></span>
</p>
<% else %>
<%= if token_balance.token.usd_value do %>
<p class="mb-0 col-md-6 text-right usd-total">
<span data-selector="token-balance-usd" data-usd-value="<%= Chain.balance_in_usd(token_balance) %>"></span>
</p>
<% end %>
<% end %>
</div>
<div class="row dropdown-row wh-sp">

@ -1,97 +0,0 @@
<tr data-identifier-hash="<%= @token.contract_address_hash %>">
<td class="stakes-td">
<!-- incremented number by order in the list -->
<span class="color-lighten">
<%= @index %>
</span>
</td>
<td class="token-icon">
<%= if System.get_env("DISPLAY_TOKEN_ICONS") === "true" do %>
<% foreign_chain_id = if Map.has_key?(@bridged_token, :foreign_chain_id), do: @bridged_token.foreign_chain_id, else: nil %>
<% chain_id_for_token_icon = if foreign_chain_id, do: foreign_chain_id |> Decimal.to_integer() |> to_string(), else: System.get_env("CHAIN_ID") %>
<% foreign_token_contract_address_hash = if Map.has_key?(@bridged_token, :foreign_token_contract_address_hash), do: Address.checksum(@bridged_token.foreign_token_contract_address_hash), else: nil %>
<% token_hash_for_token_icon = if foreign_token_contract_address_hash, do: foreign_token_contract_address_hash, else: Address.checksum(@token.contract_address_hash) %>
<%=
render BlockScoutWeb.TokensView,
"_token_icon.html",
chain_id: chain_id_for_token_icon,
address: token_hash_for_token_icon
%>
<% end %>
</td>
<td class="stakes-td token-name">
<% token = token_display_name(@token) %>
<div class="centered-container">
<div>
<div style="display: table;">
<%= link(token,
to: token_path(BlockScoutWeb.Endpoint, :show, @token.contract_address_hash),
"data-test": "token_link",
class: "text-truncate pre-wrap") %>
<%= if owl_token_amb?(@token.contract_address.hash) do %>
<span
data-toggle="tooltip"
data-placement="top"
data-html="true"
title="<%= owl_token_amb_info() %>">
<%= render BlockScoutWeb.CommonComponentsView, "_info.html", extra_class: "ml-1" %>
</span>
<% end %>
<%= if owl_token_omni?(@token.contract_address.hash) do %>
<span
data-toggle="tooltip"
data-placement="top"
data-html="true"
title="<%= owl_token_omni_info() %>">
<%= render BlockScoutWeb.CommonComponentsView, "_info.html", extra_class: "ml-1" %>
</span>
<% end %>
<%= if @bridged_token.custom_metadata do %>
<div class="card-subtitle list-title-description" style="display: table-row; text-align: left"><%= @bridged_token.custom_metadata %></div>
<% end %>
</div>
</div>
<%= if @bridged_token && @bridged_token.type do %>
<div class="bs-label right <%= @bridged_token.type %>"><%= String.upcase(@bridged_token.type) %></div>
<% end %>
<%= if @bridged_token && @bridged_token.foreign_chain_id do %>
<% tag = Chain.chain_id_display_name(@bridged_token.foreign_chain_id) %>
<div class="bs-label right ml-2 destination-<%= tag %>"><%= String.upcase(tag) %></div>
<% end %>
</div>
</td>
<td class="stakes-td">
<%= render BlockScoutWeb.AddressView,
"_link.html",
address: @token.contract_address,
contract: true,
use_custom_tooltip: false
%>
</td>
<td class="stakes-td token-total-supply">
<%= if decimals?(@token) do %>
<span data-test="token_supply"><%= format_according_to_decimals(@token.total_supply, @token.decimals) %></span>
<% else %>
<span data-test="token_supply"><%= format_integer_to_currency(@token.total_supply) %></span>
<% end %> <%= @token.symbol %>
</td>
<td class="stakes-td">
<span class="mr-4">
<span data-test="transaction_count">
<%= @token.holder_count %>
</span>
</span>
</td>
<%= if @destination == :eth do %>
<td class="stakes-td">
<span class="mr-4">
<span data-test="tvl">
<% usd_val = bridged_token_usd_cap(@bridged_token, @token) %>
<%= if Decimal.compare(usd_val, 0) == :gt do %>
<%= ChainView.format_usd_value(usd_val) %>
<% end %>
</span>
</span>
</td>
<% end %>
</tr>

@ -1,70 +0,0 @@
<section class="container" data-page="tokens">
<%= render BlockScoutWeb.Advertisement.TextAdView, "index.html", conn: @conn %>
<div class="card">
<div class="card-body" data-async-load data-async-listing="<%= @current_path %>">
<div class="tokens-list-search-input-outer-container">
<% tag = Chain.chain_id_display_name(@chain_id) %>
<h1 class="card-title"><div class="title-with-label"><%= gettext "Bridged Tokens from " %><%= @chain %></div><div class="bs-label ml-2 destination-<%= tag %>"><%= String.upcase(tag) %></div></h1>
<label class="tokens-list-search-input-container">
<input data-search-field="" class="form-control tokens-list-search-input search-input" type="text" name="filter" placeholder="Token name or symbol" id="search-text-input" />
</label>
</div>
<div>
<p class="card-subtitle list-title-description">List of the tokens bridged through OmniBridge <span class="bs-label omni">OMNI</span> and Arbitrary Message Bridge <span class="bs-label amb">AMB</span> extensions</p>
<div class="list-top-pagination-container-wrapper">
<%= 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 %>
</div>
</div>
<div class="addresses-table-container">
<div class="stakes-table-container">
<table>
<thead>
<tr>
<th class="stakes-table-th">
<div class="stakes-table-th-content">&nbsp;</div>
</th>
<th class="stakes-table-th">
<div>&nbsp;</div>
</th>
<th class="stakes-table-th">
<div class="stakes-table-th-content">Token</div>
</th>
<th class="stakes-table-th">
<div class="stakes-table-th-content">Address</div>
</th>
<th class="stakes-table-th">
<div class="stakes-table-th-content">
Total Supply
</div>
</th>
<th class="stakes-table-th">
<div class="stakes-table-th-content">
Holders Count
</div>
</th>
<%= if @destination == :eth do %>
<th class="stakes-table-th">
<div class="stakes-table-th-content">
USD Value
</div>
</th>
<% end %>
</tr>
</thead>
<tbody data-items data-selector="top-bridged-tokens-list">
<%= if @destination == :eth do %>
<%= render BlockScoutWeb.CommonComponentsView, "_table-loader.html", columns_num: 7 %>
<% else %>
<%= render BlockScoutWeb.CommonComponentsView, "_table-loader.html", columns_num: 6 %>
<% end %>
</tbody>
</table>
</div>
</div>
<%= render BlockScoutWeb.CommonComponentsView, "_pagination_container.html", position: "bottom", cur_page_number: "1", show_pagination_limit: true, data_next_page_button: true, data_prev_page_button: true %>
</div>
</div>
<script defer data-cfasync="false" src="<%= static_path(@conn, "/js/tokens.js") %>"></script>
</section>

@ -55,21 +55,6 @@
<% total_market_cap = market_cap(@market_cap_calculation, @exchange_rate) %>
<span style="display: contents;" class="dashboard-banner-chart-legend-value" data-selector="market-cap" data-usd-value="<%= total_market_cap %>">
</span>
<%= if token_bridge_supply?() do %>
<% token_bridge_market_cap = total_market_cap_from_token_bridge(@exchange_rate) %>
<% omni_bridge_market_cap = total_market_cap_from_omni_bridge() %>
<% formatted_total_market_cap = if Decimal.compare(total_market_cap, 0) == :gt, do: format_currency_value(total_market_cap), else: "N/A" %>
<% formatted_token_bridge_market_cap = if Decimal.compare(token_bridge_market_cap, 0) == :gt, do: format_currency_value(token_bridge_market_cap), else: "N/A" %>
<% formatted_omni_bridge_market_cap = if Decimal.compare(omni_bridge_market_cap, 0) == :gt, do: format_currency_value(omni_bridge_market_cap), else: "N/A" %>
<span
data-toggle="tooltip"
data-placement="top"
data-html="true"
data-template="<div class='tooltip tooltip-inversed-color tooltip-market-cap' role='tooltip'><div class='arrow'></div><div class='tooltip-inner'></div></div>"
title="<div class='custom-tooltip header'><b><%= formatted_total_market_cap %></b> is a sum of assets locked in TokenBridge and OmniBridge</div><div class='custom-tooltip description left'><b><%= formatted_token_bridge_market_cap %></b> locked in Dai in TokenBridge <br/><b><%= formatted_omni_bridge_market_cap %></b> locked in different assets on xDai in OmniBridge</div>">
<span style="display: inline-block; height: 20px; width: 12px;" class="fontawesome-icon info-circle ml-1" data-test="token-bridge-supply"></span>
</span>
<% end %>
</div>
</div>
<% end %>

@ -59,60 +59,26 @@
<% end %>
</div>
</li>
<%= if Chain.bridged_tokens_enabled?() do %>
<li class="nav-item dropdown">
<a href="#" role="button" id="navbarTokensDropdown" class="nav-link topnav-nav-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="nav-link-icon">
<%= render BlockScoutWeb.IconsView, "_tokens_icon.html" %>
</span>
<%= gettext("Tokens") %>
</a>
<div class="dropdown-menu" aria-labeledby="navbarTransactionsDropdown">
<%= link(
gettext("All"),
class: "dropdown-item #{tab_status("tokens", @conn.request_path)}",
to: tokens_path(@conn, :index)
) %>
<%= link(
gettext("Bridged from Ethereum"),
class: "dropdown-item #{tab_status("bridged-tokens/eth", @conn.request_path)}",
to: bridged_tokens_path(@conn, :show, :eth),
style: "white-space: nowrap;"
) %>
<%= link(
gettext("Bridged from BSC"),
class: "dropdown-item #{tab_status("bridged-tokens/bsc", @conn.request_path)}",
to: bridged_tokens_path(@conn, :show, :bsc)
) %>
<%= link(
gettext("Ether"),
class: "dropdown-item #{tab_status("accounts", @conn.request_path)}",
to: address_path(@conn, :index)
) %>
</div>
</li>
<% else %>
<li class="nav-item dropdown">
<a href="#" role="button" id="navbarTokensDropdown" class="nav-link topnav-nav-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="nav-link-icon">
<%= render BlockScoutWeb.IconsView, "_tokens_icon.html" %>
</span>
<%= gettext("Tokens") %>
</a>
<div class="dropdown-menu" aria-labeledby="navbarTransactionsDropdown">
<%= link(
gettext("All"),
class: "dropdown-item #{tab_status("tokens", @conn.request_path)}",
to: tokens_path(@conn, :index)
) %>
<%= link(
gettext("Ether"),
class: "dropdown-item #{tab_status("accounts", @conn.request_path)}",
to: address_path(@conn, :index)
) %>
</div>
</li>
<% end %>
<li class="nav-item dropdown">
<a href="#" role="button" id="navbarTokensDropdown" class="nav-link topnav-nav-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="nav-link-icon">
<%= render BlockScoutWeb.IconsView, "_tokens_icon.html" %>
</span>
<%= gettext("Tokens") %>
</a>
<div class="dropdown-menu" aria-labeledby="navbarTransactionsDropdown">
<%= link(
gettext("All"),
class: "dropdown-item #{tab_status("tokens", @conn.request_path)}",
to: tokens_path(@conn, :index)
) %>
<%= link(
gettext("Ether"),
class: "dropdown-item #{tab_status("accounts", @conn.request_path)}",
to: address_path(@conn, :index)
) %>
</div>
</li>
<% end %>
<%= if Application.get_env(:block_scout_web, BlockScoutWeb.ApiRouter)[:reading_enabled] || Application.get_env(:block_scout_web, :api_url) do %>
<li class="nav-item dropdown">

@ -237,7 +237,6 @@
@view_module != Elixir.BlockScoutWeb.BlockView &&
@view_module != Elixir.BlockScoutWeb.BlockTransactionView &&
@view_module != Elixir.BlockScoutWeb.AddressView &&
@view_module != Elixir.BlockScoutWeb.BridgedTokensView &&
@view_module != Elixir.BlockScoutWeb.TokensView &&
@view_module != Elixir.BlockScoutWeb.TransactionView &&
@view_module != Elixir.BlockScoutWeb.PendingTransactionView &&

@ -9,8 +9,8 @@
data-address-hash="<%= @result.address_hash %>"
>
<%= if System.get_env("DISPLAY_TOKEN_ICONS") === "true" do %>
<% chain_id_for_token_icon = if @result.foreign_chain_id, do: @result.foreign_chain_id |> Decimal.to_integer() |> to_string(), else: System.get_env("CHAIN_ID") %>
<% address_hash = if @result.foreign_token_hash, do: @result.foreign_token_hash, else: @result.address_hash %>
<% chain_id_for_token_icon = System.get_env("CHAIN_ID") %>
<% address_hash = @result.address_hash %>
<%=
render BlockScoutWeb.TokensView,
"_token_icon.html",

@ -22,22 +22,14 @@
<% true -> %>
<%= nil %>
<% end %>
<% foreign_chain_id = if Map.has_key?(@token, :foreign_chain_id), do: @token.foreign_chain_id, else: nil %>
<% tag = Chain.chain_id_display_name(foreign_chain_id) %>
<%= if token_name?(@token) do %>
<span
id="token-icon"
data-chain-id="<%= System.get_env("CHAIN_ID") %>"
data-address-hash="<%= Address.checksum(@token.contract_address_hash) %>"
data-foreign-chain-id="<%= foreign_chain_id %>"
data-foreign-address-hash="<%= if Map.has_key?(@token, :foreign_token_contract_address_hash), do: Address.checksum(@token.foreign_token_contract_address_hash), else: "" %>"
data-display-token-icons="<%= System.get_env("DISPLAY_TOKEN_ICONS") %>">
</span>
<div class="title-with-label"><%= @token.name %></div>
<%= if tag !== "" do %>
<%= render BlockScoutWeb.FormView, "_tag.html", text: "bridged", additional_classes: ["bridged", "ml-1"] %>
<%= render BlockScoutWeb.FormView, "_tag.html", text: String.upcase(tag), additional_classes: ["destination-#{tag}", "ml-1"] %>
<% end %>
<% else %>
<%= gettext("Token Details") %>
<% end %>
@ -52,13 +44,6 @@
<%= render BlockScoutWeb.CommonComponentsView, "_btn_qr_code.html" %>
</span>
</h1>
<%= if @token.bridged do %>
<div class="view-original-token-container">
<%= if Map.has_key?(@token, :foreign_token_contract_address_hash) do %>
<a data-test="original_token_contract_address" href=<%= foreign_bridged_token_explorer_link(@token) %> target="_blank">View Original Token <span class="external-token-icon"><%= render BlockScoutWeb.IconsView, "_external_link.html" %></span></a>
<% end %>
</div>
<% end %>
<dl class="row mt-4">
<dt class="col-sm-4 col-md-4 col-lg-3 text-muted">
<%= render BlockScoutWeb.CommonComponentsView, "_i_tooltip_2.html",

@ -11,7 +11,7 @@ defmodule BlockScoutWeb.AddressTokenBalanceView do
end
def filter_by_type(token_balances, type) do
Enum.filter(token_balances, fn {token_balance, _, _} -> token_balance.token.type == type end)
Enum.filter(token_balances, fn {token_balance, _} -> token_balance.token.type == type end)
end
@doc """
@ -29,7 +29,7 @@ defmodule BlockScoutWeb.AddressTokenBalanceView do
"""
def sort_by_usd_value_and_name(token_balances) do
token_balances
|> Enum.sort(fn {token_balance1, _, token1}, {token_balance2, _, token2} ->
|> Enum.sort(fn {token_balance1, token1}, {token_balance2, token2} ->
usd_value1 = token_balance1.token.usd_value
usd_value2 = token_balance2.token.usd_value

@ -446,20 +446,4 @@ defmodule BlockScoutWeb.AddressView do
end
def smart_contract_is_gnosis_safe_proxy?(_address), do: false
def is_omni_bridge?(nil), do: false
def is_omni_bridge?(address_hash) do
address_hash_str = "0x" <> Base.encode16(address_hash.bytes, case: :lower)
address_hash_str == String.downcase(System.get_env("ETH_OMNI_BRIDGE_MEDIATOR", "")) ||
address_hash_str == String.downcase(System.get_env("BSC_OMNI_BRIDGE_MEDIATOR", ""))
end
def is_amb_bridge?(nil), do: false
def is_amb_bridge?(address_hash) do
address_hash_str = "0x" <> Base.encode16(address_hash.bytes, case: :lower)
String.downcase(System.get_env("AMB_BRIDGE_MEDIATORS", "")) =~ address_hash_str
end
end

@ -2,7 +2,6 @@ defmodule BlockScoutWeb.API.RPC.TokenView do
use BlockScoutWeb, :view
alias BlockScoutWeb.API.RPC.RPCView
alias BlockScoutWeb.BridgedTokensView
def render("gettoken.json", %{token: token}) do
RPCView.render("show.json", data: prepare_token(token))
@ -13,11 +12,6 @@ defmodule BlockScoutWeb.API.RPC.TokenView do
RPCView.render("show.json", data: data)
end
def render("bridgedtokenlist.json", %{bridged_tokens: bridged_tokens}) do
data = Enum.map(bridged_tokens, &prepare_bridged_token/1)
RPCView.render("show.json", data: data)
end
def render("error.json", assigns) do
RPCView.render("error.json", assigns)
end
@ -40,25 +34,4 @@ defmodule BlockScoutWeb.API.RPC.TokenView do
"value" => token_holder.value
}
end
defp prepare_bridged_token([]) do
%{}
end
defp prepare_bridged_token([token, bridged_token]) do
total_supply = divide_decimals(token.total_supply, token.decimals)
usd_value = BridgedTokensView.bridged_token_usd_cap(bridged_token, token)
%{
"foreignChainId" => bridged_token.foreign_chain_id,
"foreignTokenContractAddressHash" => bridged_token.foreign_token_contract_address_hash,
"homeContractAddressHash" => token.contract_address_hash,
"homeDecimals" => token.decimals,
"homeHolderCount" => if(token.holder_count, do: to_string(token.holder_count), else: "0"),
"homeName" => token.name,
"homeSymbol" => token.symbol,
"homeTotalSupply" => total_supply,
"homeUsdValue" => usd_value
}
end
end

@ -1,49 +0,0 @@
defmodule BlockScoutWeb.BridgedTokensView do
use BlockScoutWeb, :view
alias BlockScoutWeb.ChainView
alias Explorer.Chain
alias Explorer.Chain.{Address, BridgedToken, 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
"<div class='custom-tooltip-header'>OWL token bridged through AMB extension with support of <i>burnOWL</i> method. It is recommended to use.</div>"
end
def owl_token_omni_info do
"<div class='custom-tooltip-header'>OWL token bridged through OmniBridge without support of <i>burnOWL</i> method. It is not recommended to use.</div>"
end
@doc """
Calculates capitalization of the bridged token in USD.
"""
@spec bridged_token_usd_cap(BridgedToken.t(), Token.t()) :: any()
def bridged_token_usd_cap(bridged_token, token) do
if bridged_token.custom_cap do
bridged_token.custom_cap
else
if bridged_token.exchange_rate && token.total_supply do
Decimal.mult(bridged_token.exchange_rate, divide_decimals(token.total_supply, token.decimals))
else
Decimal.new(0)
end
end
end
end

@ -6,7 +6,6 @@ defmodule BlockScoutWeb.ChainView do
alias BlockScoutWeb.LayoutView
alias Explorer.Chain.Cache.GasPriceOracle
alias Explorer.Chain.Supply.TokenBridge
defp market_cap(:standard, %{available_supply: available_supply, usd_value: usd_value})
when is_nil(available_supply) or is_nil(usd_value) do
@ -25,18 +24,6 @@ defmodule BlockScoutWeb.ChainView do
module.market_cap(exchange_rate)
end
defp total_market_cap_from_token_bridge(%{usd_value: usd_value}) do
TokenBridge.token_bridge_market_cap(%{usd_value: usd_value})
end
defp total_market_cap_from_omni_bridge do
TokenBridge.total_market_cap_from_omni_bridge()
end
defp token_bridge_supply? do
if System.get_env("SUPPLY_MODULE") === "TokenBridge", do: true, else: false
end
def format_usd_value(nil), do: ""
def format_usd_value(value) do

@ -10,8 +10,6 @@ defmodule BlockScoutWeb.Tokens.OverviewView do
import BlockScoutWeb.AddressView, only: [from_address_hash: 1]
@tabs ["token-transfers", "token-holders", "read-contract", "inventory"]
@etherscan_token_link "https://etherscan.io/token/"
@blockscout_base_link "https://blockscout.com/"
def decimals?(%Token{decimals: nil}), do: false
def decimals?(%Token{decimals: _}), do: true
@ -84,58 +82,4 @@ defmodule BlockScoutWeb.Tokens.OverviewView do
Decimal.mult(tokens, price)
end
end
def foreign_bridged_token_explorer_link(token) do
chain_id = Map.get(token, :foreign_chain_id)
base_token_explorer_link = get_base_token_explorer_link(chain_id)
foreign_token_contract_address_hash_string_no_prefix =
token.foreign_token_contract_address_hash.bytes
|> Base.encode16(case: :lower)
foreign_token_contract_address_hash_string = "0x" <> foreign_token_contract_address_hash_string_no_prefix
base_token_explorer_link <> foreign_token_contract_address_hash_string
end
# credo:disable-for-next-line /Complexity/
defp get_base_token_explorer_link(chain_id) when not is_nil(chain_id) do
case Decimal.to_integer(chain_id) do
181 ->
@blockscout_base_link <> "poa/qdai/tokens/"
100 ->
@blockscout_base_link <> "poa/xdai/tokens/"
99 ->
@blockscout_base_link <> "poa/core/tokens/"
77 ->
@blockscout_base_link <> "poa/sokol/tokens/"
42 ->
"https://kovan.etherscan.io/token/"
3 ->
"https://ropsten.etherscan.io/token/"
4 ->
"https://rinkeby.etherscan.io/token/"
5 ->
"https://goerli.etherscan.io/token/"
1 ->
@etherscan_token_link
56 ->
"https://bscscan.com/token/"
_ ->
@etherscan_token_link
end
end
defp get_base_token_explorer_link(_), do: @etherscan_token_link
end

@ -81,8 +81,6 @@ defmodule BlockScoutWeb.WebRouter do
resources("/tokens", TokensController, only: [:index])
resources("/bridged-tokens", BridgedTokensController, only: [:index, :show])
resources "/address", AddressController, only: [:show] do
resources("/transactions", AddressTransactionController, only: [:index], as: :transaction)

@ -121,7 +121,7 @@ msgid "API for the %{subnetwork} - BlockScout"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:123
#: lib/block_scout_web/templates/layout/_topnav.html.eex:89
msgid "APIs"
msgstr ""
@ -162,7 +162,7 @@ msgid "Address balance in xDAI (doesn't include ERC20, ERC721, ERC1155 tokens)."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:65
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:50
msgid "Address of the token contract"
msgstr ""
@ -174,9 +174,9 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:26
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:28 lib/block_scout_web/templates/address_transaction/index.html.eex:22
#: lib/block_scout_web/templates/layout/_network_selector.html.eex:21 lib/block_scout_web/templates/layout/_topnav.html.eex:72
#: lib/block_scout_web/templates/layout/_topnav.html.eex:104 lib/block_scout_web/views/address_internal_transaction_view.ex:11
#: lib/block_scout_web/views/address_token_transfer_view.ex:11 lib/block_scout_web/views/address_transaction_view.ex:11
#: lib/block_scout_web/templates/layout/_network_selector.html.eex:21 lib/block_scout_web/templates/layout/_topnav.html.eex:71
#: lib/block_scout_web/views/address_internal_transaction_view.ex:11 lib/block_scout_web/views/address_token_transfer_view.ex:11
#: lib/block_scout_web/views/address_transaction_view.ex:11
msgid "All"
msgstr ""
@ -211,12 +211,12 @@ msgid "Anything not in this list is not supported. Click on the method to be tak
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:151
#: lib/block_scout_web/templates/layout/_topnav.html.eex:117
msgid "Apps"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:115
#: lib/block_scout_web/templates/chain/show.html.eex:100
msgid "Average block time"
msgstr ""
@ -315,7 +315,7 @@ msgid "BlockScout provides analytics data, API, and Smart Contract tools for the
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:168
#: lib/block_scout_web/templates/chain/show.html.eex:153
#: lib/block_scout_web/templates/layout/_topnav.html.eex:23 lib/block_scout_web/templates/layout/_topnav.html.eex:27
msgid "Blocks"
msgstr ""
@ -337,21 +337,6 @@ msgstr ""
msgid "Blockscout is a tool for inspecting and analyzing EVM based blockchains. Blockchain explorer for Ethereum Networks."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/bridged_tokens/index.html.eex:7
msgid "Bridged Tokens from "
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:83
msgid "Bridged from BSC"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:77
msgid "Bridged from Ethereum"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:64
#: lib/block_scout_web/templates/block/overview.html.eex:216
@ -498,7 +483,7 @@ msgid "Constructor Arguments"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:66
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:51
#: lib/block_scout_web/templates/transaction/overview.html.eex:223
msgid "Contract"
msgstr ""
@ -580,8 +565,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:37
#: lib/block_scout_web/templates/address/overview.html.eex:38 lib/block_scout_web/templates/block/overview.html.eex:104
#: lib/block_scout_web/templates/block/overview.html.eex:105 lib/block_scout_web/templates/tokens/overview/_details.html.eex:50
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:51
#: lib/block_scout_web/templates/block/overview.html.eex:105 lib/block_scout_web/templates/tokens/overview/_details.html.eex:42
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:43
msgid "Copy Address"
msgstr ""
@ -723,7 +708,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/instance/overview/_details.html.eex:52
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:145
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:130
msgid "Decimals"
msgstr ""
@ -904,7 +889,7 @@ msgid "Error: Could not determine contract creator."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:137
#: lib/block_scout_web/templates/layout/_topnav.html.eex:103
msgid "Eth RPC"
msgstr ""
@ -912,10 +897,9 @@ msgstr ""
#: lib/block_scout_web/templates/address/_current_coin_balance.html.eex:11
#: lib/block_scout_web/templates/address/index.html.eex:5 lib/block_scout_web/templates/address/overview.html.eex:179
#: lib/block_scout_web/templates/block/overview.html.eex:215 lib/block_scout_web/templates/internal_transaction/_tile.html.eex:24
#: lib/block_scout_web/templates/layout/_topnav.html.eex:88 lib/block_scout_web/templates/layout/_topnav.html.eex:109
#: lib/block_scout_web/templates/layout/app.html.eex:48 lib/block_scout_web/templates/transaction/_pending_tile.html.eex:20
#: lib/block_scout_web/templates/transaction/_tile.html.eex:43 lib/block_scout_web/templates/transaction/overview.html.eex:411
#: lib/block_scout_web/views/wei_helpers.ex:78
#: lib/block_scout_web/templates/layout/_topnav.html.eex:76 lib/block_scout_web/templates/layout/app.html.eex:48
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:20 lib/block_scout_web/templates/transaction/_tile.html.eex:43
#: lib/block_scout_web/templates/transaction/overview.html.eex:411 lib/block_scout_web/views/wei_helpers.ex:78
msgid "Ether"
msgstr ""
@ -968,7 +952,7 @@ msgid "Fetching gas used..."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:126
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:111
msgid "Fetching holders..."
msgstr ""
@ -985,7 +969,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:237
#: lib/block_scout_web/templates/address/overview.html.eex:245 lib/block_scout_web/templates/tokens/overview/_details.html.eex:137
#: lib/block_scout_web/templates/address/overview.html.eex:245 lib/block_scout_web/templates/tokens/overview/_details.html.eex:122
msgid "Fetching transfers..."
msgstr ""
@ -1060,7 +1044,7 @@ msgid "Go to"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:127
#: lib/block_scout_web/templates/layout/_topnav.html.eex:93
msgid "GraphQL"
msgstr ""
@ -1084,7 +1068,7 @@ msgid "Hex (Default)"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:122
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:107
msgid "Holders"
msgstr ""
@ -1174,7 +1158,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/inventory/index.html.eex:15
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:19 lib/block_scout_web/views/tokens/overview_view.ex:44
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:19 lib/block_scout_web/views/tokens/overview_view.ex:42
msgid "Inventory"
msgstr ""
@ -1279,7 +1263,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:52
#: lib/block_scout_web/templates/layout/app.html.eex:46 lib/block_scout_web/templates/tokens/overview/_details.html.eex:98
#: lib/block_scout_web/templates/layout/app.html.eex:46 lib/block_scout_web/templates/tokens/overview/_details.html.eex:83
#: lib/block_scout_web/views/address_view.ex:142
msgid "Market Cap"
msgstr ""
@ -1359,7 +1343,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/index.html.eex:46
#: lib/block_scout_web/templates/chain/show.html.eex:231 lib/block_scout_web/templates/pending_transaction/index.html.eex:13
#: lib/block_scout_web/templates/chain/show.html.eex:216 lib/block_scout_web/templates/pending_transaction/index.html.eex:13
#: lib/block_scout_web/templates/transaction/index.html.eex:19
msgid "More transactions have come in"
msgstr ""
@ -1430,7 +1414,7 @@ msgid "Not unique Token"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:121
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:106
msgid "Number of accounts holding the token"
msgstr ""
@ -1440,7 +1424,7 @@ msgid "Number of blocks validated by this validator."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:144
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:129
msgid "Number of digits that come after the decimal place when displaying token value"
msgstr ""
@ -1450,7 +1434,7 @@ msgid "Number of transactions related to this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:132
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:117
msgid "Number of transfers for the token"
msgstr ""
@ -1553,12 +1537,12 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:41
#: lib/block_scout_web/templates/layout/app.html.eex:47 lib/block_scout_web/templates/tokens/overview/_details.html.eex:109
#: lib/block_scout_web/templates/layout/app.html.eex:47 lib/block_scout_web/templates/tokens/overview/_details.html.eex:94
msgid "Price"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:108
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:93
msgid "Price per token on the exchanges"
msgstr ""
@ -1590,7 +1574,7 @@ msgid "Query"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:132
#: lib/block_scout_web/templates/layout/_topnav.html.eex:98
msgid "RPC"
msgstr ""
@ -1608,7 +1592,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:81
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:27 lib/block_scout_web/views/address_view.ex:366
#: lib/block_scout_web/views/tokens/overview_view.ex:43
#: lib/block_scout_web/views/tokens/overview_view.ex:41
msgid "Read Contract"
msgstr ""
@ -1756,7 +1740,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:50 lib/block_scout_web/templates/address_logs/index.html.eex:23
#: lib/block_scout_web/templates/address_token/index.html.eex:60 lib/block_scout_web/templates/address_token_transfer/index.html.eex:58
#: lib/block_scout_web/templates/address_transaction/index.html.eex:50 lib/block_scout_web/templates/address_validation/index.html.eex:20
#: lib/block_scout_web/templates/block_transaction/index.html.eex:22 lib/block_scout_web/templates/chain/show.html.eex:172
#: lib/block_scout_web/templates/block_transaction/index.html.eex:22 lib/block_scout_web/templates/chain/show.html.eex:157
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:18 lib/block_scout_web/templates/tokens/holder/index.html.eex:23
#: lib/block_scout_web/templates/tokens/instance/holder/index.html.eex:23 lib/block_scout_web/templates/tokens/instance/transfer/index.html.eex:23
#: lib/block_scout_web/templates/tokens/inventory/index.html.eex:22 lib/block_scout_web/templates/tokens/transfer/index.html.eex:21
@ -1767,7 +1751,7 @@ msgid "Something went wrong, click to reload."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:237
#: lib/block_scout_web/templates/chain/show.html.eex:222
msgid "Something went wrong, click to retry."
msgstr ""
@ -1782,7 +1766,7 @@ msgid "Sources and Metadata JSON"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:153
#: lib/block_scout_web/templates/layout/_topnav.html.eex:119
msgid "Stakes"
msgstr ""
@ -1884,7 +1868,7 @@ msgid "The status of the transaction: Confirmed or Unconfirmed."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:82
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:67
msgid "The total amount of tokens issued"
msgstr ""
@ -2072,14 +2056,14 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/instance/overview/_details.html.eex:10
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:42
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:34
msgid "Token Details"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:16
#: lib/block_scout_web/templates/tokens/instance/holder/index.html.eex:16 lib/block_scout_web/templates/tokens/instance/overview/_tabs.html.eex:17
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:11 lib/block_scout_web/views/tokens/overview_view.ex:42
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:11 lib/block_scout_web/views/tokens/overview_view.ex:40
msgid "Token Holders"
msgstr ""
@ -2106,7 +2090,7 @@ msgstr ""
#: lib/block_scout_web/templates/tokens/instance/transfer/index.html.eex:16 lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:5
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:14 lib/block_scout_web/templates/transaction/_tabs.html.eex:4
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:7 lib/block_scout_web/views/address_view.ex:363
#: lib/block_scout_web/views/tokens/instance/overview_view.ex:195 lib/block_scout_web/views/tokens/overview_view.ex:41
#: lib/block_scout_web/views/tokens/instance/overview_view.ex:195 lib/block_scout_web/views/tokens/overview_view.ex:39
#: lib/block_scout_web/views/transaction_view.ex:511
msgid "Token Transfers"
msgstr ""
@ -2117,16 +2101,15 @@ msgid "Token name and symbol."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:156
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:141
msgid "Token type"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:21
#: lib/block_scout_web/templates/address/overview.html.eex:191 lib/block_scout_web/templates/address_token/overview.html.eex:58
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:13 lib/block_scout_web/templates/layout/_topnav.html.eex:68
#: lib/block_scout_web/templates/layout/_topnav.html.eex:100 lib/block_scout_web/templates/tokens/index.html.eex:10
#: lib/block_scout_web/views/address_view.ex:360
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:13 lib/block_scout_web/templates/layout/_topnav.html.eex:67
#: lib/block_scout_web/templates/tokens/index.html.eex:10 lib/block_scout_web/views/address_view.ex:360
msgid "Tokens"
msgstr ""
@ -2172,12 +2155,12 @@ msgid "Total Difficulty"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:97
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:82
msgid "Total Supply * Price"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:145
#: lib/block_scout_web/templates/chain/show.html.eex:130
msgid "Total blocks"
msgstr ""
@ -2192,7 +2175,7 @@ msgid "Total gas limit provided by all transactions in the block."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:83
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:68
msgid "Total supply"
msgstr ""
@ -2202,7 +2185,7 @@ msgid "Total transaction fee."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:124
#: lib/block_scout_web/templates/chain/show.html.eex:109
msgid "Total transactions"
msgstr ""
@ -2268,7 +2251,7 @@ msgstr ""
#: lib/block_scout_web/templates/address/overview.html.eex:202 lib/block_scout_web/templates/address/overview.html.eex:208
#: lib/block_scout_web/templates/address/overview.html.eex:216 lib/block_scout_web/templates/address_transaction/index.html.eex:13
#: lib/block_scout_web/templates/block/overview.html.eex:80 lib/block_scout_web/templates/block_transaction/index.html.eex:10
#: lib/block_scout_web/templates/chain/show.html.eex:228 lib/block_scout_web/templates/layout/_topnav.html.eex:42
#: lib/block_scout_web/templates/chain/show.html.eex:213 lib/block_scout_web/templates/layout/_topnav.html.eex:42
#: lib/block_scout_web/views/address_view.ex:362
msgid "Transactions"
msgstr ""
@ -2286,7 +2269,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:229
#: lib/block_scout_web/templates/address/overview.html.eex:235 lib/block_scout_web/templates/address/overview.html.eex:243
#: lib/block_scout_web/templates/tokens/instance/overview/_details.html.eex:50 lib/block_scout_web/templates/tokens/overview/_details.html.eex:133
#: lib/block_scout_web/templates/tokens/instance/overview/_details.html.eex:50 lib/block_scout_web/templates/tokens/overview/_details.html.eex:118
msgid "Transfers"
msgstr ""
@ -2313,7 +2296,7 @@ msgid "Type"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:155
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:140
msgid "Type of the token standard"
msgstr ""
@ -2456,12 +2439,12 @@ msgid "Via flattened source code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:167
#: lib/block_scout_web/templates/chain/show.html.eex:152
msgid "View All Blocks"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:227
#: lib/block_scout_web/templates/chain/show.html.eex:212
msgid "View All Transactions"
msgstr ""
@ -2522,7 +2505,7 @@ msgid "Waiting for transaction's confirmation..."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:153
#: lib/block_scout_web/templates/chain/show.html.eex:138
msgid "Wallet addresses"
msgstr ""
@ -2675,7 +2658,7 @@ msgid "Average"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:84
#: lib/block_scout_web/templates/chain/show.html.eex:69
msgid "Daily Transactions"
msgstr ""

@ -121,7 +121,7 @@ msgid "API for the %{subnetwork} - BlockScout"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:123
#: lib/block_scout_web/templates/layout/_topnav.html.eex:89
msgid "APIs"
msgstr ""
@ -162,7 +162,7 @@ msgid "Address balance in xDAI (doesn't include ERC20, ERC721, ERC1155 tokens)."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:65
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:50
msgid "Address of the token contract"
msgstr ""
@ -174,9 +174,9 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:26
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:28 lib/block_scout_web/templates/address_transaction/index.html.eex:22
#: lib/block_scout_web/templates/layout/_network_selector.html.eex:21 lib/block_scout_web/templates/layout/_topnav.html.eex:72
#: lib/block_scout_web/templates/layout/_topnav.html.eex:104 lib/block_scout_web/views/address_internal_transaction_view.ex:11
#: lib/block_scout_web/views/address_token_transfer_view.ex:11 lib/block_scout_web/views/address_transaction_view.ex:11
#: lib/block_scout_web/templates/layout/_network_selector.html.eex:21 lib/block_scout_web/templates/layout/_topnav.html.eex:71
#: lib/block_scout_web/views/address_internal_transaction_view.ex:11 lib/block_scout_web/views/address_token_transfer_view.ex:11
#: lib/block_scout_web/views/address_transaction_view.ex:11
msgid "All"
msgstr ""
@ -211,12 +211,12 @@ msgid "Anything not in this list is not supported. Click on the method to be tak
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:151
#: lib/block_scout_web/templates/layout/_topnav.html.eex:117
msgid "Apps"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:115
#: lib/block_scout_web/templates/chain/show.html.eex:100
msgid "Average block time"
msgstr ""
@ -315,7 +315,7 @@ msgid "BlockScout provides analytics data, API, and Smart Contract tools for the
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:168
#: lib/block_scout_web/templates/chain/show.html.eex:153
#: lib/block_scout_web/templates/layout/_topnav.html.eex:23 lib/block_scout_web/templates/layout/_topnav.html.eex:27
msgid "Blocks"
msgstr ""
@ -337,21 +337,6 @@ msgstr ""
msgid "Blockscout is a tool for inspecting and analyzing EVM based blockchains. Blockchain explorer for Ethereum Networks."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/bridged_tokens/index.html.eex:7
msgid "Bridged Tokens from "
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:83
msgid "Bridged from BSC"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:77
msgid "Bridged from Ethereum"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/block/_tile.html.eex:64
#: lib/block_scout_web/templates/block/overview.html.eex:216
@ -498,7 +483,7 @@ msgid "Constructor Arguments"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:66
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:51
#: lib/block_scout_web/templates/transaction/overview.html.eex:223
msgid "Contract"
msgstr ""
@ -580,8 +565,8 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:37
#: lib/block_scout_web/templates/address/overview.html.eex:38 lib/block_scout_web/templates/block/overview.html.eex:104
#: lib/block_scout_web/templates/block/overview.html.eex:105 lib/block_scout_web/templates/tokens/overview/_details.html.eex:50
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:51
#: lib/block_scout_web/templates/block/overview.html.eex:105 lib/block_scout_web/templates/tokens/overview/_details.html.eex:42
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:43
msgid "Copy Address"
msgstr ""
@ -723,7 +708,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/instance/overview/_details.html.eex:52
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:145
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:130
msgid "Decimals"
msgstr ""
@ -904,7 +889,7 @@ msgid "Error: Could not determine contract creator."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:137
#: lib/block_scout_web/templates/layout/_topnav.html.eex:103
msgid "Eth RPC"
msgstr ""
@ -912,10 +897,9 @@ msgstr ""
#: lib/block_scout_web/templates/address/_current_coin_balance.html.eex:11
#: lib/block_scout_web/templates/address/index.html.eex:5 lib/block_scout_web/templates/address/overview.html.eex:179
#: lib/block_scout_web/templates/block/overview.html.eex:215 lib/block_scout_web/templates/internal_transaction/_tile.html.eex:24
#: lib/block_scout_web/templates/layout/_topnav.html.eex:88 lib/block_scout_web/templates/layout/_topnav.html.eex:109
#: lib/block_scout_web/templates/layout/app.html.eex:48 lib/block_scout_web/templates/transaction/_pending_tile.html.eex:20
#: lib/block_scout_web/templates/transaction/_tile.html.eex:43 lib/block_scout_web/templates/transaction/overview.html.eex:411
#: lib/block_scout_web/views/wei_helpers.ex:78
#: lib/block_scout_web/templates/layout/_topnav.html.eex:76 lib/block_scout_web/templates/layout/app.html.eex:48
#: lib/block_scout_web/templates/transaction/_pending_tile.html.eex:20 lib/block_scout_web/templates/transaction/_tile.html.eex:43
#: lib/block_scout_web/templates/transaction/overview.html.eex:411 lib/block_scout_web/views/wei_helpers.ex:78
msgid "Ether"
msgstr ""
@ -968,7 +952,7 @@ msgid "Fetching gas used..."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:126
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:111
msgid "Fetching holders..."
msgstr ""
@ -985,7 +969,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:237
#: lib/block_scout_web/templates/address/overview.html.eex:245 lib/block_scout_web/templates/tokens/overview/_details.html.eex:137
#: lib/block_scout_web/templates/address/overview.html.eex:245 lib/block_scout_web/templates/tokens/overview/_details.html.eex:122
msgid "Fetching transfers..."
msgstr ""
@ -1060,7 +1044,7 @@ msgid "Go to"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:127
#: lib/block_scout_web/templates/layout/_topnav.html.eex:93
msgid "GraphQL"
msgstr ""
@ -1084,7 +1068,7 @@ msgid "Hex (Default)"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:122
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:107
msgid "Holders"
msgstr ""
@ -1174,7 +1158,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/inventory/index.html.eex:15
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:19 lib/block_scout_web/views/tokens/overview_view.ex:44
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:19 lib/block_scout_web/views/tokens/overview_view.ex:42
msgid "Inventory"
msgstr ""
@ -1279,7 +1263,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:52
#: lib/block_scout_web/templates/layout/app.html.eex:46 lib/block_scout_web/templates/tokens/overview/_details.html.eex:98
#: lib/block_scout_web/templates/layout/app.html.eex:46 lib/block_scout_web/templates/tokens/overview/_details.html.eex:83
#: lib/block_scout_web/views/address_view.ex:142
msgid "Market Cap"
msgstr ""
@ -1359,7 +1343,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address_transaction/index.html.eex:46
#: lib/block_scout_web/templates/chain/show.html.eex:231 lib/block_scout_web/templates/pending_transaction/index.html.eex:13
#: lib/block_scout_web/templates/chain/show.html.eex:216 lib/block_scout_web/templates/pending_transaction/index.html.eex:13
#: lib/block_scout_web/templates/transaction/index.html.eex:19
msgid "More transactions have come in"
msgstr ""
@ -1430,7 +1414,7 @@ msgid "Not unique Token"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:121
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:106
msgid "Number of accounts holding the token"
msgstr ""
@ -1440,7 +1424,7 @@ msgid "Number of blocks validated by this validator."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:144
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:129
msgid "Number of digits that come after the decimal place when displaying token value"
msgstr ""
@ -1450,7 +1434,7 @@ msgid "Number of transactions related to this address."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:132
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:117
msgid "Number of transfers for the token"
msgstr ""
@ -1553,12 +1537,12 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:41
#: lib/block_scout_web/templates/layout/app.html.eex:47 lib/block_scout_web/templates/tokens/overview/_details.html.eex:109
#: lib/block_scout_web/templates/layout/app.html.eex:47 lib/block_scout_web/templates/tokens/overview/_details.html.eex:94
msgid "Price"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:108
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:93
msgid "Price per token on the exchanges"
msgstr ""
@ -1590,7 +1574,7 @@ msgid "Query"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:132
#: lib/block_scout_web/templates/layout/_topnav.html.eex:98
msgid "RPC"
msgstr ""
@ -1608,7 +1592,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:81
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:27 lib/block_scout_web/views/address_view.ex:366
#: lib/block_scout_web/views/tokens/overview_view.ex:43
#: lib/block_scout_web/views/tokens/overview_view.ex:41
msgid "Read Contract"
msgstr ""
@ -1756,7 +1740,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_internal_transaction/index.html.eex:50 lib/block_scout_web/templates/address_logs/index.html.eex:23
#: lib/block_scout_web/templates/address_token/index.html.eex:60 lib/block_scout_web/templates/address_token_transfer/index.html.eex:58
#: lib/block_scout_web/templates/address_transaction/index.html.eex:50 lib/block_scout_web/templates/address_validation/index.html.eex:20
#: lib/block_scout_web/templates/block_transaction/index.html.eex:22 lib/block_scout_web/templates/chain/show.html.eex:172
#: lib/block_scout_web/templates/block_transaction/index.html.eex:22 lib/block_scout_web/templates/chain/show.html.eex:157
#: lib/block_scout_web/templates/pending_transaction/index.html.eex:18 lib/block_scout_web/templates/tokens/holder/index.html.eex:23
#: lib/block_scout_web/templates/tokens/instance/holder/index.html.eex:23 lib/block_scout_web/templates/tokens/instance/transfer/index.html.eex:23
#: lib/block_scout_web/templates/tokens/inventory/index.html.eex:22 lib/block_scout_web/templates/tokens/transfer/index.html.eex:21
@ -1767,7 +1751,7 @@ msgid "Something went wrong, click to reload."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:237
#: lib/block_scout_web/templates/chain/show.html.eex:222
msgid "Something went wrong, click to retry."
msgstr ""
@ -1782,7 +1766,7 @@ msgid "Sources and Metadata JSON"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:153
#: lib/block_scout_web/templates/layout/_topnav.html.eex:119
msgid "Stakes"
msgstr ""
@ -1884,7 +1868,7 @@ msgid "The status of the transaction: Confirmed or Unconfirmed."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:82
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:67
msgid "The total amount of tokens issued"
msgstr ""
@ -2072,14 +2056,14 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/instance/overview/_details.html.eex:10
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:42
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:34
msgid "Token Details"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/holder/index.html.eex:16
#: lib/block_scout_web/templates/tokens/instance/holder/index.html.eex:16 lib/block_scout_web/templates/tokens/instance/overview/_tabs.html.eex:17
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:11 lib/block_scout_web/views/tokens/overview_view.ex:42
#: lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:11 lib/block_scout_web/views/tokens/overview_view.ex:40
msgid "Token Holders"
msgstr ""
@ -2106,7 +2090,7 @@ msgstr ""
#: lib/block_scout_web/templates/tokens/instance/transfer/index.html.eex:16 lib/block_scout_web/templates/tokens/overview/_tabs.html.eex:5
#: lib/block_scout_web/templates/tokens/transfer/index.html.eex:14 lib/block_scout_web/templates/transaction/_tabs.html.eex:4
#: lib/block_scout_web/templates/transaction_token_transfer/index.html.eex:7 lib/block_scout_web/views/address_view.ex:363
#: lib/block_scout_web/views/tokens/instance/overview_view.ex:195 lib/block_scout_web/views/tokens/overview_view.ex:41
#: lib/block_scout_web/views/tokens/instance/overview_view.ex:195 lib/block_scout_web/views/tokens/overview_view.ex:39
#: lib/block_scout_web/views/transaction_view.ex:511
msgid "Token Transfers"
msgstr ""
@ -2117,16 +2101,15 @@ msgid "Token name and symbol."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:156
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:141
msgid "Token type"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/_tabs.html.eex:21
#: lib/block_scout_web/templates/address/overview.html.eex:191 lib/block_scout_web/templates/address_token/overview.html.eex:58
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:13 lib/block_scout_web/templates/layout/_topnav.html.eex:68
#: lib/block_scout_web/templates/layout/_topnav.html.eex:100 lib/block_scout_web/templates/tokens/index.html.eex:10
#: lib/block_scout_web/views/address_view.ex:360
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:13 lib/block_scout_web/templates/layout/_topnav.html.eex:67
#: lib/block_scout_web/templates/tokens/index.html.eex:10 lib/block_scout_web/views/address_view.ex:360
msgid "Tokens"
msgstr ""
@ -2172,12 +2155,12 @@ msgid "Total Difficulty"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:97
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:82
msgid "Total Supply * Price"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:145
#: lib/block_scout_web/templates/chain/show.html.eex:130
msgid "Total blocks"
msgstr ""
@ -2192,7 +2175,7 @@ msgid "Total gas limit provided by all transactions in the block."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:83
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:68
msgid "Total supply"
msgstr ""
@ -2202,7 +2185,7 @@ msgid "Total transaction fee."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:124
#: lib/block_scout_web/templates/chain/show.html.eex:109
msgid "Total transactions"
msgstr ""
@ -2268,7 +2251,7 @@ msgstr ""
#: lib/block_scout_web/templates/address/overview.html.eex:202 lib/block_scout_web/templates/address/overview.html.eex:208
#: lib/block_scout_web/templates/address/overview.html.eex:216 lib/block_scout_web/templates/address_transaction/index.html.eex:13
#: lib/block_scout_web/templates/block/overview.html.eex:80 lib/block_scout_web/templates/block_transaction/index.html.eex:10
#: lib/block_scout_web/templates/chain/show.html.eex:228 lib/block_scout_web/templates/layout/_topnav.html.eex:42
#: lib/block_scout_web/templates/chain/show.html.eex:213 lib/block_scout_web/templates/layout/_topnav.html.eex:42
#: lib/block_scout_web/views/address_view.ex:362
msgid "Transactions"
msgstr ""
@ -2286,7 +2269,7 @@ msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/address/overview.html.eex:229
#: lib/block_scout_web/templates/address/overview.html.eex:235 lib/block_scout_web/templates/address/overview.html.eex:243
#: lib/block_scout_web/templates/tokens/instance/overview/_details.html.eex:50 lib/block_scout_web/templates/tokens/overview/_details.html.eex:133
#: lib/block_scout_web/templates/tokens/instance/overview/_details.html.eex:50 lib/block_scout_web/templates/tokens/overview/_details.html.eex:118
msgid "Transfers"
msgstr ""
@ -2313,7 +2296,7 @@ msgid "Type"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:155
#: lib/block_scout_web/templates/tokens/overview/_details.html.eex:140
msgid "Type of the token standard"
msgstr ""
@ -2456,12 +2439,12 @@ msgid "Via flattened source code"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:167
#: lib/block_scout_web/templates/chain/show.html.eex:152
msgid "View All Blocks"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:227
#: lib/block_scout_web/templates/chain/show.html.eex:212
msgid "View All Transactions"
msgstr ""
@ -2522,7 +2505,7 @@ msgid "Waiting for transaction's confirmation..."
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:153
#: lib/block_scout_web/templates/chain/show.html.eex:138
msgid "Wallet addresses"
msgstr ""
@ -2675,7 +2658,7 @@ msgid "Average"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/chain/show.html.eex:84
#: lib/block_scout_web/templates/chain/show.html.eex:69
msgid "Daily Transactions"
msgstr ""

@ -89,8 +89,7 @@ defmodule BlockScoutWeb.AddressControllerTest do
"transaction_count" => 0,
"token_transfer_count" => 0,
"validation_count" => 0,
"gas_usage_count" => 0,
"crc_total_worth" => "0"
"gas_usage_count" => 0
} ==
response
end

@ -20,9 +20,9 @@ defmodule BlockScoutWeb.AddressTokenBalanceViewTest do
token_balance_a = build(:token_balance, token: build(:token, type: "ERC-20"))
token_balance_b = build(:token_balance, token: build(:token, type: "ERC-721"))
token_balances = [{token_balance_a, %{}, %{}}, {token_balance_b, %{}, %{}}]
token_balances = [{token_balance_a, %{}}, {token_balance_b, %{}}]
assert AddressTokenBalanceView.filter_by_type(token_balances, "ERC-20") == [{token_balance_a, %{}, %{}}]
assert AddressTokenBalanceView.filter_by_type(token_balances, "ERC-20") == [{token_balance_a, %{}}]
end
end
@ -116,23 +116,23 @@ defmodule BlockScoutWeb.AddressTokenBalanceViewTest do
)
token_balances = [
{token_balance_a, %{}, token_balance_a.token},
{token_balance_b, %{}, token_balance_b.token},
{token_balance_c, %{}, token_balance_c.token},
{token_balance_d, %{}, token_balance_d.token},
{token_balance_e, %{}, token_balance_e.token},
{token_balance_f, %{}, token_balance_f.token},
{token_balance_g, %{}, token_balance_g.token}
{token_balance_a, token_balance_a.token},
{token_balance_b, token_balance_b.token},
{token_balance_c, token_balance_c.token},
{token_balance_d, token_balance_d.token},
{token_balance_e, token_balance_e.token},
{token_balance_f, token_balance_f.token},
{token_balance_g, token_balance_g.token}
]
expected = [
{token_balance_b, %{}, token_balance_b.token},
{token_balance_a, %{}, token_balance_a.token},
{token_balance_c, %{}, token_balance_c.token},
{token_balance_d, %{}, token_balance_d.token},
{token_balance_g, %{}, token_balance_g.token},
{token_balance_e, %{}, token_balance_e.token},
{token_balance_f, %{}, token_balance_f.token}
{token_balance_b, token_balance_b.token},
{token_balance_a, token_balance_a.token},
{token_balance_c, token_balance_c.token},
{token_balance_d, token_balance_d.token},
{token_balance_g, token_balance_g.token},
{token_balance_e, token_balance_e.token},
{token_balance_f, token_balance_f.token}
]
assert AddressTokenBalanceView.sort_by_usd_value_and_name(token_balances) == expected

@ -125,22 +125,6 @@ config :explorer, Explorer.Counters.BlockPriorityFeeCounter,
config :explorer, Explorer.Chain.Cache.GasUsage,
enabled: System.get_env("CACHE_ENABLE_TOTAL_GAS_USAGE_COUNTER") == "true"
cache_bridge_market_cap_update_interval = System.get_env("CACHE_BRIDGE_MARKET_CAP_UPDATE_INTERVAL")
bridge_market_cap_update_interval =
if cache_bridge_market_cap_update_interval do
case Integer.parse(cache_bridge_market_cap_update_interval) do
{integer, ""} -> integer
_ -> nil
end
end
config :explorer, Explorer.Counters.Bridge,
enabled: if(System.get_env("SUPPLY_MODULE") === "TokenBridge", do: true, else: false),
enable_consolidation: System.get_env("DISABLE_BRIDGE_MARKET_CAP_UPDATER") !== "true",
update_interval_in_seconds: bridge_market_cap_update_interval || 30 * 60,
disable_lp_tokens_in_market_cap: System.get_env("DISABLE_LP_TOKENS_IN_MARKET_CAP") == "true"
config :explorer, Explorer.ExchangeRates,
enabled: System.get_env("DISABLE_EXCHANGE_RATES") != "true",
store: :ets,
@ -151,7 +135,6 @@ config :explorer, Explorer.ExchangeRates,
exchange_rates_source =
cond do
System.get_env("EXCHANGE_RATES_SOURCE") == "token_bridge" -> Explorer.ExchangeRates.Source.TokenBridge
System.get_env("EXCHANGE_RATES_SOURCE") == "coin_gecko" -> Explorer.ExchangeRates.Source.CoinGecko
System.get_env("EXCHANGE_RATES_SOURCE") == "coin_market_cap" -> Explorer.ExchangeRates.Source.CoinMarketCap
true -> Explorer.ExchangeRates.Source.CoinGecko
@ -214,9 +197,6 @@ config :explorer, Explorer.Chain.Block.Reward,
keys_manager_contract_address: System.get_env("KEYS_MANAGER_CONTRACT")
case System.get_env("SUPPLY_MODULE") do
"TokenBridge" ->
config :explorer, supply: Explorer.Chain.Supply.TokenBridge
"rsk" ->
config :explorer, supply: Explorer.Chain.Supply.RSK

File diff suppressed because it is too large Load Diff

@ -12,7 +12,7 @@ defmodule Explorer.Chain.Address.CurrentTokenBalance do
import Ecto.Query, only: [from: 2, limit: 2, offset: 2, order_by: 3, preload: 2]
alias Explorer.{Chain, PagingOptions, Repo}
alias Explorer.Chain.{Address, Block, BridgedToken, Hash, Token}
alias Explorer.Chain.{Address, Block, Hash, Token}
@default_paging_options %PagingOptions{page_size: 50}
@ -163,12 +163,10 @@ defmodule Explorer.Chain.Address.CurrentTokenBalance do
ctb in __MODULE__,
where: ctb.address_hash == ^address_hash,
where: ctb.value > 0,
left_join: bt in BridgedToken,
on: ctb.token_contract_address_hash == bt.home_token_contract_address_hash,
left_join: t in Token,
on: ctb.token_contract_address_hash == t.contract_address_hash,
preload: :token,
select: {ctb, bt, t},
select: {ctb, t},
order_by: [desc: ctb.value, asc: t.type, asc: t.name]
)
end

@ -1,97 +0,0 @@
defmodule Explorer.Chain.BridgedToken do
@moduledoc """
Represents a bridged token.
"""
use Explorer.Schema
import Ecto.Changeset
alias Explorer.Chain.{Address, BridgedToken, Hash, Token}
alias Explorer.Repo
@typedoc """
* `foreign_chain_id` - chain ID of a foreign token
* `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
* `custom_cap` - Custom capitalization for this token
* `lp_token` - Boolean flag: LP token or not
* `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_cap: Decimal.t(),
lp_token: boolean(),
type: String.t(),
exchange_rate: Decimal.t()
}
@derive {Poison.Encoder,
except: [
:__meta__,
:home_token_contract_address,
:inserted_at,
:updated_at
]}
@derive {Jason.Encoder,
except: [
:__meta__,
:home_token_contract_address,
:inserted_at,
:updated_at
]}
@primary_key false
schema "bridged_tokens" do
field(:foreign_chain_id, :decimal)
field(:foreign_token_contract_address_hash, Hash.Address)
field(:custom_metadata, :string)
field(:custom_cap, :decimal)
field(:lp_token, :boolean)
field(:type, :string)
field(:exchange_rate, :decimal)
belongs_to(
:home_token_contract_address,
Token,
foreign_key: :home_token_contract_address_hash,
primary_key: true,
references: :contract_address_hash,
type: Hash.Address
)
timestamps()
end
@required_attrs ~w(home_token_contract_address_hash)a
@optional_attrs ~w(foreign_chain_id foreign_token_contract_address_hash custom_metadata custom_cap boolean type exchange_rate)a
@doc false
def changeset(%BridgedToken{} = bridged_token, params \\ %{}) do
bridged_token
|> cast(params, @required_attrs ++ @optional_attrs)
|> validate_required(@required_attrs)
|> foreign_key_constraint(:home_token_contract_address)
|> unique_constraint(:home_token_contract_address_hash)
end
def get_unprocessed_mainnet_lp_tokens_list do
query =
from(bt in BridgedToken,
where: bt.foreign_chain_id == ^1,
where: is_nil(bt.lp_token) or bt.lp_token == true,
select: bt
)
query
|> Repo.all()
end
end

@ -4,13 +4,8 @@ defmodule Explorer.Chain.Cache.TokenExchangeRate do
"""
use GenServer
import Ecto.Query, only: [from: 2]
alias Ecto.Changeset
alias Explorer.Chain.BridgedToken
alias Explorer.Counters.Helper
alias Explorer.ExchangeRates.Source
alias Explorer.Repo
@cache_name :token_exchange_rate
@last_update_key "last_update"
@ -61,11 +56,7 @@ defmodule Explorer.Chain.Cache.TokenExchangeRate do
|> cache_key()
|> fetch_from_cache()
if is_nil(cached_value) || cached_value == :not_found_coingecko || Decimal.compare(cached_value, 0) == :eq do
fetch_from_db(token_hash)
else
cached_value
end
cached_value
end
# fetching by symbol is not recommended to use because of possible collisions
@ -82,11 +73,7 @@ defmodule Explorer.Chain.Cache.TokenExchangeRate do
|> cache_key()
|> fetch_from_cache()
if is_nil(cached_value) || cached_value == :not_found_coingecko || Decimal.compare(cached_value, 0) == :eq do
fetch_from_db(token_hash)
else
cached_value
end
cached_value
end
def cache_name, do: @cache_name
@ -111,21 +98,19 @@ defmodule Explorer.Chain.Cache.TokenExchangeRate do
is_nil(value) || value == 0
end
defp update_cache_by_symbol(token_hash, symbol) do
defp update_cache_by_symbol(_token_hash, symbol) do
put_into_cache("#{cache_key(symbol)}_#{@last_update_key}", Helper.current_time())
exchange_rate = fetch_token_exchange_rate(symbol, true)
put_into_db(token_hash, exchange_rate)
put_into_cache(cache_key(symbol), exchange_rate)
end
defp update_cache_by_address_hash_str(token_hash, address_hash_str) do
defp update_cache_by_address_hash_str(_token_hash, address_hash_str) do
put_into_cache("#{cache_key(address_hash_str)}_#{@last_update_key}", Helper.current_time())
exchange_rate = fetch_token_exchange_rate_by_address(address_hash_str, true)
put_into_db(token_hash, exchange_rate)
put_into_cache(cache_key(address_hash_str), exchange_rate)
end
@ -155,18 +140,6 @@ defmodule Explorer.Chain.Cache.TokenExchangeRate do
end
end
defp fetch_from_db(nil), do: nil
defp fetch_from_db(token_hash) do
token = get_token(token_hash)
if token do
token.exchange_rate
else
nil
end
end
defp fetch_from_cache(key) do
Helper.fetch_from_cache(key, @cache_name)
end
@ -177,26 +150,6 @@ defmodule Explorer.Chain.Cache.TokenExchangeRate do
end
end
def put_into_db(token_hash, exchange_rate) do
token = get_token(token_hash)
if token && !is_nil(exchange_rate) && exchange_rate != :not_found_coingecko do
token
|> Changeset.change(%{exchange_rate: exchange_rate})
|> Repo.update()
end
end
defp get_token(token_hash) do
query =
from(bt in BridgedToken,
where: bt.home_token_contract_address_hash == ^token_hash
)
query
|> Repo.one()
end
def cache_table_exists? do
:ets.whereis(@cache_name) !== :undefined
end

@ -201,7 +201,6 @@ defmodule Explorer.Chain.Import.Runner.Tokens do
decimals: fragment("EXCLUDED.decimals"),
type: fragment("EXCLUDED.type"),
cataloged: fragment("EXCLUDED.cataloged"),
bridged: fragment("EXCLUDED.bridged"),
skip_metadata: fragment("EXCLUDED.skip_metadata"),
# `holder_count` is not updated as a pre-existing token means the `holder_count` is already initialized OR
# need to be migrated with `priv/repo/migrations/scripts/update_new_tokens_holder_count_in_batches.sql.exs`
@ -212,14 +211,13 @@ defmodule Explorer.Chain.Import.Runner.Tokens do
],
where:
fragment(
"(EXCLUDED.name, EXCLUDED.symbol, EXCLUDED.total_supply, EXCLUDED.decimals, EXCLUDED.type, EXCLUDED.cataloged, EXCLUDED.bridged, EXCLUDED.skip_metadata) IS DISTINCT FROM (?, ?, ?, ?, ?, ?, ?, ?)",
"(EXCLUDED.name, EXCLUDED.symbol, EXCLUDED.total_supply, EXCLUDED.decimals, EXCLUDED.type, EXCLUDED.cataloged, EXCLUDED.skip_metadata) IS DISTINCT FROM (?, ?, ?, ?, ?, ?, ?)",
token.name,
token.symbol,
token.total_supply,
token.decimals,
token.type,
token.cataloged,
token.bridged,
token.skip_metadata
)
)

@ -1,298 +0,0 @@
defmodule Explorer.Chain.Supply.TokenBridge do
@moduledoc """
Defines the supply API for calculating the supply based on Token Bridge.
"""
use Explorer.Chain.Supply
import Ecto.Query,
only: [
from: 2
]
alias Explorer.Chain.{BridgedToken, Token, Wei}
alias Explorer.Chain.Cache.TokenExchangeRate, as: TokenExchangeRateCache
alias Explorer.Counters.Bridge
alias Explorer.ExchangeRates.Source
alias Explorer.{CustomContractsHelpers, Repo}
alias Explorer.SmartContract.Reader
@token_bridge_contract_address "0x7301CFA0e1756B71869E93d4e4Dca5c7d0eb0AA6"
@total_burned_coins_abi %{
"type" => "function",
"stateMutability" => "view",
"payable" => false,
"outputs" => [%{"type" => "uint256", "name" => ""}],
"name" => "totalBurntCoins",
"inputs" => [],
"constant" => true
}
# 0e8162ba=keccak256(totalBurntCoins())
@total_burned_coins_params %{"0e8162ba" => []}
@block_reward_contract_abi %{
"type" => "function",
"stateMutability" => "view",
"payable" => false,
"outputs" => [%{"type" => "address", "name" => ""}],
"name" => "blockRewardContract",
"inputs" => [],
"constant" => true
}
# 56b54bae=keccak256(blockRewardContract())
@block_reward_contract_params %{"56b54bae" => []}
@total_minted_coins_abi %{
"type" => "function",
"stateMutability" => "view",
"payable" => false,
"outputs" => [%{"type" => "uint256", "name" => ""}],
"name" => "mintedTotally",
"inputs" => [],
"constant" => true
}
# 553a5c85=keccak256(mintedTotallymintedTotally())
@total_minted_coins_params %{"553a5c85" => []}
def market_cap(%{usd_value: usd_value}) when not is_nil(usd_value) do
total_market_cap_from_token_bridge = token_bridge_market_cap(%{usd_value: usd_value})
total_market_cap_from_omni = total_market_cap_from_omni_bridge()
if Decimal.compare(total_market_cap_from_omni, 0) == :gt do
Decimal.add(total_market_cap_from_token_bridge, total_market_cap_from_omni)
else
total_market_cap_from_token_bridge
end
end
def market_cap(_) do
Decimal.new(0)
end
def token_bridge_market_cap(%{usd_value: usd_value}) when not is_nil(usd_value) do
total_coins_from_token_bridge = get_total_coins_from_token_bridge()
if total_coins_from_token_bridge do
Decimal.mult(total_coins_from_token_bridge, usd_value)
else
Decimal.new(0)
end
end
def token_bridge_market_cap(_), do: Decimal.new(0)
def circulating, do: total_chain_supply()
def total, do: total_chain_supply()
def get_total_coins_from_token_bridge, do: Bridge.fetch_token_bridge_total_supply()
def total_market_cap_from_omni_bridge, do: Bridge.fetch_omni_bridge_market_cap()
def total_chain_supply do
usd_value =
case Source.fetch_exchange_rates(Source.CoinGecko) do
{:ok, [rates]} ->
rates.usd_value
_ ->
Decimal.new(1)
end
total_coins_from_token_bridge = get_total_coins_from_token_bridge()
total_market_cap_from_omni = total_market_cap_from_omni_bridge()
if Decimal.compare(total_coins_from_token_bridge, 0) == :gt && Decimal.compare(total_market_cap_from_omni, 0) == :gt do
total_coins_from_omni_bridge = Decimal.div(total_market_cap_from_omni, usd_value)
Decimal.add(total_coins_from_token_bridge, total_coins_from_omni_bridge)
else
total_coins_from_token_bridge
end
end
defp burned_coins do
address = System.get_env("TOKEN_BRIDGE_CONTRACT") || @token_bridge_contract_address
call_contract(address, @total_burned_coins_abi, @total_burned_coins_params)
end
defp block_reward_contract do
address = System.get_env("TOKEN_BRIDGE_CONTRACT") || @token_bridge_contract_address
call_contract(address, @block_reward_contract_abi, @block_reward_contract_params)
end
defp minted_coins do
address = block_reward_contract()
call_contract(address, @total_minted_coins_abi, @total_minted_coins_params)
end
defp call_contract(address, abi, params) do
abi = [abi]
method_id =
params
|> Enum.map(fn {key, _value} -> key end)
|> List.first()
type =
abi
|> Enum.at(0)
|> Map.get("outputs", [])
|> Enum.at(0)
|> Map.get("type", "")
value =
case Reader.query_contract(address, abi, params, false) do
%{^method_id => {:ok, [result]}} ->
result
_ ->
case type do
"address" -> "0x0000000000000000000000000000000000000000"
"uint256" -> 0
_ -> 0
end
end
case type do
"address" ->
value
"uint256" ->
%Wei{value: Decimal.new(value)}
_ ->
value
end
end
def get_current_total_supply_from_token_bridge do
minted_coins()
|> Wei.sub(burned_coins())
|> Wei.to(:ether)
end
def get_current_market_cap_from_omni_bridge do
bridged_mainnet_tokens_list = get_bridged_mainnet_tokens_list()
bridged_mainnet_tokens_with_supply =
bridged_mainnet_tokens_list
|> get_bridged_mainnet_tokens_supply()
omni_bridge_market_cap = calc_omni_bridge_market_cap(bridged_mainnet_tokens_with_supply)
omni_bridge_market_cap
end
def get_current_price_for_bridged_token(_token_hash, foreign_token_contract_address_hash)
when is_nil(foreign_token_contract_address_hash),
do: nil
def get_current_price_for_bridged_token(token_hash, _foreign_token_contract_address_hash) when is_nil(token_hash),
do: nil
def get_current_price_for_bridged_token(token_hash, foreign_token_contract_address_hash) do
foreign_token_contract_address_hash_str =
"0x" <> Base.encode16(foreign_token_contract_address_hash.bytes, case: :lower)
TokenExchangeRateCache.fetch(token_hash, foreign_token_contract_address_hash_str)
end
def get_bridged_mainnet_tokens_list do
query =
from(bt in BridgedToken,
left_join: t in Token,
on: t.contract_address_hash == bt.home_token_contract_address_hash,
where: bt.foreign_chain_id == ^1,
where: t.bridged == true,
select: {bt.home_token_contract_address_hash, t.symbol, bt.custom_cap, bt.foreign_token_contract_address_hash},
order_by: [desc: t.holder_count]
)
query
|> Repo.all()
end
defp get_bridged_mainnet_tokens_supply(bridged_mainnet_tokens_list) do
bridged_mainnet_tokens_with_supply =
bridged_mainnet_tokens_list
|> Enum.map(fn {bridged_token_hash, _bridged_token_symbol, bridged_token_custom_cap,
foreign_token_contract_address_hash} ->
if bridged_token_custom_cap do
{bridged_token_hash, Decimal.new(0), Decimal.new(0), bridged_token_custom_cap}
else
bridged_token_price_from_cache =
TokenExchangeRateCache.fetch(bridged_token_hash, foreign_token_contract_address_hash)
bridged_token_price =
if bridged_token_price_from_cache && Decimal.compare(bridged_token_price_from_cache, 0) == :gt do
bridged_token_price_from_cache
else
TokenExchangeRateCache.fetch_token_exchange_rate_by_address(foreign_token_contract_address_hash)
end
query =
from(t in Token,
where: t.contract_address_hash == ^bridged_token_hash,
select: {t.total_supply, t.decimals}
)
bridged_token_balance =
query
|> Repo.one()
bridged_token_balance_formatted =
if bridged_token_balance do
{bridged_token_balance_with_decimals, decimals} = bridged_token_balance
decimals_multiplier =
10
|> :math.pow(Decimal.to_integer(decimals))
|> Decimal.from_float()
Decimal.div(bridged_token_balance_with_decimals, decimals_multiplier)
else
bridged_token_balance
end
{bridged_token_hash, bridged_token_price, bridged_token_balance_formatted, nil}
end
end)
bridged_mainnet_tokens_with_supply
end
defp calc_omni_bridge_market_cap(bridged_mainnet_tokens_with_supply) do
test_token_addresses = CustomContractsHelpers.get_custom_addresses_list(:test_tokens_addresses)
config = Application.get_env(:explorer, Explorer.Counters.Bridge)
disable_lp_tokens_in_market_cap = Keyword.get(config, :disable_lp_tokens_in_market_cap)
omni_bridge_market_cap =
bridged_mainnet_tokens_with_supply
|> Enum.filter(fn {bridged_token_hash, _, _, _} ->
bridged_token_hash_str = "0x" <> Base.encode16(bridged_token_hash.bytes, case: :lower)
!Enum.member?(test_token_addresses, bridged_token_hash_str)
end)
|> Enum.reduce(Decimal.new(0), fn {_bridged_token_hash, bridged_token_price, bridged_token_balance,
bridged_token_custom_cap},
acc ->
if !disable_lp_tokens_in_market_cap && bridged_token_custom_cap do
Decimal.add(acc, bridged_token_custom_cap)
else
if bridged_token_price do
bridged_token_cap = Decimal.mult(bridged_token_price, bridged_token_balance)
Decimal.add(acc, bridged_token_cap)
else
acc
end
end
end)
omni_bridge_market_cap
end
end

@ -37,7 +37,6 @@ defmodule Explorer.Chain.Token do
* `contract_address_hash` - Address hash foreign key
* `holder_count` - the number of `t:Explorer.Chain.Address.t/0` (except the burn address) that have a
`t:Explorer.Chain.CurrentTokenBalance.t/0` `value > 0`. Can be `nil` when data not migrated.
* `bridged` - Flag for bridged tokens from other chain
"""
@type t :: %Token{
name: String.t(),
@ -49,7 +48,6 @@ defmodule Explorer.Chain.Token do
contract_address: %Ecto.Association.NotLoaded{} | Address.t(),
contract_address_hash: Hash.Address.t(),
holder_count: non_neg_integer() | nil,
bridged: boolean(),
skip_metadata: boolean()
}
@ -78,7 +76,6 @@ defmodule Explorer.Chain.Token do
field(:type, :string)
field(:cataloged, :boolean)
field(:holder_count, :integer)
field(:bridged, :boolean)
field(:skip_metadata, :boolean)
belongs_to(
@ -94,7 +91,7 @@ defmodule Explorer.Chain.Token do
end
@required_attrs ~w(contract_address_hash type)a
@optional_attrs ~w(cataloged decimals name symbol total_supply bridged skip_metadata)a
@optional_attrs ~w(cataloged decimals name symbol total_supply skip_metadata)a
@doc false
def changeset(%Token{} = token, params \\ %{}) do

@ -1,194 +0,0 @@
defmodule Explorer.Counters.Bridge do
@moduledoc """
Caches the total supply of TokenBridge and OmniBridge.
It loads the count asynchronously and in a time interval of 30 minutes.
"""
use GenServer
alias Explorer.Chain.Cache.TokenExchangeRate
alias Explorer.Chain.Supply.TokenBridge
@bridges_table :bridges_market_cap
@current_total_supply_from_token_bridge_cache_key "current_total_supply_from_token_bridge"
@current_market_cap_from_omni_bridge_cache_key "current_market_cap_from_omni_bridge"
@ets_opts [
:set,
:named_table,
:public,
read_concurrency: true
]
# It is undesirable to automatically start the consolidation in all environments.
# Consider the test environment: if the consolidation initiates but does not
# finish before a test ends, that test will fail. This way, hundreds of
# tests were failing before disabling the consolidation and the scheduler in
# the test env.
config = Application.get_env(:explorer, Explorer.Counters.Bridge)
@enable_consolidation Keyword.get(config, :enable_consolidation)
@update_interval_in_seconds Keyword.get(config, :update_interval_in_seconds)
@doc """
Starts a process to periodically update bridges marketcaps.
"""
@spec start_link(term()) :: GenServer.on_start()
def start_link(_) do
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
end
@impl true
def init(_args) do
create_tables()
{:ok, %{consolidate?: enable_consolidation?()}, {:continue, :ok}}
end
def bridges_table_exists? do
:ets.whereis(@bridges_table) !== :undefined
end
def create_bridges_table do
unless bridges_table_exists?() do
:ets.new(@bridges_table, @ets_opts)
end
end
def create_tables do
TokenExchangeRate.create_cache_table()
create_bridges_table()
end
defp schedule_next_consolidation do
Process.send_after(self(), :consolidate, :timer.seconds(@update_interval_in_seconds))
end
@doc """
Inserts new bridged token price into the `:ets` table.
"""
def insert_price({key, info}) do
if TokenExchangeRate.cache_table_exists?() do
TokenExchangeRate.put_into_cache(key, info)
end
end
@impl true
def handle_continue(:ok, %{consolidate?: true} = state) do
consolidate()
schedule_next_consolidation()
{:noreply, state}
end
@impl true
def handle_continue(:ok, state) do
{:noreply, state}
end
@impl true
def handle_info(:consolidate, state) do
consolidate()
schedule_next_consolidation()
{:noreply, state}
end
# don't handle other messages (e.g. :ssl_closed)
def handle_info(_, state) do
{:noreply, state}
end
def fetch_token_bridge_total_supply do
if bridges_table_exists?() do
do_fetch_token_bridge_total_supply(:ets.lookup(@bridges_table, @current_total_supply_from_token_bridge_cache_key))
else
0
end
end
defp do_fetch_token_bridge_total_supply([{_, result}]), do: result
defp do_fetch_token_bridge_total_supply([]) do
update_total_supply_from_token_bridge_cache()
end
def fetch_omni_bridge_market_cap do
if bridges_table_exists?() do
do_fetch_omni_bridge_market_cap(:ets.lookup(@bridges_table, @current_market_cap_from_omni_bridge_cache_key))
else
Decimal.new(0)
end
end
defp do_fetch_omni_bridge_market_cap([{_, result}]), do: result
defp do_fetch_omni_bridge_market_cap([]) do
update_total_omni_bridge_market_cap_cache()
end
defp update_total_supply_from_token_bridge_cache do
if bridges_table_exists?() do
current_total_supply_from_token_bridge = TokenBridge.get_current_total_supply_from_token_bridge()
:ets.insert(
@bridges_table,
{@current_total_supply_from_token_bridge_cache_key, current_total_supply_from_token_bridge}
)
current_total_supply_from_token_bridge
else
0
end
end
defp update_total_omni_bridge_market_cap_cache do
if bridges_table_exists?() do
current_total_supply_from_omni_bridge = TokenBridge.get_current_market_cap_from_omni_bridge()
:ets.insert(
@bridges_table,
{@current_market_cap_from_omni_bridge_cache_key, current_total_supply_from_omni_bridge}
)
current_total_supply_from_omni_bridge
else
0
end
end
@doc """
Consolidates the info by populating the `:ets` table with the current database information.
"""
def consolidate do
bridged_mainnet_tokens_list = TokenBridge.get_bridged_mainnet_tokens_list()
bridged_mainnet_tokens_list
|> Enum.each(fn {bridged_token_hash, _bridged_token_symbol, _custom_cap, foreign_token_contract_address_hash} ->
bridged_token_price =
TokenBridge.get_current_price_for_bridged_token(bridged_token_hash, foreign_token_contract_address_hash)
cache_key = TokenExchangeRate.cache_key(foreign_token_contract_address_hash)
TokenExchangeRate.put_into_cache(cache_key, bridged_token_price)
end)
update_total_supply_from_token_bridge_cache()
update_total_omni_bridge_market_cap_cache()
end
@doc """
Returns a boolean that indicates whether consolidation is enabled
In order to choose whether or not to enable the scheduler and the initial
consolidation, change the following Explorer config:
`config :explorer, Explorer.Counters.Bridge, enable_consolidation: true`
to:
`config :explorer, Explorer.Counters.Bridge, enable_consolidation: false`
"""
def enable_consolidation?, do: @enable_consolidation
end

@ -88,11 +88,7 @@ defmodule Explorer.ExchangeRates.Source do
@spec exchange_rates_source() :: module()
defp exchange_rates_source do
if config(:source) == Explorer.ExchangeRates.Source.TokenBridge do
Explorer.ExchangeRates.Source.CoinGecko
else
config(:source) || Explorer.ExchangeRates.Source.CoinGecko
end
config(:source) || Explorer.ExchangeRates.Source.CoinGecko
end
@spec config(atom()) :: term

@ -109,7 +109,7 @@ defmodule Explorer.ExchangeRates.Source.CoinGecko do
end
def coin_id(symbol) do
id_mapping = bridged_token_symbol_to_id_mapping_to_get_price(symbol)
id_mapping = token_symbol_to_id_mapping_to_get_price(symbol)
if id_mapping do
{:ok, id_mapping}
@ -216,7 +216,7 @@ defmodule Explorer.ExchangeRates.Source.CoinGecko do
Application.get_env(:explorer, __MODULE__, [])[key]
end
defp bridged_token_symbol_to_id_mapping_to_get_price(symbol) do
defp token_symbol_to_id_mapping_to_get_price(symbol) do
case symbol do
"UNI" -> "uniswap"
"SURF" -> "surf-finance"

@ -1,71 +0,0 @@
defmodule Explorer.ExchangeRates.Source.TokenBridge do
@moduledoc """
Adapter for calculating the market cap and total supply from token bridge
while still getting other info like price in dollars and bitcoin from a secondary source
"""
alias Explorer.Chain
alias Explorer.ExchangeRates.{Source, Token}
import Source, only: [to_decimal: 1]
@behaviour Source
@impl Source
def format_data(data) do
data = secondary_source().format_data(data)
token_data =
data
|> Enum.find(fn token -> token.symbol == Explorer.coin() end)
|> build_struct
[token_data]
end
@impl Source
def source_url do
secondary_source().source_url()
end
@impl Source
def source_url(_), do: :ignore
@impl Source
def headers do
[]
end
defp build_struct(original_token) do
%Token{
available_supply: to_decimal(Chain.circulating_supply()),
total_supply: 0,
btc_value: original_token.btc_value,
id: original_token.id,
last_updated: original_token.last_updated,
market_cap_usd: market_cap_usd(Chain.circulating_supply(), original_token),
name: original_token.name,
symbol: original_token.symbol,
usd_value: original_token.usd_value,
volume_24h_usd: original_token.volume_24h_usd
}
end
defp market_cap_usd(nil, _original_token), do: Decimal.new(0)
defp market_cap_usd(supply, original_token) do
supply
|> to_decimal()
|> Decimal.mult(original_token.usd_value)
end
@spec secondary_source() :: module()
defp secondary_source do
config(:secondary_source) || Explorer.ExchangeRates.Source.CoinGecko
end
@spec config(atom()) :: term
defp config(key) do
Application.get_env(:explorer, __MODULE__, [])[key]
end
end

@ -4,8 +4,7 @@ defmodule Explorer.Market do
"""
alias Explorer.Chain.Address.CurrentTokenBalance
alias Explorer.Chain.{BridgedToken, Hash}
alias Explorer.Chain.Supply.TokenBridge
alias Explorer.Chain.Hash
alias Explorer.ExchangeRates.Token
alias Explorer.Market.{MarketHistory, MarketHistoryCache}
alias Explorer.{ExchangeRates, KnownTokens, Repo}
@ -58,18 +57,10 @@ defmodule Explorer.Market do
matches_known_address = known_address && known_address == token.contract_address_hash
usd_value =
cond do
matches_known_address ->
fetch_token_usd_value(matches_known_address, symbol)
bridged_token = mainnet_bridged_token?(token) ->
TokenBridge.get_current_price_for_bridged_token(
token.contract_address_hash,
bridged_token.foreign_token_contract_address_hash
)
true ->
nil
if matches_known_address do
fetch_token_usd_value(matches_known_address, symbol)
else
nil
end
Map.put(token, :usd_value, usd_value)
@ -84,8 +75,8 @@ defmodule Explorer.Market do
def add_price(tokens) when is_list(tokens) do
Enum.map(tokens, fn item ->
case item do
{token_balance, bridged_token, token} ->
{add_price(token_balance), bridged_token, token}
{token_balance, token} ->
{add_price(token_balance), token}
token_balance ->
add_price(token_balance)
@ -93,26 +84,6 @@ defmodule Explorer.Market do
end)
end
defp mainnet_bridged_token?(token) do
bridged_prop = Map.get(token, :bridged) || nil
if bridged_prop do
bridged_token = Repo.get_by(BridgedToken, home_token_contract_address_hash: token.contract_address_hash)
if bridged_token do
if bridged_token.foreign_chain_id do
if Decimal.compare(bridged_token.foreign_chain_id, Decimal.new(1)) == :eq, do: bridged_token, else: false
else
false
end
else
false
end
else
false
end
end
defp fetch_token_usd_value(true, symbol) do
case get_exchange_rate(symbol) do
%{usd_value: usd_value} -> usd_value

@ -0,0 +1,11 @@
defmodule Explorer.Repo.Migrations.RemoveBridgedTokens do
use Ecto.Migration
def change do
drop_if_exists(table(:bridged_tokens))
alter table(:tokens) do
remove(:bridged)
end
end
end

@ -157,7 +157,7 @@ defmodule Explorer.Chain.Address.CurrentTokenBalanceTest do
address.hash
|> CurrentTokenBalance.last_token_balances()
|> Repo.all()
|> Enum.map(fn {token_balance, _, _} -> token_balance.address_hash end)
|> Enum.map(fn {token_balance, _} -> token_balance.address_hash end)
assert token_balances == [current_token_balance.address_hash]
end
@ -195,7 +195,7 @@ defmodule Explorer.Chain.Address.CurrentTokenBalanceTest do
address.hash
|> CurrentTokenBalance.last_token_balances()
|> Repo.all()
|> Enum.map(fn {token_balance, _, _} -> token_balance.address_hash end)
|> Enum.map(fn {token_balance, _} -> token_balance.address_hash end)
assert token_balances == [current_token_balance_a.address_hash]
end

@ -1,67 +0,0 @@
defmodule Explorer.Chain.Supply.TokenBridgeTest do
use EthereumJSONRPC.Case, async: false
import Mox
# alias Explorer.Chain.Supply.TokenBridge
@moduletag :capture_log
setup :set_mox_global
setup :verify_on_exit!
describe "total_coins/1" do
@tag :no_parity
@tag :no_geth
# Flaky test
# test "calculates total coins", %{json_rpc_named_arguments: json_rpc_named_arguments} do
# if json_rpc_named_arguments[:transport] == EthereumJSONRPC.Mox do
# EthereumJSONRPC.Mox
# |> expect(:json_rpc, fn [
# %{
# id: id,
# method: "eth_call",
# params: [
# %{data: "0x553a5c85", to: "0x867305d19606aadba405ce534e303d0e225f9556"},
# "latest"
# ]
# }
# ],
# _options ->
# {:ok,
# [
# %{
# id: id,
# jsonrpc: "2.0",
# result: "0x00000000000000000000000000000000000000000000042aa8fe57ebb112dcc8"
# }
# ]}
# end)
# |> expect(:json_rpc, fn [
# %{
# id: id,
# jsonrpc: "2.0",
# method: "eth_call",
# params: [
# %{data: "0x0e8162ba", to: "0x7301CFA0e1756B71869E93d4e4Dca5c7d0eb0AA6"},
# "latest"
# ]
# }
# ],
# _options ->
# {:ok,
# [
# %{
# id: id,
# jsonrpc: "2.0",
# result: "0x00000000000000000000000000000000000000000000033cc192839185166fc6"
# }
# ]}
# end)
# end
# assert Decimal.round(TokenBridge.total_coins(), 2, :down) == Decimal.from_float(4388.55)
# end
end
end

@ -5014,7 +5014,7 @@ defmodule Explorer.ChainTest do
token_balances =
address.hash
|> Chain.fetch_last_token_balances()
|> Enum.map(fn {token_balance, _, _} -> token_balance.address_hash end)
|> Enum.map(fn {token_balance, _} -> token_balance.address_hash end)
assert token_balances == [current_token_balance.address_hash]
end

@ -1,45 +0,0 @@
defmodule Explorer.ExchangeRates.Source.TokenBridgeTest do
use Explorer.DataCase
alias Explorer.ExchangeRates
alias Explorer.ExchangeRates.Source.CoinGecko
alias Explorer.ExchangeRates.Source.TokenBridge
alias Explorer.ExchangeRates.Token
alias Plug.Conn
@json "#{File.cwd!()}/test/support/fixture/exchange_rates/coin_gecko.json"
|> File.read!()
|> Jason.decode!()
@json_btc_price """
{
"rates": {
"usd": {
"name": "US Dollar",
"unit": "$",
"value": 6547.418,
"type": "fiat"
}
}
}
"""
describe "format_data/1" do
setup do
bypass = Bypass.open()
envs = Application.get_env(:explorer, ExchangeRates)
Application.put_env(:explorer, ExchangeRates, Keyword.put(envs, :source, "coin_gecko"))
Application.put_env(:explorer, CoinGecko, base_url: "http://localhost:#{bypass.port}")
{:ok, bypass: bypass}
end
test "bring a list with one %Token{}", %{bypass: bypass} do
Bypass.expect(bypass, "GET", "/exchange_rates", fn conn ->
Conn.resp(conn, 200, @json_btc_price)
end)
assert [%Token{}] = TokenBridge.format_data(@json)
end
end
end

@ -1,52 +0,0 @@
defmodule Indexer.CalcLpTokensTotalLiqudity do
@moduledoc """
Peiodically updates LP tokens total liquidity
"""
use GenServer
require Logger
alias Explorer.Chain
@interval :timer.minutes(20)
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
interval = opts[:interval] || @interval
Process.send_after(self(), :calc_total_liqudity, interval)
{:ok, %{interval: interval}}
end
@impl GenServer
def handle_info(:calc_total_liqudity, %{interval: interval} = state) do
Logger.debug(fn -> "Calc LP tokens total liquidity" end)
calc_total_liqudity()
Process.send_after(self(), :calc_total_liqudity, interval)
{:noreply, state}
end
# don't handle other messages (e.g. :ssl_closed)
def handle_info(_, state) do
{:noreply, state}
end
defp calc_total_liqudity do
Chain.calc_lp_tokens_total_liqudity()
Logger.debug(fn -> "Total liqudity fetched for LP tokens" end)
end
end

@ -35,7 +35,7 @@ defmodule Indexer.Fetcher.TokenBalanceOnDemand do
when not is_nil(address_hash) do
stale_current_token_balances =
current_token_balances
|> Enum.filter(fn {current_token_balance, _, _} -> current_token_balance.block_number < stale_balance_window end)
|> Enum.filter(fn {current_token_balance, _} -> current_token_balance.block_number < stale_balance_window end)
if Enum.count(stale_current_token_balances) > 0 do
fetch_and_update(latest_block_number, address_hash, stale_current_token_balances)
@ -49,7 +49,7 @@ defmodule Indexer.Fetcher.TokenBalanceOnDemand do
defp fetch_and_update(block_number, address_hash, stale_current_token_balances) do
current_token_balances_update_params =
stale_current_token_balances
|> Enum.map(fn {stale_current_token_balance, _, token} ->
|> Enum.map(fn {stale_current_token_balance, token} ->
stale_current_token_balances_to_fetch = [
%{
token_contract_address_hash: "0x" <> Base.encode16(token.contract_address_hash.bytes),

@ -1,44 +0,0 @@
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
# don't handle other messages (e.g. :ssl_closed)
def handle_info(_, state) do
{: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

@ -1,54 +0,0 @@
defmodule Indexer.SetOmniBridgedMetadataForTokens do
@moduledoc """
Peiodically checks unprocessed tokens and sets bridged status.
"""
use GenServer
require Logger
alias Explorer.Chain
@interval :timer.minutes(10)
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
interval = opts[:interval] || @interval
Process.send_after(self(), :reveal_unprocessed_tokens, interval)
{:ok, %{interval: interval}}
end
@impl GenServer
def handle_info(:reveal_unprocessed_tokens, %{interval: interval} = state) do
Logger.debug(fn -> "Reveal unprocessed tokens" end)
{:ok, token_addresses} = Chain.unprocessed_token_addresses_to_reveal_bridged_tokens()
fetch_omni_bridged_tokens_metadata(token_addresses)
Process.send_after(self(), :reveal_unprocessed_tokens, interval)
{:noreply, state}
end
# don't handle other messages (e.g. :ssl_closed)
def handle_info(_, state) do
{:noreply, state}
end
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
end

@ -5,15 +5,10 @@ defmodule Indexer.Supervisor do
use Supervisor
alias Explorer.Chain
alias Indexer.{
Block,
CalcLpTokensTotalLiqudity,
PendingOpsCleaner,
PendingTransactionsSanitizer,
SetAmbBridgedMetadataForTokens,
SetOmniBridgedMetadataForTokens
PendingTransactionsSanitizer
}
alias Indexer.Block.{Catchup, Realtime}
@ -140,25 +135,8 @@ defmodule Indexer.Supervisor do
{PendingOpsCleaner, [[], []]}
]
extended_fetchers =
if Chain.bridged_tokens_enabled?() do
fetchers_with_omni_status = [{SetOmniBridgedMetadataForTokens, [[], []]} | basic_fetchers]
[{CalcLpTokensTotalLiqudity, [[], []]} | fetchers_with_omni_status]
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,
basic_fetchers,
strategy: :one_for_one
)
end

@ -63,7 +63,7 @@ CACHE_TOKEN_TRANSFERS_COUNTER_PERIOD=3600
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL=1800
CACHE_AVERAGE_BLOCK_PERIOD=1800
CACHE_MARKET_HISTORY_PERIOD=21600
CACHE_ADDRESS_TRANSACTIONS_PERIOD=1800
CACHE_ADDRESS_TRANSACTIONS_COUNTER_PERIOD=1800
CACHE_ADDRESS_TOKENS_USD_SUM_PERIOD=1800
CACHE_ADDRESS_TOKEN_TRANSFERS_COUNTER_PERIOD=1800
CACHE_BRIDGE_MARKET_CAP_UPDATE_INTERVAL=1800
@ -94,14 +94,9 @@ TXS_STATS_DAYS_TO_COMPILE_AT_INIT=10
COIN_BALANCE_HISTORY_DAYS=90
APPS_MENU=true
EXTERNAL_APPS=[]
# ETH_OMNI_BRIDGE_MEDIATOR=
# BSC_OMNI_BRIDGE_MEDIATOR=
# AMB_BRIDGE_MEDIATORS=
# GAS_PRICE=
# FOREIGN_JSON_RPC=
# RESTRICTED_LIST=
# RESTRICTED_LIST_KEY=
DISABLE_BRIDGE_MARKET_CAP_UPDATER=true
SHOW_MAINTENANCE_ALERT=false
MAINTENANCE_ALERT_MESSAGE=
CUSTOM_CONTRACT_ADDRESSES_TEST_TOKEN=

@ -256,15 +256,6 @@ endif
ifdef WOBSERVER_ENABLED
BLOCKSCOUT_CONTAINER_PARAMS += -e 'WOBSERVER_ENABLED=$(WOBSERVER_ENABLED)'
endif
ifdef OMNI_BRIDGE_MEDIATOR
BLOCKSCOUT_CONTAINER_PARAMS += -e 'OMNI_BRIDGE_MEDIATOR=$(OMNI_BRIDGE_MEDIATOR)'
endif
ifdef AMB_BRIDGE_MEDIATORS
BLOCKSCOUT_CONTAINER_PARAMS += -e 'AMB_BRIDGE_MEDIATORS=$(AMB_BRIDGE_MEDIATORS)'
endif
ifdef FOREIGN_JSON_RPC
BLOCKSCOUT_CONTAINER_PARAMS += -e 'FOREIGN_JSON_RPC=$(FOREIGN_JSON_RPC)'
endif
ifdef CACHE_BRIDGE_MARKET_CAP_UPDATE_INTERVAL
BLOCKSCOUT_CONTAINER_PARAMS += -e 'CACHE_BRIDGE_MARKET_CAP_UPDATE_INTERVAL=$(CACHE_BRIDGE_MARKET_CAP_UPDATE_INTERVAL)'
endif
@ -274,11 +265,8 @@ endif
ifdef RESTRICTED_LIST_KEY
BLOCKSCOUT_CONTAINER_PARAMS += -e 'RESTRICTED_LIST_KEY=$(RESTRICTED_LIST_KEY)'
endif
ifdef CACHE_ADDRESS_TRANSACTIONS_PERIOD
BLOCKSCOUT_CONTAINER_PARAMS += -e 'CACHE_ADDRESS_TRANSACTIONS_PERIOD=$(CACHE_ADDRESS_TRANSACTIONS_PERIOD)'
endif
ifdef DISABLE_BRIDGE_MARKET_CAP_UPDATER
BLOCKSCOUT_CONTAINER_PARAMS += -e 'DISABLE_BRIDGE_MARKET_CAP_UPDATER=$(DISABLE_BRIDGE_MARKET_CAP_UPDATER)'
ifdef CACHE_ADDRESS_TRANSACTIONS_COUNTER_PERIOD
BLOCKSCOUT_CONTAINER_PARAMS += -e 'CACHE_ADDRESS_TRANSACTIONS_COUNTER_PERIOD=$(CACHE_ADDRESS_TRANSACTIONS_COUNTER_PERIOD)'
endif
ifdef CACHE_ADDRESS_TRANSACTIONS_GAS_USAGE_COUNTER_PERIOD
BLOCKSCOUT_CONTAINER_PARAMS += -e 'CACHE_ADDRESS_TRANSACTIONS_GAS_USAGE_COUNTER_PERIOD=$(CACHE_ADDRESS_TRANSACTIONS_GAS_USAGE_COUNTER_PERIOD)'

Loading…
Cancel
Save