From 1831d86b808ebf17b906e333c47f7220f06bc5b0 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Mon, 16 Sep 2019 12:37:47 +0300 Subject: [PATCH] stream unfetched token instances --- apps/explorer/lib/explorer/chain.ex | 21 +++++++ .../20190905083522_create_token_instances.exs | 2 + apps/explorer/test/explorer/chain_test.exs | 55 +++++++++++++++++++ apps/explorer/test/support/factory.ex | 9 +++ 4 files changed, 87 insertions(+) diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 1433e4c1ce..8caaaf8018 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -2823,6 +2823,27 @@ defmodule Explorer.Chain do Repo.stream_reduce(query, initial, reducer) end + @spec stream_unfetched_token_instances( + initial :: accumulator, + reducer :: (entry :: map(), accumulator -> accumulator) + ) :: {:ok, accumulator} + when accumulator: term() + def stream_unfetched_token_instances(initial, reducer) when is_function(reducer, 2) do + query = + from( + token_transfer in TokenTransfer, + inner_join: token in Token, + on: token.contract_address_hash == token_transfer.token_contract_address_hash, + left_join: instance in Instance, + on: token_transfer.token_id == instance.token_id, + where: token.type == ^"ERC-721" and is_nil(instance.token_id), + distinct: token_transfer.token_id, + select: %{contract_address_hash: token_transfer.token_contract_address_hash, token_id: token_transfer.token_id} + ) + + Repo.stream_reduce(query, initial, reducer) + end + @doc """ Streams a list of token contract addresses that have been cataloged. """ diff --git a/apps/explorer/priv/repo/migrations/20190905083522_create_token_instances.exs b/apps/explorer/priv/repo/migrations/20190905083522_create_token_instances.exs index 271b921dbb..7ebf9c12e9 100644 --- a/apps/explorer/priv/repo/migrations/20190905083522_create_token_instances.exs +++ b/apps/explorer/priv/repo/migrations/20190905083522_create_token_instances.exs @@ -16,5 +16,7 @@ defmodule Explorer.Repo.Migrations.CreateTokenInstances do timestamps(null: false, type: :utc_datetime_usec) end + + create_if_not_exists(index(:token_instances, [:token_id])) end end diff --git a/apps/explorer/test/explorer/chain_test.exs b/apps/explorer/test/explorer/chain_test.exs index 9a665e7e7b..353622e515 100644 --- a/apps/explorer/test/explorer/chain_test.exs +++ b/apps/explorer/test/explorer/chain_test.exs @@ -3602,6 +3602,61 @@ defmodule Explorer.ChainTest do end end + describe "stream_unfetched_token_instances/2" do + test "reduces wuth given reducer and accumulator" do + token_contract_address = insert(:contract_address) + token = insert(:token, contract_address: token_contract_address, type: "ERC-721") + + transaction = + :transaction + |> insert() + |> with_block(insert(:block, number: 1)) + + token_transfer = + insert( + :token_transfer, + block_number: 1000, + to_address: build(:address), + transaction: transaction, + token_contract_address: token_contract_address, + token: token, + token_id: 11 + ) + + assert {:ok, [result]} = Chain.stream_unfetched_token_instances([], &[&1 | &2]) + assert result.token_id == token_transfer.token_id + assert result.contract_address_hash == token_transfer.token_contract_address_hash + end + + test "do not fetch records with token instances" do + token_contract_address = insert(:contract_address) + token = insert(:token, contract_address: token_contract_address, type: "ERC-721") + + transaction = + :transaction + |> insert() + |> with_block(insert(:block, number: 1)) + + token_transfer = + insert( + :token_transfer, + block_number: 1000, + to_address: build(:address), + transaction: transaction, + token_contract_address: token_contract_address, + token: token, + token_id: 11 + ) + + insert(:token_instance, + token_id: token_transfer.token_id, + token_contract_address_hash: token_transfer.token_contract_address_hash + ) + + assert {:ok, []} = Chain.stream_unfetched_token_instances([], &[&1 | &2]) + end + end + describe "search_token/1" do test "finds by part of the name" do token = insert(:token, name: "magic token", symbol: "MAGIC") diff --git a/apps/explorer/test/support/factory.ex b/apps/explorer/test/support/factory.ex index a6e07683a5..edad876a8b 100644 --- a/apps/explorer/test/support/factory.ex +++ b/apps/explorer/test/support/factory.ex @@ -26,6 +26,7 @@ defmodule Explorer.Factory do SmartContract, Token, TokenTransfer, + Token.Instance, Transaction, StakingPool, StakingPoolsDelegator @@ -542,6 +543,14 @@ defmodule Explorer.Factory do } end + def token_instance_factory do + %Instance{ + token_contract_address_hash: build(:address), + token_id: 5, + metadata: %{key: "value"} + } + end + def token_balance_factory do %TokenBalance{ address: build(:address),