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 {
28 pub source: Pubkey,
29 pub mint: Pubkey,
30 pub destination: Pubkey,
31 pub amount: u64,
32 pub decimals: u8,
33 pub authority: Pubkey,
34 pub max_top_up: Option<u16>,
37}
38
39pub struct TransferCheckedCpi<'info> {
60 pub source: AccountInfo<'info>,
61 pub mint: AccountInfo<'info>,
62 pub destination: AccountInfo<'info>,
63 pub amount: u64,
64 pub decimals: u8,
65 pub authority: AccountInfo<'info>,
66 pub max_top_up: Option<u16>,
68}
69
70impl<'info> TransferCheckedCpi<'info> {
71 pub fn instruction(&self) -> Result<Instruction, ProgramError> {
72 TransferChecked::from(self).instruction()
73 }
74
75 pub fn invoke(self) -> Result<(), ProgramError> {
76 let instruction = TransferChecked::from(&self).instruction()?;
77 let account_infos = [self.source, self.mint, self.destination, self.authority];
78 invoke(&instruction, &account_infos)
79 }
80
81 pub fn invoke_signed(self, signer_seeds: &[&[&[u8]]]) -> Result<(), ProgramError> {
82 let instruction = TransferChecked::from(&self).instruction()?;
83 let account_infos = [self.source, self.mint, self.destination, self.authority];
84 invoke_signed(&instruction, &account_infos, signer_seeds)
85 }
86}
87
88impl<'info> From<&TransferCheckedCpi<'info>> for TransferChecked {
89 fn from(account_infos: &TransferCheckedCpi<'info>) -> Self {
90 Self {
91 source: *account_infos.source.key,
92 mint: *account_infos.mint.key,
93 destination: *account_infos.destination.key,
94 amount: account_infos.amount,
95 decimals: account_infos.decimals,
96 authority: *account_infos.authority.key,
97 max_top_up: account_infos.max_top_up,
98 }
99 }
100}
101
102impl TransferChecked {
103 pub fn instruction(self) -> Result<Instruction, ProgramError> {
104 let authority_meta = if self.max_top_up.is_some() {
106 AccountMeta::new(self.authority, true)
107 } else {
108 AccountMeta::new_readonly(self.authority, true)
109 };
110
111 let mut accounts = vec![
112 AccountMeta::new(self.source, false),
113 AccountMeta::new_readonly(self.mint, false),
114 AccountMeta::new(self.destination, false),
115 authority_meta,
116 ];
117
118 if self.max_top_up.is_some() {
120 accounts.push(AccountMeta::new_readonly(
121 solana_pubkey::pubkey!("11111111111111111111111111111111"),
122 false,
123 ));
124 }
125
126 Ok(Instruction {
127 program_id: Pubkey::from(LIGHT_TOKEN_PROGRAM_ID),
128 accounts,
129 data: {
130 let mut data = vec![12u8]; data.extend_from_slice(&self.amount.to_le_bytes());
133 data.push(self.decimals);
134 if let Some(max_top_up) = self.max_top_up {
136 data.extend_from_slice(&max_top_up.to_le_bytes());
137 }
138 data
139 },
140 })
141 }
142}