1use crate::account_view::AccountView;
7use crate::address::Address;
8use crate::instruction::{CpiAccount, Signer};
9use crate::ProgramResult;
10
11pub const TOKEN_PROGRAM_ID: Address =
13 crate::address!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
14
15pub struct Transfer<'a> {
19 pub from: &'a AccountView,
20 pub to: &'a AccountView,
21 pub authority: &'a AccountView,
22 pub amount: u64,
23}
24
25impl Transfer<'_> {
26 #[inline]
27 pub fn invoke(&self) -> ProgramResult {
28 self.invoke_signed(&[])
29 }
30
31 #[inline]
32 pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
33 let mut data = [0u8; 9];
34 data[0] = 3;
35 data[1..9].copy_from_slice(&self.amount.to_le_bytes());
36
37 let accounts = [
38 CpiAccount::from(self.from),
39 CpiAccount::from(self.to),
40 CpiAccount::from(self.authority),
41 ];
42
43 invoke_token(&data, &accounts, signers)
44 }
45}
46
47pub struct MintTo<'a> {
51 pub mint: &'a AccountView,
52 pub account: &'a AccountView,
53 pub mint_authority: &'a AccountView,
54 pub amount: u64,
55}
56
57impl MintTo<'_> {
58 #[inline]
59 pub fn invoke(&self) -> ProgramResult {
60 self.invoke_signed(&[])
61 }
62
63 #[inline]
64 pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
65 let mut data = [0u8; 9];
66 data[0] = 7;
67 data[1..9].copy_from_slice(&self.amount.to_le_bytes());
68
69 let accounts = [
70 CpiAccount::from(self.mint),
71 CpiAccount::from(self.account),
72 CpiAccount::from(self.mint_authority),
73 ];
74
75 invoke_token(&data, &accounts, signers)
76 }
77}
78
79pub struct Burn<'a> {
83 pub account: &'a AccountView,
84 pub mint: &'a AccountView,
85 pub authority: &'a AccountView,
86 pub amount: u64,
87}
88
89impl Burn<'_> {
90 #[inline]
91 pub fn invoke(&self) -> ProgramResult {
92 self.invoke_signed(&[])
93 }
94
95 #[inline]
96 pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
97 let mut data = [0u8; 9];
98 data[0] = 8;
99 data[1..9].copy_from_slice(&self.amount.to_le_bytes());
100
101 let accounts = [
102 CpiAccount::from(self.account),
103 CpiAccount::from(self.mint),
104 CpiAccount::from(self.authority),
105 ];
106
107 invoke_token(&data, &accounts, signers)
108 }
109}
110
111pub struct CloseAccount<'a> {
115 pub account: &'a AccountView,
116 pub destination: &'a AccountView,
117 pub authority: &'a AccountView,
118}
119
120impl CloseAccount<'_> {
121 #[inline]
122 pub fn invoke(&self) -> ProgramResult {
123 self.invoke_signed(&[])
124 }
125
126 #[inline]
127 pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
128 let data = [9u8];
129
130 let accounts = [
131 CpiAccount::from(self.account),
132 CpiAccount::from(self.destination),
133 CpiAccount::from(self.authority),
134 ];
135
136 invoke_token(&data, &accounts, signers)
137 }
138}
139
140pub struct Approve<'a> {
144 pub source: &'a AccountView,
145 pub delegate: &'a AccountView,
146 pub authority: &'a AccountView,
147 pub amount: u64,
148}
149
150impl Approve<'_> {
151 #[inline]
152 pub fn invoke(&self) -> ProgramResult {
153 self.invoke_signed(&[])
154 }
155
156 #[inline]
157 pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
158 let mut data = [0u8; 9];
159 data[0] = 4;
160 data[1..9].copy_from_slice(&self.amount.to_le_bytes());
161
162 let accounts = [
163 CpiAccount::from(self.source),
164 CpiAccount::from(self.delegate),
165 CpiAccount::from(self.authority),
166 ];
167
168 invoke_token(&data, &accounts, signers)
169 }
170}
171
172pub struct Revoke<'a> {
176 pub source: &'a AccountView,
177 pub authority: &'a AccountView,
178}
179
180impl Revoke<'_> {
181 #[inline]
182 pub fn invoke(&self) -> ProgramResult {
183 self.invoke_signed(&[])
184 }
185
186 #[inline]
187 pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
188 let data = [5u8];
189
190 let accounts = [
191 CpiAccount::from(self.source),
192 CpiAccount::from(self.authority),
193 ];
194
195 invoke_token(&data, &accounts, signers)
196 }
197}
198
199#[inline]
202fn invoke_token(data: &[u8], accounts: &[CpiAccount], signers: &[Signer]) -> ProgramResult {
203 #[cfg(target_os = "solana")]
204 {
205 let ix = crate::instruction::InstructionView {
206 program_id: &TOKEN_PROGRAM_ID,
207 data,
208 accounts: &[],
209 };
210 let result = unsafe {
211 crate::syscalls::sol_invoke_signed_c(
212 &ix as *const _ as *const u8,
213 accounts.as_ptr() as *const u8,
214 accounts.len() as u64,
215 signers.as_ptr() as *const u8,
216 signers.len() as u64,
217 )
218 };
219 if result == 0 {
220 Ok(())
221 } else {
222 Err(crate::ProgramError::from(result))
223 }
224 }
225 #[cfg(not(target_os = "solana"))]
226 {
227 let _ = (data, accounts, signers);
228 Ok(())
229 }
230}
231
232pub mod instructions {
234 pub use super::{Approve, Burn, CloseAccount, MintTo, Revoke, Transfer};
235}