light_token/instruction/
transfer.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 Transfer {
25 pub source: Pubkey,
26 pub destination: Pubkey,
27 pub amount: u64,
28 pub authority: Pubkey,
29 pub max_top_up: Option<u16>,
32}
33
34pub struct TransferCpi<'info> {
52 pub source: AccountInfo<'info>,
53 pub destination: AccountInfo<'info>,
54 pub amount: u64,
55 pub authority: AccountInfo<'info>,
56 pub max_top_up: Option<u16>,
58}
59
60impl<'info> TransferCpi<'info> {
61 pub fn instruction(&self) -> Result<Instruction, ProgramError> {
62 Transfer::from(self).instruction()
63 }
64
65 pub fn invoke(self) -> Result<(), ProgramError> {
66 let instruction = Transfer::from(&self).instruction()?;
67 let account_infos = [self.source, self.destination, self.authority];
68 invoke(&instruction, &account_infos)
69 }
70
71 pub fn invoke_signed(self, signer_seeds: &[&[&[u8]]]) -> Result<(), ProgramError> {
72 let instruction = Transfer::from(&self).instruction()?;
73 let account_infos = [self.source, self.destination, self.authority];
74 invoke_signed(&instruction, &account_infos, signer_seeds)
75 }
76}
77
78impl<'info> From<&TransferCpi<'info>> for Transfer {
79 fn from(account_infos: &TransferCpi<'info>) -> Self {
80 Self {
81 source: *account_infos.source.key,
82 destination: *account_infos.destination.key,
83 amount: account_infos.amount,
84 authority: *account_infos.authority.key,
85 max_top_up: account_infos.max_top_up,
86 }
87 }
88}
89
90impl Transfer {
91 pub fn instruction(self) -> Result<Instruction, ProgramError> {
92 let authority_meta = if self.max_top_up.is_some() {
94 AccountMeta::new(self.authority, true)
95 } else {
96 AccountMeta::new_readonly(self.authority, true)
97 };
98
99 let mut accounts = vec![
100 AccountMeta::new(self.source, false),
101 AccountMeta::new(self.destination, false),
102 authority_meta,
103 ];
104
105 if self.max_top_up.is_some() {
107 accounts.push(AccountMeta::new_readonly(
108 solana_pubkey::pubkey!("11111111111111111111111111111111"),
109 false,
110 ));
111 }
112
113 Ok(Instruction {
114 program_id: Pubkey::from(LIGHT_TOKEN_PROGRAM_ID),
115 accounts,
116 data: {
117 let mut data = vec![3u8];
118 data.extend_from_slice(&self.amount.to_le_bytes());
119 if let Some(max_top_up) = self.max_top_up {
121 data.extend_from_slice(&max_top_up.to_le_bytes());
122 }
123 data
124 },
125 })
126 }
127}