Documentation Index Fetch the complete documentation index at: https://mintlify.com/solana-foundation/anchor/llms.txt
Use this file to discover all available pages before exploring further.
The anchor-spl crate provides CPI clients and helper modules for interacting with Solana’s core SPL programs from your Anchor programs. This page covers the available modules and how to use them effectively.
Installation
Add anchor-spl to your program’s dependencies:
Update your Cargo.toml to include the IDL build feature:
[ features ]
idl-build = [
"anchor-lang/idl-build" ,
"anchor-spl/idl-build" ,
]
[ dependencies ]
anchor-lang = "0.32.1"
anchor-spl = "0.32.1"
Available Modules
The anchor-spl crate provides the following modules for common SPL program interactions:
Token Programs
Module Description tokenOriginal Token Program instructions and account types token_2022Token Extensions Program base instructions token_2022_extensionsToken Extensions Program extension-specific instructions token_interfaceAccount types compatible with both Token Program and Token Extensions associated_tokenAssociated Token Account Program instructions
Other SPL Programs
Module Description metadataMetaplex Token Metadata Program integration memoSPL Memo Program integration stakeSolana Stake Program integration governanceSPL Governance Program integration
Token Program Integration
The most common use case is interacting with Solana’s Token Programs. The anchor-spl crate provides both program-specific modules (token, token_2022) and a unified interface (token_interface).
Using Token Interface (Recommended)
The token_interface module provides account types that work with both the original Token Program and Token Extensions Program. This is the recommended approach for maximum compatibility:
use anchor_spl :: token_interface :: {
self , Mint , TokenAccount , TokenInterface , MintTo
};
#[derive( Accounts )]
pub struct MintTokens <' info > {
#[account( mut )]
pub mint : InterfaceAccount <' info , Mint >,
#[account( mut )]
pub token_account : InterfaceAccount <' info , TokenAccount >,
pub authority : Signer <' info >,
pub token_program : Interface <' info , TokenInterface >,
}
pub fn mint_tokens ( ctx : Context < MintTokens >, amount : u64 ) -> Result <()> {
token_interface :: mint_to (
CpiContext :: new (
ctx . accounts . token_program . to_account_info (),
MintTo {
mint : ctx . accounts . mint . to_account_info (),
to : ctx . accounts . token_account . to_account_info (),
authority : ctx . accounts . authority . to_account_info (),
},
),
amount ,
) ? ;
Ok (())
}
Program-Specific Modules
For scenarios requiring specific token program features:
use anchor_spl :: token_2022 :: {
self , Token2022 , transfer_checked, TransferChecked
};
#[derive( Accounts )]
pub struct TransferWithExtensions <' info > {
#[account( mut )]
pub from : Account <' info , TokenAccount >,
#[account( mut )]
pub to : Account <' info , TokenAccount >,
pub mint : Account <' info , Mint >,
pub authority : Signer <' info >,
pub token_program : Program <' info , Token2022 >,
}
Associated Token Accounts
The associated_token module provides helper functions for working with Associated Token Accounts (ATAs):
use anchor_spl :: {
associated_token :: AssociatedToken ,
token_interface :: { Mint , TokenAccount , TokenInterface },
};
#[derive( Accounts )]
pub struct CreateATA <' info > {
#[account( mut )]
pub payer : Signer <' info >,
#[account(
init,
payer = payer,
associated_token :: mint = mint,
associated_token :: authority = payer,
)]
pub token_account : InterfaceAccount <' info , TokenAccount >,
pub mint : InterfaceAccount <' info , Mint >,
pub token_program : Interface <' info , TokenInterface >,
pub associated_token_program : Program <' info , AssociatedToken >,
pub system_program : Program <' info , System >,
}
Token Extensions
Token 2022 introduces extensions that add functionality to mints and token accounts. Use the token_2022_extensions module:
use anchor_spl :: token_2022_extensions :: {
transfer_fee, TransferFee , TransferFeeConfig ,
};
#[derive( Accounts )]
pub struct InitializeTransferFee <' info > {
#[account( mut )]
pub mint : Account <' info , Mint >,
pub authority : Signer <' info >,
pub token_program : Program <' info , Token2022 >,
}
pub fn initialize_transfer_fee (
ctx : Context < InitializeTransferFee >,
transfer_fee_basis_points : u16 ,
maximum_fee : u64 ,
) -> Result <()> {
transfer_fee :: initialize_transfer_fee_config (
CpiContext :: new (
ctx . accounts . token_program . to_account_info (),
TransferFeeConfig {
mint : ctx . accounts . mint . to_account_info (),
},
),
Some ( & ctx . accounts . authority . key ()),
Some ( & ctx . accounts . authority . key ()),
transfer_fee_basis_points ,
maximum_fee ,
) ? ;
Ok (())
}
For NFTs and fungible tokens with metadata, use the metadata module:
use anchor_spl :: metadata :: {
Metadata ,
mpl_token_metadata :: types :: DataV2 ,
};
#[derive( Accounts )]
pub struct CreateMetadata <' info > {
#[account( mut )]
pub metadata : UncheckedAccount <' info >,
pub mint : Account <' info , Mint >,
pub mint_authority : Signer <' info >,
#[account( mut )]
pub payer : Signer <' info >,
pub update_authority : SystemAccount <' info >,
pub system_program : Program <' info , System >,
pub rent : Sysvar <' info , Rent >,
pub metadata_program : Program <' info , Metadata >,
}
The metadata module requires enabling the metadata feature in your Cargo.toml: anchor-spl = { version = "0.32.1" , features = [ "metadata" ] }
Memo Program
Add on-chain memos to your transactions:
use anchor_spl :: memo :: { Memo , BuildMemo };
#[derive( Accounts )]
pub struct AddMemo <' info > {
pub signer : Signer <' info >,
pub memo_program : Program <' info , Memo >,
}
pub fn add_memo ( ctx : Context < AddMemo >, memo : String ) -> Result <()> {
let cpi_program = ctx . accounts . memo_program . to_account_info ();
let cpi_accounts = BuildMemo {
memo : memo . as_bytes (),
};
anchor_spl :: memo :: build_memo (
CpiContext :: new ( cpi_program , cpi_accounts ),
memo . as_bytes (),
) ? ;
Ok (())
}
Feature Flags
The anchor-spl crate uses feature flags to control which modules are included:
[ dependencies . anchor-spl ]
version = "0.32.1"
features = [
"token" , # Token Program
"token_2022" , # Token Extensions Program
"token_2022_extensions" , # Token Extensions
"associated_token" , # Associated Token Accounts
"metadata" , # Metaplex Metadata
"memo" , # Memo Program
"stake" , # Stake Program
"governance" , # Governance Program
]
By default, token, token_2022, token_2022_extensions, associated_token, and mint features are enabled.
Common Patterns
Creating and Minting Tokens
use anchor_lang :: prelude ::* ;
use anchor_spl :: {
associated_token :: AssociatedToken ,
token_interface :: { self , Mint , MintTo , TokenAccount , TokenInterface },
};
declare_id! ( "YourProgramIDHere" );
#[program]
pub mod token_operations {
use super ::* ;
pub fn create_and_mint (
ctx : Context < CreateAndMint >,
amount : u64 ,
) -> Result <()> {
// Mint tokens to the associated token account
token_interface :: mint_to (
CpiContext :: new (
ctx . accounts . token_program . to_account_info (),
MintTo {
mint : ctx . accounts . mint . to_account_info (),
to : ctx . accounts . token_account . to_account_info (),
authority : ctx . accounts . mint_authority . to_account_info (),
},
),
amount ,
) ? ;
Ok (())
}
}
#[derive( Accounts )]
pub struct CreateAndMint <' info > {
#[account( mut )]
pub mint_authority : Signer <' info >,
#[account(
mut ,
mint :: authority = mint_authority,
mint :: decimals = 9,
)]
pub mint : InterfaceAccount <' info , Mint >,
#[account(
init_if_needed,
payer = mint_authority,
associated_token :: mint = mint,
associated_token :: authority = mint_authority,
)]
pub token_account : InterfaceAccount <' info , TokenAccount >,
pub token_program : Interface <' info , TokenInterface >,
pub associated_token_program : Program <' info , AssociatedToken >,
pub system_program : Program <' info , System >,
}
Transfer with Authority
use anchor_spl :: token_interface :: { self , Transfer };
pub fn transfer_tokens (
ctx : Context < TransferTokens >,
amount : u64 ,
) -> Result <()> {
token_interface :: transfer (
CpiContext :: new (
ctx . accounts . token_program . to_account_info (),
Transfer {
from : ctx . accounts . from . to_account_info (),
to : ctx . accounts . to . to_account_info (),
authority : ctx . accounts . authority . to_account_info (),
},
),
amount ,
) ? ;
Ok (())
}
#[derive( Accounts )]
pub struct TransferTokens <' info > {
#[account( mut )]
pub from : InterfaceAccount <' info , TokenAccount >,
#[account( mut )]
pub to : InterfaceAccount <' info , TokenAccount >,
pub authority : Signer <' info >,
pub token_program : Interface <' info , TokenInterface >,
}
Best Practices
Use InterfaceAccount for Token Compatibility
Always use InterfaceAccount<'info, T> and Interface<'info, TokenInterface> when you want your program to work with both Token Program and Token Extensions Program: // Good - Works with both programs
pub mint : InterfaceAccount <' info , Mint >,
pub token_program : Interface <' info , TokenInterface >,
// Limited - Only works with original Token Program
pub mint : Account <' info , Mint >,
pub token_program : Program <' info , Token >,
Always validate that token accounts belong to the expected token program: require_eq! (
ctx . accounts . token_account . owner,
ctx . accounts . token_program . key (),
ErrorCode :: InvalidTokenProgram
);
Validate Mint Relationships
Ensure token accounts belong to the correct mint: #[account(
mut ,
token :: mint = mint,
token :: authority = authority,
)]
pub token_account : InterfaceAccount <' info , TokenAccount >,
Resources