Crates.io | pinocchio-derive |
lib.rs | pinocchio-derive |
version | 0.1.0 |
created_at | 2025-07-09 04:18:18.281698+00 |
updated_at | 2025-07-09 04:18:18.281698+00 |
description | Helper derive macros for Pinocchio programs |
homepage | |
repository | https://github.com/joeymeere/pinocchio-util |
max_upload_size | |
id | 1744148 |
size | 16,883 |
pinocchio-util is crate designed to make your life just a little bit easier when building pinocchio
programs.
While only being around for a relatively short time, Pinocchio has quickly become a go-to library for building efficient Solana programs. It strikes an effective balance between low-level control and developer ergonomics, which is one of the reasons I love it.
That being said, I've noticed a variety of recurring patterns between my own programs, and programs built by others. This crate encompasses some of the tools I've used over time to make implementing those patterns a bit easier.
Install this crate with the following command:
cargo add pinocchio-util
or add this to your Cargo.toml
:
pinocchio-util = "0.0.1"
Load an immutable reference to an account's data as an arbitrary type
let account_data = load::<UserData>(&account)?;
Load a mutable reference to an account's data as an arbitrary type:
let mut account_data = load_mut::<UserData>(&account)?;
Extract an account's discriminator:
/// Defaults to first 8 bytes like classic Anchor does
let discriminator = load_discriminator(&account, None).unwrap();
/// You can also define an arbitrary length, which some programs
/// >= Anchor 0.30.0 do to save bytes
let discriminator = load_discriminator(&account, Some(4)).unwrap();
This crate also exposes various traits like DataLen
, AccountUpdates
, Validate
, and Context
. These are useful in their own right, but are best used with the derive
feature outlined below.
Enable the derive
feature to leverage various procedural macros:
pinocchio-util = { version = "0.0.1", features = ["derive"] }
Now that you've enabled them, you can add them to the various structs in your program:
#[derive(Context, Validate)]
pub struct BasicContext<'info> {
// This is the signer
#[validate(is_signer)]
pub from: &'info AccountInfo,
// This does match my random id
#[validate(id = RANDOM_ID)]
pub to: &'info AccountInfo,
// This is a program, and this is the system program
#[validate(is_executable, id = pinocchio_system::ID)]
pub system_program: &'info AccountInfo,
}
// ...
let ctx = BasicContext::build(accounts)
.map_err(|_| ProgramError::InvalidArgument)?;