1+ import { type Abi , toFunctionSelector } from "viem" ;
2+ import { resolveContractAbi } from "../../../contract/actions/resolve-abi.js" ;
13import type { BaseTransactionOptions } from "../../../transaction/types.js" ;
24import { fetchTokenMetadata } from "../../../utils/nft/fetchTokenMetadata.js" ;
35import { type NFT , parseNFT } from "../../../utils/nft/parseNft.js" ;
@@ -6,6 +8,10 @@ import {
68 type TokenURIParams ,
79 tokenURI ,
810} from "../__generated__/IERC721A/read/tokenURI.js" ;
11+ import {
12+ isTokenByIndexSupported ,
13+ tokenByIndex ,
14+ } from "../__generated__/IERC721Enumerable/read/tokenByIndex.js" ;
915
1016export { isTokenURISupported as isGetNFTSupported } from "../__generated__/IERC721A/read/tokenURI.js" ;
1117
@@ -19,6 +25,10 @@ export type GetNFTParams = Prettify<
1925 * Whether to include the owner of the NFT.
2026 */
2127 includeOwner ?: boolean ;
28+ /**
29+ * Whether to check tokenId by index.
30+ */
31+ ignoreTokenIndex ?: boolean ;
2232 }
2333> ;
2434
@@ -39,24 +49,38 @@ export type GetNFTParams = Prettify<
3949export async function getNFT (
4050 options : BaseTransactionOptions < GetNFTParams > ,
4151) : Promise < NFT > {
52+ const abi = await resolveContractAbi < Abi > ( options . contract ) ;
53+ const selectors = abi
54+ . filter ( ( f ) => f . type === "function" )
55+ . map ( ( f ) => toFunctionSelector ( f ) ) ;
56+ const hasTokenByIndex = isTokenByIndexSupported ( selectors ) ;
57+
58+ let tokenId = options . tokenId ;
59+ if ( ! options . ignoreTokenIndex && hasTokenByIndex ) {
60+ tokenId = await tokenByIndex ( {
61+ contract : options . contract ,
62+ index : options . tokenId ,
63+ } ) ;
64+ }
65+
4266 const [ uri , owner ] = await Promise . all ( [
43- tokenURI ( options ) . catch ( ( ) => null ) ,
67+ tokenURI ( { contract : options . contract , tokenId } ) . catch ( ( ) => null ) ,
4468 options . includeOwner
4569 ? import ( "../__generated__/IERC721A/read/ownerOf.js" )
46- . then ( ( m ) => m . ownerOf ( options ) )
70+ . then ( ( m ) => m . ownerOf ( { contract : options . contract , tokenId } ) )
4771 . catch ( ( ) => null )
4872 : null ,
4973 ] ) ;
5074
5175 if ( ! uri ?. trim ( ) ) {
5276 return parseNFT (
5377 {
54- id : options . tokenId ,
78+ id : tokenId ,
5579 type : "ERC721" ,
5680 uri : "" ,
5781 } ,
5882 {
59- tokenId : options . tokenId ,
83+ tokenId,
6084 tokenUri : "" ,
6185 type : "ERC721" ,
6286 owner,
@@ -67,15 +91,15 @@ export async function getNFT(
6791 return parseNFT (
6892 await fetchTokenMetadata ( {
6993 client : options . contract . client ,
70- tokenId : options . tokenId ,
94+ tokenId,
7195 tokenUri : uri ,
7296 } ) . catch ( ( ) => ( {
73- id : options . tokenId ,
97+ id : tokenId ,
7498 type : "ERC721" ,
7599 uri,
76100 } ) ) ,
77101 {
78- tokenId : options . tokenId ,
102+ tokenId : tokenId ,
79103 tokenUri : uri ,
80104 type : "ERC721" ,
81105 owner,
0 commit comments