Solana program scaffold
Skill Solonnikov/agent-skills/skills/solana-program-scaffold
Scaffolds a Solana on-chain program with Anchor — workspace setup, PDA patterns, dual SOL/SPL token support, constraint-driven validation, on-chain randomness via SlotHashes, testing with the TypeScript Anchor client, and mainnet deployment. Use when starting a new Solana program, adding a new instruction to an existing one, or standardizing an ad-hoc Anchor project.From its SKILL.md
npx -y skills add Solonnikov/agent-skills --skill solana-program-scaffoldAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
5.6 KB, ~1.3k tokens by cl100k_base, as published. Nobody here has run it
Solana Program Scaffold
Bootstrap an Anchor-based Solana program with current conventions. Covers workspace layout, PDA derivation, SOL-vs-SPL dual instruction patterns, #[derive(Accounts)] constraints, testing, and deployment.
When to use
- Starting a new Solana program from scratch.
- Adding instructions to an existing Anchor program and wanting a consistent account/PDA/testing pattern.
- Standardizing a quick-prototype program that has drifted.
- Migrating a native Rust program to Anchor (or vice versa — but almost always prefer Anchor).
Before you start
Decide:
- Anchor vs native Rust. Default to Anchor 0.31+. Native Rust is only worth it for extreme byte-level optimization or when Anchor's IDL constraints don't fit. This skill assumes Anchor.
- SOL, SPL, or both? Programs that accept value typically need both a SOL flow and an SPL flow. Anchor encourages these as parallel instruction variants (
place_bet_sol/place_bet_spl) rather than a single polymorphic instruction. - PDA strategy. Which accounts are PDAs? What seeds identify them? Common patterns: singleton (
[b"factory"]), indexed ([b"item", counter.to_le_bytes()]), per-user ([b"user_account", user.key().as_ref()]). - Randomness source. If the program needs randomness, decide now: SlotHashes sysvar (provably fair, cheap, manipulable by validators within a slot), Switchboard VRF (true randomness, paid), or commit-reveal (no extra deps, but requires two transactions).
- Testing model. Anchor's default is TypeScript/Mocha via
anchor test. Good for integration-level. For Rust-native unit tests, add atests/Cargo target. LiteSVM / Bankrun give much faster in-memory testing than the built-insolana-test-validator.
Authoring workflow
- Init the workspace.
anchor init my-programgives youprograms/,tests/,Anchor.toml. Commit the scaffold before writing anything. - Decide your account types first —
#[account]structs insrc/state.rs. Every PDA stores its ownbumpfor safe re-derivation. - Write instructions as modules under
src/instructions/. One file per instruction. Each exports anAccountsstruct and a handler function. - Register instructions in
lib.rsinside the#[program]module. Keeplib.rsas a dispatch table — no business logic here. - Custom errors in
src/errors.rsvia#[error_code]. Reference them inline in constraints:constraint = cond @ MyError::Variant. - Tests in
tests/— TypeScript via the Anchor client, with the IDL loaded fromtarget/idl/<program>.json. - Deployment —
anchor build, verify binary size, deploy withsolana program deployoranchor deploy. For mainnet, transfer upgrade authority to a multisig / hardware wallet after initial deploy.
Non-negotiable rules
- Every PDA stores its
bumpon its account and re-derives with that exact bump. Never re-derive a PDA without storing the bump — it's expensive and error-prone. - Every account constraint in
#[derive(Accounts)]has an attributed error.constraint = foo == bar @ MyError::NotBar— not bareconstraint = foo == bar. Unattributed constraints produce opaqueConstraintRawerrors that are miserable to debug. - Dual SOL/SPL instructions stay parallel, not unified. If your program accepts both, keep
place_bet_solandplace_bet_splas separate instructions with separate account contexts. A single polymorphic instruction that branches onmint == Pubkey::default()looks cleaner but breaks Anchor's type guarantees. ownerchecks are constraints, not runtimeifstatements. Put them in#[derive(Accounts)], not in the handler body.- Never use
Clock::get()?.unix_timestamporblock.timestamp-equivalent as randomness. Use SlotHashes sysvar or Switchboard VRF. - Sign your deployment transactions with a local keypair you keep offline for mainnet.
--keypair ~/.config/solana/id.jsonfor devnet is fine; a production upgrade authority should be a hardware wallet or multisig. - Binary size matters.
target/deploy/<program>.soover ~200 KB risks hitting per-slot compute limits and incurs painful rent. Strip withRUSTFLAGS="-C strip=symbols"if you're close.
References
- Anchor workspace setup — init,
Cargo.tomlfeatures,Anchor.toml,lib.rsshape. - PDA patterns — singleton, indexed, per-user, vault PDAs; storing and verifying bumps.
- Accounts and constraints —
#[derive(Accounts)]attributes, constraint-with-error pattern, ownership + state validation. - SOL vs SPL token flows — why they're parallel, how to structure vault PDAs for SPL, mint discrimination.
- On-chain randomness — SlotHashes sysvar pattern, limitations, when to use Switchboard VRF instead.
- Testing with the TypeScript Anchor client — IDL-based client, PDA derivation from TS, smoke tests vs unit tests, LiteSVM alternative.
- Deployment and upgrade authority — build → verify size → deploy → initialize → transfer authority.
What ships with it: 7 files
34.4 KB alongside SKILL.md
references/
- accounts-and-constraints.md5.3 KB
- anchor-setup.md4.0 KB
- deployment.md4.4 KB
- pda-patterns.md5.4 KB
- randomness.md4.4 KB
- sol-vs-spl.md5.8 KB
- testing.md5.1 KB