From Solana Finance
Provides coding guidelines and context for building Solana software, including TypeScript clients, Rust programs, Anchor/Quasar frameworks, and LiteSVM tests.
How this skill is triggered — by the user, by Claude, or both
Slash command
/solana-finance:solanaThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Apply these rules to ensure code quality, maintainability, and adherence to project standards.
Apply these rules to ensure code quality, maintainability, and adherence to project standards.
Don't write things that aren't currently true — anywhere. Chat, code comments, variable names, PR titles, READMEs, commit messages.
InitializeMarket is not true because a struct cannot 'initialize a market' - structs do not do things, only functions can do things.TODO comment with a link to a git issue (if it exists) and telling the next programmer when they can delete the workaround.Actively fix untrue things when you see them. Don't let "close enough" wording stand in for the truthful one.
Grep before naming. Before sending any prose, walkthrough, README, comment, or commit message that names a specific identifier (function, struct, file, account, module, field, constant), grep the source for that exact identifier and confirm it exists. "I'm pretty sure that's the name" is not enough. If the identifier doesn't exist, either use the real name or apply the rename to the code first, then write the prose.
Describe what is, not what was removed. READMEs, doc-comments, and code comments document current state — not history. Lines like "no floats", "no longer uses X", "replaces the previous Y approach" belong in CHANGELOGs and PR descriptions, not source artefacts. A first-time reader has no history and "no longer uses I64F64" creates ambient confusion ("wait, should I be worried?"). Sweep before sending: grep for no longer, removed, previously, used to, formerly, dropped, now uses, replaces the previous — each hit is a candidate for deletion.
The marginal cost of completeness is near zero with AI. Do the whole thing.
Do it right. Do it with tests. Do it with documentation. Do it so well that the user is genuinely impressed - not politely satisfied, actually impressed. Never offer to "table this for later" when the permanent solve is within reach. Never leave a dangling thread when tying it off takes five more minutes. Never present a workaround when the real fix exists.
The standard isn't "good enough" - it's "holy shit, that's done." Search before building. Test before shipping.
Ship the complete thing. When the user asks for something, the answer is the finished product, not a plan to build it. Time is not an excuse. Fatigue is not an excuse. Complexity is not an excuse. Boil the ocean.
Before declaring success, declaring that work is complete, or celebrating, run the project's actual tests using the correct command for that project (for example: anchor test for Anchor workspaces, the project's TypeScript test command for TypeScript clients/tests, or cargo test for Rust crates). If the tests fail, there is more work to do. Don't stop until the relevant test command passes on the code you have made.
Create all program state through the program's own instruction handlers in tests. Injecting pre-fabricated accounts (hand-built account data passed straight into the SVM) hides missing init instructions and missing constraints - a program can pass every test while being unusable onchain. Pre-fabricated accounts are only acceptable for accounts a foreign program would have created (an oracle's price account, a mainnet-dumped fixture).
Tests that use a zero or degenerate value for a parameter (e.g. duration: 0) test only the boundary where opposite comparisons coincide. Use nonzero, asymmetric values and test both sides of every boundary.
Do not write placeholder tests. Placeholder tests don't count as tests, placeholder tests passing does not achieve your task.
assert.ok(true) or similar are placeholder tests and do not count as testsDo not stop until documentation like README.md and CHANGELOG.md are also updated with your changes. If you have made a feature, and it is not documented in the README or changelog, there is more work to do and you must continue working.
When summarizing your work, show the work items you have achieved with this symbol '✅' and if there is any more work to do, add a '❌' for each remaining work item.
Use these official documentation sources:
Remember this is Solana not Ethereum. Ethereum is not relevant to any documentation you write. Do not assume people know or care about Ethereum.
Token program terminology:
Onchain / offchain (one word, no hyphen)
Token amount units: a major unit is the human-scale denomination — dollar, pound, yen, SOL. A minor unit is the smallest denomination, the raw integer programs operate on — cent, penny, sen, lamport. Use these terms; do not say 'base units'.
Some tools in Solana unfortunately use the same word 'instructions' for both the input and the functions. To avoid confusion, use 'instruction handlers' for the functions that handle instructions, and 'instructions' for the input to those functions.
Do not use 'Solana Labs' documentation. The company has been replaced by Anza.
Do not use 'Coral XYZ' documentation or packages. Coral used to maintain Anchor, but Anchor is now maintained by the Solana Foundation (solana.org). The TypeScript package has been moved from @coral-xyz/anchor to @anchor-lang/core.
Do not use any documentaton or tools from Project Serum, which collapsed many years ago.
Do not use yarn. Yarn has no reason to exist and only adds unnecessary dependencies and is not commonly used for new JS/TS projects in 2026. Replace Yarn with npm everywhere you see it. Use npm for new projects as it does not require additional dependencies. Keep using pnpm if the project already uses pnpm.
Do not use Switchboard Functions - this product is dead and no longer maintained. (Note: Switchboard oracles are still active and usable.)
Do not use Clockwork - this product is dead. For scheduled instruction handler invocation, use TukTuk instead.
Do not use [https://github.com/solana-developers/program-examples]. As of June 2026 these examples are out of date, going back to Anchor 0.26 in 2022, use a bunch of deprecated tools, have security failures and broken tests, and have been this way for more than a year.
Use the latest stable Anchor, Rust, TypeScript, Solana Kit, and Kite you can. If a bug occurs, favor updating rather than rolling back.
Every project must have a README.md file in the project root that includes:
anchor test)Keep the README focused and practical. Avoid generic boilerplate - write documentation that would actually help someone understand and work with this specific project.
## 1. Overview or ### 3.6 Liquidation. Numbered headings break when a section is inserted or removed.These apply to READMEs, docs, blog posts, and PR descriptions for finance-related projects (AMMs, escrows, lending, leasing, CLOBs, prediction markets, stablecoins).
take_lease, return_lease, liquidate). Plain-English mechanics without handler names leave the reader unable to connect the narrative to the code.Your golden rule is "perfection isn't achieved when there's nothing more to add, rather perfection is achieved when there is nothing more to be taken away".
Remove:
Before deleting "stale" scaffolding, confirm it is actually dead: grep the CI workflows (.github/workflows/) and package scripts for references. Test files and package.json scripts that look like leftovers are sometimes exactly what CI runs.
/// Pool authority PDA. above pub pool_authority is noise. Either explain something the name doesn't (seed derivation, mutability rationale, type-choice reason, an invariant the reader can't see from the type) or delete the line.Don't remove existing comments unless they are no longer useful or accurate.
When you change a configuration value, or pin a version in any config file (Anchor.toml, Cargo.toml, package.json, CI workflows, .gitignore, rust-toolchain.toml), leave a comment explaining why. The next reader needs the rationale, not just the value.
.gitignore exceptions: why is this file tracked despite the rule?TODO)Example:
# Pinned: 0.8.7 conflicts with litesvm's dep tree.
# Unpin when litesvm upgrades its ahash requirement.
ahash = "=0.8.6"
When you remove a section, only add why to the git commit, so the file is free of information that does not apply to its existing state.
CRITICAL - Verify Before Use:
Ensure good variable naming. Rather than add comments to explain what things are, give them useful names.
Don't do this:
// Foo
const shlerg = getFoo();
Do this instead:
const foo = getFoo();
Naming conventions:
shoes), items within arrays should be the singular (shoes.forEach((shoe) => {...}))calculateFoo or getBarcontext rather than ctx). Never use e for something thrown, use thrownObject, never use v when you mean value. There is almost no case where a single character variable is a good idea outside math (eg p and q for cryptography).transaction. Name instructions some variant of instruction. Name signatures some variant of signature. Do not confuse them - eg if the type looks like an instruction, you should not call it a 'transaction' because that is deceptive.You can still add comments for additional context, just be careful to avoid comments that are explaining things that would be better conveyed by good variable naming.
This is a magic number. Don't do this:
const FINALIZE_EVENT_DISCRIMINATOR = new Uint8Array([
27, 75, 117, 221, 191, 213, 253, 249,
]);
Instead do this:
const FINALIZE_EVENT_DISCRIMINATOR = getEventDiscriminator(
arciumIdl,
"FinalizeComputationEvent",
);
// In production we'd do this differently or **Implementation incomplete** - Needs program config handling and proper PDA derivations or **WORK IN PROGRESS** in the final code you produce, or functions that return placeholder data. Instead: do the fucking work.The rules above apply to every file in the project. In addition, read the file that matches the language you are editing:
.ts): see TYPESCRIPT.md.rs files using anchor_lang, LiteSVM tests): see ANCHOR.md, plus RUST.md for the shared rules.rs files using quasar_lang/quasar_spl): see QUASAR.md, plus RUST.md for the shared rulesIf a task touches more than one, read each.
For setting up a Solana toolchain in CI or a fresh remote container (Agave, platform-tools behind TLS-intercepting proxies, the Quasar CLI, building Anchor projects without the anchor CLI): see ENVIRONMENT.md.
Do not add "Co-Authored-By: Claude" or similar attribution when creating git commits.
Use the Linux/Git style scope: description for commit titles. Do not use 'Conventional commits'.
npx claudepluginhub quicknode/solana-finance-skillScans Solana/Anchor Rust programs for 6 critical vulnerabilities: arbitrary CPI, improper PDA validation, missing signer/ownership checks, sysvar spoofing. Use for security audits.
Scans Solana programs for 6 critical vulnerabilities including arbitrary CPI, improper PDA validation, missing signer/ownership checks, and sysvar spoofing. Use when auditing Solana/Anchor programs.