Files

14 KiB

title, description
title description
@solana/kit Quick Start Quick-start guide for @solana/kit using createClient + .use() plugin composition for RPC, signers, transaction sending, account fetching, and common Solana patterns.

@solana/kit Reference

@solana/kit is the JavaScript SDK for building Solana applications. Modular, tree-shakable, full TypeScript support. Clients are built by composing plugins onto createClient() via .use().

Contents

Installation

npm install @solana/kit @solana/kit-plugin-rpc @solana/kit-plugin-signer
# or: pnpm add @solana/kit @solana/kit-plugin-rpc @solana/kit-plugin-signer

For LiteSVM testing add @solana/kit-plugin-litesvm. For browser wallet connection add @solana/kit-plugin-wallet. For Codama-generated program clients add the relevant @solana-program/* package(s).

Minimum version: Solana Kit v7 (plugin packages 0.13+). @solana/kit-plugin-wallet needs 0.14+ specifically — its React hooks take the client as an explicit argument only from that version on.

Quick Start

Local Development

import { createClient } from '@solana/kit';
import { solanaLocalRpc } from '@solana/kit-plugin-rpc';
import { signerFromFile } from '@solana/kit-plugin-signer';

// `signerFromFile` sets BOTH payer and identity to the loaded keypair (the common case).
// Other options:
//   - `signer(existingSigner)`              // explicit signer you already hold
//   - `generatedSigner()` + `airdropSigner(lamports(n))` // fresh local/devnet signer, funded after RPC is installed
//   - `payer(...)` + `identity(...)`        // when fees and authority come from different keypairs
const client = await createClient()
  .use(signerFromFile('~/.config/solana/id.json'))
  .use(solanaLocalRpc());

console.log('Payer:', client.payer.address);
await client.sendTransaction([myInstruction]);

Production (Mainnet/Devnet)

import { createClient } from '@solana/kit';
import { solanaDevnetRpc, solanaMainnetRpc } from '@solana/kit-plugin-rpc';
import { signer } from '@solana/kit-plugin-signer';

const client = createClient()
  .use(signer(mySigner)) // sets payer + identity; use payer(...) + identity(...) if they differ
  .use(solanaDevnetRpc()); // or solanaMainnetRpc({ rpcUrl: 'https://...' })

await client.sendTransaction([myInstruction]);

solanaDevnetRpc() defaults to https://api.devnet.solana.com and bundles airdrop. solanaMainnetRpc({ rpcUrl }) is type-narrowed to a mainnet URL — no devnet-only methods like airdrop.

Testing with LiteSVM

import { createClient, lamports } from '@solana/kit';
import { litesvm } from '@solana/kit-plugin-litesvm';
import { airdropSigner, generatedSigner } from '@solana/kit-plugin-signer';

const client = await createClient()
  .use(generatedSigner())
  .use(litesvm())
  .use(airdropSigner(lamports(1_000_000_000n)));

client.svm.addProgramFromFile(myProgramAddress, 'program.so');
await client.sendTransaction([myInstruction]);

Full documentation: LiteSVM.

Client API

After applying solanaRpc / solanaLocalRpc / solanaDevnetRpc / solanaMainnetRpc (or litesvm), the client exposes:

Property/Method Description
client.rpc RPC methods (getBalance, getAccountInfo, etc.)
client.rpcSubscriptions WebSocket subscriptions (RPC plugins only)
client.payer Transaction fee payer signer (set by signer() or payer())
client.identity Authority signer (set by signer() or identity())
client.sendTransaction(instructions) Plan + sign + send in one call
client.sendTransactions(plan) Execute a planned multi-tx plan
client.planTransaction(s) Plan without executing
client.getMinimumBalance(dataSize) Rent-exempt minimum lamports
client.airdrop(address, lamports) Faucet (devnet/local/litesvm only)
client.svm LiteSVM instance (litesvm plugin only)

solanaRpc({ ... }) accepts rpcUrl (required) plus rpcSubscriptionsUrl, transactionConfig (priority fees), maxConcurrency, skipPreflight, and the underlying rpcConfig / rpcSubscriptionsConfig. See plugins.md for the full options table, plugin catalog, and custom composition.

Core Concepts

Branded Types

import { address, lamports, signature } from '@solana/kit';

const myAddress = address('So11111111111111111111111111111111111111112');
const myLamports = lamports(1_000_000_000n);
const mySig = signature('5eykt...');

SOL ↔ Lamports

Sol is a fixed-point value ({ raw, decimals: 9, ... }), not a bigint — convert before passing it to an instruction:

import { lamports, lamportsToSol, sol, solToLamports, formatDecimalFixedPoint } from '@solana/kit';

solToLamports(sol('1.5')); // lamports(1_500_000_000n)
lamportsToSol(lamports(1_500_000_000n)); // Sol fixed-point representing 1.5

// Display
const formatter = new Intl.NumberFormat(undefined, { maximumFractionDigits: 5 });
formatDecimalFixedPoint(formatter, lamportsToSol(balance)); // "1.5"

sol() parses in 'strict' rounding mode by default and throws on more than 9 fractional digits; pass a RoundingMode (e.g. sol('1.1234567891', 'round')) to accept a rounded result. In TypeScript never hand-roll / 1e9 — floats lose precision on large balances.

Signers

import { generateKeyPairSigner } from '@solana/kit';
const signer = await generateKeyPairSigner();
// signer.address — the public key
// signer is a TransactionSigner

Codec Direction

  • encode(): values → Uint8Array
  • decode(): Uint8Array → values

Always use native codecs (e.g., getBase58Codec()). Never import bs58.

See codecs.md for full codec patterns.

Common Patterns

Send SOL Transfer

import { createClient, address, lamports } from '@solana/kit';
import { solanaLocalRpc } from '@solana/kit-plugin-rpc';
import { signerFromFile } from '@solana/kit-plugin-signer';
import { getTransferSolInstruction } from '@solana-program/system';

const client = await createClient()
  .use(signerFromFile('~/.config/solana/id.json'))
  .use(solanaLocalRpc());

const ix = getTransferSolInstruction({
  source: client.payer,
  destination: address('recipient...'),
  amount: lamports(1_000_000_000n),
});

await client.sendTransaction([ix]);

Fetch Account

import { fetchEncodedAccount, assertAccountExists, decodeAccount } from '@solana/kit';

const account = await fetchEncodedAccount(client.rpc, myAddress);
assertAccountExists(account);
const decoded = decodeAccount(account, myDecoder);

See accounts.md for batch fetching, PDAs, subscriptions, and token queries.

Token Operations

Use the tokenProgram() plugin from @solana-program/token for a fluent token API. It auto-derives ATAs, auto-creates them if needed, and defaults the payer from the client.

import { createClient, generateKeyPairSigner } from '@solana/kit';
import { solanaLocalRpc } from '@solana/kit-plugin-rpc';
import { signerFromFile } from '@solana/kit-plugin-signer';
import { tokenProgram } from '@solana-program/token';

const client = await createClient()
  .use(signerFromFile('~/.config/solana/id.json'))
  .use(solanaLocalRpc())
  .use(tokenProgram());

const mintAuthority = await generateKeyPairSigner();
const mint = await generateKeyPairSigner();

// Create a new mint
await client.token.instructions
  .createMint({ newMint: mint, decimals: 2, mintAuthority: mintAuthority.address })
  .sendTransaction();

// Mint tokens to an owner's ATA (created automatically if needed)
await client.token.instructions
  .mintToATA({
    mint: mint.address,
    owner: recipientAddress,
    mintAuthority,
    amount: 1_000_000n,
    decimals: 2,
  })
  .sendTransaction();

// Transfer tokens to a recipient's ATA (auto-derives source + destination)
await client.token.instructions
  .transferToATA({
    mint: mint.address,
    authority: ownerSigner,
    recipient: recipientAddress,
    amount: 500n,
    decimals: 2,
  })
  .sendTransaction();

See programs/token.md for low-level instruction patterns and programs/token-2022.md for Token Extensions.

Custom Program Operations

Programs that ship a Kit plugin follow the same .use() pattern:

import { createClient } from '@solana/kit';
import { solanaDevnetRpc } from '@solana/kit-plugin-rpc';
import { signer } from '@solana/kit-plugin-signer';
import { myProgram } from '@my-programs/operations';

const client = createClient()
  .use(signer(mySigner))
  .use(solanaDevnetRpc())
  .use(myProgram());

await client.myProgram.instructions
  .handyInstruction({ /* args */ })
  .sendTransaction();

