2

Within my Rust program I would like to get the mint token balance of an account. I found the spl_token sdk but it only has functions to convert from a balance to a ui balance. I saw that an account has an amount field but this seems to be for the SOL amount or am I wrong?

2 Answers 2

0

Assuming Anchor.

#[account(
mut,
associated_token::mint=mint,
associated_token::authority=user,
)]
pub user_token_account: Box<Account<'info, TokenAccount>>,
user_token_account.amount

The SOL is accessed by lamports().

You can use reload after the CPI to get the updated value.

https://book.anchor-lang.com/anchor_in_depth/CPIs.html#reloading-an-account

6
  • Thank you for your response. So then it is the amount field. Unfortunately it appears that since calls to transfer do not complete immediately getting the balance immediately after the transfer does not work. Is there a way to wait some time within a Solana program or would this not be allowed since it can cause a delay or program completion.
    – David Choi
    Commented Aug 31, 2022 at 18:40
  • Not sure, but if you know how much you're transferring and you get the transfer result. You can manage it yourself.
    – Ohad Dahan
    Commented Aug 31, 2022 at 18:46
  • What you're trying to do?
    – Ohad Dahan
    Commented Aug 31, 2022 at 18:46
  • I'm trying to log token balances so that a backend system can later retrieve the pre transfer and post transfer balances (we would use the web3js connection.getTransaction function's logMessages field). I don't want to just log the transfer on execution because there's always a small chance a transfer could fail. That's why I need to log it upon commit.
    – David Choi
    Commented Aug 31, 2022 at 19:03
  • solana-labs.github.io/solana-web3.js/… => preBalances/postBalances doesn't have what you need?. In general if a transfer failed you probably abort the transaction. So if you insist on relying on msg! , just print it after the transfer finished. Store value prior, store transfer value, print the diff/sum after.
    – Ohad Dahan
    Commented Aug 31, 2022 at 20:10
2

In case you are using pure Solana Rust and not Anchor, this is how to do it, assuming Token-2022 program:

use spl_token_2022::{
    state::Account,
    extension::StateWithExtensions,
};

// ATA => Associated Token Account
// ata_info => &AccountInfo
// mint_info => &AccountInfo
let ata_data = ata_info.data.borrow();
let ata_state = StateWithExtensions::<Account>::unpack(&ata_data)?;

// Always check if you got the correct ATA for the mint
if &ata_state.base.mint != &mint_info.key {
    msg!("Token account doesn't match the expected mint");
    return Err(ProgramError::InvalidArgument);
}

msg!("balance={}", ata_state.base.amount);

For reference, the deserialized struct from the associated token account looks like this:

StateWithExtensions {
  base: Account {
    mint: 5zpRyR6d3cd3kBvkcjvqsLqQqPzoCbuyLtBTaE6mSvH3,
    owner: 7Lf9P1Ez7KuevTi2fgB8E4XRAMEWg74d7W2nbteT5oHW,
    amount: 1,
    delegate: None,
    state: Frozen,
    is_native: None,
    delegated_amount: 0,
    close_authority: None
  },
  tlv_data: [7, 0, 0, 0]
} 

In case you are still using the old Token program:

use spl_token::state::Account;

// ATA => Associated Token Account
// ata_info => &AccountInfo
// mint_info => &AccountInfo
let ata_data = ata_info.data.borrow();
let ata_state = Account::unpack(&ata_data)?;

// Always check if you got the correct ATA for the mint
if &ata_state.mint != &mint_info.key {
    msg!("Token account doesn't match the expected mint");
    return Err(ProgramError::InvalidArgument);
}

msg!("balance={}", ata_state.amount);

The struct stored in ata_state has the following shape:

pub struct Account {
    pub mint: Pubkey,
    pub owner: Pubkey,
    pub amount: u64,
    pub delegate: COption<Pubkey>,
    pub state: AccountState,
    pub is_native: COption<u64>,
    pub delegated_amount: u64,
    pub close_authority: COption<Pubkey>,
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.