Kit client

@solana/kit ships createClient, a small host you extend with plugins. Each plugin adds a capability — an RPC connection, a signer, transaction planning — and the composed client backs scripts, server routes, and UIs alike.

Building a React app? The React guide wraps this same client with @solana/react so components read wallet state and RPC data through hooks. Start there and drop back here when you need finer control.

Install

Terminal
$
npm install @solana/kit @solana/kit-plugin-rpc @solana/kit-plugin-signer

Use any package manager. Kit is v7+ and the @solana/kit-plugin-* packages are 0.13+.

Create a client

Compose plugins with .use(...). Set a signer first, then the RPC connection. solanaDevnetRpc() adds client.rpc, subscriptions, the transaction planner/executor, and the client.sendTransaction helper — so an app rarely needs to wire those pieces itself.

import { createClient, generateKeyPairSigner } from "@solana/kit";
import { solanaDevnetRpc } from "@solana/kit-plugin-rpc";
import { signer } from "@solana/kit-plugin-signer";
const payer = await generateKeyPairSigner();
const client = createClient().use(signer(payer)).use(solanaDevnetRpc());
const slot = await client.rpc.getSlot().send();
console.log("current slot", slot);

The signer plugin sets both the fee payer and the app identity. The RPC bundle requires a payer to be in place first, which is why the order matters.

Signer variants

@solana/kit-plugin-signer exposes three roles so you only grant what a client needs:

  • signer(x) — sets both client.payer and client.identity.
  • payer(x) — fee payer only.
  • identity(x) — app authority only.

Each has *FromFile(path) (Node), generated*(), generated*WithSol(amount), and airdrop*() variants for tests and scripts.

Send a transaction

Build instructions with a generated program client, then hand them to client.sendTransaction. The planner resolves the blockhash, estimates compute, signs with the client's payer, and submits.

import { getTransferSolInstruction } from "@solana-program/system";
import { address, lamports } from "@solana/kit";
const transfer = getTransferSolInstruction({
source: client.payer,
destination: address("Fke...address"),
amount: lamports(10_000_000n) // 0.01 SOL
});
const { context } = await client.sendTransaction([transfer]);
console.log("submitted", context.signature);

sendTransaction resolves to a result object; the transaction signature is at result.context.signature. It asserts the plan fits a single transaction and throws otherwise — use sendTransactions when a batch may span multiple transactions.

Pick an RPC bundle

@solana/kit-plugin-rpc ships cluster presets:

  • solanaDevnetRpc() — devnet defaults, airdrop enabled (client.airdrop).
  • solanaMainnetRpc() — mainnet; airdrop is a compile-time error.
  • solanaLocalRpc()http://127.0.0.1:8899 for a local validator.
  • solanaRpc({ rpcUrl }) — any endpoint.
import { solanaRpc } from "@solana/kit-plugin-rpc";
const client = createClient()
.use(signer(payer))
.use(solanaRpc({ rpcUrl: "https://your-rpc-provider.example" }));

Compose granularly

The presets bundle the RPC connection, planner, executor, and send helpers, so most apps never need the pieces individually. Drop to the granular plugins only to customize one — for example a custom planner or a different subscription channel. This path also needs @solana/kit-plugin-instruction-plan, which the presets otherwise include for you:

import {
solanaRpcConnection,
rpcAirdrop,
rpcTransactionPlanner,
rpcTransactionPlanExecutor
} from "@solana/kit-plugin-rpc";
import { planAndSendTransactions } from "@solana/kit-plugin-instruction-plan";
const client = createClient()
.use(signer(payer))
.use(solanaRpcConnection({ rpcUrl: "https://api.devnet.solana.com" }))
.use(rpcAirdrop())
.use(rpcTransactionPlanner())
.use(rpcTransactionPlanExecutor())
.use(planAndSendTransactions());

Add program clients

Generated @solana-program/* packages expose client plugins so program calls hang off the client. Install the program you need and .use() its plugin:

import { tokenProgram } from "@solana-program/token";
const client = createClient()
.use(signer(payer))
.use(solanaDevnetRpc())
.use(tokenProgram()); // adds client.token

Signing without a browser wallet

Running headless in an API route, worker, or script? Sign with a backend key-management service instead of a raw keypair. See Keychain and Signing in Production.

Common patterns for Solana devs

  • Shared setup: Build the client once in a core module and import it into scripts, server routes, and your UI.
  • Server-side reads: A client with just signer + solanaRpc (no wallet plugin) reads accounts and simulates transactions from the server.
  • Local testing: Swap the RPC bundle for .use(litesvm()) from @solana/kit-plugin-litesvm to run against an in-memory validator (Node only).
  • Testability: The composed client is easy to mock — stub RPC responses or signers without a browser wallet present.

Is this page helpful?

Table of Contents

Edit Page
© 2026 Solana Foundation. All rights reserved.