From a8d1eaa98322900e518d1232d9fabdfd893598c3 Mon Sep 17 00:00:00 2001 From: Qwerty5Uiop Date: Thu, 6 Jul 2023 13:20:27 +0400 Subject: [PATCH] Add TokenTotalSupplyUpdater --- CHANGELOG.md | 1 + .../fetcher/token_total_supply_updater.ex | 69 +++++++++++++++++++ apps/indexer/lib/indexer/supervisor.ex | 2 + .../lib/indexer/transform/token_transfers.ex | 27 +------- 4 files changed, 74 insertions(+), 25 deletions(-) create mode 100644 apps/indexer/lib/indexer/fetcher/token_total_supply_updater.ex diff --git a/CHANGELOG.md b/CHANGELOG.md index fca657601e..9d23abb6f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - [#7784](https://github.com/blockscout/blockscout/pull/7784) - Search improvements: Add new fields, light refactoring - [#7811](https://github.com/blockscout/blockscout/pull/7811) - Filter addresses before insertion - [#7895](https://github.com/blockscout/blockscout/pull/7895) - API v2: Add sorting to tokens page +- [#7859](https://github.com/blockscout/blockscout/pull/7859) - Add TokenTotalSupplyUpdater ### Fixes diff --git a/apps/indexer/lib/indexer/fetcher/token_total_supply_updater.ex b/apps/indexer/lib/indexer/fetcher/token_total_supply_updater.ex new file mode 100644 index 0000000000..407e7407d7 --- /dev/null +++ b/apps/indexer/lib/indexer/fetcher/token_total_supply_updater.ex @@ -0,0 +1,69 @@ +defmodule Indexer.Fetcher.TokenTotalSupplyUpdater do + @moduledoc """ + Periodically updates tokens total_supply + """ + + use GenServer + + alias Explorer.{Chain, Repo} + alias Explorer.Chain.Token + alias Explorer.Counters.AverageBlockTime + alias Explorer.Token.MetadataRetriever + alias Timex.Duration + + @default_update_interval :timer.seconds(10) + + def start_link(_) do + GenServer.start_link(__MODULE__, :ok, name: __MODULE__) + end + + def init(_) do + schedule_next_update() + + {:ok, []} + end + + def add_tokens(contract_address_hashes) do + GenServer.cast(__MODULE__, {:add_tokens, contract_address_hashes}) + end + + def handle_cast({:add_tokens, contract_address_hashes}, state) do + {:noreply, Enum.uniq(List.wrap(contract_address_hashes) ++ state)} + end + + def handle_info(:update, contract_address_hashes) do + Enum.each(contract_address_hashes, &update_token/1) + + schedule_next_update() + + {:noreply, []} + end + + defp schedule_next_update do + update_interval = + case AverageBlockTime.average_block_time() do + {:error, :disabled} -> @default_update_interval + block_time -> round(Duration.to_milliseconds(block_time)) + end + + Process.send_after(self(), :update, update_interval) + end + + defp update_token(nil), do: :ok + + defp update_token(address_hash_string) do + {:ok, address_hash} = Chain.string_to_address_hash(address_hash_string) + + token = Repo.get_by(Token, contract_address_hash: address_hash) + + if token && !token.skip_metadata do + token_params = MetadataRetriever.get_total_supply_of(address_hash_string) + + if token_params !== %{} do + {:ok, _} = Chain.update_token(token, token_params) + end + end + + :ok + end +end diff --git a/apps/indexer/lib/indexer/supervisor.ex b/apps/indexer/lib/indexer/supervisor.ex index 38b2e39f6d..249dc7a3f5 100644 --- a/apps/indexer/lib/indexer/supervisor.ex +++ b/apps/indexer/lib/indexer/supervisor.ex @@ -28,6 +28,7 @@ defmodule Indexer.Supervisor do ReplacedTransaction, Token, TokenBalance, + TokenTotalSupplyUpdater, TokenUpdater, TransactionAction, UncleBlock, @@ -125,6 +126,7 @@ defmodule Indexer.Supervisor do # Out-of-band fetchers {EmptyBlocksSanitizer.Supervisor, [[json_rpc_named_arguments: json_rpc_named_arguments]]}, {PendingTransactionsSanitizer, [[json_rpc_named_arguments: json_rpc_named_arguments]]}, + {TokenTotalSupplyUpdater, [[]]}, # Temporary workers {UncatalogedTokenTransfers.Supervisor, [[]]}, diff --git a/apps/indexer/lib/indexer/transform/token_transfers.ex b/apps/indexer/lib/indexer/transform/token_transfers.ex index 6ea41b6500..3292cd2935 100644 --- a/apps/indexer/lib/indexer/transform/token_transfers.ex +++ b/apps/indexer/lib/indexer/transform/token_transfers.ex @@ -9,6 +9,7 @@ defmodule Indexer.Transform.TokenTransfers do alias Explorer.{Chain, Repo} alias Explorer.Chain.{Token, TokenTransfer} alias Explorer.Token.MetadataRetriever + alias Indexer.Fetcher.TokenTotalSupplyUpdater @burn_address "0x0000000000000000000000000000000000000000" @@ -57,7 +58,7 @@ defmodule Indexer.Transform.TokenTransfers do token_transfer.token_contract_address_hash end) |> Enum.uniq() - |> Enum.each(&update_token/1) + |> TokenTotalSupplyUpdater.add_tokens() tokens_uniq = tokens |> Enum.uniq() @@ -260,30 +261,6 @@ defmodule Indexer.Transform.TokenTransfers do {token, token_transfer} end - defp update_token(nil), do: :ok - - defp update_token(address_hash_string) do - {:ok, address_hash} = Chain.string_to_address_hash(address_hash_string) - - token = Repo.get_by(Token, contract_address_hash: address_hash) - - if token && !token.skip_metadata do - token_params = - address_hash_string - |> MetadataRetriever.get_total_supply_of() - - token_to_update = - token - |> Repo.preload([:contract_address]) - - if token_params !== %{} do - {:ok, _} = Chain.update_token(token_to_update, token_params) - end - end - - :ok - end - def parse_erc1155_params( %{ first_topic: unquote(TokenTransfer.erc1155_batch_transfer_signature()),