1#![allow(deprecated)]
3use anchor_lang::{
4 context::CpiContext,
5 solana_program::{account_info::AccountInfo, pubkey::Pubkey},
6 Accounts, Result,
7};
8pub use {spl_token_2022::ID, spl_token_2022_interface as spl_token_2022};
9
10#[deprecated(
11 since = "0.28.0",
12 note = "please use `transfer_checked` or `transfer_checked_with_fee` instead"
13)]
14pub fn transfer<'info>(
15 ctx: CpiContext<'_, '_, '_, 'info, Transfer<'info>>,
16 amount: u64,
17) -> Result<()> {
18 #[allow(deprecated)]
19 let ix = spl_token_2022::instruction::transfer(
20 &ctx.program_id,
21 ctx.accounts.from.key,
22 ctx.accounts.to.key,
23 ctx.accounts.authority.key,
24 &[],
25 amount,
26 )?;
27 anchor_lang::solana_program::program::invoke_signed(
28 &ix,
29 &[ctx.accounts.from, ctx.accounts.to, ctx.accounts.authority],
30 ctx.signer_seeds,
31 )
32 .map_err(Into::into)
33}
34
35pub fn transfer_checked<'info>(
36 ctx: CpiContext<'_, '_, '_, 'info, TransferChecked<'info>>,
37 amount: u64,
38 decimals: u8,
39) -> Result<()> {
40 let ix = spl_token_2022::instruction::transfer_checked(
41 &ctx.program_id,
42 ctx.accounts.from.key,
43 ctx.accounts.mint.key,
44 ctx.accounts.to.key,
45 ctx.accounts.authority.key,
46 &[],
47 amount,
48 decimals,
49 )?;
50 anchor_lang::solana_program::program::invoke_signed(
51 &ix,
52 &[
53 ctx.accounts.from,
54 ctx.accounts.mint,
55 ctx.accounts.to,
56 ctx.accounts.authority,
57 ],
58 ctx.signer_seeds,
59 )
60 .map_err(Into::into)
61}
62
63pub fn mint_to<'info>(
64 ctx: CpiContext<'_, '_, '_, 'info, MintTo<'info>>,
65 amount: u64,
66) -> Result<()> {
67 let ix = spl_token_2022::instruction::mint_to(
68 &ctx.program_id,
69 ctx.accounts.mint.key,
70 ctx.accounts.to.key,
71 ctx.accounts.authority.key,
72 &[],
73 amount,
74 )?;
75 anchor_lang::solana_program::program::invoke_signed(
76 &ix,
77 &[ctx.accounts.to, ctx.accounts.mint, ctx.accounts.authority],
78 ctx.signer_seeds,
79 )
80 .map_err(Into::into)
81}
82
83pub fn mint_to_checked<'info>(
84 ctx: CpiContext<'_, '_, '_, 'info, MintToChecked<'info>>,
85 amount: u64,
86 decimals: u8,
87) -> Result<()> {
88 let ix = spl_token_2022::instruction::mint_to_checked(
89 &ctx.program_id,
90 ctx.accounts.mint.key,
91 ctx.accounts.to.key,
92 ctx.accounts.authority.key,
93 &[],
94 amount,
95 decimals,
96 )?;
97 anchor_lang::solana_program::program::invoke_signed(
98 &ix,
99 &[ctx.accounts.to, ctx.accounts.mint, ctx.accounts.authority],
100 ctx.signer_seeds,
101 )
102 .map_err(Into::into)
103}
104
105pub fn burn<'info>(ctx: CpiContext<'_, '_, '_, 'info, Burn<'info>>, amount: u64) -> Result<()> {
106 let ix = spl_token_2022::instruction::burn(
107 &ctx.program_id,
108 ctx.accounts.from.key,
109 ctx.accounts.mint.key,
110 ctx.accounts.authority.key,
111 &[],
112 amount,
113 )?;
114 anchor_lang::solana_program::program::invoke_signed(
115 &ix,
116 &[ctx.accounts.from, ctx.accounts.mint, ctx.accounts.authority],
117 ctx.signer_seeds,
118 )
119 .map_err(Into::into)
120}
121
122pub fn burn_checked<'info>(
123 ctx: CpiContext<'_, '_, '_, 'info, BurnChecked<'info>>,
124 amount: u64,
125 decimals: u8,
126) -> Result<()> {
127 let ix = spl_token_2022::instruction::burn_checked(
128 &ctx.program_id,
129 ctx.accounts.from.key,
130 ctx.accounts.mint.key,
131 ctx.accounts.authority.key,
132 &[],
133 amount,
134 decimals,
135 )?;
136 anchor_lang::solana_program::program::invoke_signed(
137 &ix,
138 &[ctx.accounts.from, ctx.accounts.mint, ctx.accounts.authority],
139 ctx.signer_seeds,
140 )
141 .map_err(Into::into)
142}
143
144pub fn approve<'info>(
145 ctx: CpiContext<'_, '_, '_, 'info, Approve<'info>>,
146 amount: u64,
147) -> Result<()> {
148 let ix = spl_token_2022::instruction::approve(
149 &ctx.program_id,
150 ctx.accounts.to.key,
151 ctx.accounts.delegate.key,
152 ctx.accounts.authority.key,
153 &[],
154 amount,
155 )?;
156 anchor_lang::solana_program::program::invoke_signed(
157 &ix,
158 &[
159 ctx.accounts.to,
160 ctx.accounts.delegate,
161 ctx.accounts.authority,
162 ],
163 ctx.signer_seeds,
164 )
165 .map_err(Into::into)
166}
167
168pub fn approve_checked<'info>(
169 ctx: CpiContext<'_, '_, '_, 'info, ApproveChecked<'info>>,
170 amount: u64,
171 decimals: u8,
172) -> Result<()> {
173 let ix = spl_token_2022::instruction::approve_checked(
174 &ctx.program_id,
175 ctx.accounts.to.key,
176 ctx.accounts.mint.key,
177 ctx.accounts.delegate.key,
178 ctx.accounts.authority.key,
179 &[],
180 amount,
181 decimals,
182 )?;
183 anchor_lang::solana_program::program::invoke_signed(
184 &ix,
185 &[
186 ctx.accounts.to,
187 ctx.accounts.mint,
188 ctx.accounts.delegate,
189 ctx.accounts.authority,
190 ],
191 ctx.signer_seeds,
192 )
193 .map_err(Into::into)
194}
195
196pub fn revoke<'info>(ctx: CpiContext<'_, '_, '_, 'info, Revoke<'info>>) -> Result<()> {
197 let ix = spl_token_2022::instruction::revoke(
198 &ctx.program_id,
199 ctx.accounts.source.key,
200 ctx.accounts.authority.key,
201 &[],
202 )?;
203 anchor_lang::solana_program::program::invoke_signed(
204 &ix,
205 &[ctx.accounts.source, ctx.accounts.authority],
206 ctx.signer_seeds,
207 )
208 .map_err(Into::into)
209}
210
211pub fn initialize_account<'info>(
212 ctx: CpiContext<'_, '_, '_, 'info, InitializeAccount<'info>>,
213) -> Result<()> {
214 let ix = spl_token_2022::instruction::initialize_account(
215 &ctx.program_id,
216 ctx.accounts.account.key,
217 ctx.accounts.mint.key,
218 ctx.accounts.authority.key,
219 )?;
220 anchor_lang::solana_program::program::invoke(
221 &ix,
222 &[
223 ctx.accounts.account,
224 ctx.accounts.mint,
225 ctx.accounts.authority,
226 ctx.accounts.rent,
227 ],
228 )
229 .map_err(Into::into)
230}
231
232pub fn initialize_account3<'info>(
233 ctx: CpiContext<'_, '_, '_, 'info, InitializeAccount3<'info>>,
234) -> Result<()> {
235 let ix = spl_token_2022::instruction::initialize_account3(
236 &ctx.program_id,
237 ctx.accounts.account.key,
238 ctx.accounts.mint.key,
239 ctx.accounts.authority.key,
240 )?;
241 anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.account, ctx.accounts.mint])
242 .map_err(Into::into)
243}
244
245pub fn close_account<'info>(ctx: CpiContext<'_, '_, '_, 'info, CloseAccount<'info>>) -> Result<()> {
246 let ix = spl_token_2022::instruction::close_account(
247 &ctx.program_id,
248 ctx.accounts.account.key,
249 ctx.accounts.destination.key,
250 ctx.accounts.authority.key,
251 &[], )?;
253 anchor_lang::solana_program::program::invoke_signed(
254 &ix,
255 &[
256 ctx.accounts.account,
257 ctx.accounts.destination,
258 ctx.accounts.authority,
259 ],
260 ctx.signer_seeds,
261 )
262 .map_err(Into::into)
263}
264
265pub fn freeze_account<'info>(
266 ctx: CpiContext<'_, '_, '_, 'info, FreezeAccount<'info>>,
267) -> Result<()> {
268 let ix = spl_token_2022::instruction::freeze_account(
269 &ctx.program_id,
270 ctx.accounts.account.key,
271 ctx.accounts.mint.key,
272 ctx.accounts.authority.key,
273 &[], )?;
275 anchor_lang::solana_program::program::invoke_signed(
276 &ix,
277 &[
278 ctx.accounts.account,
279 ctx.accounts.mint,
280 ctx.accounts.authority,
281 ],
282 ctx.signer_seeds,
283 )
284 .map_err(Into::into)
285}
286
287pub fn thaw_account<'info>(ctx: CpiContext<'_, '_, '_, 'info, ThawAccount<'info>>) -> Result<()> {
288 let ix = spl_token_2022::instruction::thaw_account(
289 &ctx.program_id,
290 ctx.accounts.account.key,
291 ctx.accounts.mint.key,
292 ctx.accounts.authority.key,
293 &[], )?;
295 anchor_lang::solana_program::program::invoke_signed(
296 &ix,
297 &[
298 ctx.accounts.account,
299 ctx.accounts.mint,
300 ctx.accounts.authority,
301 ],
302 ctx.signer_seeds,
303 )
304 .map_err(Into::into)
305}
306
307pub fn initialize_mint<'info>(
308 ctx: CpiContext<'_, '_, '_, 'info, InitializeMint<'info>>,
309 decimals: u8,
310 authority: &Pubkey,
311 freeze_authority: Option<&Pubkey>,
312) -> Result<()> {
313 let ix = spl_token_2022::instruction::initialize_mint(
314 &ctx.program_id,
315 ctx.accounts.mint.key,
316 authority,
317 freeze_authority,
318 decimals,
319 )?;
320 anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.mint, ctx.accounts.rent])
321 .map_err(Into::into)
322}
323
324pub fn initialize_mint2<'info>(
325 ctx: CpiContext<'_, '_, '_, 'info, InitializeMint2<'info>>,
326 decimals: u8,
327 authority: &Pubkey,
328 freeze_authority: Option<&Pubkey>,
329) -> Result<()> {
330 let ix = spl_token_2022::instruction::initialize_mint2(
331 &ctx.program_id,
332 ctx.accounts.mint.key,
333 authority,
334 freeze_authority,
335 decimals,
336 )?;
337 anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.mint]).map_err(Into::into)
338}
339
340pub fn set_authority<'info>(
341 ctx: CpiContext<'_, '_, '_, 'info, SetAuthority<'info>>,
342 authority_type: spl_token_2022::instruction::AuthorityType,
343 new_authority: Option<Pubkey>,
344) -> Result<()> {
345 let ix = spl_token_2022::instruction::set_authority(
346 &ctx.program_id,
347 ctx.accounts.account_or_mint.key,
348 new_authority.as_ref(),
349 authority_type,
350 ctx.accounts.current_authority.key,
351 &[], )?;
353 anchor_lang::solana_program::program::invoke_signed(
354 &ix,
355 &[ctx.accounts.account_or_mint, ctx.accounts.current_authority],
356 ctx.signer_seeds,
357 )
358 .map_err(Into::into)
359}
360
361pub fn sync_native<'info>(ctx: CpiContext<'_, '_, '_, 'info, SyncNative<'info>>) -> Result<()> {
362 let ix = spl_token_2022::instruction::sync_native(&ctx.program_id, ctx.accounts.account.key)?;
363 anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.account]).map_err(Into::into)
364}
365
366pub fn get_account_data_size<'info>(
367 ctx: CpiContext<'_, '_, '_, 'info, GetAccountDataSize<'info>>,
368 extension_types: &[spl_token_2022::extension::ExtensionType],
369) -> Result<u64> {
370 let ix = spl_token_2022::instruction::get_account_data_size(
371 &ctx.program_id,
372 ctx.accounts.mint.key,
373 extension_types,
374 )?;
375 anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.mint])?;
376 anchor_lang::solana_program::program::get_return_data()
377 .ok_or(anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData)
378 .and_then(|(key, data)| {
379 if key != ctx.program_id {
380 Err(anchor_lang::solana_program::program_error::ProgramError::IncorrectProgramId)
381 } else {
382 data.try_into().map(u64::from_le_bytes).map_err(|_| {
383 anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData
384 })
385 }
386 })
387 .map_err(Into::into)
388}
389
390pub fn initialize_mint_close_authority<'info>(
391 ctx: CpiContext<'_, '_, '_, 'info, InitializeMintCloseAuthority<'info>>,
392 close_authority: Option<&Pubkey>,
393) -> Result<()> {
394 let ix = spl_token_2022::instruction::initialize_mint_close_authority(
395 &ctx.program_id,
396 ctx.accounts.mint.key,
397 close_authority,
398 )?;
399 anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.mint]).map_err(Into::into)
400}
401
402pub fn initialize_immutable_owner<'info>(
403 ctx: CpiContext<'_, '_, '_, 'info, InitializeImmutableOwner<'info>>,
404) -> Result<()> {
405 let ix = spl_token_2022::instruction::initialize_immutable_owner(
406 &ctx.program_id,
407 ctx.accounts.account.key,
408 )?;
409 anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.account]).map_err(Into::into)
410}
411
412pub fn amount_to_ui_amount<'info>(
413 ctx: CpiContext<'_, '_, '_, 'info, AmountToUiAmount<'info>>,
414 amount: u64,
415) -> Result<String> {
416 let ix = spl_token_2022::instruction::amount_to_ui_amount(
417 &ctx.program_id,
418 ctx.accounts.account.key,
419 amount,
420 )?;
421 anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.account])?;
422 anchor_lang::solana_program::program::get_return_data()
423 .ok_or(anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData)
424 .and_then(|(key, data)| {
425 if key != ctx.program_id {
426 Err(anchor_lang::solana_program::program_error::ProgramError::IncorrectProgramId)
427 } else {
428 String::from_utf8(data).map_err(|_| {
429 anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData
430 })
431 }
432 })
433 .map_err(Into::into)
434}
435
436pub fn ui_amount_to_amount<'info>(
437 ctx: CpiContext<'_, '_, '_, 'info, UiAmountToAmount<'info>>,
438 ui_amount: &str,
439) -> Result<u64> {
440 let ix = spl_token_2022::instruction::ui_amount_to_amount(
441 &ctx.program_id,
442 ctx.accounts.account.key,
443 ui_amount,
444 )?;
445 anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.account])?;
446 anchor_lang::solana_program::program::get_return_data()
447 .ok_or(anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData)
448 .and_then(|(key, data)| {
449 if key != ctx.program_id {
450 Err(anchor_lang::solana_program::program_error::ProgramError::IncorrectProgramId)
451 } else {
452 data.try_into().map(u64::from_le_bytes).map_err(|_| {
453 anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData
454 })
455 }
456 })
457 .map_err(Into::into)
458}
459
460#[derive(Accounts)]
461pub struct Transfer<'info> {
462 pub from: AccountInfo<'info>,
463 pub to: AccountInfo<'info>,
464 pub authority: AccountInfo<'info>,
465}
466
467#[derive(Accounts)]
468pub struct TransferChecked<'info> {
469 pub from: AccountInfo<'info>,
470 pub mint: AccountInfo<'info>,
471 pub to: AccountInfo<'info>,
472 pub authority: AccountInfo<'info>,
473}
474
475#[derive(Accounts)]
476pub struct MintTo<'info> {
477 pub mint: AccountInfo<'info>,
478 pub to: AccountInfo<'info>,
479 pub authority: AccountInfo<'info>,
480}
481
482#[derive(Accounts)]
483pub struct MintToChecked<'info> {
484 pub mint: AccountInfo<'info>,
485 pub to: AccountInfo<'info>,
486 pub authority: AccountInfo<'info>,
487}
488
489#[derive(Accounts)]
490pub struct Burn<'info> {
491 pub mint: AccountInfo<'info>,
492 pub from: AccountInfo<'info>,
493 pub authority: AccountInfo<'info>,
494}
495
496#[derive(Accounts)]
497pub struct BurnChecked<'info> {
498 pub mint: AccountInfo<'info>,
499 pub from: AccountInfo<'info>,
500 pub authority: AccountInfo<'info>,
501}
502
503#[derive(Accounts)]
504pub struct Approve<'info> {
505 pub to: AccountInfo<'info>,
506 pub delegate: AccountInfo<'info>,
507 pub authority: AccountInfo<'info>,
508}
509
510#[derive(Accounts)]
511pub struct ApproveChecked<'info> {
512 pub to: AccountInfo<'info>,
513 pub mint: AccountInfo<'info>,
514 pub delegate: AccountInfo<'info>,
515 pub authority: AccountInfo<'info>,
516}
517
518#[derive(Accounts)]
519pub struct Revoke<'info> {
520 pub source: AccountInfo<'info>,
521 pub authority: AccountInfo<'info>,
522}
523
524#[derive(Accounts)]
525pub struct InitializeAccount<'info> {
526 pub account: AccountInfo<'info>,
527 pub mint: AccountInfo<'info>,
528 pub authority: AccountInfo<'info>,
529 pub rent: AccountInfo<'info>,
530}
531
532#[derive(Accounts)]
533pub struct InitializeAccount3<'info> {
534 pub account: AccountInfo<'info>,
535 pub mint: AccountInfo<'info>,
536 pub authority: AccountInfo<'info>,
537}
538
539#[derive(Accounts)]
540pub struct CloseAccount<'info> {
541 pub account: AccountInfo<'info>,
542 pub destination: AccountInfo<'info>,
543 pub authority: AccountInfo<'info>,
544}
545
546#[derive(Accounts)]
547pub struct FreezeAccount<'info> {
548 pub account: AccountInfo<'info>,
549 pub mint: AccountInfo<'info>,
550 pub authority: AccountInfo<'info>,
551}
552
553#[derive(Accounts)]
554pub struct ThawAccount<'info> {
555 pub account: AccountInfo<'info>,
556 pub mint: AccountInfo<'info>,
557 pub authority: AccountInfo<'info>,
558}
559
560#[derive(Accounts)]
561pub struct InitializeMint<'info> {
562 pub mint: AccountInfo<'info>,
563 pub rent: AccountInfo<'info>,
564}
565
566#[derive(Accounts)]
567pub struct InitializeMint2<'info> {
568 pub mint: AccountInfo<'info>,
569}
570
571#[derive(Accounts)]
572pub struct SetAuthority<'info> {
573 pub current_authority: AccountInfo<'info>,
574 pub account_or_mint: AccountInfo<'info>,
575}
576
577#[derive(Accounts)]
578pub struct SyncNative<'info> {
579 pub account: AccountInfo<'info>,
580}
581
582#[derive(Accounts)]
583pub struct GetAccountDataSize<'info> {
584 pub mint: AccountInfo<'info>,
585}
586
587#[derive(Accounts)]
588pub struct InitializeMintCloseAuthority<'info> {
589 pub mint: AccountInfo<'info>,
590}
591
592#[derive(Accounts)]
593pub struct InitializeImmutableOwner<'info> {
594 pub account: AccountInfo<'info>,
595}
596
597#[derive(Accounts)]
598pub struct AmountToUiAmount<'info> {
599 pub account: AccountInfo<'info>,
600}
601
602#[derive(Accounts)]
603pub struct UiAmountToAmount<'info> {
604 pub account: AccountInfo<'info>,
605}
606
607#[derive(Clone)]
608pub struct Token2022;
609
610impl anchor_lang::Id for Token2022 {
611 fn id() -> Pubkey {
612 ID
613 }
614}