anchor_spl/
token_interface.rs1use anchor_lang::__private::bytemuck::Pod;
2use anchor_lang::solana_program::program_pack::Pack;
3use anchor_lang::solana_program::pubkey::Pubkey;
4use spl_token_2022::extension::ExtensionType;
5use spl_token_2022::extension::{BaseStateWithExtensions, Extension, StateWithExtensions};
6use std::ops::Deref;
7
8pub use crate::token_2022::*;
9#[cfg(feature = "token_2022_extensions")]
10pub use crate::token_2022_extensions::*;
11
12static IDS: [Pubkey; 2] = [spl_token::ID, spl_token_2022::ID];
13
14#[derive(Clone, Debug, Default, PartialEq, Copy)]
15pub struct TokenAccount(spl_token_2022::state::Account);
16
17impl anchor_lang::AccountDeserialize for TokenAccount {
18 fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result<Self> {
19 spl_token_2022::extension::StateWithExtensions::<spl_token_2022::state::Account>::unpack(
20 buf,
21 )
22 .map(|t| TokenAccount(t.base))
23 .map_err(Into::into)
24 }
25}
26
27impl anchor_lang::AccountSerialize for TokenAccount {}
28
29impl anchor_lang::Owners for TokenAccount {
30 fn owners() -> &'static [Pubkey] {
31 &IDS
32 }
33}
34
35impl Deref for TokenAccount {
36 type Target = spl_token_2022::state::Account;
37
38 fn deref(&self) -> &Self::Target {
39 &self.0
40 }
41}
42
43#[derive(Clone, Debug, Default, PartialEq, Copy)]
44pub struct Mint(spl_token_2022::state::Mint);
45
46impl anchor_lang::AccountDeserialize for Mint {
47 fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result<Self> {
48 spl_token_2022::extension::StateWithExtensions::<spl_token_2022::state::Mint>::unpack(buf)
49 .map(|t| Mint(t.base))
50 .map_err(Into::into)
51 }
52}
53
54impl anchor_lang::AccountSerialize for Mint {}
55
56impl anchor_lang::Owners for Mint {
57 fn owners() -> &'static [Pubkey] {
58 &IDS
59 }
60}
61
62impl Deref for Mint {
63 type Target = spl_token_2022::state::Mint;
64
65 fn deref(&self) -> &Self::Target {
66 &self.0
67 }
68}
69
70#[derive(Clone)]
71pub struct TokenInterface;
72
73impl anchor_lang::Ids for TokenInterface {
74 fn ids() -> &'static [Pubkey] {
75 &IDS
76 }
77}
78
79pub type ExtensionsVec = Vec<ExtensionType>;
80
81pub fn find_mint_account_size(extensions: Option<&ExtensionsVec>) -> anchor_lang::Result<usize> {
82 if let Some(extensions) = extensions {
83 Ok(ExtensionType::try_calculate_account_len::<
84 spl_token_2022::state::Mint,
85 >(extensions)?)
86 } else {
87 Ok(spl_token_2022::state::Mint::LEN)
88 }
89}
90
91pub fn get_mint_extension_data<T: Extension + Pod>(
92 account: &anchor_lang::solana_program::account_info::AccountInfo,
93) -> anchor_lang::Result<T> {
94 let mint_data = account.data.borrow();
95 let mint_with_extension =
96 StateWithExtensions::<spl_token_2022::state::Mint>::unpack(&mint_data)?;
97 let extension_data = *mint_with_extension.get_extension::<T>()?;
98 Ok(extension_data)
99}