Merge pull request #6043 from blockscout/fix-erc1155-tokens-fetching

Fix token instance fetching
pull/6045/head
Victor Baranov 2 years ago committed by GitHub
commit c8b074f35b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 6
      apps/block_scout_web/lib/block_scout_web/controllers/tokens/instance/holder_controller.ex
  3. 8
      apps/block_scout_web/lib/block_scout_web/controllers/tokens/instance/metadata_controller.ex
  4. 4
      apps/block_scout_web/lib/block_scout_web/controllers/tokens/instance/transfer_controller.ex
  5. 44
      apps/block_scout_web/test/block_scout_web/controllers/tokens/instance/transfer_controller_test.exs
  6. 14
      apps/explorer/lib/explorer/chain.ex
  7. 2
      apps/explorer/lib/explorer/chain/token/instance.ex

@ -29,6 +29,7 @@
- [#5786](https://github.com/blockscout/blockscout/pull/5786) - Replace `current_path` with `Controller.current_full_path` in two controllers - [#5786](https://github.com/blockscout/blockscout/pull/5786) - Replace `current_path` with `Controller.current_full_path` in two controllers
- [#5948](https://github.com/blockscout/blockscout/pull/5948) - Fix unexpected messages in `CoinBalanceOnDemand` - [#5948](https://github.com/blockscout/blockscout/pull/5948) - Fix unexpected messages in `CoinBalanceOnDemand`
- [#6013](https://github.com/blockscout/blockscout/pull/6013) - Fix ERC-1155 tokens fetching - [#6013](https://github.com/blockscout/blockscout/pull/6013) - Fix ERC-1155 tokens fetching
- [#6043](https://github.com/blockscout/blockscout/pull/6043) - Fix token instance fetching
### Chore ### Chore

@ -56,12 +56,12 @@ defmodule BlockScoutWeb.Tokens.Instance.HolderController do
with {:ok, hash} <- Chain.string_to_address_hash(token_address_hash), with {:ok, hash} <- Chain.string_to_address_hash(token_address_hash),
{:ok, token} <- Chain.token_from_address_hash(hash, options), {:ok, token} <- Chain.token_from_address_hash(hash, options),
{:ok, token_transfer} <- {:ok, token_instance} <-
Chain.erc721_token_instance_from_token_id_and_token_address(token_id, hash) do Chain.erc721_or_erc1155_token_instance_from_token_id_and_token_address(token_id, hash) do
render( render(
conn, conn,
"index.html", "index.html",
token_instance: token_transfer, token_instance: %{instance: token_instance, token_id: Decimal.new(token_id)},
current_path: Controller.current_full_path(conn), current_path: Controller.current_full_path(conn),
token: Market.add_price(token), token: Market.add_price(token),
total_token_transfers: Chain.count_token_transfers_from_token_hash_and_token_id(hash, token_id) total_token_transfers: Chain.count_token_transfers_from_token_hash_and_token_id(hash, token_id)

@ -9,13 +9,13 @@ defmodule BlockScoutWeb.Tokens.Instance.MetadataController do
with {:ok, hash} <- Chain.string_to_address_hash(token_address_hash), with {:ok, hash} <- Chain.string_to_address_hash(token_address_hash),
{:ok, token} <- Chain.token_from_address_hash(hash, options), {:ok, token} <- Chain.token_from_address_hash(hash, options),
{:ok, token_transfer} <- {:ok, token_instance} <-
Chain.erc721_token_instance_from_token_id_and_token_address(token_id, hash) do Chain.erc721_or_erc1155_token_instance_from_token_id_and_token_address(token_id, hash) do
if token_transfer.instance && token_transfer.instance.metadata do if token_instance.metadata do
render( render(
conn, conn,
"index.html", "index.html",
token_instance: token_transfer, token_instance: %{instance: token_instance, token_id: Decimal.new(token_id)},
current_path: Controller.current_full_path(conn), current_path: Controller.current_full_path(conn),
token: Market.add_price(token), token: Market.add_price(token),
total_token_transfers: Chain.count_token_transfers_from_token_hash_and_token_id(hash, token_id) total_token_transfers: Chain.count_token_transfers_from_token_hash_and_token_id(hash, token_id)

@ -58,12 +58,12 @@ defmodule BlockScoutWeb.Tokens.Instance.TransferController do
with {:ok, hash} <- Chain.string_to_address_hash(token_address_hash), with {:ok, hash} <- Chain.string_to_address_hash(token_address_hash),
{:ok, token} <- Chain.token_from_address_hash(hash, options), {:ok, token} <- Chain.token_from_address_hash(hash, options),
{:ok, token_transfer} <- {:ok, token_instance} <-
Chain.erc721_or_erc1155_token_instance_from_token_id_and_token_address(token_id, hash) do Chain.erc721_or_erc1155_token_instance_from_token_id_and_token_address(token_id, hash) do
render( render(
conn, conn,
"index.html", "index.html",
token_instance: token_transfer, token_instance: %{instance: token_instance, token_id: Decimal.new(token_id)},
current_path: Controller.current_full_path(conn), current_path: Controller.current_full_path(conn),
token: Market.add_price(token), token: Market.add_price(token),
total_token_transfers: Chain.count_token_transfers_from_token_hash_and_token_id(hash, token_id) total_token_transfers: Chain.count_token_transfers_from_token_hash_and_token_id(hash, token_id)

@ -2,43 +2,29 @@ defmodule BlockScoutWeb.Tokens.Instance.TransferControllerTest do
use BlockScoutWeb.ConnCase, async: false use BlockScoutWeb.ConnCase, async: false
describe "GET token-transfers/2" do describe "GET token-transfers/2" do
test "works for ERC-721 tokens", %{conn: conn} do test "fetches the instance", %{conn: conn} do
contract_address = insert(:address) contract_address = insert(:address)
insert(:token, contract_address: contract_address) insert(:token, contract_address: contract_address)
token_id = 10 contract_address_hash = contract_address.hash
%{log_index: log_index} = token_id = Decimal.new(10)
insert(:token_transfer,
from_address: contract_address,
token_contract_address: contract_address,
token_id: token_id
)
conn = get(conn, "/token/#{contract_address.hash}/instance/#{token_id}/token-transfers") insert(:token_instance,
token_contract_address_hash: contract_address_hash,
token_id: token_id
)
assert %{assigns: %{token_instance: %{log_index: ^log_index}}} = conn conn = get(conn, "/token/#{contract_address_hash}/instance/#{token_id}/token-transfers")
end
test "works for ERC-1155 tokens", %{conn: conn} do
contract_address = insert(:address)
insert(:token, contract_address: contract_address)
token_id = 10
%{log_index: log_index} =
insert(:token_transfer,
from_address: contract_address,
token_contract_address: contract_address,
token_id: nil,
token_ids: [token_id]
)
conn = get(conn, "/token/#{contract_address.hash}/instance/#{token_id}/token-transfers")
assert %{assigns: %{token_instance: %{log_index: ^log_index}}} = conn assert %{
assigns: %{
token_instance: %{
instance: %{token_contract_address_hash: ^contract_address_hash, token_id: ^token_id}
}
}
} = conn
end end
end end
end end

@ -4882,20 +4882,10 @@ defmodule Explorer.Chain do
end end
@spec erc721_or_erc1155_token_instance_from_token_id_and_token_address(binary(), Hash.Address.t()) :: @spec erc721_or_erc1155_token_instance_from_token_id_and_token_address(binary(), Hash.Address.t()) ::
{:ok, TokenTransfer.t()} | {:error, :not_found} {:ok, Instance.t()} | {:error, :not_found}
def erc721_or_erc1155_token_instance_from_token_id_and_token_address(token_id, token_contract_address) do def erc721_or_erc1155_token_instance_from_token_id_and_token_address(token_id, token_contract_address) do
query = query =
from(tt in TokenTransfer, from(i in Instance, where: i.token_contract_address_hash == ^token_contract_address and i.token_id == ^token_id)
left_join: instance in Instance,
on:
tt.token_contract_address_hash == instance.token_contract_address_hash and
(tt.token_id == instance.token_id or fragment("? @> ARRAY[?::decimal]", tt.token_ids, instance.token_id)),
where:
tt.token_contract_address_hash == ^token_contract_address and
(tt.token_id == ^token_id or fragment("? @> ARRAY[?::decimal]", tt.token_ids, ^Decimal.new(token_id))),
limit: 1,
select: %{tt | instance: instance}
)
case Repo.one(query) do case Repo.one(query) do
nil -> {:error, :not_found} nil -> {:error, :not_found}

@ -18,7 +18,7 @@ defmodule Explorer.Chain.Token.Instance do
@type t :: %Instance{ @type t :: %Instance{
token_id: non_neg_integer(), token_id: non_neg_integer(),
token_contract_address_hash: Hash.Address.t(), token_contract_address_hash: Hash.Address.t(),
metadata: map(), metadata: map() | nil,
error: String.t() error: String.t()
} }

Loading…
Cancel
Save