0

Here is the code to send nft from signer(authority) to current contract and I'm not sure if I'm getting mint_address for each nft is correct. I have to use BTreeMap in order to randomly claim nft onchain and anchor does not support BTreeMap yet so I have to do the non anchor way. But I'm stucking with MissingAccount error when do transfer_checked and I haven't found any solution about this yet. enter image description here

Here is the mock minting nft and the token_account is mint_address in contract

let mint_account = Keypair::new();
    let token_program = &id();
    let rent = banks_client.get_rent().await.unwrap();
    let mint_rent = rent.minimum_balance(Mint::LEN);

    let token_mint_a_account_ix = solana_program::system_instruction::create_account(
        &payer.pubkey(),
        &mint_account.pubkey(),
        mint_rent,
        Mint::LEN as u64,
        token_program,
    );

    let token_mint_a_ix = instruction::initialize_mint(
        token_program,
        &mint_account.pubkey(),
        &payer.pubkey(),
        None,
        0,
    ).unwrap();

    // create mint transaction
    let token_mint_a_tx = Transaction::new_signed_with_payer(
        &[token_mint_a_account_ix, token_mint_a_ix],
        Some(&payer.pubkey()),
        &[&payer, &mint_account],
        recent_blockhash,
    );

    banks_client
        .process_transaction(token_mint_a_tx)
        .await
        .unwrap();

    // Create account that can hold the newly minted tokens
    let account_rent = rent.minimum_balance(Account::LEN);
    let token_account = Keypair::new();
    let new_token_account_ix = system_instruction::create_account(
        &payer.pubkey(),
        &token_account.pubkey(),
        account_rent,
        Account::LEN as u64,
        token_program,
    );

    let initialize_account_ix = instruction::initialize_account(
        token_program,
        &token_account.pubkey(),
        &mint_account.pubkey(),
        &payer.pubkey(),
    )
    .unwrap();

    let create_new_token_account_tx = Transaction::new_signed_with_payer(
        &[new_token_account_ix, initialize_account_ix],
        Some(&payer.pubkey()),
        &[&payer, &token_account],
        recent_blockhash,
    );
    banks_client
        .process_transaction(create_new_token_account_tx)
        .await
        .unwrap();

    // Mint tokens into newly created account
    let mint_amount: u64 = 1;
    let mint_to_ix = instruction::mint_to(
        &token_program,
        &mint_account.pubkey(),
        &token_account.pubkey(),
        &payer.pubkey(),
        &[],
        mint_amount.clone(),
    ).unwrap();

    let mint_to_tx = Transaction::new_signed_with_payer(
        &[mint_to_ix],
        Some(&payer.pubkey()),
        &[&payer, &payer],
        recent_blockhash,
    );
    banks_client.process_transaction(mint_to_tx).await.unwrap();

    // Inspect account
    let token_account_info = banks_client
        .get_account(token_account.pubkey().clone())
        .await
        .unwrap()
        .expect("could not fetch account information");
    let account_data = Account::unpack(&token_account_info.data).unwrap();
    println!("account data: {:?}", account_data);
    assert_eq!(
        account_data.amount,
        mint_amount.clone(),
        "not correct amount"
    );

Can anyone pls give me some tutorial or example about this?

1 Answer 1

1

To describe it briefly,You want a feature to transfer a NFT to a Contract and back from the Contract to the user ? Assuming this is the problem the solution to it could be you can have a PDA Account which is the owner of the TokenAccount of the NFT you wish to send to. So once the TokenAccount is created you can transfer the NFT to it The Code for creating the ATA looks like this

let create_escrow_ata_ix =
            spl_associated_token_account::instruction::create_associated_token_account(
                payer_info.key,
                escrow_info.key,
                attribute_mint_info.key,
            );

        invoke(
            &create_escrow_ata_ix,
            &[
                payer_info.clone(),
                attribute_dst_token_info.clone(),
                escrow_info.clone(),
                attribute_mint_info.clone(),
                system_program_info.clone(),
                token_program_info.clone(),
            ],
        )?;

And to transfer the NFT from the contract or from the user to the contract this code can be used

 let transfer_ix = spl_token::instruction::transfer(
            &spl_token::id(),
            attribute_src_token_info.key,
            attribute_dst_token_info.key,
            payer_info.key,
            &[payer_info.key],
            args.amount,
        )?;

        invoke(
            &transfer_ix,
            &[
                attribute_src_token_info.clone(),
                attribute_dst_token_info.clone(),
                payer_info.clone(),
                token_program_info.clone(),
            ],
        )?

Would recommend to go through this blog post if you are not aware of how PDA's and token accounts work. LINK

1
  • Hi @Pratik.js, thanks for your answer. But I did the same way as yours but it still return Missing Account error. Could you please share your repo?
    – marethyu
    Commented Jan 19, 2023 at 2:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.