diff --git a/.changeset/sour-kiwis-wink.md b/.changeset/sour-kiwis-wink.md new file mode 100644 index 00000000000..94a9c4e721f --- /dev/null +++ b/.changeset/sour-kiwis-wink.md @@ -0,0 +1,5 @@ +--- +"thirdweb": patch +--- + +Better fallbacks for live NFT data cache miss diff --git a/apps/dashboard/src/@/constants/thirdweb.server.ts b/apps/dashboard/src/@/constants/thirdweb.server.ts index 67e151e4c92..cf73743d190 100644 --- a/apps/dashboard/src/@/constants/thirdweb.server.ts +++ b/apps/dashboard/src/@/constants/thirdweb.server.ts @@ -6,6 +6,7 @@ import { import { THIRDWEB_BUNDLER_DOMAIN, THIRDWEB_INAPP_WALLET_DOMAIN, + THIRDWEB_INSIGHT_API_DOMAIN, THIRDWEB_PAY_DOMAIN, THIRDWEB_RPC_DOMAIN, THIRDWEB_SOCIAL_API_DOMAIN, @@ -32,6 +33,7 @@ export function getThirdwebClient(jwt?: string) { storage: THIRDWEB_STORAGE_DOMAIN, social: THIRDWEB_SOCIAL_API_DOMAIN, bundler: THIRDWEB_BUNDLER_DOMAIN, + insight: THIRDWEB_INSIGHT_API_DOMAIN, }); } diff --git a/apps/dashboard/src/constants/urls.ts b/apps/dashboard/src/constants/urls.ts index aca7f7a9eb2..7a83c1e4f40 100644 --- a/apps/dashboard/src/constants/urls.ts +++ b/apps/dashboard/src/constants/urls.ts @@ -20,3 +20,6 @@ export const THIRDWEB_SOCIAL_API_DOMAIN = export const THIRDWEB_BUNDLER_DOMAIN = process.env.NEXT_PUBLIC_BUNDLER_URL || "bundler.thirdweb-dev.com"; + +export const THIRDWEB_INSIGHT_API_DOMAIN = + process.env.NEXT_PUBLIC_INSIGHT_API_URL || "insight.thirdweb-dev.com"; diff --git a/packages/thirdweb/src/extensions/erc1155/read/getNFT.ts b/packages/thirdweb/src/extensions/erc1155/read/getNFT.ts index e51f8b5e57c..ed9aa4fcd0d 100644 --- a/packages/thirdweb/src/extensions/erc1155/read/getNFT.ts +++ b/packages/thirdweb/src/extensions/erc1155/read/getNFT.ts @@ -50,7 +50,6 @@ export async function getNFT( async function getNFTFromInsight( options: BaseTransactionOptions, ): Promise { - const tokenId = options.tokenId; const nft = await getNFTInsight({ client: options.contract.client, chain: options.contract.chain, @@ -58,22 +57,8 @@ async function getNFTFromInsight( tokenId: options.tokenId, }); if (!nft) { - return parseNFT( - { - id: tokenId, - type: "ERC1155", - uri: "", - }, - { - tokenId: options.tokenId, - tokenUri: "", - type: "ERC1155", - owner: null, - supply: 0n, - tokenAddress: options.contract.address, - chainId: options.contract.chain.id, - }, - ); + // fresh contracts might be delayed in indexing, so we fallback to RPC + return getNFTFromRPC(options); } return nft; } diff --git a/packages/thirdweb/src/extensions/erc1155/read/getNFTs.ts b/packages/thirdweb/src/extensions/erc1155/read/getNFTs.ts index 5578c8c5b8c..7f4280e452f 100644 --- a/packages/thirdweb/src/extensions/erc1155/read/getNFTs.ts +++ b/packages/thirdweb/src/extensions/erc1155/read/getNFTs.ts @@ -65,16 +65,28 @@ async function getNFTsFromInsight( ): Promise { const { contract, start, count = Number(DEFAULT_QUERY_ALL_COUNT) } = options; - const result = await getContractNFTs({ - client: contract.client, - chains: [contract.chain], - contractAddress: contract.address, - queryOptions: { - limit: count, - page: start ? Math.floor(start / count) : undefined, - }, - }); + const [result, supply] = await Promise.all([ + getContractNFTs({ + client: contract.client, + chains: [contract.chain], + contractAddress: contract.address, + queryOptions: { + limit: count, + page: start ? Math.floor(start / count) : undefined, + }, + }), + nextTokenIdToMint(options).catch(() => maxUint256), + ]); + const currentOffset = start ?? 0; + const expectedResultLength = Math.min( + count, + Math.max(0, Number(supply) - currentOffset), + ); + if (result.length < expectedResultLength) { + // fresh contracts might be delayed in indexing, so we fallback to RPC + return getNFTsFromRPC(options); + } return result; } @@ -95,6 +107,7 @@ async function getNFTsFromRPC( getNFT({ ...options, tokenId: i, + useIndexer: false, }), ); } diff --git a/packages/thirdweb/src/extensions/erc721/read/getNFT.ts b/packages/thirdweb/src/extensions/erc721/read/getNFT.ts index b988ec86671..e37061fe2b7 100644 --- a/packages/thirdweb/src/extensions/erc721/read/getNFT.ts +++ b/packages/thirdweb/src/extensions/erc721/read/getNFT.ts @@ -78,7 +78,6 @@ export async function getNFT( async function getNFTFromInsight( options: BaseTransactionOptions, ): Promise { - const tokenId = options.tokenId; const nft = await getNFTInsight({ client: options.contract.client, chain: options.contract.chain, @@ -87,21 +86,8 @@ async function getNFTFromInsight( includeOwners: options.includeOwner, }); if (!nft) { - return parseNFT( - { - id: tokenId, - type: "ERC721", - uri: "", - }, - { - tokenId, - tokenUri: "", - type: "ERC721", - owner: null, - tokenAddress: options.contract.address, - chainId: options.contract.chain.id, - }, - ); + // fresh contracts might be delayed in indexing, so we fallback to RPC + return getNFTFromRPC(options); } return nft; } diff --git a/packages/thirdweb/src/extensions/erc721/read/getNFTs.ts b/packages/thirdweb/src/extensions/erc721/read/getNFTs.ts index 9c8c9fdc501..516065751bf 100644 --- a/packages/thirdweb/src/extensions/erc721/read/getNFTs.ts +++ b/packages/thirdweb/src/extensions/erc721/read/getNFTs.ts @@ -104,16 +104,29 @@ async function getNFTsFromInsight( ): Promise { const { contract, start, count = Number(DEFAULT_QUERY_ALL_COUNT) } = options; - const result = await getContractNFTs({ - client: contract.client, - chains: [contract.chain], - contractAddress: contract.address, - includeOwners: options.includeOwners ?? false, - queryOptions: { - limit: count, - page: start ? Math.floor(start / count) : undefined, - }, - }); + const [result, supply] = await Promise.all([ + getContractNFTs({ + client: contract.client, + chains: [contract.chain], + contractAddress: contract.address, + includeOwners: options.includeOwners ?? false, + queryOptions: { + limit: count, + page: start ? Math.floor(start / count) : undefined, + }, + }), + totalSupply(options), + ]); + + const currentOffset = start ?? 0; + const expectedResultLength = Math.min( + count, + Math.max(0, Number(supply) - currentOffset), + ); + if (result.length < expectedResultLength) { + // fresh contracts might be delayed in indexing, so we fallback to RPC + return getNFTsFromRPC(options); + } return result; } @@ -158,6 +171,7 @@ async function getNFTsFromRPC( ...options, tokenId: i, includeOwner: options.includeOwners ?? false, + useIndexer: false, }), ); }