shank-parse
A proc-macro crate that generates type-safe Rust client code at compile time from Shank / Anchor IDL JSON files for Solana programs.
Features
- Zero boilerplate — point the macro at an IDL file and get fully-typed instruction builders, account/type (de)serializers, and a program-ID constant.
- Compile-time code generation — the IDL is read and transformed during
cargo build; no runtime overhead. - Borsh-backed (de)serialization — every generated struct/enum derives
BorshSerialize/BorshDeserialize, so nested structs, arrays of defined types, andOptions all just work.borshis re-exported byshank-parse, so your crate doesn't need to depend on it directly. - Panic-free generated code — generated functions never
unwrap/expect/panic; fallible operations returnResult<_, std::io::Error>. - Supports Shank & Anchor IDL format — works with any IDL that follows the common Shank/Anchor JSON schema.
- Submodule layout — generated code is organized into
instructions,accounts, andtypessubmodules (mirroring the IDL sections).
Installation
[]
= "2"
= "4"
Usage
Place your IDL JSON file anywhere inside your crate (e.g. idl/my_program.json) and invoke the macro once:
shank_parse!;
The path is resolved relative to your crate's root (CARGO_MANIFEST_DIR).
Example — Counter program
Given idl/counter.json (a Shank IDL with an InitCounter instruction):
shank_parse!;
use Counter;
use ;
use ;
use ID;
Generated submodules
| Submodule | Contents |
|---|---|
<program>::instructions |
Instruction builder functions (returning Result<Instruction, std::io::Error>) and their <Instruction>Accounts structs |
<program>::accounts |
Account structs with a from_account_data(&[u8]) -> Result<Self, std::io::Error> deserializer (ignores trailing bytes) |
<program>::types |
The IDL types section — every struct/enum defined there, each deriving borsh and with an inherent try_from_slice(&[u8]) -> Result<Self, std::io::Error>. Field-less enums also get from_u8 / to_u8. |
<program>::errors |
pub const error codes |
<program>::ID |
Pubkey constant from metadata.address in the IDL |
Decoding values
Any type from the types section decodes from borsh bytes via try_from_slice.
For "event"-style data carried in a Program data: <base64> (or
Program log: instruction data: <base64>) log line, extract and base64-decode
the payload, then:
- For an enum,
try_from_slicereads the leadingu8variant tag (the discriminant) and dispatches to the matching variant. - For a struct,
try_from_slicedecodes the fields directly (no discriminant).
IDL format
The macro expects a JSON file following the Shank/Anchor IDL schema:
Workspace layout
shank-parse/
├── lib/ # shank-parse — the public-facing crate
└── macro/ # shank-parse-macro — the proc-macro implementation
License
MIT — see LICENSE.