use solana_program::{ account_info::AccountInfo, entrypoint::ProgramResult, pubkey::Pubkey, rent::Rent, sysvar::Sysvar, }; /// Creates a new pda. #[inline(always)] pub fn create_pda<'a, 'info>( target_account: &'a AccountInfo<'info>, owner: &Pubkey, space: usize, pda_seeds: &[&[u8]], system_program: &'a AccountInfo<'info>, payer: &'a AccountInfo<'info>, ) -> ProgramResult { let rent = Rent::get()?; if target_account.lamports().eq(&0) { // If balance is zero, create account solana_program::program::invoke_signed( &solana_program::system_instruction::create_account( payer.key, target_account.key, rent.minimum_balance(space), space as u64, owner, ), &[ payer.clone(), target_account.clone(), system_program.clone(), ], &[pda_seeds], )?; } else { // Otherwise, if balance is nonzero: // 1) transfer sufficient lamports for rent exemption let rent_exempt_balance = rent .minimum_balance(space) .saturating_sub(target_account.lamports()); if rent_exempt_balance.gt(&0) { solana_program::program::invoke( &solana_program::system_instruction::transfer( payer.key, target_account.key, rent_exempt_balance, ), &[ payer.clone(), target_account.clone(), system_program.clone(), ], )?; } // 2) allocate space for the account solana_program::program::invoke_signed( &solana_program::system_instruction::allocate(target_account.key, space as u64), &[target_account.clone(), system_program.clone()], &[pda_seeds], )?; // 3) assign our program as the owner solana_program::program::invoke_signed( &solana_program::system_instruction::assign(target_account.key, owner), &[target_account.clone(), system_program.clone()], &[pda_seeds], )?; } Ok(()) } #[cfg(feature = "spl")] #[inline(always)] pub fn create_ata<'info>( funder_info: &AccountInfo<'info>, owner_info: &AccountInfo<'info>, token_account_info: &AccountInfo<'info>, mint_info: &AccountInfo<'info>, system_program: &AccountInfo<'info>, token_program: &AccountInfo<'info>, associated_token_program: &AccountInfo<'info>, ) -> ProgramResult { solana_program::program::invoke( &spl_associated_token_account::instruction::create_associated_token_account( funder_info.key, owner_info.key, mint_info.key, &spl_token::id(), ), &[ funder_info.clone(), token_account_info.clone(), owner_info.clone(), mint_info.clone(), system_program.clone(), token_program.clone(), associated_token_program.clone(), ], ) } #[cfg(feature = "spl")] #[inline(always)] pub fn transfer<'info>( authority_info: &AccountInfo<'info>, from_info: &AccountInfo<'info>, to_info: &AccountInfo<'info>, token_program: &AccountInfo<'info>, amount: u64, ) -> ProgramResult { solana_program::program::invoke( &spl_token::instruction::transfer( &spl_token::id(), from_info.key, to_info.key, authority_info.key, &[authority_info.key], amount, )?, &[ token_program.clone(), from_info.clone(), to_info.clone(), authority_info.clone(), ], ) } #[cfg(feature = "spl")] #[inline(always)] pub fn transfer_signed<'info>( authority_info: &AccountInfo<'info>, from_info: &AccountInfo<'info>, to_info: &AccountInfo<'info>, token_program: &AccountInfo<'info>, amount: u64, signer_seeds: &[&[&[u8]]], ) -> ProgramResult { solana_program::program::invoke_signed( &spl_token::instruction::transfer( &spl_token::id(), from_info.key, to_info.key, authority_info.key, &[authority_info.key], amount, )?, &[ token_program.clone(), from_info.clone(), to_info.clone(), authority_info.clone(), ], signer_seeds, ) } #[cfg(feature = "spl")] #[inline(always)] pub fn mint_to_signed<'info>( mint_info: &AccountInfo<'info>, to_info: &AccountInfo<'info>, authority_info: &AccountInfo<'info>, token_program: &AccountInfo<'info>, amount: u64, signer_seeds: &[&[&[u8]]], ) -> ProgramResult { solana_program::program::invoke_signed( &spl_token::instruction::mint_to( &spl_token::id(), mint_info.key, to_info.key, authority_info.key, &[authority_info.key], amount, )?, &[ token_program.clone(), mint_info.clone(), to_info.clone(), authority_info.clone(), ], signer_seeds, ) } #[cfg(feature = "spl")] #[inline(always)] pub fn burn<'info>( token_account_info: &AccountInfo<'info>, mint_info: &AccountInfo<'info>, authority_info: &AccountInfo<'info>, token_program: &AccountInfo<'info>, amount: u64, ) -> ProgramResult { solana_program::program::invoke( &spl_token::instruction::burn( &spl_token::id(), token_account_info.key, mint_info.key, authority_info.key, &[authority_info.key], amount, )?, &[ token_program.clone(), token_account_info.clone(), mint_info.clone(), authority_info.clone(), ], ) }