Use address_current_token_balances in address tokens tab

pull/1226/head
fvictorio 6 years ago
parent 7a3dce7c8d
commit cd51e7cb29
  1. 2
      apps/block_scout_web/lib/block_scout_web/templates/address_token/_tokens.html.eex
  2. 4
      apps/block_scout_web/lib/block_scout_web/views/address_token_view.ex
  3. 19
      apps/block_scout_web/test/block_scout_web/controllers/address_token_controller_test.exs
  4. 2
      apps/block_scout_web/test/block_scout_web/features/viewing_addresses_test.exs
  5. 25
      apps/block_scout_web/test/block_scout_web/views/address_token_view_test.exs
  6. 30
      apps/explorer/lib/explorer/chain/address/token.ex
  7. 10
      apps/explorer/lib/explorer/chain/token.ex
  8. 73
      apps/explorer/test/explorer/chain/address/token_test.exs

@ -8,7 +8,7 @@
) do %> ) do %>
<%= token_name(@token) %> <%= token_name(@token) %>
<% end %> <% end %>
<span><%= @token.type %> - <%= number_of_transfers(@token) %></span> <span><%= @token.type %> - <%= @token.contract_address_hash %></span>
</div> </div>
<div class="col-md-5 d-flex flex-column text-md-right mt-3 mt-md-0"> <div class="col-md-5 d-flex flex-column text-md-right mt-3 mt-md-0">
<span class="tile-title-lg text-md-right align-bottom"> <span class="tile-title-lg text-md-right align-bottom">

@ -1,7 +1,3 @@
defmodule BlockScoutWeb.AddressTokenView do defmodule BlockScoutWeb.AddressTokenView do
use BlockScoutWeb, :view use BlockScoutWeb, :view
def number_of_transfers(token) do
ngettext("%{count} transfer", "%{count} transfers", token.transfers_count)
end
end end

@ -33,14 +33,14 @@ defmodule BlockScoutWeb.AddressTokenControllerTest do
|> insert(name: "token2") |> insert(name: "token2")
insert( insert(
:token_balance, :address_current_token_balance,
address: address, address: address,
token_contract_address_hash: token1.contract_address_hash, token_contract_address_hash: token1.contract_address_hash,
value: 1000 value: 1000
) )
insert( insert(
:token_balance, :address_current_token_balance,
address: address, address: address,
token_contract_address_hash: token2.contract_address_hash, token_contract_address_hash: token2.contract_address_hash,
value: 0 value: 0
@ -82,13 +82,12 @@ defmodule BlockScoutWeb.AddressTokenControllerTest do
token = insert(:token, name: "A Token#{i}", type: "ERC-20") token = insert(:token, name: "A Token#{i}", type: "ERC-20")
insert( insert(
:token_balance, :address_current_token_balance,
token_contract_address_hash: token.contract_address_hash, token_contract_address_hash: token.contract_address_hash,
address: address, address: address,
value: 1000 value: 1000
) )
insert(:token_transfer, token_contract_address: token.contract_address, from_address: address)
acc ++ [token.name] acc ++ [token.name]
end) end)
|> Enum.sort() |> Enum.sort()
@ -96,21 +95,21 @@ defmodule BlockScoutWeb.AddressTokenControllerTest do
token = insert(:token, name: "Another Token", type: "ERC-721") token = insert(:token, name: "Another Token", type: "ERC-721")
insert( insert(
:token_balance, :address_current_token_balance,
token_contract_address_hash: token.contract_address_hash, token_contract_address_hash: token.contract_address_hash,
address: address, address: address,
value: 1000 value: 1000
) )
insert(:token_transfer, token: token, from_address: address) %Token{name: name, type: type, inserted_at: inserted_at} = token
%Token{name: name, type: type} = token
start_supervised!(BlockValidationCounter) start_supervised!(BlockValidationCounter)
conn = conn =
get(conn, address_token_path(BlockScoutWeb.Endpoint, :index, address.hash), %{ get(conn, address_token_path(BlockScoutWeb.Endpoint, :index, address.hash), %{
"name" => name, "token_name" => name,
"type" => type "token_type" => type,
"token_inserted_at" => inserted_at
}) })
actual_tokens = actual_tokens =
@ -128,7 +127,7 @@ defmodule BlockScoutWeb.AddressTokenControllerTest do
token = insert(:token, name: "A Token#{i}", type: "ERC-20") token = insert(:token, name: "A Token#{i}", type: "ERC-20")
insert( insert(
:token_balance, :address_current_token_balance,
token_contract_address_hash: token.contract_address_hash, token_contract_address_hash: token.contract_address_hash,
address: address, address: address,
value: 1000 value: 1000

@ -429,7 +429,7 @@ defmodule BlockScoutWeb.ViewingAddressesTest do
token_contract_address: contract_address token_contract_address: contract_address
) )
insert(:token_balance, address: lincoln, token_contract_address_hash: contract_address.hash) insert(:address_current_token_balance, address: lincoln, token_contract_address_hash: contract_address.hash)
start_supervised!(BlockValidationCounter) start_supervised!(BlockValidationCounter)
BlockValidationCounter.consolidate_blocks() BlockValidationCounter.consolidate_blocks()

