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