thirdweb-dev / js

Best in class web3 SDKs for Browser, Node and Mobile apps
https://thirdweb.com
Apache License 2.0
430 stars 328 forks source link

useNFTs hook not returning all NFTs for the contract #1485

Closed nagrawal3 closed 11 months ago

nagrawal3 commented 1 year ago

I am using useNFTs hook from thirdweb to get all the nfts issued on the polygon mainnet chain. Total NFTs returned doesn't contain all NFTs issued by the contract.

NFT Contract: 0x95e6603e219e6D08A9AE46f29201fA1610FA76B4

Total NFT count on contract is 70 with id between 0-69, and I am only receiving 68 with id between 0-67. Above contract has 2 NFTs burned/transferred to zero address.

import { useNFTs, useContract } from '@thirdweb-dev/react';
import { useState, useEffect } from 'react';
import { zeroAddress } from 'viem';

export type UserType = {
  address: string,
  name: string,
  id?: string,
  uri?: string,
}

export function useBadgeUsers(addressOrName: string, {
  filterZeroAddress = false,
  startIndex = 0,
  addressCount = 100
}) {
  const [users, setUsers] = useState<UserType[]>([]);
  const { contract } = useContract(addressOrName);
  const { data: nfts, error } = useNFTs(contract, { start: startIndex, count: addressCount });

  if (error) {
    console.log('Error fetching NFTs from given address', error);
  }

  useEffect(() => {
    let usersArray = nfts?.map(nft => ({
      address: nft.owner as string,
      name: nft.metadata.name as string,
      id: nft.metadata.id as string,
      uri: nft.metadata.uri as string
    }));

    if (filterZeroAddress) usersArray = usersArray?.filter((user) => user.address != zeroAddress)
    if (usersArray) setUsers(usersArray as []);
  }, [nfts, filterZeroAddress]);

  return users;
}

Verified the results by running Alchemy curl command to received all NFTs issued by the contract:

curl --request GET \
     --url 'https://polygon-mainnet.g.alchemy.com/nft/v2/<Alchemy API Key>/getNFTsForCollection?contractAddress=0x95e6603e219e6D08A9AE46f29201fA1610FA76B4&withMetadata=true&startToken=0&limit=100' \
     --header 'accept: application/json'

Let me know if anyone else faced similar issue, or have some solution

joaquim-verges commented 1 year ago

@nagrawal3 thanks for the detailed report - I checked the contract and it looks like 3 NFTs (token ids '1', '9' and '59') have been burned on that contract. Your totalSupply() function takes into account those burns, and returns 67 (tried it on the contract explorer https://thirdweb.com/polygon/0x95e6603e219e6D08A9AE46f29201fA1610FA76B4/explorer)

so when we get all NFTs, we respect your totalSupply and will at most fetch that amount.

nagrawal3 commented 1 year ago

https://thirdweb.com/polygon/0x95e6603e219e6D08A9AE46f29201fA1610FA76B4/explorer

@joaquim-verges thank you for your response. What you mention makes sense, but is there a way to use the thirdweb library to fetch NFTs not assigned to zeroAddress?

joaquim-verges commented 1 year ago

@nagrawal3 the way you're filtering makes sense, but the problem is on the contract - you would need a way to tell how many total nfts have been minted regardless of burned.

Another option would be to use events, filtered by from as the zero address https://portal.thirdweb.com/typescript/sdk.contractevents.getevents

stale[bot] commented 11 months ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.