diff --git a/CHANGELOG.md b/CHANGELOG.md index e9dfddb009..2bec02ebbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Current ### Features +- [#3224](https://github.com/poanetwork/blockscout/pull/3224) - Top tokens page ### Fixes - [#3220](https://github.com/poanetwork/blockscout/pull/3220) - Allow interaction with navbar menu at block-not-found page diff --git a/apps/block_scout_web/assets/css/components/_navbar.scss b/apps/block_scout_web/assets/css/components/_navbar.scss index d97f0483d5..a9a1442166 100644 --- a/apps/block_scout_web/assets/css/components/_navbar.scss +++ b/apps/block_scout_web/assets/css/components/_navbar.scss @@ -155,7 +155,7 @@ $navbar-logo-width: auto !default; width: 340px; } @media (min-width: 1366px) { - width: 500px; + width: 380px; } @media (min-width: 1440px) { width: 580px; diff --git a/apps/block_scout_web/lib/block_scout_web/chain.ex b/apps/block_scout_web/lib/block_scout_web/chain.ex index 3aa660fbe4..23efee7c7a 100644 --- a/apps/block_scout_web/lib/block_scout_web/chain.ex +++ b/apps/block_scout_web/lib/block_scout_web/chain.ex @@ -24,6 +24,7 @@ defmodule BlockScoutWeb.Chain do Block, InternalTransaction, Log, + Token, TokenTransfer, Transaction, Wei @@ -107,6 +108,16 @@ defmodule BlockScoutWeb.Chain do end end + def paging_options(%{"contract_address_hash" => contract_address_hash, "holder_count" => holder_count}) do + with {holder_count, ""} <- Integer.parse(holder_count), + {:ok, contract_address_hash} <- string_to_address_hash(contract_address_hash) do + [paging_options: %{@default_paging_options | key: {holder_count, contract_address_hash}}] + else + _ -> + [paging_options: @default_paging_options] + end + end + def paging_options(%{ "block_number" => block_number_string, "transaction_index" => transaction_index_string, @@ -205,6 +216,10 @@ defmodule BlockScoutWeb.Chain do %{"hash" => hash, "fetched_coin_balance" => Decimal.to_string(fetched_coin_balance.value)} end + defp paging_params(%Token{contract_address_hash: contract_address_hash, holder_count: holder_count}) do + %{"contract_address_hash" => contract_address_hash, "holder_count" => holder_count} + end + defp paging_params({%Reward{block: %{number: number}}, _}) do %{"block_number" => number, "index" => 0} end diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/tokens_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/tokens_controller.ex new file mode 100644 index 0000000000..0a133d9f7f --- /dev/null +++ b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/tokens_controller.ex @@ -0,0 +1,60 @@ +defmodule BlockScoutWeb.TokensController do + use BlockScoutWeb, :controller + + import BlockScoutWeb.Chain, only: [paging_options: 1, next_page_params: 3, split_list_by_page: 1] + + alias BlockScoutWeb.TokensView + alias Explorer.Chain + alias Phoenix.View + + def index(conn, %{"type" => "JSON"} = params) do + tokens = + params + |> paging_options() + |> Chain.list_top_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( + TokensView, + "_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 diff --git a/apps/block_scout_web/lib/block_scout_web/templates/icons/_tokens_icon.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/icons/_tokens_icon.html.eex new file mode 100644 index 0000000000..6d808a1800 --- /dev/null +++ b/apps/block_scout_web/lib/block_scout_web/templates/icons/_tokens_icon.html.eex @@ -0,0 +1,4 @@ + + + + diff --git a/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex index 12575322f6..7698f84521 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex @@ -75,6 +75,14 @@ <%= gettext("Accounts") %> <% end %> + <% end %> <%= if Application.get_env(:block_scout_web, BlockScoutWeb.ApiRouter)[:reading_enabled] || Application.get_env(:block_scout_web, :api_url) do %>