โ Anchor Framework
The most popular framework for Solana development
Anchor is a framework for Solana's Sealevel runtime that makes it easier to build secure and efficient Solana programs. It provides a collection of tools and abstractions that simplify common tasks.
Why Use Anchor?
Less Boilerplate
Reduces hundreds of lines of code to just a few with Rust macros.
Security Built-in
Automatic security checks for common vulnerabilities.
IDL Generation
Auto-generates TypeScript client for easy frontend integration.
Testing Framework
Built-in testing support with Mocha and Chai.
Key Features
Macros & Attributes
- #[program]: Defines your program module
- #[derive(Accounts)]: Validates and deserializes accounts
- #[account]: Defines account data structures
- #[error_code]: Custom error definitions
Account Constraints
Anchor provides powerful constraint system:
- init: Initialize new account
- mut: Mark account as mutable
- seeds & bump: PDA constraints
- has_one: Verify account relationships
- constraint: Custom validation logic
Basic Anchor Program Structure
use anchor_lang::prelude::*;
declare_id!("Your-Program-ID-Here");
#[program]
pub mod my_program {
use super::*;
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
// Your instruction logic
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(mut)]
pub user: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[account]
pub struct MyAccount {
pub data: u64,
}
Common Patterns
Initialize Account
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(
init,
payer = user,
space = 8 + 8
)]
pub my_account: Account<'info, MyAccount>,
#[account(mut)]
pub user: Signer<'info>,
pub system_program: Program<'info, System>,
}
Update Account
#[derive(Accounts)]
pub struct Update<'info> {
#[account(mut)]
pub my_account: Account<'info, MyAccount>,
}
PDA Accounts
#[derive(Accounts)]
pub struct CreatePDA<'info> {
#[account(
init,
payer = user,
space = 8 + 32,
seeds = [b"my-seed", user.key().as_ref()],
bump
)]
pub pda_account: Account<'info, PDAAccount>,
#[account(mut)]
pub user: Signer<'info>,
pub system_program: Program<'info, System>,
}
Error Handling
#[error_code]
pub enum MyError {
#[msg("The amount is too large")]
AmountTooLarge,
#[msg("Unauthorized access")]
Unauthorized,
}
// Usage in instruction
pub fn transfer(ctx: Context<Transfer>, amount: u64) -> Result<()> {
require!(amount <= 100, MyError::AmountTooLarge);
Ok(())
}
Testing with Anchor
import * as anchor from "@coral-xyz/anchor";
describe("my-program", () => {
const provider = anchor.AnchorProvider.env();
anchor.setProvider(provider);
const program = anchor.workspace.MyProgram;
it("Initializes account", async () => {
await program.methods
.initialize()
.accounts({
myAccount: myAccountKeypair.publicKey,
user: provider.wallet.publicKey,
systemProgram: anchor.web3.SystemProgram.programId,
})
.signers([myAccountKeypair])
.rpc();
});
});
Advanced Features
Cross-Program Invocation (CPI)
use anchor_spl::token::{self, Transfer};
pub fn transfer_tokens(ctx: Context<TransferTokens>, amount: u64) -> Result<()> {
let cpi_accounts = Transfer {
from: ctx.accounts.from.to_account_info(),
to: ctx.accounts.to.to_account_info(),
authority: ctx.accounts.authority.to_account_info(),
};
let cpi_program = ctx.accounts.token_program.to_account_info();
let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);
token::transfer(cpi_ctx, amount)?;
Ok(())
}
Learning Resources
Next Steps
Ready to build? Check out our project tutorials to start building real applications with Anchor!