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
460pub fn reallocate<'info>(
461 ctx: CpiContext<'_, '_, '_, 'info, Reallocate<'info>>,
462 extension_types: &[spl_token_2022::extension::ExtensionType],
463) -> Result<()> {
464 let ix = spl_token_2022::instruction::reallocate(
465 &ctx.program_id,
466 ctx.accounts.account.key,
467 ctx.accounts.payer.key,
468 ctx.accounts.authority.key,
469 &[],
470 extension_types,
471 )?;
472 anchor_lang::solana_program::program::invoke_signed(
473 &ix,
474 &[
475 ctx.accounts.account,
476 ctx.accounts.payer,
477 ctx.accounts.system_program,
478 ctx.accounts.authority,
479 ],
480 ctx.signer_seeds,
481 )
482 .map_err(Into::into)
483}
484
485pub fn withdraw_excess_lamports<'info>(
486 ctx: CpiContext<'_, '_, '_, 'info, WithdrawExcessLamports<'info>>,
487) -> Result<()> {
488 let ix = spl_token_2022::instruction::withdraw_excess_lamports(
489 &ctx.program_id,
490 ctx.accounts.source.key,
491 ctx.accounts.destination.key,
492 ctx.accounts.authority.key,
493 &[],
494 )?;
495 anchor_lang::solana_program::program::invoke_signed(
496 &ix,
497 &[
498 ctx.accounts.source,
499 ctx.accounts.destination,
500 ctx.accounts.authority,
501 ],
502 ctx.signer_seeds,
503 )
504 .map_err(Into::into)
505}
506
507pub fn create_native_mint<'info>(
508 ctx: CpiContext<'_, '_, '_, 'info, CreateNativeMint<'info>>,
509) -> Result<()> {
510 let ix =
511 spl_token_2022::instruction::create_native_mint(&ctx.program_id, ctx.accounts.payer.key)?;
512 anchor_lang::solana_program::program::invoke_signed(
513 &ix,
514 &[
515 ctx.accounts.payer,
516 ctx.accounts.native_mint,
517 ctx.accounts.system_program,
518 ],
519 ctx.signer_seeds,
520 )
521 .map_err(Into::into)
522}
523
524pub fn initialize_non_transferable_mint<'info>(
525 ctx: CpiContext<'_, '_, '_, 'info, InitializeNonTransferableMint<'info>>,
526) -> Result<()> {
527 let ix = spl_token_2022::instruction::initialize_non_transferable_mint(
528 &ctx.program_id,
529 ctx.accounts.mint.key,
530 )?;
531 anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.mint]).map_err(Into::into)
532}
533
534#[derive(Accounts)]
535pub struct Transfer<'info> {
536 pub from: AccountInfo<'info>,
537 pub to: AccountInfo<'info>,
538 pub authority: AccountInfo<'info>,
539}
540
541#[derive(Accounts)]
542pub struct TransferChecked<'info> {
543 pub from: AccountInfo<'info>,
544 pub mint: AccountInfo<'info>,
545 pub to: AccountInfo<'info>,
546 pub authority: AccountInfo<'info>,
547}
548
549#[derive(Accounts)]
550pub struct MintTo<'info> {
551 pub mint: AccountInfo<'info>,
552 pub to: AccountInfo<'info>,
553 pub authority: AccountInfo<'info>,
554}
555
556#[derive(Accounts)]
557pub struct MintToChecked<'info> {
558 pub mint: AccountInfo<'info>,
559 pub to: AccountInfo<'info>,
560 pub authority: AccountInfo<'info>,
561}
562
563#[derive(Accounts)]
564pub struct Burn<'info> {
565 pub mint: AccountInfo<'info>,
566 pub from: AccountInfo<'info>,
567 pub authority: AccountInfo<'info>,
568}
569
570#[derive(Accounts)]
571pub struct BurnChecked<'info> {
572 pub mint: AccountInfo<'info>,
573 pub from: AccountInfo<'info>,
574 pub authority: AccountInfo<'info>,
575}
576
577#[derive(Accounts)]
578pub struct Approve<'info> {
579 pub to: AccountInfo<'info>,
580 pub delegate: AccountInfo<'info>,
581 pub authority: AccountInfo<'info>,
582}
583
584#[derive(Accounts)]
585pub struct ApproveChecked<'info> {
586 pub to: AccountInfo<'info>,
587 pub mint: AccountInfo<'info>,
588 pub delegate: AccountInfo<'info>,
589 pub authority: AccountInfo<'info>,
590}
591
592#[derive(Accounts)]
593pub struct Revoke<'info> {
594 pub source: AccountInfo<'info>,
595 pub authority: AccountInfo<'info>,
596}
597
598#[derive(Accounts)]
599pub struct InitializeAccount<'info> {
600 pub account: AccountInfo<'info>,
601 pub mint: AccountInfo<'info>,
602 pub authority: AccountInfo<'info>,
603 pub rent: AccountInfo<'info>,
604}
605
606#[derive(Accounts)]
607pub struct InitializeAccount3<'info> {
608 pub account: AccountInfo<'info>,
609 pub mint: AccountInfo<'info>,
610 pub authority: AccountInfo<'info>,
611}
612
613#[derive(Accounts)]
614pub struct CloseAccount<'info> {
615 pub account: AccountInfo<'info>,
616 pub destination: AccountInfo<'info>,
617 pub authority: AccountInfo<'info>,
618}
619
620#[derive(Accounts)]
621pub struct FreezeAccount<'info> {
622 pub account: AccountInfo<'info>,
623 pub mint: AccountInfo<'info>,
624 pub authority: AccountInfo<'info>,
625}
626
627#[derive(Accounts)]
628pub struct ThawAccount<'info> {
629 pub account: AccountInfo<'info>,
630 pub mint: AccountInfo<'info>,
631 pub authority: AccountInfo<'info>,
632}
633
634#[derive(Accounts)]
635pub struct InitializeMint<'info> {
636 pub mint: AccountInfo<'info>,
637 pub rent: AccountInfo<'info>,
638}
639
640#[derive(Accounts)]
641pub struct InitializeMint2<'info> {
642 pub mint: AccountInfo<'info>,
643}
644
645#[derive(Accounts)]
646pub struct SetAuthority<'info> {
647 pub current_authority: AccountInfo<'info>,
648 pub account_or_mint: AccountInfo<'info>,
649}
650
651#[derive(Accounts)]
652pub struct SyncNative<'info> {
653 pub account: AccountInfo<'info>,
654}
655
656#[derive(Accounts)]
657pub struct GetAccountDataSize<'info> {
658 pub mint: AccountInfo<'info>,
659}
660
661#[derive(Accounts)]
662pub struct InitializeMintCloseAuthority<'info> {
663 pub mint: AccountInfo<'info>,
664}
665
666#[derive(Accounts)]
667pub struct InitializeImmutableOwner<'info> {
668 pub account: AccountInfo<'info>,
669}
670
671#[derive(Accounts)]
672pub struct AmountToUiAmount<'info> {
673 pub account: AccountInfo<'info>,
674}
675
676#[derive(Accounts)]
677pub struct UiAmountToAmount<'info> {
678 pub account: AccountInfo<'info>,
679}
680
681#[derive(Accounts)]
682pub struct Reallocate<'info> {
683 pub account: AccountInfo<'info>,
684 pub payer: AccountInfo<'info>,
685 pub system_program: AccountInfo<'info>,
686 pub authority: AccountInfo<'info>,
687}
688
689#[derive(Accounts)]
690pub struct WithdrawExcessLamports<'info> {
691 pub source: AccountInfo<'info>,
692 pub destination: AccountInfo<'info>,
693 pub authority: AccountInfo<'info>,
694}
695
696#[derive(Accounts)]
697pub struct CreateNativeMint<'info> {
698 pub payer: AccountInfo<'info>,
699 pub native_mint: AccountInfo<'info>,
700 pub system_program: AccountInfo<'info>,
701}
702
703#[derive(Accounts)]
704pub struct InitializeNonTransferableMint<'info> {
705 pub mint: AccountInfo<'info>,
706}
707
708#[derive(Clone)]
709pub struct Token2022;
710
711impl anchor_lang::Id for Token2022 {
712 fn id() -> Pubkey {
713 ID
714 }
715}