2

Given that I have the following program

use anchor_lang::prelude::*;
use anchor_spl::token::{self, Mint, Token, TokenAccount, Transfer as SplTransfer};

declare_id!("7M7NGDAWNmqyrr2HQznFzwHD9xuwgUBhTfQTUxTAwxZy");

#[derive(Accounts)]
pub struct TransferSpl<'info> {
    pub from: Signer<'info>,
    #[account(mut, has_one = mint)]
    pub from_ata: Account<'info, TokenAccount>,
    #[account(
        mut,
        has_one = mint,
    )]
    pub to_ata: Account<'info, TokenAccount>,
    #[account(address = token::ID)] // Ensure the correct token program ID
    pub token_program: Program<'info, Token>,
    pub mint: Account<'info, Mint>, // Add the expected token mint
}

#[program]
pub mod solana_lamport_transfer {
    use super::*;

    pub fn transfer_spl_tokens(ctx: Context<TransferSpl>, amount: u64) -> Result<()> {
        let destination = &ctx.accounts.to_ata;
        let source = &ctx.accounts.from_ata;
        let token_program = &ctx.accounts.token_program;
        let authority = &ctx.accounts.from;

        // require!(
        //     source.mint == mint.key(),
        //     CustomError::InvalidSourceTokenAccount
        // );
        // require!(
        //     destination.mint == mint.key(),
        //     CustomError::InvalidDestinationTokenAccount
        // );

        // Transfer tokens from taker to initializer
        let cpi_accounts = SplTransfer {
            from: source.to_account_info().clone(),
            to: destination.to_account_info().clone(),
            authority: authority.to_account_info().clone(),
        };
        let cpi_program = token_program.to_account_info();

        token::transfer(CpiContext::new(cpi_program, cpi_accounts), amount)?;
        Ok(())
    }
}

#[error_code]
pub enum CustomError {
    #[msg("The source token account is not associated with the expected mint.")]
    InvalidSourceTokenAccount,
    #[msg("The destination token account is not associated with the expected mint.")]
    InvalidDestinationTokenAccount,
}

how can I update the code to allow the transfer of the known mint token to a known account (if possible program owned, i.e. a holding account), and the allowance of transferring that same token from the known account to the invoker.

I tried adding a PDA but wasn't quite sure how to get it all working. Had the account have another pda field that had a seed and a bump and tried having to_ata owner be the key of that pda but then you get into the business of the pda not being able to own a token account b/c it falls off the curve.

Here is a playground link: https://beta.solpg.io/664f8dcfcffcf4b13384d0ef

Any ideas? Thanks

EDIT: Final solution ended up being a bit more than the accepted answer. Playground Link

1 Answer 1

3

This looks okay, What I would add is checking whether the holding account to_ata is initialized, If it's not you could use anchor associated_token constraints

#[derive(Accounts)]
pub struct TransferSpl<'info> {
    pub from: Signer<'info>,
    #[account(mut, has_one = mint)]
    pub from_ata: Account<'info, TokenAccount>,
    #[account(
        init_if_needed,
        payer = from,
        associated_token::mint = mint,
        associated_token::authority = holding,
    )]
    pub to_ata: Account<'info, TokenAccount>,
    #[account(mut)]
    pub holding: Account<'info, Holding>,
    #[account(address = token::ID)] // Ensure the correct token program ID
    pub token_program: Program<'info, Token>,
    pub mint: Account<'info, Mint>, // Add the expected token mint
}

The code snippet above will transfer the token to the holding PDA and give it authority over the token. You will need to use the seeds used to create the holding account to make transfers from it.

On the client side, here is how you'll make use of getAssociatedTokenSync to derive the token account

    let to_ata = getAssociatedTokenAddressSync(
                    mint,
                    holding,
                    true // because you are making a PDA token account
                ),
2
  • hmm updating to the following on playground -> beta.solpg.io/664fb49bcffcf4b13384d0f1 it throws "AnchorError caused by account: associated_token_program. Error Code: InvalidProgramId. Error Number: 3008. Error Message: Program ID was not as expected." When trying to test it
    – mstelz
    Commented May 23 at 21:25
  • 1
    ah needed to change the associated_token_program line to: pub associated_token_program: Program<'info, AssociatedToken>,
    – mstelz
    Commented May 23 at 21:29

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.