@solana/kit Basics
9 examples to get you started with @solana/kit - 6 basic and 3 intermediate.
Prerequisites
Install kit 7.0.0 and the system program helpers:
npm install @solana/kit@7.0.0 @solana-program/systemSet RPC_URL to a devnet endpoint (provider URL recommended over public rate limits).
Basic Examples
1. Create an RPC Client
Typed JSON-RPC with .send() on every method.
import { createSolanaRpc, address } from "@solana/kit";
const rpc = createSolanaRpc("https://api.devnet.solana.com");
const slot = await rpc.getSlot().send();
console.log(slot);createSolanaRpcreturns a tree-shakable client - import only what you use.- Every RPC call ends with
.send()for explicit network I/O. - Swap the URL for mainnet-beta when you intend real SOL.
Related: RPC & Subscriptions - subscriptions and providers
2. Read an Account Balance
Addresses are branded strings - not byte arrays in app code.
import { createSolanaRpc, address, lamports } from "@solana/kit";
const rpc = createSolanaRpc(process.env.RPC_URL!);
const owner = address("YOUR_WALLET_PUBKEY");
const { value } = await rpc.getBalance(owner).send();
console.log(Number(value) / 1e9);address()validates base58 and returns a typedAddress.- Balances return
Lamports(bigint) - convert carefully for display. - Cache reads in UI; chain state changes every slot.
Related: RPC & Subscriptions - HTTP vs WebSocket
3. Generate a Keypair Signer
Server scripts and tests use explicit signers.
import { generateKeyPairSigner } from "@solana/kit";
const signer = await generateKeyPairSigner();
console.log(signer.address);generateKeyPairSignercreates an Ed25519 key usable in transaction messages.- Browser apps should prefer wallet signers, not embedded secret keys.
- Persist secrets with chmod 600 and never commit to git.
Related: Keypairs & Signers - CryptoKey and file import
4. Load a Keypair from JSON
Match the solana-keygen array format.
import { createKeyPairSignerFromBytes } from "@solana/kit";
import { readFileSync } from "node:fs";
const secret = Uint8Array.from(
JSON.parse(readFileSync("./dev-wallet.json", "utf8"))
);
const signer = await createKeyPairSignerFromBytes(secret);- The JSON file is a 64-byte secret key array.
- Use separate keypairs per cluster (devnet vs mainnet).
- In CI, load from environment secrets - not repo files.
Related: Keypairs & Signers - signer traits
5. Fetch Latest Blockhash
Blockhashes expire - refresh per transaction batch.
const { value: blockhash } = await rpc.getLatestBlockhash().send();
console.log(blockhash.blockhash, blockhash.lastValidBlockHeight);- Lifetime is tied to
lastValidBlockHeight- stale hashes fail confirmation. - Fetch once per user gesture, not once per page load.
- Pair with retry logic on blockhash expiry errors.
Related: Building Transaction Messages - lifetimes
6. Build a Version 0 Message
Functional pipe composes immutable message transforms.
import {
createTransactionMessage,
pipe,
setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash,
appendTransactionMessageInstruction,
} from "@solana/kit";
import { getTransferSolInstruction } from "@solana-program/system";
const message = pipe(
createTransactionMessage({ version: 0 }),
(m) => setTransactionMessageFeePayerSigner(signer, m),
(m) => setTransactionMessageLifetimeUsingBlockhash(blockhash, m),
(m) =>
appendTransactionMessageInstruction(
getTransferSolInstruction({
source: signer,
destination: recipient,
amount: 10_000_000n,
}),
m
)
);- Version 0 messages support address lookup tables.
- Instructions come from
@solana-program/*packages, not string program IDs. - Amounts are
bigintlamports.
Related: Building Transaction Messages - full pipeline
Intermediate Examples
7. Sign and Send
Signers are resolved from the message, then RPC submits the wire transaction.
import {
signTransactionMessageWithSigners,
getSignatureFromTransaction,
sendAndConfirmTransactionFactory,
} from "@solana/kit";
const signed = await signTransactionMessageWithSigners(message);
const signature = getSignatureFromTransaction(signed);
const sendAndConfirm = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
await sendAndConfirm(signed, { commitment: "confirmed" });signTransactionMessageWithSignerscollects required signers from the message.- Use WebSocket subscriptions for confirmation when available.
- Log signatures for support tickets and explorer links.
Related: Signing & Sending - confirmation strategies
8. Subscribe to Account Changes
Push updates beat polling for wallet UIs.
import { createSolanaRpcSubscriptions, address } from "@solana/kit";
const rpcSubscriptions = createSolanaRpcSubscriptions("wss://api.devnet.solana.com");
const abort = new AbortController();
const notifications = await rpcSubscriptions
.accountNotifications(address("YOUR_ACCOUNT"), { commitment: "confirmed" })
.subscribe({ abortSignal: abort.signal });
for await (const n of notifications) {
console.log(n.value.lamports);
}- Always abort subscriptions on unmount.
- Use
wss://endpoints - HTTP URLs fail for subscriptions. - Provider tiers differ in subscription caps.
Related: RPC & Subscriptions - subscription types
9. Encode Account Data with Codecs
Kit codecs replace hand-rolled Buffer layouts.
import {
getU32Encoder,
getU32Decoder,
getStructEncoder,
getStructDecoder,
} from "@solana/kit";
const layout = getStructEncoder([["count", getU32Encoder()]]);
const bytes = layout.encode({ count: 42 });
const decoded = getStructDecoder([["count", getU32Decoder()]]).decode(bytes);- Encoders and decoders are separate for tree-shaking.
- Pair with Codama-generated layouts for program accounts.
- Prefer generated codecs over copy-pasted IDL offsets.
Related: Codecs & Serialization - advanced layouts
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.