@ -1,25 +0,0 @@
defmodule BlockScoutWeb.AddressTokenViewTest do
use BlockScoutWeb.ConnCase, async: true
alias BlockScoutWeb.AddressTokenView
describe "number_of_transfers/1" do
test "returns the singular form when there is only one transfer" do
token = %{transfers_count: 1}
assert AddressTokenView.number_of_transfers(token) == "1 transfer"
end
test "returns the plural form when there is more than one transfer" do
token = %{transfers_count: 2}
assert AddressTokenView.number_of_transfers(token) == "2 transfers"
end
test "returns the plural form when there are 0 transfers" do
token = %{transfers_count: 0}
assert AddressTokenView.number_of_transfers(token) == "0 transfers"
end
end
end

@ -16,9 +16,10 @@ defmodule Explorer.Chain.Address.Token do
import Ecto.Query import Ecto.Query
alias Explorer.{Chain, PagingOptions} alias Explorer.{Chain, PagingOptions}
alias Explorer.Chain.{Address, Address.TokenBalance, Hash} alias Explorer.Chain.{Address, Hash}
alias Explorer.Chain.Address.CurrentTokenBalance
@enforce_keys [:contract_address_hash, :inserted_at, :name, :symbol, :balance, :decimals, :type, :transfers_count] @enforce_keys [:contract_address_hash, :inserted_at, :name, :symbol, :balance, :decimals, :type]
defstruct @enforce_keys defstruct @enforce_keys
@default_paging_options %PagingOptions{page_size: 50} @default_paging_options %PagingOptions{page_size: 50}
@ -31,20 +32,18 @@ defmodule Explorer.Chain.Address.Token do
def list_address_tokens_with_balance(address_hash, options \\ []) do def list_address_tokens_with_balance(address_hash, options \\ []) do
paging_options = Keyword.get(options, :paging_options, @default_paging_options) paging_options = Keyword.get(options, :paging_options, @default_paging_options)
Chain.Token address_hash
|> Chain.Token.join_with_transfers() |> join_with_last_balance()
|> join_with_last_balance(address_hash) |> order_filter_and_group()
|> order_filter_and_group(address_hash)
|> page_tokens(paging_options) |> page_tokens(paging_options)
|> limit(^paging_options.page_size) |> limit(^paging_options.page_size)
end end
defp order_filter_and_group(query, address_hash) do defp order_filter_and_group(query) do
from( from(
[token, transfer, balance] in query, [token, balance] in query,
order_by: fragment("? DESC, LOWER(?) ASC NULLS LAST", token.type, token.name), order_by: fragment("? DESC, LOWER(?) ASC NULLS LAST", token.type, token.name),
where: where: balance.value > 0,
(transfer.to_address_hash == ^address_hash or transfer.from_address_hash == ^address_hash) and balance.value > 0,
group_by: [token.name, token.symbol, balance.value, token.type, token.contract_address_hash], group_by: [token.name, token.symbol, balance.value, token.type, token.contract_address_hash],
select: %Address.Token{ select: %Address.Token{
contract_address_hash: token.contract_address_hash, contract_address_hash: token.contract_address_hash,
@ -53,24 +52,21 @@ defmodule Explorer.Chain.Address.Token do
symbol: token.symbol, symbol: token.symbol,
balance: balance.value, balance: balance.value,
decimals: max(token.decimals), decimals: max(token.decimals),
type: token.type, type: token.type
transfers_count: count(token.contract_address_hash)
} }
) )
end end
defp join_with_last_balance(queryable, address_hash) do defp join_with_last_balance(address_hash) do
last_balance_query = last_balance_query =
from( from(
tb in TokenBalance, tb in CurrentTokenBalance,
where: tb.address_hash == ^address_hash, where: tb.address_hash == ^address_hash,
distinct: :token_contract_address_hash,
order_by: [desc: :block_number],
select: %{value: tb.value, token_contract_address_hash: tb.token_contract_address_hash} select: %{value: tb.value, token_contract_address_hash: tb.token_contract_address_hash}
) )
from( from(
t in queryable, t in Chain.Token,
join: tb in subquery(last_balance_query), join: tb in subquery(last_balance_query),
on: tb.token_contract_address_hash == t.contract_address_hash on: tb.token_contract_address_hash == t.contract_address_hash
) )

