I want to build a governance program where only accounts which hold the NFT of a particular collection can vote. How can i check on chain if an accounts holds an NFT of a particular collection. Would this be computationally expensive?
1 Answer
You can fetch the metadata of a mint onchain using mpl_token_metadata
crate. Steps to get the collection account on an account :
Get the metadata PDA for a mint address
pub fn get_metadata(mint: Pubkey) -> Pubkey { let (metadata, _) = Pubkey::find_program_address( &[ mpl_token_metadata::state::PREFIX.as_bytes(), mpl_token_metadata::id().as_ref(), mint.as_ref(), ], &mpl_token_metadata::id(), ); metadata }
Read the metadata data
let mint_metadata= Metadata::from_account_info(&ctx.accounts.mint_metadata_address.to_account_info())?;
Check the collection NFT on the mint
if mint_metadata.collection.is_some() { let collection = mint_metadata.collection.unwrap(); if collection.verified { // Do your stuff here } }
Suggestion - You can store your collection NFT mint address in some global variable (PDA data on a static seed) and then on 3rd step along with the exist check add another check if it belongs to that particular collection or not that you have stored.
-
In the step 2 are we fetching the metadata address using the function in step 1? Commented Jul 26, 2022 at 14:39
-
1You can either use this function or pass the metadata calculated from JS file in the accounts array and verify if PDA address calculated from here and passed are same or not– maddyCommented Jul 26, 2022 at 17:56
-
mpl_token_metadata
does not haveid
andstate
function. Do I have to use a specific version of mpl-token-metadata? Commented Jan 19 at 13:18