solana/anchor-idl

Anchor IDL & CPI Guide

solanadocs✅ Verifiedconfidence highhealth -1%
v0.30.0·by Coral (Anchor)·Updated 3/20/2026

Overview

Anchor is the standard framework for Solana program development. It provides a Rust DSL, automatic IDL (Interface Description Language) generation, and a TypeScript client. This skill covers IDL structure, CPI (Cross-Program Invocation), and account constraints.

IDL Structure

After anchor build, the IDL is generated at target/idl/<program>.json:

{
  "version": "0.1.0",
  "name": "my_program",
  "instructions": [
    {
      "name": "initialize",
      "accounts": [
        { "name": "counter", "isMut": true, "isSigner": false },
        { "name": "user", "isMut": true, "isSigner": true },
        { "name": "systemProgram", "isMut": false, "isSigner": false }
      ],
      "args": [{ "name": "initValue", "type": "u64" }]
    }
  ],
  "accounts": [
    {
      "name": "Counter",
      "type": { "kind": "struct", "fields": [{ "name": "count", "type": "u64" }] }
    }
  ]
}

Account Constraints

use anchor_lang::prelude::*;

#[program]
mod my_program {
    pub fn initialize(ctx: Context<Initialize>, init_value: u64) -> Result<()> {
        ctx.accounts.counter.count = init_value;
        Ok(())
    }
}

#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(
        init,
        payer = user,
        space = 8 + 8,  // discriminator + u64
        seeds = [b"counter", user.key().as_ref()],
        bump
    )]
    pub counter: Account<'info, Counter>,
    #[account(mut)]
    pub user: Signer<'info>,
    pub system_program: Program<'info, System>,
}

#[account]
pub struct Counter {
    pub count: u64,
}

CPI (Cross-Program Invocation)

use anchor_spl::token::{self, Token, TokenAccount, Transfer};

pub fn transfer_tokens(ctx: Context<TransferCtx>, 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_ctx = CpiContext::new(ctx.accounts.token_program.to_account_info(), cpi_accounts);
    token::transfer(cpi_ctx, amount)?;
    Ok(())
}

CPI with PDA Signer

// PDA signs on behalf of the program
let seeds = &[b"vault", &[ctx.bumps.vault]];
let signer_seeds = &[&seeds[..]];
let cpi_ctx = CpiContext::new_with_signer(
    ctx.accounts.token_program.to_account_info(),
    cpi_accounts,
    signer_seeds,
);

TypeScript Client

import { Program, AnchorProvider, web3 } from '@coral-xyz/anchor'
import { MyProgram, IDL } from './idl/my_program'

const provider = AnchorProvider.env()
const program = new Program<MyProgram>(IDL, provider)

// Call instruction
await program.methods
  .initialize(new BN(42))
  .accounts({ counter: counterPda, user: provider.wallet.publicKey })
  .rpc()

// Fetch account
const counter = await program.account.counter.fetch(counterPda)
console.log(counter.count.toString())

Installation

cargo install --git https://github.com/coral-xyz/anchor anchor-cli
anchor init my_project
npm install @coral-xyz/anchor

Reference