Skip to content

Instantly share code, notes, and snippets.

@belivenn
Last active April 8, 2024 22:02
Show Gist options
  • Select an option

  • Save belivenn/45aca827e19e40b5cbf1d6c1c05a81a5 to your computer and use it in GitHub Desktop.

Select an option

Save belivenn/45aca827e19e40b5cbf1d6c1c05a81a5 to your computer and use it in GitHub Desktop.
Solana Stack Exchange Answer
use anchor_lang::prelude::*;
use anchor_spl::{
token_interface::{TokenAccount, Mint, TokenInterface, TransferChecked, transfer_checked},
associated_token::AssociatedToken}
};
declare_id!("exampleid00121312312312312312312");
#[program]
pub mod SolanStackExchange {
use super::*;
//send tokens from ata to pda
pub fn send_tokens(ctx: Context<SendTokens>, amount: u64) -> Result<()> {
// send spls to pda
ctx.accounts.send_spl_tokens_to_pda(amount)
}
// withdraw tokens from pda to ata
pub fn withdraw_tokens_from_pda(ctx: Context<SendTokens>, amount: u64) -> Result<()> {
// Withdraw tokens
ctx.accounts.withdraw_tokens_from_pda(amount)
}
pub fn close_pda(ctx: Context<ClosePda>) -> Result<()> {
// Close a pda account
ctx.accounts.close_pda(&ctx.bumps)
}
}
#[derive(Accounts)]
pub struct SendTokens<'info> {
#[account(mut)]
//Signer
owner: Signer<'info>,
#[account(
mut,
associated_token::mint = mint,
associated_token::authority = owner
)]
//Signer ATA
owner_ata: InterfaceAccount<'info, TokenAccount>,
#[account(
mut,
//Example seeds
seeds = [b"vault", owner.key().as_ref(), mint.key().as_ref()],
bump = pda.bump,
token::mint = mint,
token::authority = pda
)]
//PDA - VAULT
pda: InterfaceAccount<'info, TokenAccount>,
//SPL_TOKEN/TOKEN2022
mint: InterfaceAccount<'info, Mint>,
token_program: Interface<'info, TokenInterface>,
associated_token_program: Program<'info, AssociatedToken>,
system_program: Program<'info, System>
}
impl<'info> SendTokens<'info> {
pub fn send_spl_tokens_to_pda(
&mut self,
amount: u64
) -> Result<()> {
//Transfer Checked CPI, This works for SPLS AND TOKEN2022
let accounts = TransferChecked {
from: self.owner_ata.to_account_info(),
to: self.pda.to_account_info(),
authority: self.owner.to_account_info(),
mint: self.mint.to_account_info()
};
let ctx = CpiContext::new(
self.token_program.to_account_info(),
accounts,
);
transfer_checked(ctx, amount, self.mint.decimals)
}
pub fn withdraw_tokens_from_pda(
&mut self,
amount: u64
) -> Result<()> {
let accounts = TransferChecked {
from: self.pda.to_account_info(),
to: self.owner_ata.to_account_info(),
authority: self.pda.to_account_info(),
mint: self.mint.to_account_info()
};
let seeds = &[
&b"pda"[..],
&self.owner.key().to_bytes()[..],
&self.mint.key().to_bytes()[..],
&[self.pda.bump],
];
let signer_seeds = &[&seeds[..]];
let ctx = CpiContext::new_with_signer(
self.token_program.to_account_info(),
accounts,
signer_seeds
);
transfer_checked(ctx, amount, self.mint.decimals)
}
}
#[derive(Accounts)]
pub struct ClosePda<'info> {
#[account(mut)]
owner: Signer<'info>,
#[account(
mut,
seeds = [b"pda"owner.key().as_ref(), mint.key().as_ref()],
bump = pda.bump
token::mint = mint,
token::authority = pda
)]
pda: InterfaceAccount<'info, TokenAccount>,
mint: InterfaceAccount<'info, Mint>,
token_program: Interface<'info, TokenInterface>,
associated_token_program: Program<'info, AssociatedToken>,
system_program: Program<'info, System>
}
impl<'info> ClosePda<'info> {
pub fn close_pda(
&self
) -> Result<()> {
let accounts = CloseAccount {
account: self.pda.to_account_info(),
destination: self.owner.to_account_info(),
authority: self.owner.to_account_info()
};
let seeds = &[
&b"pda"[..],
&self.owner.key().to_bytes()[..],
&self.mint.key().to_bytes()[..],
&[self.pda.bump],
];
let signer_seeds = &[&seeds[..]];
let ctx = CpiContext::new_with_signer(
self.token_program.to_account_info(),
accounts,
signer_seeds
);
close_account(ctx)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment