anchor_parser/lib.rs
1#![cfg_attr(docsrs, feature(doc_cfg))]
2
3//! # anchor-parser
4//!
5//! Generates Rust types and helpers from Anchor IDL JSON files using `solana-sdk`
6//! types directly (no `anchor-lang` dependency).
7//!
8//! ## Generated modules
9//!
10//! | Module | Contents |
11//! |--------|----------|
12//! | `accounts` | Account structs with discriminators and deserialization |
13//! | `events` | Event structs with `from_logs` parsing |
14//! | `instructions` | Builder functions → `solana_sdk::instruction::Instruction` |
15//! | `types` | Shared structs, enums, and type aliases |
16//! | `constants` | Program constants |
17//! | `utils` | `Event` / `Account` wrapper enums for generic parsing |
18//!
19//! ## Usage
20//!
21//! ```ignore
22//! anchor_parser::declare_program!(my_program);
23//!
24//! use my_program::accounts::MyAccount;
25//! use my_program::events::MyEvent;
26//! use my_program::instructions;
27//! use my_program::constants;
28//! use my_program::utils::Event;
29//!
30//! // Build an instruction
31//! let ix = instructions::update(
32//! &my_program::ID,
33//! &instructions::UpdateAccounts { authority, my_account },
34//! 42,
35//! );
36//!
37//! // Fetch an account (requires "client" feature)
38//! use anchor_parser::client;
39//! let account = client::fetch_account::<MyAccount>(&rpc_client, &address).await?;
40//! let accounts = client::fetch_accounts::<MyAccount>(&rpc_client, &[addr1, addr2]).await?;
41//!
42//! // Deserialize from raw account data
43//! let account = MyAccount::from_account_data(&raw_bytes)?;
44//!
45//! // Parse events from emit! logs
46//! let events = MyEvent::from_logs(&log_messages);
47//! let all_events = Event::from_logs(&log_messages);
48//!
49//! // Parse events from emit_cpi! inner instruction data (bs58-encoded)
50//! let events = MyEvent::from_cpi_logs(&inner_ix_data_strings);
51//! let all_events = Event::from_cpi_logs(&inner_ix_data_strings);
52//! ```
53
54pub use anchor_parser_macros::declare_program;
55
56// ── Async RPC client (requires "client" feature) ──────────────────────
57
58#[cfg(feature = "client")]
59#[cfg_attr(docsrs, doc(cfg(feature = "client")))]
60pub mod client;
61
62// ── Public trait for account deserialization ───────────────────────────
63
64/// Trait implemented by generated account types.
65///
66/// Provides a discriminator and a method to deserialize from raw account data
67/// (discriminator prefix + serialized payload).
68pub trait AccountDeserialize: Sized {
69 /// The discriminator bytes that prefix this account's on-chain data.
70 const DISCRIMINATOR: &'static [u8];
71
72 /// Deserialize from raw account data (including discriminator prefix).
73 fn deserialize(data: &[u8]) -> Result<Self, std::io::Error>;
74}
75
76// ── Private re-exports for generated code ─────────────────────────────
77
78/// Re-exports used by the generated `declare_program!` code.
79///
80/// **Do not use directly.** This module is an implementation detail.
81#[doc(hidden)]
82pub mod __private {
83 pub use solana_sdk::instruction::{AccountMeta, Instruction};
84 pub use solana_sdk::pubkey::Pubkey;
85
86 pub use borsh::{BorshDeserialize, BorshSerialize};
87
88 // Bytemuck re-exports
89 pub use bytemuck::{Pod, Zeroable};
90
91 /// Decode a base64 string. Returns `None` on failure.
92 pub fn base64_decode(input: &str) -> Option<Vec<u8>> {
93 use base64::Engine;
94 base64::engine::general_purpose::STANDARD.decode(input).ok()
95 }
96
97 /// Decode a bs58 string. Returns `None` on failure.
98 pub fn bs58_decode(input: &str) -> Option<Vec<u8>> {
99 bs58::decode(input).into_vec().ok()
100 }
101
102 /// Read a `Pod` type from a byte slice (handles unaligned data).
103 pub fn bytemuck_read<T: bytemuck::Pod>(data: &[u8]) -> T {
104 bytemuck::pod_read_unaligned(data)
105 }
106}