1use solana_program::{
2 account_info::AccountInfo, entrypoint::ProgramResult, msg, program::invoke_signed,
3 program_error::ProgramError, program_pack::Pack, pubkey::Pubkey, rent::Rent,
4 system_instruction, system_instruction::create_account, sysvar::Sysvar,
5};
6
7#[allow(missing_docs)]
8pub struct Cpi {}
9
10impl Cpi {
11 #[allow(missing_docs)]
12 pub fn create_account<'a>(
13 program_id: &Pubkey,
14 system_program: &AccountInfo<'a>,
15 fee_payer: &AccountInfo<'a>,
16 account_to_create: &AccountInfo<'a>,
17 signer_seeds: &[&[u8]],
18 space: usize,
19 ) -> ProgramResult {
20 let account_lamports = account_to_create.lamports();
21 if account_lamports != 0 && account_to_create.data_is_empty() {
22 let defund_created_account = system_instruction::transfer(
23 account_to_create.key,
24 fee_payer.key,
25 account_lamports,
26 );
27 invoke_signed(
28 &defund_created_account,
29 &[
30 system_program.clone(),
31 fee_payer.clone(),
32 account_to_create.clone(),
33 ],
34 &[signer_seeds],
35 )?;
36 }
37 let create_state_instruction = create_account(
38 fee_payer.key,
39 account_to_create.key,
40 Rent::get()?.minimum_balance(space),
41 space as u64,
42 program_id,
43 );
44
45 invoke_signed(
46 &create_state_instruction,
47 &[
48 system_program.clone(),
49 fee_payer.clone(),
50 account_to_create.clone(),
51 ],
52 &[signer_seeds],
53 )
54 }
55
56 #[allow(clippy::too_many_arguments)]
57 pub fn allocate_and_create_token_account<'a>(
58 token_account_owner: &Pubkey,
59 spl_token_program: &AccountInfo<'a>,
60 payer_info: &AccountInfo<'a>,
61 signer_seeds: &[&[u8]],
62 token_account: &AccountInfo<'a>,
63 mint_account: &AccountInfo<'a>,
64 rent_account: &AccountInfo<'a>,
65 system_program_info: &AccountInfo<'a>,
66 ) -> Result<(), ProgramError> {
67 msg!("Initializing token account");
68 let size = spl_token::state::Account::LEN;
69 let required_lamports = Rent::get()?.minimum_balance(size);
70 let ix_allocate = create_account(
71 payer_info.key,
72 token_account.key,
73 required_lamports,
74 size as u64,
75 &spl_token::ID,
76 );
77 invoke_signed(
78 &ix_allocate,
79 &[
80 system_program_info.clone(),
81 payer_info.clone(),
82 token_account.clone(),
83 ],
84 &[signer_seeds],
85 )?;
86 let ix_initialize = spl_token::instruction::initialize_account2(
87 &spl_token::ID,
88 token_account.key,
89 mint_account.key,
90 token_account_owner,
91 )?;
92 invoke_signed(
93 &ix_initialize,
94 &[
95 spl_token_program.clone(),
96 token_account.clone(),
97 mint_account.clone(),
98 rent_account.clone(),
99 ],
100 &[signer_seeds],
101 )?;
102 Ok(())
103 }
104}