Merge pull request #1095 from poanetwork/wsa-async-task-to-check-token-metadata
Async task to check token metadatapull/1126/head v1.2.0-beta
commit
c5fa7210b8
@ -0,0 +1,16 @@ |
||||
defmodule Explorer.Chain.TokenTest do |
||||
use Explorer.DataCase |
||||
|
||||
import Explorer.Factory |
||||
|
||||
alias Explorer.Chain |
||||
|
||||
describe "cataloged_tokens/0" do |
||||
test "filters only cataloged tokens" do |
||||
token = insert(:token, cataloged: true) |
||||
insert(:token, cataloged: false) |
||||
|
||||
assert Repo.all(Chain.Token.cataloged_tokens()) == [token.contract_address_hash] |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,51 @@ |
||||
defmodule Indexer.Token.MetadataUpdater do |
||||
@moduledoc """ |
||||
Updates metadata for cataloged tokens |
||||
""" |
||||
|
||||
use GenServer |
||||
|
||||
alias Explorer.Chain |
||||
alias Explorer.Chain.Token |
||||
alias Explorer.Token.MetadataRetriever |
||||
|
||||
def start_link(initial_state) do |
||||
GenServer.start_link(__MODULE__, initial_state, name: __MODULE__) |
||||
end |
||||
|
||||
@impl true |
||||
def init(state) do |
||||
send(self(), :update_tokens) |
||||
|
||||
{:ok, state} |
||||
end |
||||
|
||||
@impl true |
||||
def handle_info(:update_tokens, state) do |
||||
{:ok, tokens} = Chain.stream_cataloged_token_contract_address_hashes([], &[&1 | &2]) |
||||
|
||||
tokens |
||||
|> Enum.reverse() |
||||
|> update_metadata() |
||||
|
||||
Process.send_after(self(), :update_tokens, :timer.hours(state.update_interval) * 24) |
||||
|
||||
{:noreply, state} |
||||
end |
||||
|
||||
@doc false |
||||
def update_metadata(token_addresses) when is_list(token_addresses) do |
||||
Enum.each(token_addresses, fn address -> |
||||
case Chain.token_from_address_hash(address) do |
||||
{:ok, %Token{cataloged: true} = token} -> |
||||
update_metadata(token) |
||||
end |
||||
end) |
||||
end |
||||
|
||||
def update_metadata(%Token{contract_address_hash: contract_address_hash} = token) do |
||||
contract_functions = MetadataRetriever.get_functions_of(contract_address_hash) |
||||
|
||||
Chain.update_token(%{token | updated_at: DateTime.utc_now()}, contract_functions) |
||||
end |
||||
end |
@ -0,0 +1,107 @@ |
||||
defmodule Indexer.Token.MetadataUpdaterTest do |
||||
use Explorer.DataCase |
||||
|
||||
import Mox |
||||
|
||||
alias Explorer.Chain |
||||
alias Explorer.Chain.Token |
||||
alias Indexer.Token.MetadataUpdater |
||||
|
||||
setup :verify_on_exit! |
||||
setup :set_mox_global |
||||
|
||||
test "updates tokens metadata on start" do |
||||
insert(:token, name: nil, symbol: nil, decimals: 10, cataloged: true) |
||||
|
||||
expect( |
||||
EthereumJSONRPC.Mox, |
||||
:json_rpc, |
||||
1, |
||||
fn [%{id: "decimals"}, %{id: "name"}, %{id: "symbol"}, %{id: "totalSupply"}], _opts -> |
||||
{:ok, |
||||
[ |
||||
%{ |
||||
id: "decimals", |
||||
result: "0x0000000000000000000000000000000000000000000000000000000000000012" |
||||
}, |
||||
%{ |
||||
id: "name", |
||||
result: |
||||
"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000642616e636f720000000000000000000000000000000000000000000000000000" |
||||
}, |
||||
%{ |
||||
id: "symbol", |
||||
result: |
||||
"0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003424e540000000000000000000000000000000000000000000000000000000000" |
||||
}, |
||||
%{ |
||||
id: "totalSupply", |
||||
result: "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" |
||||
} |
||||
]} |
||||
end |
||||
) |
||||
|
||||
pid = start_supervised!({MetadataUpdater, %{update_interval: 0}}) |
||||
|
||||
wait_for_results(fn -> |
||||
updated = Repo.one!(from(t in Token, where: t.cataloged == true and not is_nil(t.name), limit: 1)) |
||||
|
||||
assert updated.name != nil |
||||
assert updated.symbol != nil |
||||
end) |
||||
|
||||
# Terminates the process so it finishes all Ecto processes. |
||||
GenServer.stop(pid) |
||||
end |
||||
|
||||
describe "update_metadata/1" do |
||||
test "updates the metadata for a list of tokens" do |
||||
token = insert(:token, name: nil, symbol: nil, decimals: 10) |
||||
|
||||
expect( |
||||
EthereumJSONRPC.Mox, |
||||
:json_rpc, |
||||
1, |
||||
fn [%{id: "decimals"}, %{id: "name"}, %{id: "symbol"}, %{id: "totalSupply"}], _opts -> |
||||
{:ok, |
||||
[ |
||||
%{ |
||||
id: "decimals", |
||||
result: "0x0000000000000000000000000000000000000000000000000000000000000012" |
||||
}, |
||||
%{ |
||||
id: "name", |
||||
result: |
||||
"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000642616e636f720000000000000000000000000000000000000000000000000000" |
||||
}, |
||||
%{ |
||||
id: "symbol", |
||||
result: |
||||
"0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003424e540000000000000000000000000000000000000000000000000000000000" |
||||
}, |
||||
%{ |
||||
id: "totalSupply", |
||||
result: "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" |
||||
} |
||||
]} |
||||
end |
||||
) |
||||
|
||||
MetadataUpdater.update_metadata([token.contract_address_hash]) |
||||
|
||||
expected_supply = Decimal.new(1_000_000_000_000_000_000) |
||||
|
||||
decimals_expected = Decimal.new(18) |
||||
|
||||
assert {:ok, |
||||
%Token{ |
||||
name: "Bancor", |
||||
symbol: "BNT", |
||||
total_supply: ^expected_supply, |
||||
decimals: ^decimals_expected, |
||||
cataloged: true |
||||
}} = Chain.token_from_address_hash(token.contract_address_hash) |
||||
end |
||||
end |
||||
end |
Loading…
Reference in new issue