Solana on-chain program to find address of wallet holding NFT

361 views Asked by At

In an on-chain program I would like to find the wallet holding a particular NFT, is it possible? how can I do that?

Please note - I do NOT want to do this in the client, but totally inside an on-chain program.

I have a Mint address only, how to I find the wallet address? I can do it off-chain with getProgramAccount() but how to do it on-chain?

2

There are 2 answers

0
XXX On BEST ANSWER

It's not possible.

Mint -> Token Accounts is a 1:Many relationship, the getProgramAccount() off-chain RPC call wades through a ton of data to find the Token Accounts for a Mint, you could not do this on-chain.

In the special case of an NFT (supply=1) there is just one Token Account you want, but that relationship is not maintained on-chain.

If this was Ethereum, you could just change your ERC20 token contract to store the Owner Address on-chain, but it's Solana... you can't modify the SPL program (without your token no longer being a token)... so you are stuffed.

Solana is very constrained when it comes to development possibilities.

nb: the limitation isn't down to not being able to dynamically load accounts, as you would know the account that holds the relationship (PDA) upfront... the problem is you can't make a modded SPL program like you can mod an ERC20 token.

2
Jon C On

Certainly, here's a quick way to do it on-chain:

use solana_program::{account_info::AccountInfo, msg, pubkey::Pubkey};
use spl_token::state::Account;

pub fn process_instruction(
    program_id: &Pubkey,
    accounts: &[AccountInfo],
    input: &[u8],
) -> ProgramResult {
    let token_account = Account::unpack(accounts[0].try_borrow_data().unwrap()).unwrap();
    msg!("{}", token_account.owner);
}

So you're directly deserializing the account data as a token account using Account::unpack, and then logging the owner field, which is the wallet.