Speedup token transfers list query

pull/3012/head
Victor Baranov 5 years ago
parent 2a48a45c2b
commit 21ca08b899
  1. 1
      CHANGELOG.md
  2. 65
      apps/explorer/lib/explorer/etherscan.ex

@ -5,6 +5,7 @@
- [#2834](https://github.com/poanetwork/blockscout/pull/2834) - always redirect to checksummed hash - [#2834](https://github.com/poanetwork/blockscout/pull/2834) - always redirect to checksummed hash
### Fixes ### Fixes
- [#3012](https://github.com/poanetwork/blockscout/pull/3012) - Speedup token transfers list query
- [#3009](https://github.com/poanetwork/blockscout/pull/3009) - Fix broken export to CSV - [#3009](https://github.com/poanetwork/blockscout/pull/3009) - Fix broken export to CSV
- [#3007](https://github.com/poanetwork/blockscout/pull/3007) - Fix copy UTF8 tx input action - [#3007](https://github.com/poanetwork/blockscout/pull/3007) - Fix copy UTF8 tx input action
- [#2996](https://github.com/poanetwork/blockscout/pull/2996) - Fix awesomplete lib loading in Firefox - [#2996](https://github.com/poanetwork/blockscout/pull/2996) - Fix awesomplete lib loading in Firefox

@ -3,7 +3,7 @@ defmodule Explorer.Etherscan do
The etherscan context. The etherscan context.
""" """
import Ecto.Query, only: [from: 2, where: 3, or_where: 3, union: 2] import Ecto.Query, only: [from: 2, where: 3, or_where: 3, union: 2, subquery: 1]
alias Explorer.Etherscan.Logs alias Explorer.Etherscan.Logs
alias Explorer.{Chain, Repo} alias Explorer.{Chain, Repo}
@ -374,6 +374,8 @@ defmodule Explorer.Etherscan do
end end
@token_transfer_fields ~w( @token_transfer_fields ~w(
block_number
block_hash
token_contract_address_hash token_contract_address_hash
transaction_hash transaction_hash
from_address_hash from_address_hash
@ -382,31 +384,17 @@ defmodule Explorer.Etherscan do
)a )a
defp list_token_transfers(address_hash, contract_address_hash, block_height, options) do defp list_token_transfers(address_hash, contract_address_hash, block_height, options) do
query = tt_query =
from( from(
t in Transaction, tt in TokenTransfer,
inner_join: tt in TokenTransfer,
on: tt.transaction_hash == t.hash and tt.block_number == t.block_number and tt.block_hash == t.block_hash,
inner_join: tkn in assoc(tt, :token), inner_join: tkn in assoc(tt, :token),
inner_join: b in assoc(t, :block),
where: tt.from_address_hash == ^address_hash, where: tt.from_address_hash == ^address_hash,
or_where: tt.to_address_hash == ^address_hash, or_where: tt.to_address_hash == ^address_hash,
order_by: [{^options.order_by_direction, t.block_number}], order_by: [{^options.order_by_direction, tt.block_number}, {^options.order_by_direction, tt.log_index}],
limit: ^options.page_size, limit: ^options.page_size,
offset: ^offset(options), offset: ^offset(options),
select: select:
merge(map(tt, ^@token_transfer_fields), %{ merge(map(tt, ^@token_transfer_fields), %{
transaction_nonce: t.nonce,
transaction_index: t.index,
transaction_gas: t.gas,
transaction_gas_price: t.gas_price,
transaction_gas_used: t.gas_used,
transaction_cumulative_gas_used: t.cumulative_gas_used,
transaction_input: t.input,
block_hash: b.hash,
block_number: b.number,
block_timestamp: b.timestamp,
confirmations: fragment("? - ?", ^block_height, t.block_number),
token_id: tt.token_id, token_id: tt.token_id,
token_name: tkn.name, token_name: tkn.name,
token_symbol: tkn.symbol, token_symbol: tkn.symbol,
@ -416,10 +404,45 @@ defmodule Explorer.Etherscan do
}) })
) )
query tt_specific_token_query =
tt_query
|> where_contract_address_match(contract_address_hash)
wrapped_query =
from(
tt in subquery(tt_specific_token_query),
inner_join: t in Transaction,
on: tt.transaction_hash == t.hash and tt.block_number == t.block_number and tt.block_hash == t.block_hash,
inner_join: b in assoc(t, :block),
select: %{
token_contract_address_hash: tt.token_contract_address_hash,
transaction_hash: tt.transaction_hash,
from_address_hash: tt.from_address_hash,
to_address_hash: tt.to_address_hash,
amount: tt.amount,
transaction_nonce: t.nonce,
transaction_index: t.index,
transaction_gas: t.gas,
transaction_gas_price: t.gas_price,
transaction_gas_used: t.gas_used,
transaction_cumulative_gas_used: t.cumulative_gas_used,
transaction_input: t.input,
block_hash: b.hash,
block_number: b.number,
block_timestamp: b.timestamp,
confirmations: fragment("? - ?", ^block_height, t.block_number),
token_id: tt.token_id,
token_name: tt.token_name,
token_symbol: tt.token_symbol,
token_decimals: tt.token_decimals,
token_type: tt.token_type,
token_log_index: tt.token_log_index
}
)
wrapped_query
|> where_start_block_match(options) |> where_start_block_match(options)
|> where_end_block_match(options) |> where_end_block_match(options)
|> where_contract_address_match(contract_address_hash)
|> Repo.all() |> Repo.all()
end end
@ -450,7 +473,7 @@ defmodule Explorer.Etherscan do
defp where_contract_address_match(query, nil), do: query defp where_contract_address_match(query, nil), do: query
defp where_contract_address_match(query, contract_address_hash) do defp where_contract_address_match(query, contract_address_hash) do
where(query, [_, tt], tt.token_contract_address_hash == ^contract_address_hash) where(query, [tt, _], tt.token_contract_address_hash == ^contract_address_hash)
end end
defp offset(options), do: (options.page_number - 1) * options.page_size defp offset(options), do: (options.page_number - 1) * options.page_size

Loading…
Cancel
Save