spl_token_2022/
generic_token_account.rs1use {
4 crate::state::AccountState,
5 solana_program::pubkey::{Pubkey, PUBKEY_BYTES},
6};
7
8const SPL_TOKEN_ACCOUNT_MINT_OFFSET: usize = 0;
9const SPL_TOKEN_ACCOUNT_OWNER_OFFSET: usize = 32;
10
11pub trait GenericTokenAccount {
14 fn valid_account_data(account_data: &[u8]) -> bool;
16
17 fn unpack_account_owner_unchecked(account_data: &[u8]) -> &Pubkey {
20 Self::unpack_pubkey_unchecked(account_data, SPL_TOKEN_ACCOUNT_OWNER_OFFSET)
21 }
22
23 fn unpack_account_mint_unchecked(account_data: &[u8]) -> &Pubkey {
26 Self::unpack_pubkey_unchecked(account_data, SPL_TOKEN_ACCOUNT_MINT_OFFSET)
27 }
28
29 fn unpack_pubkey_unchecked(account_data: &[u8], offset: usize) -> &Pubkey {
33 bytemuck::from_bytes(&account_data[offset..offset + PUBKEY_BYTES])
34 }
35
36 fn unpack_account_owner(account_data: &[u8]) -> Option<&Pubkey> {
38 if Self::valid_account_data(account_data) {
39 Some(Self::unpack_account_owner_unchecked(account_data))
40 } else {
41 None
42 }
43 }
44
45 fn unpack_account_mint(account_data: &[u8]) -> Option<&Pubkey> {
47 if Self::valid_account_data(account_data) {
48 Some(Self::unpack_account_mint_unchecked(account_data))
49 } else {
50 None
51 }
52 }
53}
54
55pub const ACCOUNT_INITIALIZED_INDEX: usize = 108;
57
58pub fn is_initialized_account(account_data: &[u8]) -> bool {
61 *account_data
62 .get(ACCOUNT_INITIALIZED_INDEX)
63 .unwrap_or(&(AccountState::Uninitialized as u8))
64 != AccountState::Uninitialized as u8
65}