light_token/instruction/
transfer_checked.rs1use light_sdk_types::LIGHT_TOKEN_PROGRAM_ID;
2use solana_account_info::AccountInfo;
3use solana_cpi::{invoke, invoke_signed};
4use solana_instruction::{AccountMeta, Instruction};
5use solana_program_error::ProgramError;
6use solana_pubkey::Pubkey;
7
8pub struct TransferChecked {
29 pub source: Pubkey,
30 pub mint: Pubkey,
31 pub destination: Pubkey,
32 pub amount: u64,
33 pub decimals: u8,
34 pub authority: Pubkey,
35 pub fee_payer: Pubkey,
37}
38
39pub struct TransferCheckedCpi<'info> {
63 pub source: AccountInfo<'info>,
64 pub mint: AccountInfo<'info>,
65 pub destination: AccountInfo<'info>,
66 pub amount: u64,
67 pub decimals: u8,
68 pub authority: AccountInfo<'info>,
69 pub system_program: AccountInfo<'info>,
70 pub fee_payer: AccountInfo<'info>,
72}
73
74impl<'info> TransferCheckedCpi<'info> {
75 pub fn instruction(&self) -> Result<Instruction, ProgramError> {
76 TransferChecked::from(self).instruction()
77 }
78
79 pub fn invoke(self) -> Result<(), ProgramError> {
80 let instruction = TransferChecked::from(&self).instruction()?;
81 let account_infos = [
82 self.source,
83 self.mint,
84 self.destination,
85 self.authority,
86 self.system_program,
87 self.fee_payer,
88 ];
89 invoke(&instruction, &account_infos)
90 }
91
92 pub fn invoke_signed(self, signer_seeds: &[&[&[u8]]]) -> Result<(), ProgramError> {
93 let instruction = TransferChecked::from(&self).instruction()?;
94 let account_infos = [
95 self.source,
96 self.mint,
97 self.destination,
98 self.authority,
99 self.system_program,
100 self.fee_payer,
101 ];
102 invoke_signed(&instruction, &account_infos, signer_seeds)
103 }
104}
105
106impl<'info> From<&TransferCheckedCpi<'info>> for TransferChecked {
107 fn from(account_infos: &TransferCheckedCpi<'info>) -> Self {
108 Self {
109 source: *account_infos.source.key,
110 mint: *account_infos.mint.key,
111 destination: *account_infos.destination.key,
112 amount: account_infos.amount,
113 decimals: account_infos.decimals,
114 authority: *account_infos.authority.key,
115 fee_payer: *account_infos.fee_payer.key,
116 }
117 }
118}
119
120impl_with_top_up!(TransferChecked, TransferCheckedWithTopUp);
121
122impl TransferChecked {
123 fn build_instruction(self, max_top_up: Option<u16>) -> Result<Instruction, ProgramError> {
124 let accounts = vec![
125 AccountMeta::new(self.source, false),
126 AccountMeta::new_readonly(self.mint, false),
127 AccountMeta::new(self.destination, false),
128 AccountMeta::new_readonly(self.authority, true),
129 AccountMeta::new_readonly(Pubkey::default(), false),
130 AccountMeta::new(self.fee_payer, true),
131 ];
132
133 let mut data = vec![12u8];
134 data.extend_from_slice(&self.amount.to_le_bytes());
135 data.push(self.decimals);
136 if let Some(max_top_up) = max_top_up {
137 data.extend_from_slice(&max_top_up.to_le_bytes());
138 }
139
140 Ok(Instruction {
141 program_id: Pubkey::from(LIGHT_TOKEN_PROGRAM_ID),
142 accounts,
143 data,
144 })
145 }
146}