solana-program & solana-sdk
solana-program is the on-chain standard library for native Rust programs targeting Agave 4.1.1 sBPF. solana-sdk (and split client crates) power off-chain Rust binaries that build transactions, sign, and talk to RPC. Together they are the foundation beneath Anchor 0.32.1 and lightweight frameworks like Pinocchio.
Recipe
Quick-reference recipe card - copy-paste ready.
# On-chain (Cargo.toml)
[dependencies]
solana-program = "2.2"
# Off-chain client binary
[dependencies]
solana-sdk = "2.2"use solana_program::{
account_info::AccountInfo,
entrypoint,
entrypoint::ProgramResult,
pubkey::Pubkey,
};When to reach for this:
- Writing native on-chain programs without Anchor macros.
- Building Rust CLIs, bots, or test harnesses off-chain.
- Understanding what Anchor expands into under the hood.
- Auditing low-level account validation and CPI helpers.
Working Example
// programs/native_counter/src/lib.rs (on-chain)
use solana_program::{
account_info::{next_account_info, AccountInfo},
entrypoint,
entrypoint::ProgramResult,
msg,
program_error::ProgramError,
pubkey::Pubkey,
};
entrypoint!(process_instruction);
pub fn process_instruction(
_program_id: &Pubkey,
accounts: &[AccountInfo],
_instruction_data: &[u8],
) -> ProgramResult {
let iter = &mut accounts.iter();
let payer = next_account_info(iter)?;
if !payer.is_signer {
return Err(ProgramError::MissingRequiredSignature);
}
msg!("payer: {}", payer.key);
Ok(())
}// client/src/main.rs (off-chain)
use solana_sdk::{
signature::{Keypair, Signer},
system_instruction,
transaction::Transaction,
};
use solana_client::rpc_client::RpcClient;
fn main() {
let rpc = RpcClient::new("https://api.devnet.solana.com".to_string());
let payer = Keypair::new();
let ix = system_instruction::transfer(&payer.pubkey(), &payer.pubkey(), 1);
let bh = rpc.get_latest_blockhash().unwrap();
let tx = Transaction::new_signed_with_payer(&[ix], Some(&payer.pubkey()), &[&payer], bh);
let _sig = rpc.send_and_confirm_transaction(&tx).unwrap();
}What this demonstrates:
- On-chain entrypoint receives accounts and instruction data.
- Signer checks are manual in native code.
- Off-chain SDK composes system instructions and signs transactions.
- RPC client is separate (
solana-client) but pairs withsolana-sdktypes.
Deep Dive
How It Works
solana-programisno_stdfriendly for sBPF targets viacargo build-sbf.solana-sdktargets full Rust std for hosts building and signing transactions.- Crates split in 2.x lines - import only what each binary needs to reduce compile time.
- Anchor
anchor-langre-exports and wraps manysolana-programprimitives.
Rust Crate Table (on-chain vs off-chain)
| Crate | Target | Role | Typical version line |
|---|---|---|---|
solana-program | sBPF program | AccountInfo, CPI, sysvars, program_error | Align with Agave 4.1.1 SDK bundle |
solana-sdk | host binary | Pubkey, Instruction, Transaction, Signer | Same major as solana-program |
solana-client | host binary | RpcClient, thin RPC wrappers | Matches validator RPC semantics |
solana-rpc-client-api | host | Request types | Internal to client stacks |
TypeScript / NPM Table (client parity)
| Package | Role | Pin (this site) |
|---|---|---|
@solana/kit | Modern functional RPC + tx pipeline | 7.0.0 |
@solana/web3.js | Legacy client (migration source) | Avoid new greenfield usage |
@solana/spl-token | SPL helpers | Match token program revision |
Rust Notes
// Programs: avoid std-only crates in Cargo.toml
// Clients: prefer solana_sdk::commitment_config::CommitmentConfig::confirmed()
// CPI example imports
use solana_program::program::invoke;Gotchas
- Mixing 1.x and 2.x crate families - type mismatches across workspace. Fix: one SDK generation per repo, aligned with Agave 4.1.1.
stdin on-chain crates - breakscargo build-sbf. Fix: auditcargo treefor forbidden deps.- Using
solana-sdkinside programs - pulls incompatible features. Fix:solana-programonly on-chain. - Duplicate pubkey types across crates - conversion churn. Fix: standardize imports per binary.
- Assuming Anchor hides validation - native code must enforce owner/signer manually.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
anchor-lang 0.32.1 | Product velocity, IDL | Minimal CU/size native |
pinocchio | Lightweight native | Need Anchor IDL ecosystem |
@solana/kit | TypeScript dApps | Rust-only backend |
solana-py / solders | Python services | Rust performance critical path |
FAQs
Which version matches Agave 4.1.1?
Follow Agave release notes and solana-install 3.0.10 SDK crate versions for that channel.
Is solana-sdk deprecated?
Split into finer crates over time - follow Agave migration guides; concepts remain the same.
Entrypoint macro required?
Yes for standard deploy loaders; Pinocchio uses alternate entry patterns.
Testing native programs?
LiteSVM 0.6.x or Mollusk with solana-sdk types in tests.
IDL generation?
Native programs lack Anchor IDL unless you hand-write or use Shank.
Cross-language clients?
Prefer Codama from IDL to @solana/kit 7.0.0 rather than hand ports.
Feature flags?
Keep program Cargo.toml minimal - each feature can bloat ELF size.
Verifiable builds?
solana-verify hashes must match deployed .so from this toolchain.
no_std logging?
msg! maps to program logs consumed off-chain via RPC.
Where is clock sysvar?
solana_program::sysvar::clock::Clock on-chain; SDK sysvar helpers off-chain.
Related
- anchor-lang & anchor-spl - framework crates
- Native Program Basics - native patterns
- Rust for Solana Basics - Rust primer
- @solana/kit Basics - TS client stack
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.