So you want to display a Metaplex NFT
This guide will attempt to give an overview of the technical/coding steps that are required to render a Metaplex NFT with any programming language/platform. I'll attempt to write it in a programming language-agnostic manner; you'll need to fill in the particular methods of performing the steps with your coding language of choice.
For the purposes of discussion, we'll call the Solana account that holds the Metaplex NFTs the "NFT-Account."
Step 1: Call getTokenAccountsByOwner
The first thing you need to do is call the getTokenAccountsByOwner
JSON RPC method as documented here:
https://docs.solana.com/developing/clients/jsonrpc-api#gettokenaccountsbyowner
The first parameter you'll pass is of course the NFT-Account address. You'll also need to pass a programId
argument with the Solana Token Program ID, which is TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
. I also recommend the jsonParsed
argument at this point.
Both the NFT-Account and Token program account need to be encoded as Base58.
Step 2: Locate NFT Accounts
From the list of accounts that you get back from the RPC call, you'll want to find NFT token accounts. For each account, you'll want to look in the tokenAmount
data object/properties. You're looking for accounts with an amount
of 1 and a decimals
value of 0.
Step 3: Derive PDAs for the NFT accounts
The next step is to derive a Prorgram Derived Address for each NFT account address. PDAs are discussed here:
The actual technical details of PDA generation is actually still something of a mystery even to me, so I can't explain the nitty gritty details on how or why they are generated. Suffice it to say that you need the PDA that is generated from the NFT token accounts to actually get the on-chain Metaplex NFT metadata. The best way to see how to generate a PDA is in the metaplex source, which you can find here:
You'll need a few things to generate the PDA. The first is an array of "seeds," which includes:
- The Metaplex seed constant:
metadata
- The metadata public key:
metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s
- The NFT token account mint address, which is also returned from the RPC call.
With that seed data, you can perform the findProgramAddress
operation and that will result in a PDA account/address. Both data items 2 and 3 need to be Base58 encoded.
Step 4: Call getAccountInfo for each PDA account
For each PDA account address, you then need to call the getAccountInfo
JSON RPC method:
https://docs.solana.com/developing/clients/jsonrpc-api#getaccountinfo
Step 5: Borsh deserialize the Metaplex meta
For each account info object that you get back from the previous call, you will need to need to Borsh deserialize the data
property in the resulting JSON. There are Borsh libraries for most programming languages which are listed here:
You will be deserializing the data property into a programming-language specific version of the Metadata object hierarchy. The Javascript version of that data is here:
One of the child objects there, Data
, has the specific property we are looking for: uri
. That URI is the link to the Arweave JSON metadata file.
Step 6: Parse the NFT JSON data
As noted, the uri
property points to an Arweave JSON file that is formatted based on a common NFT JSON standard. I believe it is ERC721/ERC1155 format. The format is documented in detail here:
https://docs.metaplex.com/nft-standard#json-structure
Step 7: Use the JSON data to display
That JSON is the final place for information about your NFT. All the actual user-relevant metadata is there, as well as links to the relevant asset file or files to display or render.
Step 8: Display your snazzy NFT!
I hope this was helpful! If you liked this guide, say hey on Twitter!
In step 3 and 4, when you call getAccountInfo and findProgramAddress, you need to call it on a specific program (token metadata). Probably mention that.
I'd also mention that if we want to be strict here, you also want to derive the edition PDA which is [metadata, metadata program, mint_id, 'edition'], and also get THAT account. If the account does not exist, the token you're looking at is just part of a normal mint (like USDC or COPE) that has decided to use token-metadata to name itself. To make it more clear, ANY token that does not have an edition account is NOT an NFT.
If that account does exist, and it's of the MasterEdition type, then you know it's an original and may or may not have printing capabilities. The Master Editions' max_supply field being null means it is unlimited and can have unlimited editions printed from it using the mint_edition_from_master_edition_via_token contract endpoint on token metadata contract. The max_supply field being set means it can only have that many children editions. If the account exists and it's of the Edition type, it is a child edition of some master edition and is either a Limited Edition (printed from a finite supply) or an Open Edition (printed from an infinite supply).