|
|
|
@ -8,7 +8,7 @@ defmodule Explorer.Chain.Address do |
|
|
|
|
use Explorer.Schema |
|
|
|
|
|
|
|
|
|
alias Ecto.Changeset |
|
|
|
|
alias Explorer.Chain |
|
|
|
|
alias Explorer.{Chain, PagingOptions} |
|
|
|
|
|
|
|
|
|
alias Explorer.Chain.{ |
|
|
|
|
Address, |
|
|
|
@ -25,7 +25,7 @@ defmodule Explorer.Chain.Address do |
|
|
|
|
Withdrawal |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
alias Explorer.Chain.Cache.NetVersion |
|
|
|
|
alias Explorer.Chain.Cache.{Accounts, NetVersion} |
|
|
|
|
|
|
|
|
|
@optional_attrs ~w(contract_code fetched_coin_balance fetched_coin_balance_block_number nonce decompiled verified gas_used transactions_count token_transfers_count)a |
|
|
|
|
@required_attrs ~w(hash)a |
|
|
|
@ -304,4 +304,68 @@ defmodule Explorer.Chain.Address do |
|
|
|
|
@for.checksum(address) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
@default_paging_options %PagingOptions{page_size: 50} |
|
|
|
|
@doc """ |
|
|
|
|
Lists the top `t:Explorer.Chain.Address.t/0`'s' in descending order based on coin balance and address hash. |
|
|
|
|
|
|
|
|
|
""" |
|
|
|
|
@spec list_top_addresses :: [{Address.t(), non_neg_integer()}] |
|
|
|
|
def list_top_addresses(options \\ []) do |
|
|
|
|
paging_options = Keyword.get(options, :paging_options, @default_paging_options) |
|
|
|
|
|
|
|
|
|
if is_nil(paging_options.key) do |
|
|
|
|
paging_options.page_size |
|
|
|
|
|> Accounts.take_enough() |
|
|
|
|
|> case do |
|
|
|
|
nil -> |
|
|
|
|
get_addresses(options) |
|
|
|
|
|
|
|
|
|
accounts -> |
|
|
|
|
Enum.map( |
|
|
|
|
accounts, |
|
|
|
|
&{&1, &1.transactions_count || 0} |
|
|
|
|
) |
|
|
|
|
end |
|
|
|
|
else |
|
|
|
|
fetch_top_addresses(options) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp get_addresses(options) do |
|
|
|
|
accounts_with_n = fetch_top_addresses(options) |
|
|
|
|
|
|
|
|
|
accounts_with_n |
|
|
|
|
|> Enum.map(fn {address, _n} -> address end) |
|
|
|
|
|> Accounts.update() |
|
|
|
|
|
|
|
|
|
accounts_with_n |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp fetch_top_addresses(options) do |
|
|
|
|
paging_options = Keyword.get(options, :paging_options, @default_paging_options) |
|
|
|
|
|
|
|
|
|
base_query = |
|
|
|
|
from(a in Address, |
|
|
|
|
where: a.fetched_coin_balance > ^0, |
|
|
|
|
order_by: [desc: a.fetched_coin_balance, asc: a.hash], |
|
|
|
|
preload: [:names, :smart_contract], |
|
|
|
|
select: {a, a.transactions_count} |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
base_query |
|
|
|
|
|> page_addresses(paging_options) |
|
|
|
|
|> limit(^paging_options.page_size) |
|
|
|
|
|> Chain.select_repo(options).all() |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp page_addresses(query, %PagingOptions{key: nil}), do: query |
|
|
|
|
|
|
|
|
|
defp page_addresses(query, %PagingOptions{key: {coin_balance, hash}}) do |
|
|
|
|
from(address in query, |
|
|
|
|
where: |
|
|
|
|
(address.fetched_coin_balance == ^coin_balance and address.hash > ^hash) or |
|
|
|
|
address.fetched_coin_balance < ^coin_balance |
|
|
|
|
) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|