Bridged tokens table

pull/3261/head
Victor Baranov 4 years ago
parent 2c83052850
commit 019916096d
  1. 1
      CHANGELOG.md
  2. 60
      apps/block_scout_web/lib/block_scout_web/controllers/tokens/bridged_tokens_controller.ex
  3. 36
      apps/block_scout_web/lib/block_scout_web/templates/bridged_tokens/_tile.html.eex
  4. 45
      apps/block_scout_web/lib/block_scout_web/templates/bridged_tokens/index.html.eex
  5. 39
      apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex
  6. 1
      apps/block_scout_web/lib/block_scout_web/templates/layout/app.html.eex
  7. 22
      apps/block_scout_web/lib/block_scout_web/views/bridged_tokens_view.ex
  8. 2
      apps/block_scout_web/lib/block_scout_web/web_router.ex
  9. 32
      apps/block_scout_web/priv/gettext/default.pot
  10. 32
      apps/block_scout_web/priv/gettext/en/LC_MESSAGES/default.po
  11. 22
      apps/explorer/lib/explorer/chain.ex

@ -1,6 +1,7 @@
## Current ## Current
### Features ### Features
- [#3261](https://github.com/poanetwork/blockscout/pull/3261) - Bridged tokens table
### Fixes ### Fixes
- [#3256](https://github.com/poanetwork/blockscout/pull/3256) - Fix for invisible validator address at block page and wrong alert text color at xDai - [#3256](https://github.com/poanetwork/blockscout/pull/3256) - Fix for invisible validator address at block page and wrong alert text color at xDai

@ -0,0 +1,60 @@
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
alias Explorer.Chain
alias Phoenix.View
def index(conn, %{"type" => "JSON"} = params) do
tokens =
params
|> paging_options()
|> Chain.list_top_bridged_tokens()
{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 ->
tokens_path(
conn,
:index,
Map.delete(next_page_params, "type")
)
end
items =
tokens_page
|> Enum.with_index(1)
|> Enum.map(fn {token, index} ->
View.render_to_string(
BridgedTokensView,
"_tile.html",
token: token,
index: index
)
end)
json(
conn,
%{
items: items,
next_page_path: next_page_path
}
)
end
def index(conn, _params) do
total_supply = Chain.total_supply()
render(conn, "index.html",
current_path: current_path(conn),
total_supply: total_supply
)
end
end

@ -0,0 +1,36 @@
<tr>
<td class="stakes-td">
<!-- incremented number by order in the list -->
<span class="color-lighten">
<%= @index %>
</span>
</td>
<td class="stakes-td">
<% token = token_display_name(@token) %>
<%= link(token,
to: token_path(BlockScoutWeb.Endpoint, :show, @token.contract_address_hash),
"data-test": "token_link",
class: "text-truncate") %>
</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">
<%= 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>
</td>
</tr>

@ -0,0 +1,45 @@
<section class="container">
<div class="card">
<div class="card-body" data-async-load data-async-listing="<%= @current_path %>">
<h1 class="card-title"><%= gettext "Bridged Tokens" %></h1>
<%= 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 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 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>
</tr>
</thead>
<tbody data-items data-selector="top-tokens-list">
<%= render BlockScoutWeb.CommonComponentsView, "_table-loader.html", total_supply: @total_supply %>
</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/async-listing-load.js") %>"></script>
</section>

@ -75,14 +75,37 @@
<%= gettext("Accounts") %> <%= gettext("Accounts") %>
<% end %> <% end %>
</li> </li>
<li class="nav-item"> <%= if Application.get_env(:block_scout_web, :multi_token_bridge_mediator) && Application.get_env(:block_scout_web, :multi_token_bridge_mediator) != "" do %>
<%= link to: tokens_path(@conn, :index), class: "nav-link topnav-nav-link #{tab_status("tokens", @conn.request_path)}" do %> <li class="nav-item dropdown">
<span class="nav-link-icon"> <a href="#" role="button" id="navbarTokensDropdown" class="nav-link topnav-nav-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<%= render BlockScoutWeb.IconsView, "_tokens_icon.html" %> <span class="nav-link-icon">
</span> <%= render BlockScoutWeb.IconsView, "_tokens_icon.html" %>
<%= gettext("Tokens") %> </span>
<% end %> <%= gettext("Tokens") %>
</li> </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"),
class: "dropdown-item #{tab_status("tokens", @conn.request_path)}",
to: bridged_tokens_path(@conn, :index)
) %>
</div>
</li>
<% else %>
<li class="nav-item">
<%= link to: tokens_path(@conn, :index), class: "nav-link topnav-nav-link #{tab_status("tokens", @conn.request_path)}" do %>
<span class="nav-link-icon">
<%= render BlockScoutWeb.IconsView, "_tokens_icon.html" %>
</span>
<%= gettext("Tokens") %>
<% end %>
</li>
<% end %>
<% end %> <% end %>
<%= if Application.get_env(:block_scout_web, BlockScoutWeb.ApiRouter)[:reading_enabled] || Application.get_env(:block_scout_web, :api_url) do %> <%= 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"> <li class="nav-item dropdown">

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

@ -0,0 +1,22 @@
defmodule BlockScoutWeb.BridgedTokensView do
use BlockScoutWeb, :view
alias Explorer.Chain.Token
def decimals?(%Token{decimals: nil}), do: false
def decimals?(%Token{decimals: _}), do: true
def token_display_name(%Token{name: nil, symbol: nil}), do: ""
def token_display_name(%Token{name: "", symbol: ""}), do: ""
def token_display_name(%Token{name: name, symbol: nil}), do: name
def token_display_name(%Token{name: name, symbol: ""}), do: name
def token_display_name(%Token{name: nil, symbol: symbol}), do: symbol
def token_display_name(%Token{name: "", symbol: symbol}), do: symbol
def token_display_name(%Token{name: name, symbol: symbol}), do: "#{name} (#{symbol})"
end

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

@ -107,7 +107,7 @@ msgid "API for the %{subnetwork} - BlockScout"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:93 #: lib/block_scout_web/templates/layout/_topnav.html.eex:116
msgid "APIs" msgid "APIs"
msgstr "" msgstr ""
@ -138,6 +138,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:25 #: lib/block_scout_web/templates/address_token_transfer/index.html.eex:25
#: lib/block_scout_web/templates/address_transaction/index.html.eex:23 #: lib/block_scout_web/templates/address_transaction/index.html.eex:23
#: lib/block_scout_web/templates/layout/_network_selector.html.eex:21 #: lib/block_scout_web/templates/layout/_network_selector.html.eex:21
#: lib/block_scout_web/templates/layout/_topnav.html.eex:88
#: lib/block_scout_web/views/address_internal_transaction_view.ex:8 #: lib/block_scout_web/views/address_internal_transaction_view.ex:8
#: lib/block_scout_web/views/address_token_transfer_view.ex:8 #: lib/block_scout_web/views/address_token_transfer_view.ex:8
#: lib/block_scout_web/views/address_transaction_view.ex:10 #: lib/block_scout_web/views/address_transaction_view.ex:10
@ -631,7 +632,7 @@ msgid "Error: Could not determine contract creator."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:107 #: lib/block_scout_web/templates/layout/_topnav.html.eex:130
msgid "Eth RPC" msgid "Eth RPC"
msgstr "" msgstr ""
@ -732,7 +733,7 @@ msgid "Github"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:97 #: lib/block_scout_web/templates/layout/_topnav.html.eex:120
msgid "GraphQL" msgid "GraphQL"
msgstr "" msgstr ""
@ -1186,7 +1187,7 @@ msgid "Query"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:102 #: lib/block_scout_web/templates/layout/_topnav.html.eex:125
msgid "RPC" msgid "RPC"
msgstr "" msgstr ""
@ -1244,13 +1245,13 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:14 #: lib/block_scout_web/templates/address_logs/index.html.eex:14
#: lib/block_scout_web/templates/layout/_topnav.html.eex:172 #: lib/block_scout_web/templates/layout/_topnav.html.eex:195
#: lib/block_scout_web/templates/layout/_topnav.html.eex:203 #: lib/block_scout_web/templates/layout/_topnav.html.eex:226
msgid "Search" msgid "Search"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:166 #: lib/block_scout_web/templates/layout/_topnav.html.eex:189
msgid "Search by address, token symbol name, transaction hash, or block number" msgid "Search by address, token symbol name, transaction hash, or block number"
msgstr "" msgstr ""
@ -1852,7 +1853,8 @@ msgstr ""
#: lib/block_scout_web/templates/address/_tabs.html.eex:17 #: lib/block_scout_web/templates/address/_tabs.html.eex:17
#: lib/block_scout_web/templates/address_token/index.html.eex:8 #: lib/block_scout_web/templates/address_token/index.html.eex:8
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:11 #: lib/block_scout_web/templates/address_token_transfer/index.html.eex:11
#: lib/block_scout_web/templates/layout/_topnav.html.eex:83 #: lib/block_scout_web/templates/layout/_topnav.html.eex:84
#: lib/block_scout_web/templates/layout/_topnav.html.eex:105
#: lib/block_scout_web/templates/tokens/index.html.eex:4 #: lib/block_scout_web/templates/tokens/index.html.eex:4
#: lib/block_scout_web/views/address_view.ex:343 #: lib/block_scout_web/views/address_view.ex:343
msgid "Tokens" msgid "Tokens"
@ -1934,7 +1936,7 @@ msgid "Write Proxy"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:120 #: lib/block_scout_web/templates/layout/_topnav.html.eex:143
msgid "Apps" msgid "Apps"
msgstr "" msgstr ""
@ -1944,7 +1946,7 @@ msgid "Copy Raw Trace"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:170 #: lib/block_scout_web/templates/layout/_topnav.html.eex:193
msgid "Search by address, token symbol, name, transaction hash, or block number" msgid "Search by address, token symbol, name, transaction hash, or block number"
msgstr "" msgstr ""
@ -1973,3 +1975,13 @@ msgstr ""
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:10 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:10
msgid "page" msgid "page"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:93
msgid "Bridged"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/bridged_tokens/index.html.eex:4
msgid "Bridged Tokens"
msgstr ""

@ -107,7 +107,7 @@ msgid "API for the %{subnetwork} - BlockScout"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:93 #: lib/block_scout_web/templates/layout/_topnav.html.eex:116
msgid "APIs" msgid "APIs"
msgstr "" msgstr ""
@ -138,6 +138,7 @@ msgstr ""
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:25 #: lib/block_scout_web/templates/address_token_transfer/index.html.eex:25
#: lib/block_scout_web/templates/address_transaction/index.html.eex:23 #: lib/block_scout_web/templates/address_transaction/index.html.eex:23
#: lib/block_scout_web/templates/layout/_network_selector.html.eex:21 #: lib/block_scout_web/templates/layout/_network_selector.html.eex:21
#: lib/block_scout_web/templates/layout/_topnav.html.eex:88
#: lib/block_scout_web/views/address_internal_transaction_view.ex:8 #: lib/block_scout_web/views/address_internal_transaction_view.ex:8
#: lib/block_scout_web/views/address_token_transfer_view.ex:8 #: lib/block_scout_web/views/address_token_transfer_view.ex:8
#: lib/block_scout_web/views/address_transaction_view.ex:10 #: lib/block_scout_web/views/address_transaction_view.ex:10
@ -631,7 +632,7 @@ msgid "Error: Could not determine contract creator."
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:107 #: lib/block_scout_web/templates/layout/_topnav.html.eex:130
msgid "Eth RPC" msgid "Eth RPC"
msgstr "" msgstr ""
@ -732,7 +733,7 @@ msgid "Github"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:97 #: lib/block_scout_web/templates/layout/_topnav.html.eex:120
msgid "GraphQL" msgid "GraphQL"
msgstr "" msgstr ""
@ -1186,7 +1187,7 @@ msgid "Query"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:102 #: lib/block_scout_web/templates/layout/_topnav.html.eex:125
msgid "RPC" msgid "RPC"
msgstr "" msgstr ""
@ -1244,13 +1245,13 @@ msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/address_logs/index.html.eex:14 #: lib/block_scout_web/templates/address_logs/index.html.eex:14
#: lib/block_scout_web/templates/layout/_topnav.html.eex:172 #: lib/block_scout_web/templates/layout/_topnav.html.eex:195
#: lib/block_scout_web/templates/layout/_topnav.html.eex:203 #: lib/block_scout_web/templates/layout/_topnav.html.eex:226
msgid "Search" msgid "Search"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:166 #: lib/block_scout_web/templates/layout/_topnav.html.eex:189
msgid "Search by address, token symbol name, transaction hash, or block number" msgid "Search by address, token symbol name, transaction hash, or block number"
msgstr "" msgstr ""
@ -1852,7 +1853,8 @@ msgstr ""
#: lib/block_scout_web/templates/address/_tabs.html.eex:17 #: lib/block_scout_web/templates/address/_tabs.html.eex:17
#: lib/block_scout_web/templates/address_token/index.html.eex:8 #: lib/block_scout_web/templates/address_token/index.html.eex:8
#: lib/block_scout_web/templates/address_token_transfer/index.html.eex:11 #: lib/block_scout_web/templates/address_token_transfer/index.html.eex:11
#: lib/block_scout_web/templates/layout/_topnav.html.eex:83 #: lib/block_scout_web/templates/layout/_topnav.html.eex:84
#: lib/block_scout_web/templates/layout/_topnav.html.eex:105
#: lib/block_scout_web/templates/tokens/index.html.eex:4 #: lib/block_scout_web/templates/tokens/index.html.eex:4
#: lib/block_scout_web/views/address_view.ex:343 #: lib/block_scout_web/views/address_view.ex:343
msgid "Tokens" msgid "Tokens"
@ -1934,7 +1936,7 @@ msgid "Write Proxy"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:120 #: lib/block_scout_web/templates/layout/_topnav.html.eex:143
msgid "Apps" msgid "Apps"
msgstr "" msgstr ""
@ -1944,7 +1946,7 @@ msgid "Copy Raw Trace"
msgstr "" msgstr ""
#, elixir-format #, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:170 #: lib/block_scout_web/templates/layout/_topnav.html.eex:193
msgid "Search by address, token symbol, name, transaction hash, or block number" msgid "Search by address, token symbol, name, transaction hash, or block number"
msgstr "" msgstr ""
@ -1973,3 +1975,13 @@ msgstr ""
#: lib/block_scout_web/templates/smart_contract/_functions.html.eex:10 #: lib/block_scout_web/templates/smart_contract/_functions.html.eex:10
msgid "page" msgid "page"
msgstr "" msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/layout/_topnav.html.eex:93
msgid "Bridged"
msgstr ""
#, elixir-format
#: lib/block_scout_web/templates/bridged_tokens/index.html.eex:4
msgid "Bridged Tokens"
msgstr ""

@ -1798,6 +1798,13 @@ defmodule Explorer.Chain do
fetch_top_tokens(paging_options) fetch_top_tokens(paging_options)
end end
@spec list_top_bridged_tokens :: [{Token.t(), non_neg_integer()}]
def list_top_bridged_tokens(options \\ []) do
paging_options = Keyword.get(options, :paging_options, @default_paging_options)
fetch_top_bridged_tokens(paging_options)
end
defp fetch_top_tokens(paging_options) do defp fetch_top_tokens(paging_options) do
base_query = base_query =
from(t in Token, from(t in Token,
@ -1812,6 +1819,21 @@ defmodule Explorer.Chain do
|> Repo.all() |> Repo.all()
end end
defp fetch_top_bridged_tokens(paging_options) do
base_query =
from(t in Token,
where: t.total_supply > ^0,
where: t.bridged,
order_by: [desc: t.holder_count, asc: t.name],
preload: [:contract_address]
)
base_query
|> page_tokens(paging_options)
|> limit(^paging_options.page_size)
|> Repo.all()
end
@doc """ @doc """
Calls `reducer` on a stream of `t:Explorer.Chain.Block.t/0` without `t:Explorer.Chain.Block.Reward.t/0`. Calls `reducer` on a stream of `t:Explorer.Chain.Block.t/0` without `t:Explorer.Chain.Block.Reward.t/0`.
""" """

Loading…
Cancel
Save