Skip to main content

carbon_token_program_decoder/accounts/
mod.rs

1//! This code was AUTOGENERATED using the Codama library.
2use {
3    crate::{TokenProgramDecoder, PROGRAM_ID},
4    solana_program_pack::Pack,
5};
6
7#[cfg(feature = "postgres")]
8pub mod postgres;
9
10#[cfg(feature = "graphql")]
11pub mod graphql;
12
13pub mod mint;
14pub mod multisig;
15pub mod token;
16
17#[derive(Debug, Clone, PartialEq)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19#[cfg_attr(feature = "serde", serde(tag = "type", content = "data"))]
20pub enum TokenProgramAccount {
21    Mint(Box<mint::Mint>),
22    Multisig(Box<multisig::Multisig>),
23    Token(Box<token::Token>),
24}
25
26impl<'a> carbon_core::account::AccountDecoder<'a> for TokenProgramDecoder {
27    type AccountType = TokenProgramAccount;
28
29    fn decode_account(
30        &self,
31        account: &'a solana_account::Account,
32    ) -> Option<carbon_core::account::DecodedAccount<Self::AccountType>> {
33        if account.owner != PROGRAM_ID {
34            return None;
35        }
36
37        if let Ok(data) = spl_token_interface::state::Mint::unpack(&account.data) {
38            return Some(carbon_core::account::DecodedAccount {
39                lamports: account.lamports,
40                data: TokenProgramAccount::Mint(Box::new(mint::Mint::from(data))),
41                owner: account.owner,
42                executable: account.executable,
43                rent_epoch: account.rent_epoch,
44            });
45        }
46        if let Ok(data) = spl_token_interface::state::Account::unpack(&account.data) {
47            return Some(carbon_core::account::DecodedAccount {
48                lamports: account.lamports,
49                data: TokenProgramAccount::Token(Box::new(token::Token::from(data))),
50                owner: account.owner,
51                executable: account.executable,
52                rent_epoch: account.rent_epoch,
53            });
54        }
55        if let Ok(data) = spl_token_interface::state::Multisig::unpack(&account.data) {
56            return Some(carbon_core::account::DecodedAccount {
57                lamports: account.lamports,
58                data: TokenProgramAccount::Multisig(Box::new(multisig::Multisig::from(data))),
59                owner: account.owner,
60                executable: account.executable,
61                rent_epoch: account.rent_epoch,
62            });
63        }
64
65        None
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use {
72        super::*, carbon_core::account::AccountDecoder, solana_program_pack::Pack,
73        solana_pubkey::Pubkey,
74    };
75
76    const TOKEN_PROGRAM_ID: Pubkey =
77        solana_pubkey::Pubkey::from_str_const("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
78
79    #[test]
80    fn decode_token_account_uses_spl_token_pack_layout() {
81        let mint = Pubkey::new_from_array([1; 32]);
82        let owner = Pubkey::new_from_array([2; 32]);
83        let source = spl_token_interface::state::Account {
84            mint,
85            owner,
86            amount: 58_727_131,
87            state: spl_token_interface::state::AccountState::Initialized,
88            ..Default::default()
89        };
90        let mut data = vec![0u8; spl_token_interface::state::Account::LEN];
91        spl_token_interface::state::Account::pack(source, &mut data).expect("pack account");
92
93        let account = solana_account::Account {
94            lamports: 2_039_280,
95            data,
96            owner: TOKEN_PROGRAM_ID,
97            executable: false,
98            rent_epoch: 0,
99        };
100
101        let decoded = TokenProgramDecoder
102            .decode_account(&account)
103            .expect("account should decode");
104
105        match decoded.data {
106            TokenProgramAccount::Token(token) => {
107                assert_eq!(token.mint, mint);
108                assert_eq!(token.owner, owner);
109                assert_eq!(token.amount, 58_727_131);
110                assert_eq!(token.state, crate::types::AccountState::Initialized);
111            }
112            _ => panic!("expected token account"),
113        }
114    }
115}