RPC Queries

// Balance
const { value: balance } = await client.rpc.getBalance(myAddress).send();

// Token accounts
const { value: tokenAccs } = await client.rpc.getTokenAccountsByOwner(
  owner,
  { mint: mintAddr },
  { encoding: 'jsonParsed' },
).send();

// Latest blockhash
const { value: blockhash } = await client.rpc.getLatestBlockhash().send();

Codama Program Clients

@solana-program/* packages are Codama-generated, Kit-compatible instruction builders:

Package Purpose
@solana-program/system Account creation, transfers, nonces
@solana-program/token SPL Token operations
@solana-program/token-2022 Token Extensions (transfer fees, metadata, etc.)
@solana-program/compute-budget CU limits & priority fees
@solana-program/memo Memo program
@solana-program/stake Staking operations

Note: These packages export both low-level get{Name}Instruction() helpers and higher-level program plugins (e.g., tokenProgram()) that attach fluent APIs to the client. ATA functions are in @solana-program/token and @solana-program/token-2022, not a separate package.

See codama.md for naming conventions and patterns.

Package Overview

Package Purpose
@solana/kit Main SDK, re-exports all sub-packages, exports createClient
@solana/kit-plugin-rpc All-in-one RPC plugins: solanaRpc, solanaMainnetRpc, solanaDevnetRpc, solanaLocalRpc (plus low-level rpc, rpcAirdrop, rpcTransactionPlanner, rpcTransactionPlanExecutor)
@solana/kit-plugin-signer Signer plugins. Default signer* variants set both payer and identity (signer, generatedSigner, signerFromFile). Use airdropSigner to fund an already-installed signer; use generatedSignerWithSol only when an airdrop function is already installed. Role-specific payer* and identity* variants for when the two roles differ.
@solana/kit-plugin-wallet Browser wallet connection (Wallet Standard): walletSigner, walletPayer, walletIdentity, walletWithoutSigner; adds client.wallet (getState(), connect()); React hooks in @solana/kit-plugin-wallet/react
@solana/kit-plugin-litesvm All-in-one litesvm plugin (Node.js only) for in-memory testing
@solana/kit-plugin-instruction-plan planAndSendTransactions and instruction batching primitives
@solana/addresses Address validation
@solana/accounts Account fetching/decoding
@solana/codecs Data encoding/decoding
@solana/rpc JSON RPC client primitives
@solana/rpc-subscriptions WebSocket subscription primitives
@solana/transactions Compile/sign/serialize
@solana/transaction-messages Build tx messages
@solana/signers Signing abstraction
@solana/keychain Common Signing Interface for external signers
@solana/instruction-plans Multi-instruction batching
@solana/errors Error identification/decoding
@solana/functional Pipe and compose utilities
@solana/react Kit-native React bindings (ClientProvider, useClient, data/subscription hooks, SWR & TanStack Query adapters). Its legacy Wallet Standard hooks are being deprecated — use @solana/kit-plugin-wallet/react
@solana/compat Type conversions between Kit and legacy web3.js v1 values

Deprecated packages — do not install: @solana/kit-plugins (umbrella), @solana/kit-plugin-airdrop (use rpcAirdrop/litesvmAirdrop), @solana/kit-plugin-payer (use @solana/kit-plugin-signer), @solana/kit-client-rpc / @solana/kit-client-litesvm (use the solanaRpc / litesvm all-in-one plugins).

Best Practices

  1. Compose with .use() — createClient().use(signer(...)).use(solanaRpc(...)); the signer plugin must come before the RPC/litesvm plugin. Use the role-specific payer() + identity() variants only when fees and authority come from different keypairs.
  2. Use branded types — address(), lamports(), signature().
  3. Use @solana-program/* instruction builders over hand-rolled instruction data.
  4. Handle account existence — assertAccountExists() before decode.
  5. Set compute budget — pass transactionConfig to solanaRpc({ ... }) or use manual CU estimation for production. See programs/compute-budget.md.

Reference Files

  • plugins.md — Plugin catalog, custom composition, ordering rules
  • accounts.md — Fetching, decoding, batch, PDAs, subscriptions
  • codecs.md — Complete codec patterns
  • react.md — React hooks and wallet integration
  • codama.md — Codama patterns, naming conventions, program clients
  • gotchas.md — Common type errors & fixes
  • advanced.md — Manual transaction building, direct RPC, building plugins, custom clients
  • programs/ — Program client references (system, token, token-2022, compute-budget)