safe_associated_token_account/tools/
account.rs1use {
4 solana_program::{
5 account_info::AccountInfo,
6 entrypoint::ProgramResult,
7 program::{get_return_data, invoke, invoke_signed},
8 program_error::ProgramError,
9 pubkey::Pubkey,
10 rent::Rent,
11 system_instruction,
12 },
13 safe_token_2022::extension::ExtensionType,
14 std::convert::TryInto,
15};
16
17pub fn create_pda_account<'a>(
19 payer: &AccountInfo<'a>,
20 rent: &Rent,
21 space: usize,
22 owner: &Pubkey,
23 system_program: &AccountInfo<'a>,
24 new_pda_account: &AccountInfo<'a>,
25 new_pda_signer_seeds: &[&[u8]],
26) -> ProgramResult {
27 if new_pda_account.lamports() > 0 {
28 let required_lamports = rent
29 .minimum_balance(space)
30 .max(1)
31 .saturating_sub(new_pda_account.lamports());
32
33 if required_lamports > 0 {
34 invoke(
35 &system_instruction::transfer(payer.key, new_pda_account.key, required_lamports),
36 &[
37 payer.clone(),
38 new_pda_account.clone(),
39 system_program.clone(),
40 ],
41 )?;
42 }
43
44 invoke_signed(
45 &system_instruction::allocate(new_pda_account.key, space as u64),
46 &[new_pda_account.clone(), system_program.clone()],
47 &[new_pda_signer_seeds],
48 )?;
49
50 invoke_signed(
51 &system_instruction::assign(new_pda_account.key, owner),
52 &[new_pda_account.clone(), system_program.clone()],
53 &[new_pda_signer_seeds],
54 )
55 } else {
56 invoke_signed(
57 &system_instruction::create_account(
58 payer.key,
59 new_pda_account.key,
60 rent.minimum_balance(space).max(1),
61 space as u64,
62 owner,
63 ),
64 &[
65 payer.clone(),
66 new_pda_account.clone(),
67 system_program.clone(),
68 ],
69 &[new_pda_signer_seeds],
70 )
71 }
72}
73
74pub fn get_account_len<'a>(
77 mint: &AccountInfo<'a>,
78 safe_token_program: &AccountInfo<'a>,
79 extension_types: &[ExtensionType],
80) -> Result<usize, ProgramError> {
81 invoke(
82 &safe_token_2022::instruction::get_account_data_size(
83 safe_token_program.key,
84 mint.key,
85 extension_types,
86 )?,
87 &[mint.clone(), safe_token_program.clone()],
88 )?;
89 get_return_data()
90 .ok_or(ProgramError::InvalidInstructionData)
91 .and_then(|(key, data)| {
92 if key != *safe_token_program.key {
93 return Err(ProgramError::IncorrectProgramId);
94 }
95 data.try_into()
96 .map(usize::from_le_bytes)
97 .map_err(|_| ProgramError::InvalidInstructionData)
98 })
99}