anchor-parser
Generate Rust types and helpers from Anchor IDL
JSON files using solana-sdk types directly — no anchor-lang dependency
required.
Features
- Accounts — Structs with discriminator constants and deserialization (Borsh & bytemuck/zero-copy).
- Events — Structs with
from_logs(emit!) andfrom_cpi_logs(emit_cpi!) parsers. - Instructions — Builder functions that return
solana_sdk::instruction::Instruction. - Types — Shared structs, enums, and type aliases from the IDL.
- Constants — Program constants with doc comments.
- Utils —
EventandAccountwrapper enums for generic parsing across all program types.
Installation
[]
= "2.0.0"
Quick start
- Place an Anchor IDL JSON file in an
idls/directory at your crate root:
my-crate/
├── Cargo.toml
├── idls/
│ └── my_program.json
└── src/
└── main.rs
- Declare the program:
use declare_program;
declare_program!;
This generates a my_program module with the following sub-modules:
| Module | Contents |
|---|---|
my_program::accounts |
Account structs with DISCRIMINATOR and from_account_data |
my_program::events |
Event structs with from_logs and from_cpi_logs |
my_program::instructions |
Builder functions → Instruction |
my_program::types |
Shared structs, enums, type aliases |
my_program::constants |
Program constants |
my_program::utils |
Event / Account wrapper enums |
The program ID is available as my_program::ID.
Usage
Accounts
use MyAccount;
// Deserialize from raw account data (discriminator + payload)
let account = from_account_data?;
// Check discriminator
assert_eq!;
Events
use SwapEvent;
// Parse events from emit! logs (base64-encoded "Program data:" log lines)
let events = from_logs;
// Parse events from emit_cpi! inner instruction data (bs58-encoded)
let cpi_events = from_cpi_logs;
Both methods accept any IntoIterator<Item = I> where I: AsRef<str> —
vec, slice, array, iterator, &[String], &[&str], etc.
Event & Account enums
The utils module provides wrapper enums that try all known discriminators:
use ;
// Parse any program event from logs
let events: = from_logs;
let events: = from_cpi_logs;
match &events
// Parse any program account from raw data
let account: Account = parse?;
Instructions
use instructions;
let ix = swap;
// ix: solana_sdk::instruction::Instruction
Constants
use constants;
let fee = FEE_DENOMINATOR; // u64
let prefix = POOL_PREFIX; // &[u8]
from_logs vs from_cpi_logs
| Method | Source | Input | Decoding |
|---|---|---|---|
from_logs |
emit! |
Transaction log messages | Scans for "Program data: <base64>" lines, base64-decodes, skips 8-byte discriminator, borsh-deserializes |
from_cpi_logs |
emit_cpi! |
Inner instruction data strings | bs58-decodes each string, skips 16 bytes (8-byte CPI event tag + 8-byte discriminator), borsh-deserializes |
Both methods share the same generic signature:
How emit_cpi! events work
Anchor's emit_cpi! emits events as self-CPI inner instructions.
The instruction data is laid out as:
[8 bytes: Anchor CPI event tag] [8 bytes: event discriminator] [borsh payload]
To use from_cpi_logs, pass the bs58-encoded inner instruction data strings
(not log messages) from instructions targeting your program.
Supported serialization formats
| Format | Accounts | Events |
|---|---|---|
| Borsh | ✅ | ✅ |
| Bytemuck (zero-copy) | ✅ | — |
| Bytemuck-unsafe (packed) | ✅ | — |
IDL compatibility
Supports the Anchor IDL JSON format. The IDL file name
(without .json) becomes the Rust module name.
Tests
The test suite covers four real-world programs (306 tests total):
| Program | IDL | Tests |
|---|---|---|
| Pumpfun | idls/pumpfun.json |
47 |
| Meteora DAMM v2 | idls/meteora_damm_v2.json |
83 |
| Meteora DLMM | idls/meteora_dlmm.json |
112 |
| Raydium CLMM | idls/raydium_clmm.json |
64 |
License
MIT