# Anchor — full corpus # LLM Wiki An open-source template for building LLM-powered knowledge bases, following [Andrej Karpathy's "LLM Wiki" pattern](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f). You provide raw sources. The LLM reads them, writes structured wiki pages, cross-links everything, and maintains it over time. You never edit the wiki directly — you curate sources and ask questions. ## How It Works The system has three layers: ``` raw/ Sources you collect (articles, transcripts, notes, PDFs) wiki/ LLM-written & maintained pages (summaries, concepts, entities, syntheses) CLAUDE.md Schema that tells the LLM how to structure everything ``` Three operations drive the workflow: | Operation | Trigger | What happens | |-----------|---------|--------------| | **Ingest** | "ingest raw/my-source.txt" | LLM reads the source, creates a summary page, creates/updates concept and entity pages, adds cross-links, updates the index and log | | **Query** | Ask any question | LLM searches the wiki, synthesizes an answer with citations, optionally creates a synthesis page for novel insights | | **Lint** | "lint" or "health check" | LLM audits all pages for orphans, contradictions, missing links, incomplete sections, and low-confidence claims — fixes what it can, reports the rest | ## Quick Start 1. **Clone this repo** ```bash git clone https://github.com/YOUR_USERNAME/llm-wiki.git my-knowledge-base cd my-knowledge-base ``` 2. **Customize CLAUDE.md** for your domain - Update the Purpose section with your topic - Replace the placeholder tagging taxonomy with your own categories - Adjust confidence level descriptions if needed - Everything else (workflows, page formats, linking rules) works as-is 3. **Drop sources into `raw/`** - Text files, transcripts, articles, notes — any plain text - These are immutable once added; the LLM never modifies them 4. **Tell the LLM to ingest** ``` ingest raw/my-first-source.txt ``` The LLM will create summary pages, concept pages, entity pages, cross-links, and update the index. 5. **Ask questions** ``` What are the key differences between X and Y? ``` The LLM answers from the wiki, citing specific pages. 6. **Run health checks** ``` lint ``` The LLM audits the wiki and fixes issues. ## Directory Structure ``` . ├── CLAUDE.md # Schema — the LLM's instructions ├── raw/ # Your source documents (immutable) └── wiki/ ├── index.md # Master catalog of all pages ├── log.md # Append-only activity log ├── dashboard.md # Dataview dashboard (Obsidian) ├── analytics.md # Charts View analytics (Obsidian) ├── flashcards.md # Spaced repetition cards ├── summaries/ # One page per source document ├── concepts/ # Concept and framework pages ├── entities/ # People, tools, organizations, etc. ├── syntheses/ # Cross-cutting analyses and comparisons ├── journal/ # Research/session journal entries │ └── template.md # Journal entry template └── presentations/ # Marp slide decks ``` ## Enhancements This template includes several extras beyond the core wiki pattern: ### Dataview Dashboard (`wiki/dashboard.md`) Live queries that surface low-confidence pages, recent updates, concepts by tag, and pages with the most sources. Requires the [Dataview](https://github.com/blacksmithgu/obsidian-dataview) Obsidian plugin. ### Charts View Analytics (`wiki/analytics.md`) Visual analytics with pie charts, bar charts, and word clouds. Requires the [Charts View](https://github.com/caronchen/obsidian-chartsview-plugin) Obsidian plugin. ### Mermaid Diagrams Use Mermaid code blocks in any wiki page to create flowcharts, sequence diagrams, or concept maps. Native support in Obsidian and GitHub. ### Marp Slides (`wiki/presentations/`) Create slide decks from markdown using [Marp](https://marp.app/). Drop presentation files in this directory. ### Research Journal (`wiki/journal/`) Track your research sessions, experiments, or applied work with the included template. The LLM can reference journal entries when answering queries. ### Spaced Repetition (`wiki/flashcards.md`) Flashcards in the format used by the [Spaced Repetition](https://github.com/st3v3nmw/obsidian-spaced-repetition) Obsidian plugin. Ask the LLM to generate flashcards from any wiki page. ### MCP Server This repo works with Claude Code's MCP server capabilities. Point an MCP-compatible client at this repo and the LLM can read/write the wiki programmatically. ## Customizing for Your Domain The schema in `CLAUDE.md` is domain-agnostic. To adapt it: 1. **Purpose** — Describe your knowledge domain in one paragraph 2. **Tagging taxonomy** — Replace placeholder categories with your own (e.g., for a cooking KB: `cuisine`, `technique`, `ingredient`, `equipment`) 3. **Confidence levels** — Adjust the descriptions to match your domain's evidence standards 4. **Entity types** — Update the entity page description to match what entities mean in your domain (people, tools, companies, etc.) 5. **Journal template** — Customize `wiki/journal/template.md` for your workflow Everything else — page format, linking conventions, workflows, rules — is universal and works across domains. ## Example Domains This template works for any knowledge-intensive topic: - **Research notes** — papers, experiments, methodologies - **Book analysis** — themes, characters, author techniques - **Competitive analysis** — companies, products, market trends - **Course notes** — lectures, readings, key concepts - **Personal development** — frameworks, habits, book summaries - **Technical documentation** — APIs, architectures, design patterns - **Hobby deep-dives** — any subject you want to master ## License MIT --- title: "Anchor KB — Master Index" type: index updated: 2026-06-25 anchor_version: "1.1.1" --- # Anchor KB — Master Index **Domain:** Anchor — the Rust framework for building Solana programs (smart contracts): the `#[program]`/`#[derive(Accounts)]` macros, account constraints and types, PDAs, CPI, the IDL, errors/events, SPL tokens via `anchor-spl`, the TS/Rust clients, testing, the CLI/AVM toolchain, and program security. **Corpus:** 66 provenance-stamped sources in `raw/` — the official Anchor docs (`solana-foundation/anchor` → `docs/content/docs/**/*.mdx`), the README, and release notes (to v1.1.1). **Pages:** 16 (12 concepts · 1 entity · 1 summary · 2 syntheses). **Scope:** program development *with Anchor* — the broader chain (account model, RPC, SPL internals, staking) lives in the sibling `solana` wiki. ## Concepts (core ideas + operational how-tos) - [[concepts/what-is-anchor]] — what Anchor is, why use it, install (Rust/Solana CLI/`avm`/`anchor`), `anchor init` - [[concepts/project-structure]] — the `#[program]` module, instruction handlers, `declare_id!`, `Anchor.toml` - [[concepts/accounts-and-constraints]] — `#[derive(Accounts)]`, the `#[account(...)]` constraints (`init`/`mut`/`seeds`/`bump`/`has_one`/`payer`/`space`/`close`), account types - [[concepts/pdas]] — Program Derived Addresses: seeds, canonical bump, the `seeds`/`bump` constraints - [[concepts/cpi]] — Cross-Program Invocation: `CpiContext`, cpi modules, PDA signers (`with_signer`) - [[concepts/idl]] — the IDL, discriminators, `declare_program!` - [[concepts/errors-and-events]] — `#[error_code]`, `err!`/`require!`, `#[event]` + `emit!`/`emit_cpi!` - [[concepts/spl-tokens]] — SPL tokens via `anchor-spl`: create mint/account, mint, transfer (CPI), Token-2022 extensions - [[concepts/clients]] — calling a program from the TypeScript and Rust clients (`methods`, `.rpc()`) - [[concepts/advanced-account-features]] — zero-copy (`AccountLoader`), `space`/`InitSpace`, type conversion - [[concepts/testing]] — `anchor test`, the TS harness, litesvm / mollusk / fuzzing - [[concepts/security]] — common Anchor pitfalls/exploit classes and the constraints that prevent them ## Entities - [[entities/anchor-cli-and-avm]] — the `anchor` CLI command set, the `avm` version manager, and verifiable builds ## Summaries - [[summaries/reference-catalog]] — map of the Anchor reference surface (full constraint list, account types, space, examples) — mapped, not paged ## Syntheses (workflows & decisions) - [[syntheses/quickstart-build-a-program]] — end-to-end: install → `anchor init` → write → `anchor build`/`test` → `anchor deploy` - [[syntheses/program-security-checklist]] — each common vulnerability mapped to the Anchor constraint/pattern that defends it ## Statistics - **Total pages**: 16 - **Concepts**: 12 · **Entities**: 1 · **Summaries**: 1 · **Syntheses**: 2 - **Sources ingested**: 66 (raw/, immutable) - **High confidence**: 13 · **Medium confidence**: 3 · **Low confidence**: 0 ## Coverage notes Strong: the Anchor program model (accounts/constraints/PDAs/CPI), IDL, errors/events, SPL tokens, clients, testing, the CLI/AVM toolchain, and a security checklist. Pinned to Anchor v1.x (release notes to v1.1.1); freshness = source fetch date 2026-06-25. Note: the official docs import the TS client as `@anchor-lang/core` (preserved verbatim). The `security`/footguns source pages are thin and point to the external `sealevel-attacks` repo, so the security pages are partly synthesized (`confidence: medium` on the checklist). Mapped, not paged (see [[summaries/reference-catalog]]): the exhaustive account-constraint and account-type reference, the example-program catalog, and broad Solana concepts covered by the `solana` wiki. For those, see the Anchor docs and the `solana` wiki. --- title: "Accounts and Constraints" type: concept tags: [anchor, accounts, constraints, validation] updated: 2026-06-25 confidence: high sources: [raw/github_doc-docs-content-docs-references-account-constraints-mdx.md, raw/github_doc-docs-content-docs-references-account-types-mdx.md, raw/github_doc-docs-content-docs-basics-program-structure-mdx.md] --- # Accounts and Constraints `#[derive(Accounts)]` is applied to a struct to specify the accounts an instruction requires; it implements the `Accounts` trait (validation plus de/serialization). Each field is one account. Anchor validates two ways together: **account types** (the field's Rust type) and **account constraints** (the `#[account(..)]` attribute). Validation runs before the handler; afterward accounts are read via `ctx.accounts`. ## Account Types - `Account<'info, T>` — container that checks ownership on deserialization (used with `#[account]` custom types) - `Signer<'info>` — validates the account signed the transaction - `Program<'info, T>` — validates the account is the given program (e.g. `Program<'info, System>`) - `SystemAccount<'info>` — owned by the System Program - `UncheckedAccount<'info>` — explicit `AccountInfo` wrapper; no checks (requires a `/// CHECK:` comment) - `Sysvar<'info, T>` — validates and deserializes a sysvar (e.g. `Rent`, `Clock`) - `AccountLoader<'info, T>` — on-demand zero-copy deserialization - `InterfaceAccount<'info, T>` / `Interface<'info, T>` — token-program-agnostic accounts/programs (Token or Token2022) - `Box>` saves stack space; `Option>` marks an optional account ## Constraints Applied with `#[account(..)]`; many accept a custom error with `@ `: ```rust #[account(signer)] // account signed the tx #[account(mut)] // mutable; persists state changes #[account(init, payer = , space = )] // create + initialize via System Program CPI #[account(init_if_needed, payer = )] // init only if absent (requires init-if-needed feature) #[account(seeds = , bump)] // account is a PDA from this program #[account(has_one = )] // account. matches target field's key #[account(address = )] // account key matches the pubkey #[account(owner = )] // account owner matches expr #[account(close = )] // close, send lamports to target, reset data #[account(zero)] // discriminator is zero; for accounts > 10 KiB #[account(constraint = )] // expr must evaluate to true ``` `init` requires `payer` and `space`. `space` includes the 8-byte discriminator that `#[account]` adds (e.g. `space = 8 + 8` for a `u64`). See [[concepts/advanced-account-features]] for `realloc`, `init_if_needed`, and zero-copy; [[concepts/spl-tokens]] for the `token::`, `mint::`, and `associated_token::` SPL constraints. ## #[account] Custom Types `#[account]` (e.g. `#[account] pub struct NewAccount { data: u64 }`) is applied to structs defining custom account data. It assigns the program owner, sets an 8-byte discriminator (first 8 bytes of SHA256 of `account:`) on the first 8 bytes of data, and auto-de/serializes. The discriminator is checked on deserialization to confirm the expected type. ## Instruction Arguments Access an instruction's arguments in constraints with `#[instruction(..)]`, placed after `#[derive(Accounts)]`; list arguments in handler order (trailing ones may be omitted, leading ones may not be skipped). This lets `space` depend on an arg: ```rust #[derive(Accounts)] #[instruction(input: String)] pub struct Initialize<'info> { #[account(init, payer = signer, space = 8 + 4 + input.len())] pub new_account: Account<'info, DataAccount>, } ``` See [[concepts/pdas]] for seeds/bump and [[concepts/security]] for using constraints as security checks. --- title: "Advanced Account Features" type: concept tags: [anchor, zero-copy, account-loader, space, type-conversion] updated: 2026-06-25 confidence: high sources: [raw/github_doc-docs-content-docs-features-zero-copy-mdx.md, raw/github_doc-docs-content-docs-references-space-mdx.md, raw/github_doc-docs-content-docs-references-type-conversion-mdx.md] --- # Advanced Account Features ## Account space With `init`, `space` must equal the serialized data size plus **8 bytes** for Anchor's discriminator. Sizes: `bool`/`u8` = 1, `u16` = 2, `u32` = 4, `u64` = 8, `u128` = 16, `Pubkey` = 32, `[T; n]` = `space(T) * n`, `Vec` = `4 + space(T) * n`, `String` = `4 + bytes`, `Option` = `1 + space(T)`, `Enum` = `1 + largest variant`. `#[derive(InitSpace)]` computes the size, adding an `INIT_SPACE` constant; use `#[max_len(n)]` to bound `Vec`/`String` fields. You still add 8 for the discriminator: ```rust #[account] #[derive(InitSpace)] pub struct ExampleAccount { pub data: u64, #[max_len(50)] pub string_one: String, } #[account(init, payer = payer, space = 8 + ExampleAccount::INIT_SPACE)] pub data: Account<'info, ExampleAccount>, ``` This applies only to non-`zero-copy` accounts; zero-copy uses `repr(C)` layout. ## Zero-copy accounts Zero-copy deserialization reads/writes account data directly from memory without copying, casting raw bytes to the struct type. This avoids the stack (4KB) and heap (32KB) limits of `Account`, supports accounts up to 10MB, and greatly reduces compute. Use it for large accounts (orderbooks, event queues); use regular `Account` for small or dynamic data. Add `bytemuck` with the `min_const_generics` feature, then annotate with `#[account(zero_copy)]`. All fields must be `Copy` (fixed-size arrays, not `Vec`/`String`): ```rust #[account(zero_copy)] pub struct Data { pub data: [u8; 10232], // 10240 - 8 discriminator bytes } ``` `#[account(zero_copy)]` auto-derives `Copy`, `Clone`, `bytemuck::Zeroable`, `bytemuck::Pod`, and `#[repr(C)]`. For nested types inside a zero-copy account, use `#[zero_copy]` (without `account`). ### AccountLoader Deserialize zero-copy accounts with `AccountLoader<'info, T>` (e.g. `#[account(init, space = 8 + 10232, payer = payer)] pub data_account: AccountLoader<'info, Data>`). Access via `load_init()` (first-time init; returns a mutable ref and sets the discriminator), `load_mut()` (mutable access; struct needs `#[account(mut)]`), or `load()` (read-only) — e.g. `let account = &mut ctx.accounts.data_account.load_init()?;`. `init` allocates at most 10240 bytes (CPI limit). For larger accounts (up to 10MB / 10_485_760 bytes), use `#[account(zero)]` and create the account in a separate System Program instruction first; `zero` verifies the discriminator has not been set. ## Rust-to-TypeScript type conversion Anchor maps Rust types to TS for client calls. `u64`/`u128`/`i64`/`i128` → `anchor.BN` (e.g. `new anchor.BN(99)`); smaller integers and floats → `number`. `String` → `string`, `[T; N]`/`Vec` → `Array`, `Option` → `T | null | undefined`. Enum variants become objects: unit `{ one: {} }`, named `{ two: { val: 99 } }`, tuple `{ three: [12, -34] }`. See [[concepts/accounts-and-constraints]], [[concepts/pdas]], and [[concepts/clients]]. --- title: "Anchor Clients (TypeScript & Rust)" type: concept tags: [anchor, clients, typescript, rust, methods] updated: 2026-06-25 confidence: high sources: [raw/github_doc-docs-content-docs-clients-index-mdx.md, raw/github_doc-docs-content-docs-clients-typescript-mdx.md, raw/github_doc-docs-content-docs-clients-rust-mdx.md] --- # Anchor Clients Anchor's client libraries consume a program's [[concepts/idl]]: `@anchor-lang/core` for TypeScript/JavaScript and `anchor-client` for Rust. ## TypeScript client Create a `Program` from the IDL and an `AnchorProvider` (a `Connection` plus optional `Wallet`): ```typescript import { Program, AnchorProvider, setProvider } from "@anchor-lang/core"; const provider = new AnchorProvider(connection, wallet, {}); setProvider(provider); export const program = new Program(idl as HelloAnchor, provider); ``` `idl.json` lives at `/target/idl/.json` and the TS type at `/target/types/.ts`. Inside an Anchor test file, the workspace provides the program directly: `anchor.workspace.HelloAnchor as Program`. ### Invoking instructions Use the `MethodsBuilder` API: ```typescript const sig = await program.methods .initialize(data) .accounts({ newAccount: newAccountKp.publicKey, signer: wallet.publicKey }) .signers([newAccountKp]) .rpc(); ``` - `.rpc()` — sends a signed transaction, returns a `TransactionSignature`. The provider's `Wallet` is automatically a signer. - `.transaction()` — builds a `Transaction` without sending. - `.instruction()` — builds a `TransactionInstruction` to combine with others. Some addresses resolve automatically from the IDL (common accounts like the System Program, and PDAs). `.signers` should only be used with `.rpc()`. ### Fetching accounts Use `program.account.`: ```typescript const account = await program.account.newAccount.fetch(ACCOUNT_ADDRESS); const accounts = await program.account.newAccount.all(); const many = await program.account.newAccount.fetchMultiple([ADDR_ONE, ADDR_TWO]); ``` `all()` also accepts a `memcmp` filter (`{ memcmp: { offset: 8, bytes: "" } }`); the first 8 bytes are the account discriminator. ## Rust client The `anchor-client` crate interacts with programs from Rust. Client modules are generated from the IDL with `declare_program!` (see [[concepts/idl]]). Create a `Client`, get a `program` handle, then build/send instructions: ```rust declare_program!(example); use example::{accounts::Counter, client::accounts, client::args}; let provider = Client::new_with_options(Cluster::Localnet, payer.clone(), CommitmentConfig::confirmed()); let program = provider.program(example::ID)?; let initialize_ix = program .request() .accounts(accounts::Initialize { counter: counter.pubkey(), payer: program.payer(), system_program: system_program::ID }) .args(args::Initialize) .instructions()? .remove(0); let signature = program.request().instruction(initialize_ix).signer(counter.clone()).send().await?; // Fetch + deserialize account data let counter_account: Counter = program.account::(counter.pubkey()).await?; ``` Dependencies: `anchor-client = { version = "1.0.2", features = ["async"] }` and `anchor-lang = "1.0.2"`. For Rust-to-TS type mapping see [[summaries/reference-catalog]]. --- title: "Cross Program Invocation (CPI)" type: concept tags: [anchor, cpi, cpi-context, pda-signer] updated: 2026-06-25 confidence: high sources: [raw/github_doc-docs-content-docs-basics-cpi-mdx.md] --- # Cross Program Invocation (CPI) A Cross Program Invocation (CPI) is one program invoking an instruction of another, enabling composability. Implementing one requires (1) the program ID called, (2) the accounts needed, and (3) any instruction data arguments. ## CpiContext The typical Anchor approach builds a `CpiContext` holding the target `program_id` and accounts, then passes it to an Anchor helper. This CPIs into the System Program's transfer: ```rust use anchor_lang::prelude::*; use anchor_lang::system_program::{transfer, Transfer}; pub fn sol_transfer(ctx: Context, amount: u64) -> Result<()> { let cpi_context = CpiContext::new( ctx.accounts.system_program.to_account_info(), Transfer { from: ctx.accounts.sender.to_account_info(), to: ctx.accounts.recipient.to_account_info(), }, ); transfer(cpi_context, amount)?; Ok(()) } ``` The accounts struct must include every account the CPI touches, including the program invoked: ```rust #[derive(Accounts)] pub struct SolTransfer<'info> { #[account(mut)] sender: Signer<'info>, // from account #[account(mut)] recipient: SystemAccount<'info>, // to account system_program: Program<'info, System>, // program ID } ``` The `CpiContext::new(...)` + helper pattern abstracts over the lower-level `invoke()` with `system_instruction::transfer` used in native Rust programs; both are functionally equivalent. ## CPI with PDA Signers When the sender is a PDA the program must "sign" for, attach `signer_seeds` to the `CpiContext` with `.with_signer()`. Read the bump from `ctx.bumps` followed by the PDA account name: ```rust let bump_seed = ctx.bumps.pda_account; let signer_seeds: &[&[&[u8]]] = &[&[b"pda", recipient.key().as_ref(), &[bump_seed]]]; let cpi_context = CpiContext::new(program_id, Transfer { from, to }).with_signer(signer_seeds); transfer(cpi_context, amount)?; ``` The `pda_account` is declared with matching `seeds`/`bump` so its address is derived deterministically: ```rust #[account(mut, seeds = [b"pda", recipient.key().as_ref()], bump)] pda_account: SystemAccount<'info>, ``` When the CPI is processed, the Solana runtime validates that the provided seeds and caller program ID derive a valid PDA, then adds the PDA as a signer. This lets a program sign for PDAs derived from its own program ID. Under the hood, `.with_signer()` wraps `invoke_signed()`, which takes the same `signer_seeds`. See [[concepts/pdas]] for deriving PDAs and bumps, [[concepts/spl-tokens]] for token CPIs, and [[concepts/accounts-and-constraints]] for the account types used here. --- title: "Errors and Events" type: concept tags: [anchor, errors, events, error-code, emit] updated: 2026-06-25 confidence: high sources: [raw/github_doc-docs-content-docs-features-errors-mdx.md, raw/github_doc-docs-content-docs-features-events-mdx.md] --- # Errors and Events ## Custom Errors All Anchor handlers return `Result` — a type alias wrapping the standard Rust `Result` where `E` is Anchor's `Error`: `pub type Result = std::result::Result;`. Define custom errors with `#[error_code]`. Anchor assigns each variant a code starting from 6000 and enables custom messages via `#[msg(...)]`: ```rust #[error_code] pub enum MyError { #[msg("My custom error message")] MyCustomError, #[msg("My second custom error message")] MySecondCustomError, } ``` ### Throwing errors Use `err!` to return a custom error: `return err!(MyError::DataTooLarge);`. The `require!` macro combines a condition check with returning an error if false: `require!(amount >= 10, CustomError::AmountTooSmall);`. Related: `require_eq!`, `require_neq!` (non-pubkey equality), `require_keys_eq!`, `require_keys_neq!` (pubkeys), `require_gt!`, `require_gte!`. On error, Anchor's TypeScript SDK returns a detailed error. Catch it in tests via `error.error.errorCode.code` and `error.error.errorMessage`: ```typescript } catch (error) { assert.strictEqual(error.error.errorCode.code, "AmountTooLarge"); assert.strictEqual(error.error.errorMessage, "Amount must be less than or equal to 100"); } ``` Error code numbering: instruction errors `>= 100`, constraint errors `>= 2000`, account errors `>= 3000`, custom user errors `>= 6000`. ## Events Two macros emit events. Define the payload with `#[event]`: ```rust #[event] pub struct CustomEvent { pub message: String, } ``` ### `emit!` `emit!()` (e.g. `emit!(CustomEvent { message: input });`) emits directly to program logs via the `sol_log_data()` syscall, encoded as base64 prefixed with `Program data:`. Simpler, though logs may be truncated by some data providers. Clients subscribe with `program.addEventListener("customEvent", cb)` and tear down with `program.removeEventListener(listenerId)`. ### `emit_cpi!` `emit_cpi!()` emits through a self-CPI, including the event data in the instruction data (less likely to be truncated, but extra compute cost). Enable the `event-cpi` feature in `Cargo.toml`, and add `#[event_cpi]` to the instruction's `#[derive(Accounts)]` struct: ```rust #[event_cpi] #[derive(Accounts)] pub struct EmitEvent {} ``` CPI-emitted events cannot be directly subscribed to; fetch the transaction and decode the event from the inner instruction data: ```typescript const eventIx = transactionData.meta.innerInstructions[0].instructions[0]; const rawData = anchor.utils.bytes.bs58.decode(eventIx.data); const base64Data = anchor.utils.bytes.base64.encode(rawData.subarray(8)); const event = program.coder.events.decode(base64Data); ``` See also [[concepts/clients]] and [[concepts/security]]. --- title: "The Anchor IDL" type: concept tags: [anchor, idl, declare-program, clients] updated: 2026-06-25 confidence: high sources: [raw/github_doc-docs-content-docs-basics-idl-mdx.md, raw/github_doc-docs-content-docs-features-declare-program-mdx.md] --- # The Anchor IDL An Interface Description Language (IDL) file is a standardized JSON file describing an Anchor program's instructions and accounts, providing a consistent format for generating client code. `anchor build` generates the IDL at `/target/idl/.json`. It can also be stored on-chain via the Program Metadata system — run `anchor idl init` to upload it. ## Structure The IDL mirrors the program. `instructions` corresponds to the `#[program]` module's instructions, each with its `accounts` and `args`. `accounts` corresponds to `#[account]`-annotated structs, and `types` describes their fields. ```json title="JSON" { "address": "BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd", "metadata": { "name": "hello_anchor", "version": "0.1.0", "spec": "0.1.0" }, "instructions": [ { "name": "initialize", "discriminator": [175, 175, 109, 31, 13, 152, 155, 237], "accounts": [ { "name": "new_account", "writable": true, "signer": true }, { "name": "system_program", "address": "11111111111111111111111111111111" } ], "args": [{ "name": "data", "type": "u64" }] } ], "accounts": [ { "name": "NewAccount", "discriminator": [176, 95, 4, 118, 91, 177, 125, 232] } ] } ``` ## Discriminators Anchor assigns a unique 8-byte discriminator to each instruction and account type — the first 8 bytes of the SHA256 hash of a prefix plus the name: - Instruction: `sha256("global:initialize")` — included as the first 8 bytes of instruction data automatically by the Anchor client. - Account: `sha256("account:NewAccount")` — set when the account is created and checked when deserializing on-chain. As of Anchor v0.30, discriminators are included in the IDL file. ## Using the IDL: `declare_program!` The `declare_program!()` macro generates Rust modules from a program's IDL for use in both on-chain and off-chain code, enabling dependency-free composability. Place the IDL in an `/idls` directory; the macro takes the IDL file name as its single argument: ```rust declare_program!(example); // Looks for /idls/example.json ``` Generated modules: `cpi` (CPI helpers), `client` (accounts and args for building instructions), `accounts` (account data types), `program` (program ID constant), plus `constants`, `events`, `types`, and `error`. Bring them into scope, e.g. `use example::{accounts::Counter, cpi::{self, accounts::{Increment, Initialize}}, program::Example};`. Both the TypeScript and Rust clients consume the IDL — see [[concepts/clients]]. For making CPIs into another program, see [[concepts/cpi]]. --- title: "Program Derived Addresses (PDAs)" type: concept tags: [anchor, pda, seeds, bump] updated: 2026-06-25 confidence: high sources: [raw/github_doc-docs-content-docs-basics-pda-mdx.md] --- # Program Derived Addresses (PDAs) A Program Derived Address (PDA) is an address derived deterministically from pre-defined inputs (seeds) and a program ID. In Anchor you use account constraints to define the seeds, and those constraints double as security checks ensuring the correct address is derived. ## seeds and bump Constraints - `seeds`: array of optional seeds — static values or dynamic references to account data. - `bump`: the bump seed; ensures the address falls off the Ed25519 curve and is a valid PDA. - `seeds::program` (optional): the program ID used to derive the PDA. Only needed when it is not the current program. `seeds` and `bump` are required together. Seed forms: ```rust #[account(seeds = [], bump)] // no optional seeds #[account(seeds = [b"hello_world"], bump)] // single static seed #[account(seeds = [b"hello_world", signer.key().as_ref()], bump)] // static + dynamic account ref pub pda_account: SystemAccount<'info>, ``` ## Bump: Automatic vs. Stored With `bump` alone (no value), the bump is calculated each invocation (the canonical bump). To save compute units, provide an explicit value, typically a bump stored on an account: `#[account(seeds = [b"hello_world"], bump = pda_account.bump_seed)]` (where `CustomAccount` has a `pub bump_seed: u8` field). The bump for any PDA in the `Accounts` struct is also exposed at runtime via `ctx.bumps.`. ## Deriving from Another Program Use `seeds::program` when interacting with PDAs created by a different program — `#[account(seeds = [b"hello_world"], bump, seeds::program = other_program.key())]` alongside a `pub other_program: Program<'info, OtherProgram>` field. ## Creating a PDA Account (init) `init` is commonly combined with `seeds` and `bump` to create an account whose address is a PDA. It invokes the System Program and must be used with `payer` and `space` (space includes the 8-byte discriminator): ```rust #[account( init, payer = signer, space = 8 + 1, seeds = [b"hello_world", signer.key().as_ref()], bump, )] pub pda_account: Account<'info, CustomAccount>, ``` ## Seeds in the IDL Seeds in the `seeds` constraint are included in the IDL. Static seeds become byte values (`kind: "const"`); dynamic seeds are recorded as account references (`kind: "account"`). This lets the Anchor client automatically resolve the PDA when building instructions, so callers don't derive it manually. The client equivalent of derivation is `PublicKey.findProgramAddressSync([...], program.programId)`. See [[concepts/cpi]] for signing CPIs with a PDA, [[concepts/accounts-and-constraints]] for constraints generally, and [[concepts/idl]]. --- title: "Anchor Program Structure" type: concept tags: [anchor, program, macros, anchor-toml] updated: 2026-06-25 confidence: high sources: [raw/github_doc-docs-content-docs-basics-program-structure-mdx.md, raw/github_doc-docs-content-docs-references-anchor-toml-mdx.md] --- # Anchor Program Structure Anchor uses Rust macros to reduce boilerplate and implement common security checks. The main macros in `lib.rs`: - `declare_id!`: the program's on-chain address - `#[program]`: the module containing instruction logic - `#[derive(Accounts)]`: applied to structs to indicate an instruction's required accounts - `#[account]`: applied to structs to create custom account types ## Example lib.rs ```rust use anchor_lang::prelude::*; declare_id!("11111111111111111111111111111111"); #[program] mod hello_anchor { use super::*; pub fn initialize(ctx: Context, data: u64) -> Result<()> { ctx.accounts.new_account.data = data; msg!("Changed data to: {}!", data); Ok(()) } } #[derive(Accounts)] pub struct Initialize<'info> { #[account(init, payer = signer, space = 8 + 8)] pub new_account: Account<'info, NewAccount>, #[account(mut)] pub signer: Signer<'info>, pub system_program: Program<'info, System>, } #[account] pub struct NewAccount { data: u64, } ``` ## declare_id! Specifies the program ID (on-chain address). By default the program ID is the public key of the keypair at `/target/deploy/your_program_name.json`. Run `anchor keys sync` to update `declare_id` with that keypair's public key — useful after cloning a repo where the committed ID won't match a local `anchor build`. ## #[program] and Instruction Handlers `#[program]` annotates the module containing all instruction handlers. Each public function is an invokable instruction. The first parameter is a `Context` where `T` implements the `Accounts` trait; additional parameters are optional instruction arguments. `Context` exposes non-argument inputs by dot notation: - `ctx.accounts`: the accounts required for the instruction - `ctx.program_id`: the program's public key (address) - `ctx.remaining_accounts`: additional accounts not in the `Accounts` struct - `ctx.bumps`: bump seeds for any PDA accounts in the `Accounts` struct See [[concepts/accounts-and-constraints]] for `#[derive(Accounts)]` and `#[account]`, and [[concepts/idl]] for the emitted interface. ## Anchor.toml The workspace config file. `[provider]` (required) sets the wallet and cluster; `[programs.]` lists program addresses; `[scripts]` defines commands runnable with `anchor run