Solana Fundamentals Best Practices
The foundations to internalize before writing programs, clients, or infrastructure on Agave 4.1.1.
How to Use This List
- Walk A through C before your first program deploy
- Revisit D when onboarding new team members from EVM backgrounds
- Treat E as a pre-mainnet gate - every item should pass
A - Mental Model
- State lives in accounts, not programs. Programs are stateless executables that read/write accounts passed to them.
- Every entity is an account. Wallets, programs, token mints, and data structs are all accounts with lamports, owner, and data fields.
- Transactions declare all accounts upfront. Sealevel uses this list for parallel scheduling and lock enforcement.
- Only the owner program writes account data. Security follows from ownership rules, not from hiding addresses.
B - Currency and Precision
- Store and transmit lamports as integers. Use
bigintin TypeScript; avoidf64casts in Rust programs. - Convert SOL to lamports at the UI boundary. Parse decimal strings with integer math, not floating point.
- Read SPL decimals separately from SOL. Token amounts use mint-specific decimals, not 1e9.
- Fund new accounts to rent-exempt minimum. Query
getMinimumBalanceForRentExemptionbeforeinit.
C - Clusters and Environment
- Default to devnet for application development. Use local validator (Surfpool 0.12.0 or
solana-test-validator) for CI. - Pin RPC URL, CLI config, and wallet network to the same cluster. Mismatches produce "account not found" errors.
- Never airdrop or test with mainnet keypairs. Use separate keypair files per environment.
- Verify genesis hash when debugging cluster issues.
solana genesis-hashconfirms you are on the intended network.
D - Keys and Signing
- Never commit keypair JSON to version control. Add
*.jsonkey files to.gitignore; use secrets managers in production. - Mark every signing account with
isSigner: true. Missing signer flags cause runtime rejection. - Use PDAs for program-controlled addresses. Users sign; programs sign for PDAs via seeds.
- Keep fee payer funded but not over-funded. Service wallets hold minimal SOL for fees only.
E - Transactions and Confirmation
- Use
confirmedcommitment for most dapp actions. Reservefinalizedfor high-value settlements. - Refresh blockhash on every retry. Expired blockhashes cause silent drops.
- Simulate before submit during development. Decode program errors from simulation logs.
- Subscribe to signature notifications over polling. WebSockets reduce RPC load and latency.
- Read explorer logs for failed transactions. On-chain errors are in program logs, not just RPC error codes.
FAQs
What is the single most important mental model shift?
State lives in accounts, not inside programs. Design account layouts before writing instruction logic.
Should I use devnet or localnet for CI?
Localnet. Surfpool 0.12.0 or solana-test-validator avoids rate limits and cluster instability.
Why are floats dangerous for SOL amounts?
JavaScript number cannot represent all lamport values exactly. Use bigint end-to-end.
What commitment level should a swap UI use?
confirmed for display. Consider finalized before releasing funds from escrow.
How do I safely share a transaction with a teammate?
Explorer link with ?cluster= param matching the network where the tx was sent.
When should I read the EVM comparison page?
Before designing any "one contract stores everything" pattern. Solana needs account-per-entity design.
What tooling versions should I pin?
Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, @solana/kit 7.0.0 per this site's manifest.
Is processed commitment safe for UX?
No. Transactions can be dropped or reordered at processed. Wait for confirmed minimum.
How do I validate a new teammate's setup?
solana config get, solana balance, solana airdrop 1, send 0.001 SOL, confirm in explorer with correct cluster param.
Should I use web3.js v1 for new projects?
No. Use @solana/kit 7.0.0 for new TypeScript clients. web3.js v1 is legacy.
What is the first CLI command every developer should run?
solana config set --url devnet && solana airdrop 2How do slots relate to user-facing latency?
Slots (~400 ms) drive block production. User confirmation should track commitment levels, not slot counts.
Related
- Solana Basics - hands-on orientation examples
- The Solana Mental Model vs. EVM - deepest model shift
- How a Transaction Flows - confirmation best practices in context
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, and LiteSVM 0.6.x.