@solana/kit In Detail
@solana/kit 7.0.0 is the modern TypeScript client stack for Solana: functional composition, branded types, tree-shakable modules, and explicit network I/O. It is the default for new clients in 2026. Legacy @solana/web3.js v1 is a migration source, not a greenfield default.
This page maps RPC, subscriptions, keypairs and signers, transaction messages, codecs, address lookup tables (ALTs), and the web3.js v1 migration path before the focused recipe pages.
Summary
Kit splits what web3.js v1 packed into Connection, Transaction, and PublicKey into smaller, typed surfaces. You create an RPC client for HTTP JSON-RPC, a subscriptions client for WebSockets, and you build transaction messages with pure transforms (pipe, fee payer, blockhash lifetime, instructions) before signing and sending.
Signers are the unit of authorization: local KeyPairSigners for scripts and tests, wallet-backed signers for browsers, all sharing one interface so fee payer and instruction authorities are not ad hoc public-key strings. Addresses are branded base58 strings validated at construction. Amounts that touch the chain are bigint lamports, not floating SOL and not BN by default.
Codecs encode and decode instruction and account layouts without assuming Anchor codegen. Version 0 messages plus ALTs shrink account lists when multi-hop DeFi or large remaining-account sets would blow size limits. Migration is intentional: port reads first, then message build and wallet sign, then delete web3.js so you do not run two client mental models forever.
Foundations
What kit is for
@solana/kit is a client SDK, not an on-chain framework. It talks to RPC nodes, builds wire-format transactions, signs (or hands signing to a wallet), and decodes account bytes. On-chain logic still lives in programs (native, Anchor 0.32.1, Pinocchio, and so on).
web3.js v1 vs kit 7.x at a glance
| Concern | web3.js v1 | @solana/kit 7.0.0 |
|---|---|---|
| RPC entry | new Connection(url) | createSolanaRpc(url) + .send() |
| Live updates | connection.onAccountChange | createSolanaRpcSubscriptions + async iterators |
| Addresses | PublicKey class | address() branded string |
| Signing identity | Keypair / adapter quirks | Signer interfaces (KeyPairSigner, wallet signers) |
| Transaction shape | Mutable Transaction / VersionedTransaction | Immutable message transforms, then sign |
| Program helpers | Monolith + assorted packages | Scoped packages (e.g. @solana-program/system) |
| Layouts | Manual Buffer / borsh helpers | Composable encoders/decoders |
| Bundle shape | Large shared surface | Tree-shakable imports |
Mutable class APIs encouraged editing a tx object until it worked. Kit prefers a pipeline: create message, set fee payer and lifetime, append instructions, optionally compress with ALTs, sign, then send and confirm.
Core branded pieces
Address: validated base58 public key string for accounts and programs.Lamports/ bigint amounts: chain-facing integers; convert only at the UI edge.Signer: something that can authorize a role (fee payer, transfer source, authority).- Transaction message: versioned structure holding fee payer, lifetime, and instructions before signatures exist.
- Codec: encoder/decoder pair for a byte layout (struct, enum, fixed/variable arrays, addresses).
Where each recipe page sits
| Topic | Role in the stack |
|---|---|
| RPC & Subscriptions | HTTP reads and WebSocket notification streams |
| Keypairs & Signers | Local keys, wallet signers, fee payer roles |
| Building Transaction Messages | pipe, lifetime, instructions, compute budget |
| Codecs & Serialization | Instruction data and account decode/encode |
| Address Lookup Tables | Version-0 size reduction via on-chain tables |
| Migrating from web3.js v1 | Pattern map and phased cutover |
Mechanics
One productive client flow is fixed enough to memorize; other flows specialize this pipeline.
End-to-end client pipeline
App / script / route handler
|
| 1. createSolanaRpc(+ subscriptions)
| 2. resolve Signer(s) and Address values
| 3. fetch blockhash (lifetime) and any account reads
| 4. createTransactionMessage({ version: 0 })
| 5. set fee payer + lifetime + instructions (pipe)
| 6. optional: compress with address lookup tables
| 7. signTransactionMessageWithSigners (or wallet)
| 8. send + confirm at chosen commitment
v
Agave-class RPC / cluster
1. RPC and subscriptions
createSolanaRpc(url) returns a typed JSON-RPC proxy. Methods do not hit the network until you call .send(). That makes request construction, batching strategies, and testing less magical than fire-on-call methods.
Subscriptions use a separate client (createSolanaRpcSubscriptions) over WebSocket. Notification APIs return streams you consume with for await and cancel with AbortSignal. HTTP and WS URLs must target the same cluster; a common production bug is HTTPS mainnet with WSS still on devnet.
Commitment (processed, confirmed, finalized) is a first-class option on reads and confirmations. Product UX usually waits on confirmed; irreversible off-chain effects should wait on finalized.
2. Keypairs and signers
Scripts and tests generate or load key material:
generateKeyPairSigner()for ephemeral Ed25519 identities.createKeyPairSignerFromBytes(or related import helpers) forsolana-keygenJSON arrays.
Browser apps should not embed secret keys. Wallet adapters and Wallet Standard integrations expose signers that implement the same roles without revealing private keys. Fee payers use helpers like setTransactionMessageFeePayerSigner so the message carries both address and signing capability.
Off-chain message signing for auth is a sibling concern: same identity, different payload. Keep domain separation so login signatures cannot be confused with transaction approvals.
3. Transaction messages
Prefer version 0 messages for new work. Build immutably:
createTransactionMessage({ version: 0 })- Set fee payer (signer-aware).
- Set lifetime from a fresh
getLatestBlockhashresult. - Append instructions (compute budget first when you set CU limit/price).
- Sign once the message is complete.
pipe keeps multi-step transforms readable. Instructions often come from scoped packages such as @solana-program/system (getTransferSolInstruction) rather than a single monolithic SystemProgram object. Multi-instruction transactions remain atomic on-chain: all succeed or none commit.
Stale blockhashes expire. Fetch lifetime close to submit, and design retries to rebuild messages rather than reusing a dead lifetime.
4. Codecs and serialization
Programs speak bytes. Kit codecs compose small primitives into structs:
- Fixed widths:
u8,u32,u64, and friends as encoders/decoders. getAddressEncoder/getAddressDecoderfor 32-byte pubkeys in layouts.getStructEncoder/getStructDecoderfor ordered field layouts.- Discriminators (often 8-byte Anchor hashes or custom tags) as leading fields.
Use codecs when you lack a generated client, when indexing raw accounts, or when validating instruction data before send. Prefer Codama or Anchor-generated clients for known program APIs; keep hand-rolled codecs for edges generators do not cover.
Endianness, padding, and option tags must match the on-chain layout. A clean TypeScript type that diverges from the program's borsh/bytemuck layout is still wrong on the wire.
5. Address lookup tables
Legacy and oversized account lists fail with size or account-count limits. Version 0 messages can reference accounts through address lookup tables: on-chain tables of addresses that the runtime expands during processing so the wire transaction carries compact indexes instead of full keys for every account.
Client-side, fetch table account data, build a full logical message, then compress with helpers such as compressTransactionMessageUsingAddressLookupTables. Tables must exist and be activated before production use; create/extend/freeze is operational work, not free at submit time.
Use ALTs for large DeFi routes, bulk NFT ops, and repeated large account sets. Skip ALT complexity for simple two-account transfers.
6. Sign, send, confirm
After the message is complete, signTransactionMessageWithSigners resolves embedded signers. Factories such as sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions }) wait for the chosen commitment. A signature means submission was accepted; product correctness still depends on confirmation policy and errors (expired blockhash, funds, simulation).
Advanced
Migration mindset from web3.js v1
Do not rewrite the entire app in one PR if the surface is large. A durable sequence:
| Phase | Scope | Exit criteria |
|---|---|---|
| 1 | RPC reads only | Balances, accounts, and slots use kit RPC |
| 2 | Message build + wallet sign | User flows sign kit messages |
| 3 | Remove web3.js | Single dependency tree in CI |
| 4 | Generated program clients | Codama/IDL clients for your programs |
Convert PublicKey to Address at module boundaries once. Standardize on bigint for lamports. Replace implicit confirm habits with explicit factories and commitment. Kill dual stacks on a deadline; endless partial migration doubles bug surface.
Tree-shaking and package boundaries
Import only the helpers you need. Prefer @solana-program/* instruction builders over copy-pasted account metas. Keep wallet code out of server/edge bundles; load file keypairs only in dedicated Node scripts.
Commitment, providers, and reliability
Public RPCs rate-limit aggressively. Production needs a provider URL, separate HTTP and WS endpoints, and backoff on 429/5xx. Subscriptions drop; reconnect with backoff and resync from HTTP rather than assuming a gap-free stream.
Codecs in multi-service systems
Share layout modules (or generate once) across frontend, workers, and indexers. Divergent hand-rolled parsers are a silent incident class. Version account data on-chain when layouts evolve; decode via discriminator or version fields.
ALTs in product design
Treat lookup tables as infrastructure: ownership, authority, extension cadence, and freeze policy belong in runbooks. Avoid stale cached table views; measure wire size before and after compression in CI for critical routes.
Testing posture
Unit-test pure message transforms and codecs offline. Integration-test send/confirm on local validators (Solana CLI 3.0.10 / Agave-class) or Surfpool-style envs. Simulate before send to catch meta errors cheaper than mainnet retries.
Common Misconceptions
Misconception: Kit is "web3.js with different import paths."
The programming model changed: immutable messages, branded types, explicit .send(), and signer interfaces. Treating it as a rename guarantees awkward hybrid code.
Misconception: PublicKey and Address are interchangeable everywhere.
They are not the same type. Convert at boundaries; do not pass class instances into kit APIs expecting branded strings.
Misconception: If .send() is annoying, skip it or wrap it away forever.
.send() makes I/O explicit. You can thin-wrap for app ergonomics, but hiding all network boundaries tends to recreate the old implicit Connection mess.
Misconception: Browser dapps should ship KeyPairSigners in the bundle.
User authority belongs in wallets. Local keypair signers are for servers, CI, and tests (with secret hygiene).
Misconception: Codecs are only for people without Anchor.
Generated clients cover known programs. Codecs still matter for unknown accounts, custom layouts, migrations, and indexers.
Misconception: ALTs replace careful account design.
They compress references; they do not remove lock contention, CU cost, or the need for correct writable/signer metas.
Misconception: A signature string means the transfer is final.
Confirmation commitment decides durability. Design UX and backend effects around that ladder.
Misconception: Running kit and web3.js side by side indefinitely is fine.
It works briefly. Long term you pay double dependency weight and double cognitive load. Plan removal.
FAQs
What is @solana/kit in one sentence?
A modular TypeScript client stack for Solana RPC, signing, transaction messages, codecs, and related helpers, designed for tree-shaking and explicit composition in the 7.x line.
Should new projects still start on web3.js v1?
No. Prefer @solana/kit 7.0.0 for new TypeScript clients. Use web3.js v1 only while migrating legacy code.
Why does every RPC method need .send()?
So building a request is pure and network I/O is intentional. That improves typing, testing, and control over retries and batching.
What is a Signer versus an Address?
An Address identifies an account. A Signer can prove authority for that address (or a role) when a transaction requires signatures.
When do I use createTransactionMessage versus older Transaction classes?
Use kit transaction messages for all new kit code. Avoid constructing web3.js Transaction objects if you have already adopted kit signing and send helpers.
Where do System Program transfers come from now?
From scoped packages such as @solana-program/system (for example getTransferSolInstruction), composed into a message with fee payer and lifetime set.
Do I need codecs if I use Codama or Anchor clients?
Not for every instruction. You still want codec literacy for raw account inspection, custom programs, and services that cannot take a full generated client.
When are address lookup tables worth it?
When version-0 transactions would otherwise exceed size or account limits, especially multi-account DeFi routes and bulk operations that reuse large address sets.
How do subscriptions relate to getAccountInfo?
HTTP reads give point-in-time state. Subscriptions push updates; after reconnects, rebaseline with HTTP so you do not miss gaps.
What commitment should I confirm with?
Many app actions use confirmed. Use finalized before irreversible external side effects. Treat processed as optimistic UI only.
How should I migrate a large React dapp?
Phase it: kit RPC reads, then message build and wallet signing, then remove web3.js, then generated program clients. See Migrating from web3.js v1.
Does kit replace Anchor?
No. Anchor targets on-chain programs (and its own client tooling). Kit is the general TypeScript client stack for talking to the cluster and composing transactions.
Where should I go after this page?
Start with RPC & Subscriptions and Keypairs & Signers, then Building Transaction Messages. Add codecs and ALTs when layouts or size force the issue; use the migration guide if you still ship web3.js v1.
Related
- RPC & Subscriptions - typed HTTP JSON-RPC and WebSocket notification streams
- Keypairs & Signers - KeyPairSigner, wallet signers, and fee payer roles
- Building Transaction Messages - pipe composition, lifetime, instructions, compute budget
- Codecs & Serialization - composable encoders and decoders for account and ix data
- Address Lookup Tables - version-0 compression with on-chain lookup tables
- Migrating from web3.js v1 - pattern map and phased removal of legacy clients
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, Rust 1.91.1, and @solana/kit 7.0.0.