Skip to main content

anchor_spl/
token_interface.rs

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