Skip to main content

  1. TransferChecked validates that the decimals parameter matches the mint’s decimals.
  2. Use for Light→Light transfers when you need decimal verification.
  3. For transfers involving SPL or Token 2022 accounts, use Transfer Interface instead.
1

Prerequisites

Cargo.toml
[dependencies]
light-token = "0.4.0"
light-client = { version = "0.19.0", features = ["v2"] }
solana-sdk = "2"
borsh = "0.10.4"
tokio = { version = "1", features = ["full"] }
Test with Lite-SVM (…)
# Initialize project
cargo init my-light-project
cd my-light-project

# Run tests
cargo test
use light_program_test::{LightProgramTest, ProgramTestConfig};
use solana_sdk::signer::Signer;

#[tokio::test]
async fn test_example() {
    // In-memory test environment 
    let mut rpc = LightProgramTest::new(ProgramTestConfig::default())
        .await
        .unwrap();

    let payer = rpc.get_payer().insecure_clone();
    println!("Payer: {}", payer.pubkey());
}
2

Transfer with Decimal Check

View the source code and full example with shared test utilities.
use borsh::BorshDeserialize;
use light_client::rpc::Rpc;
use light_token_client::actions::{CreateAta, TransferChecked};
use rust_client::{setup, SetupContext};
use solana_sdk::{signature::Keypair, signer::Signer};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let SetupContext {
        mut rpc,
        payer,
        mint,
        associated_token_account,
        decimals,
        ..
    } = setup().await;

    // Create recipient associated token account
    let recipient = Keypair::new();
    let (_signature, recipient_associated_token_account) = CreateAta {
        mint,
        owner: recipient.pubkey(),
        idempotent: true,
    }
    .execute(&mut rpc, &payer)
    .await?;

    // TransferChecked validates decimals match the mint's decimals.
    // Only use for Light->Light transfers.
    // Use TransferInterface for all other transfers (Light, SPL or Token-2022).
    let sig = TransferChecked {
        source: associated_token_account,
        mint,
        destination: recipient_associated_token_account,
        amount: 1000,
        decimals,
    }
    .execute(&mut rpc, &payer, &payer)
    .await?;

    let data = rpc
        .get_account(recipient_associated_token_account)
        .await?
        .ok_or("Account not found")?;
    let token = light_token_interface::state::Token::deserialize(&mut &data.data[..])?;
    println!("Balance: {} Tx: {sig}", token.amount);

    Ok(())
}

Next Steps

Learn how to close Light Token accounts