# anchor-parser
[](https://crates.io/crates/anchor-parser)
[](https://docs.rs/anchor-parser)
[](https://github.com/goni098/anchor-parser/blob/main/LICENSE)
Generate Rust types and helpers from [Anchor](https://www.anchor-lang.com/) 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!`) and `from_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** — `Event` and `Account` wrapper enums for generic parsing across
all program types.
## Installation
```toml
[dependencies]
anchor-parser = "2.1.0"
```
## Quick start
1. 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
```
2. Declare the program:
```rust
use anchor_parser::declare_program;
declare_program!(my_program);
```
This generates a `my_program` module with the following sub-modules:
| `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
```rust
use my_program::accounts::MyAccount;
// Deserialize from raw account data (discriminator + payload)
let account = MyAccount::from_account_data(&raw_bytes)?;
// Check discriminator
assert_eq!(MyAccount::DISCRIMINATOR, [/* 8 bytes */]);
```
### Events
```rust
use my_program::events::SwapEvent;
// Parse events from emit! logs (base64-encoded "Program data:" log lines)
let events = SwapEvent::from_logs(&log_messages);
// Parse events from emit_cpi! inner instruction data (bs58-encoded)
let cpi_events = SwapEvent::from_cpi_logs(&inner_instruction_data);
```
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:
```rust
use my_program::utils::{Event, Account};
// Parse any program event from logs
let events: Vec<Event> = Event::from_logs(&log_messages);
let events: Vec<Event> = Event::from_cpi_logs(&log_messages);
match &events[0] {
Event::SwapEvent(e) => println!("swap amount: {}", e.amount_0),
Event::PoolCreatedEvent(e) => println!("new pool: {}", e.pool_state),
_ => {}
}
// Parse any program account from raw data
let account: Account = Account::parse(&raw_bytes)?;
```
### Instructions
```rust
use my_program::instructions;
let ix = instructions::swap(
&my_program::ID,
&instructions::SwapAccounts {
payer: wallet.pubkey(),
pool_state: pool_address,
// ...
},
amount,
min_out,
);
// ix: solana_sdk::instruction::Instruction
```
### Constants
```rust
use my_program::constants;
let fee = constants::FEE_DENOMINATOR; // u64
let prefix = constants::POOL_PREFIX; // &[u8]
```
## `from_logs` vs `from_cpi_logs`
| `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:
```rust
pub fn from_logs<T, I>(logs: T) -> Vec<Self>
where
T: IntoIterator<Item = I>,
I: AsRef<str>,
```
### How `emit_cpi!` events work
Anchor's `emit_cpi!` emits events as **self-CPI inner instructions**.
The instruction data is laid out as:
```text
[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
| 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
```sh
cargo test
```
The test suite covers four real-world programs (306 tests total):
| 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