carbon-token-program-decoder 2.0.0

Token Program Decoder
Documentation
//! This code was AUTOGENERATED using the Codama library.
use {
    crate::{TokenProgramDecoder, PROGRAM_ID},
    solana_program_pack::Pack,
};

#[cfg(feature = "postgres")]
pub mod postgres;

#[cfg(feature = "graphql")]
pub mod graphql;

pub mod mint;
pub mod multisig;
pub mod token;

#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(tag = "type", content = "data"))]
pub enum TokenProgramAccount {
    Mint(Box<mint::Mint>),
    Multisig(Box<multisig::Multisig>),
    Token(Box<token::Token>),
}

impl<'a> carbon_core::account::AccountDecoder<'a> for TokenProgramDecoder {
    type AccountType = TokenProgramAccount;

    fn decode_account(
        &self,
        account: &'a solana_account::Account,
    ) -> Option<carbon_core::account::DecodedAccount<Self::AccountType>> {
        if account.owner != PROGRAM_ID {
            return None;
        }

        if let Ok(data) = spl_token_interface::state::Mint::unpack(&account.data) {
            return Some(carbon_core::account::DecodedAccount {
                lamports: account.lamports,
                data: TokenProgramAccount::Mint(Box::new(mint::Mint::from(data))),
                owner: account.owner,
                executable: account.executable,
                rent_epoch: account.rent_epoch,
            });
        }
        if let Ok(data) = spl_token_interface::state::Account::unpack(&account.data) {
            return Some(carbon_core::account::DecodedAccount {
                lamports: account.lamports,
                data: TokenProgramAccount::Token(Box::new(token::Token::from(data))),
                owner: account.owner,
                executable: account.executable,
                rent_epoch: account.rent_epoch,
            });
        }
        if let Ok(data) = spl_token_interface::state::Multisig::unpack(&account.data) {
            return Some(carbon_core::account::DecodedAccount {
                lamports: account.lamports,
                data: TokenProgramAccount::Multisig(Box::new(multisig::Multisig::from(data))),
                owner: account.owner,
                executable: account.executable,
                rent_epoch: account.rent_epoch,
            });
        }

        None
    }
}

#[cfg(test)]
mod tests {
    use {
        super::*, carbon_core::account::AccountDecoder, solana_program_pack::Pack,
        solana_pubkey::Pubkey,
    };

    const TOKEN_PROGRAM_ID: Pubkey =
        solana_pubkey::Pubkey::from_str_const("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");

    #[test]
    fn decode_token_account_uses_spl_token_pack_layout() {
        let mint = Pubkey::new_from_array([1; 32]);
        let owner = Pubkey::new_from_array([2; 32]);
        let source = spl_token_interface::state::Account {
            mint,
            owner,
            amount: 58_727_131,
            state: spl_token_interface::state::AccountState::Initialized,
            ..Default::default()
        };
        let mut data = vec![0u8; spl_token_interface::state::Account::LEN];
        spl_token_interface::state::Account::pack(source, &mut data).expect("pack account");

        let account = solana_account::Account {
            lamports: 2_039_280,
            data,
            owner: TOKEN_PROGRAM_ID,
            executable: false,
            rent_epoch: 0,
        };

        let decoded = TokenProgramDecoder
            .decode_account(&account)
            .expect("account should decode");

        match decoded.data {
            TokenProgramAccount::Token(token) => {
                assert_eq!(token.mint, mint);
                assert_eq!(token.owner, owner);
                assert_eq!(token.amount, 58_727_131);
                assert_eq!(token.state, crate::types::AccountState::Initialized);
            }
            _ => panic!("expected token account"),
        }
    }
}