337 lines
14 KiB
Markdown
337 lines
14 KiB
Markdown
---
|
|
title: "@solana/kit Quick Start"
|
|
description: 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](#installation)
|
|
- [Quick Start](#quick-start)
|
|
- [Client API](#client-api)
|
|
- [Core Concepts](#core-concepts)
|
|
- [Common Patterns](#common-patterns)
|
|
- [Codama Program Clients](#codama-program-clients)
|
|
- [Package Overview](#package-overview)
|
|
- [Best Practices](#best-practices)
|
|
- [Reference Files](#reference-files)
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
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
|
|
|
|
```ts
|
|
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)
|
|
|
|
```ts
|
|
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
|
|
|
|
```ts
|
|
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](https://www.litesvm.com/docs/typescript/getting-started).
|
|
|
|
## 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](plugins.md) for the full options table, plugin catalog, and custom composition.
|
|
|
|
## Core Concepts
|
|
|
|
### Branded Types
|
|
|
|
```ts
|
|
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:
|
|
|
|
```ts
|
|
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
|
|
|
|
```ts
|
|
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](codecs.md) for full codec patterns.
|
|
|
|
## Common Patterns
|
|
|
|
### Send SOL Transfer
|
|
|
|
```ts
|
|
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
|
|
|
|
```ts
|
|
import { fetchEncodedAccount, assertAccountExists, decodeAccount } from '@solana/kit';
|
|
|
|
const account = await fetchEncodedAccount(client.rpc, myAddress);
|
|
assertAccountExists(account);
|
|
const decoded = decodeAccount(account, myDecoder);
|
|
```
|
|
|
|
See [accounts.md](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.
|
|
|
|
```ts
|
|
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](programs/token.md) for low-level instruction patterns and [programs/token-2022.md](programs/token-2022.md) for Token Extensions.
|
|
|
|
### Custom Program Operations
|
|
|
|
Programs that ship a Kit plugin follow the same `.use()` pattern:
|
|
|
|
```ts
|
|
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
|
|
|
|
```ts
|
|
// 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](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](programs/compute-budget.md).
|
|
|
|
## Reference Files
|
|
|
|
- [plugins.md](plugins.md) — Plugin catalog, custom composition, ordering rules
|
|
- [accounts.md](accounts.md) — Fetching, decoding, batch, PDAs, subscriptions
|
|
- [codecs.md](codecs.md) — Complete codec patterns
|
|
- [react.md](react.md) — React hooks and wallet integration
|
|
- [codama.md](codama.md) — Codama patterns, naming conventions, program clients
|
|
- [gotchas.md](gotchas.md) — Common type errors & fixes
|
|
- [advanced.md](advanced.md) — Manual transaction building, direct RPC, building plugins, custom clients
|
|
- [programs/](programs/) — Program client references (system, token, token-2022, compute-budget)
|