anchor_spl/
token_interface.rs

1use 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}