@ -22,7 +22,7 @@ defmodule Explorer.Chain.Token do
import Ecto.{Changeset, Query} import Ecto.{Changeset, Query}
alias Ecto.Changeset alias Ecto.Changeset
alias Explorer.Chain.{Address, Hash, Token, TokenTransfer} alias Explorer.Chain.{Address, Hash, Token}
@typedoc """ @typedoc """
* `:name` - Name of the token * `:name` - Name of the token
@ -87,14 +87,6 @@ defmodule Explorer.Chain.Token do
end end
end end
def join_with_transfers(queryable \\ Token) do
from(
t in queryable,
join: tt in TokenTransfer,
on: tt.token_contract_address_hash == t.contract_address_hash
)
end
@doc """ @doc """
Builds an `Ecto.Query` to fetch the cataloged tokens. Builds an `Ecto.Query` to fetch the cataloged tokens.

@ -16,26 +16,12 @@ defmodule Explorer.Chain.Address.TokenTest do
|> Repo.preload(:contract_address) |> Repo.preload(:contract_address)
insert( insert(
:token_balance, :address_current_token_balance,
address: address, address: address,
token_contract_address_hash: token.contract_address_hash, token_contract_address_hash: token.contract_address_hash,
value: 1000 value: 1000
) )
insert(
:token_transfer,
token_contract_address: token.contract_address,
from_address: address,
to_address: build(:address)
)
insert(
:token_transfer,
token_contract_address: token.contract_address,
from_address: build(:address),
to_address: address
)
fetched_token = fetched_token =
address.hash address.hash
|> Address.Token.list_address_tokens_with_balance() |> Address.Token.list_address_tokens_with_balance()
@ -49,8 +35,7 @@ defmodule Explorer.Chain.Address.TokenTest do
symbol: "TC", symbol: "TC",
balance: Decimal.new(1000), balance: Decimal.new(1000),
decimals: Decimal.new(0), decimals: Decimal.new(0),
type: "ERC-721", type: "ERC-721"
transfers_count: 2
} }
end end
@ -63,7 +48,7 @@ defmodule Explorer.Chain.Address.TokenTest do
|> Repo.preload(:contract_address) |> Repo.preload(:contract_address)
insert( insert(
:token_balance, :address_current_token_balance,
address: address, address: address,
token_contract_address_hash: token.contract_address_hash, token_contract_address_hash: token.contract_address_hash,
value: 1000 value: 1000
@ -82,7 +67,7 @@ defmodule Explorer.Chain.Address.TokenTest do
|> Repo.preload(:contract_address) |> Repo.preload(:contract_address)
insert( insert(
:token_balance, :address_current_token_balance,
address: address, address: address,
token_contract_address_hash: token2.contract_address_hash, token_contract_address_hash: token2.contract_address_hash,
value: 1000 value: 1000
@ -113,7 +98,7 @@ defmodule Explorer.Chain.Address.TokenTest do
|> Repo.preload(:contract_address) |> Repo.preload(:contract_address)
insert( insert(
:token_balance, :address_current_token_balance,
address: address, address: address,
token_contract_address_hash: token.contract_address_hash, token_contract_address_hash: token.contract_address_hash,
value: 1000 value: 1000
@ -132,7 +117,7 @@ defmodule Explorer.Chain.Address.TokenTest do
|> Repo.preload(:contract_address) |> Repo.preload(:contract_address)
insert( insert(
:token_balance, :address_current_token_balance,
address: address, address: address,
token_contract_address_hash: token2.contract_address_hash, token_contract_address_hash: token2.contract_address_hash,
value: 1000 value: 1000
@ -151,7 +136,7 @@ defmodule Explorer.Chain.Address.TokenTest do
|> Repo.preload(:contract_address) |> Repo.preload(:contract_address)
insert( insert(
:token_balance, :address_current_token_balance,
address: address, address: address,
token_contract_address_hash: token3.contract_address_hash, token_contract_address_hash: token3.contract_address_hash,
value: 1000 value: 1000
@ -182,7 +167,7 @@ defmodule Explorer.Chain.Address.TokenTest do
|> Repo.preload(:contract_address) |> Repo.preload(:contract_address)
insert( insert(
:token_balance, :address_current_token_balance,
address: address, address: address,
token_contract_address_hash: token.contract_address_hash, token_contract_address_hash: token.contract_address_hash,
value: 1000 value: 1000
@ -201,7 +186,7 @@ defmodule Explorer.Chain.Address.TokenTest do
|> Repo.preload(:contract_address) |> Repo.preload(:contract_address)
insert( insert(
:token_balance, :address_current_token_balance,
address: address, address: address,
token_contract_address_hash: token2.contract_address_hash, token_contract_address_hash: token2.contract_address_hash,
value: 1000 value: 1000
@ -220,7 +205,7 @@ defmodule Explorer.Chain.Address.TokenTest do
|> Repo.preload(:contract_address) |> Repo.preload(:contract_address)
insert( insert(
:token_balance, :address_current_token_balance,
address: address, address: address,
token_contract_address_hash: token3.contract_address_hash, token_contract_address_hash: token3.contract_address_hash,
value: 1000 value: 1000
@ -267,44 +252,6 @@ defmodule Explorer.Chain.Address.TokenTest do
assert fetched_token == nil assert fetched_token == nil
end end
test "brings the value of the last balance" do
address = insert(:address)
token =
:token
|> insert(name: "atoken", type: "ERC-721", decimals: 0, symbol: "AT")
|> Repo.preload(:contract_address)
insert(
:token_balance,
address: address,
token_contract_address_hash: token.contract_address_hash,
value: 1000
)
insert(
:token_balance,
address: address,
token_contract_address_hash: token.contract_address_hash,
value: 1234
)
insert(
:token_transfer,
token_contract_address: token.contract_address,
from_address: address,
to_address: build(:address)
)
fetched_token =
address.hash
|> Address.Token.list_address_tokens_with_balance()
|> Repo.all()
|> List.first()
assert fetched_token.balance == Decimal.new(1234)
end
test "ignores token if the last balance is zero" do test "ignores token if the last balance is zero" do
address = insert(:address) address = insert(:address)

Loading…
Cancel
Save