use log::error; use mpl_token_metadata::accounts::Metadata; use solana_account_decoder::{UiAccountData, UiAccountEncoding}; use solana_client::rpc_client::RpcClient; use solana_client::rpc_config::RpcAccountInfoConfig; use solana_client::rpc_request::TokenAccountsFilter; use solana_program::program_pack::Pack; use solana_program::pubkey::Pubkey; use solana_sdk::account::Account; use solana_sdk::signature::Signature; use solana_transaction_status_client_types::{EncodedConfirmedTransactionWithStatusMeta, UiTransactionEncoding}; use spl_token::state::Mint; use crate::dto::{ParsedAccount, TokenInfo}; use crate::{ find_metadata_account}; pub fn get_token_info(client: &RpcClient, mint_pubkey: &Pubkey) -> anyhow::Result { let account = fetch_account(client, mint_pubkey); let mint = Mint::unpack(&*account?.data); match mint { Ok(mint) => Ok(TokenInfo { mint_address: mint_pubkey.to_string(), decimals: mint.decimals, mint_authority: mint.mint_authority.is_some(), freeze_authority: mint.freeze_authority.is_some(), supply: mint.supply, }), Err(e) => Err(anyhow::Error::msg(format!("ProgramError: {:?}", e))), } } pub fn get_transactions( client: &RpcClient, signature: &Signature, ) -> solana_client::client_error::Result { let config = solana_client::rpc_config::RpcTransactionConfig { encoding: Some(UiTransactionEncoding::Base64), commitment: Some(solana_sdk::commitment_config::CommitmentConfig::confirmed()), max_supported_transaction_version: Some(0), }; client.get_transaction_with_config(&signature, config) } pub fn get_token_metadata(client: &RpcClient, mint: &Pubkey) -> anyhow::Result { let (metadata_pubkey, _) = find_metadata_account(mint); let account = client.get_account(&metadata_pubkey)?; let metadata = Metadata::safe_deserialize(&mut account.data.as_ref())?; Ok(metadata) } pub fn get_dev_balance_for_token(rpc: &RpcClient, dev_pubkey: &Pubkey, mint: &Pubkey) -> anyhow::Result { let token_accounts = rpc.get_token_accounts_by_owner(dev_pubkey, TokenAccountsFilter::Mint(*mint))?; let mut total_balance: f64 = 0.0; for account_info in token_accounts { let amount_option = match account_info.account.data.clone() { UiAccountData::Json(test) => { let json = serde_json::to_value(&test.parsed)?; let token: ParsedAccount = serde_json::from_value(json)?; token.info.tokenAmount.uiAmount } _ => { error!("Cannot parse account_data"); None } }; total_balance += amount_option.unwrap_or_else(|| 0.0); } Ok(total_balance) } fn fetch_account(rpc_client: &RpcClient, mint_pubkey: &Pubkey) -> anyhow::Result { let config = RpcAccountInfoConfig { encoding: Some(UiAccountEncoding::Base64), ..RpcAccountInfoConfig::default() }; match rpc_client.get_account_with_config(&mint_pubkey, config) { Ok(response) => match response.value { Some(account) => Ok(account), None => Err(anyhow::Error::msg(format!("Account not found"))), }, Err(e) => Err(anyhow::Error::msg(format!("RPC error {}", e))), } }