Use when adding new error messages to React, or seeing "unknown error code" warnings.
npx skills add sendaifun/skills --skill "solana-kit-migration"
Install specific skill from multi-skill repository
# Description
Helps developers understand when to use @solana/kit vs @solana/web3.js (v1), provides migration guidance, API mappings, and handles edge cases for Solana JavaScript SDK transitions
# SKILL.md
name: solana-kit-migration
description: Helps developers understand when to use @solana/kit vs @solana/web3.js (v1), provides migration guidance, API mappings, and handles edge cases for Solana JavaScript SDK transitions
Solana Kit Migration Assistant
This skill helps you navigate the transition between @solana/web3.js (v1.x) and @solana/kit (formerly web3.js 2.0), providing guidance on when to use each library and how to migrate between them.
Overview
The Solana JavaScript ecosystem has two major SDK options:
| Library | Status | Use Case |
|---|---|---|
@solana/web3.js (1.x) |
Maintenance mode | Legacy projects, Anchor-dependent apps |
@solana/kit |
Active development | New projects, performance-critical apps |
Key Decision: @solana/kit is the future, but migration isn't always straightforward.
When to Use Each Library
Use @solana/kit When:
- Starting a new project without Anchor dependencies
- Bundle size matters - Kit is tree-shakeable (26% smaller bundles)
- Performance is critical - ~200ms faster confirmation latency, 10x faster crypto ops
- Using standard programs (System, Token, Associated Token)
- Building browser applications where bundle size impacts load time
- Type safety is important - Better TypeScript support catches errors at compile time
- Using modern JavaScript - Native BigInt, WebCrypto, AsyncIterators
Use @solana/web3.js (v1.x) When:
- Using Anchor - Anchor doesn't support Kit out of the box yet
- Existing large codebase - Migration cost outweighs benefits
- Dependencies require v1 - Check if your SDKs support Kit
- Rapid prototyping - v1's OOP style may be more familiar
- Documentation/examples - More community resources for v1
Use Both (Hybrid Approach) When:
- Gradual migration - Use
@solana/compatfor interoperability - Mixed dependencies - Some libs require v1, some support Kit
- Feature-by-feature migration - Convert hot paths first
Quick Decision Flowchart
START
β
ββ New project? ββββββββββββββββββββββββββββββββββββββββββ
β β β
β ββ Using Anchor? βββΊ YES βββΊ Use @solana/web3.js β
β β β
β ββ No Anchor? βββΊ Use @solana/kit β
β β
ββ Existing project? βββββββββββββββββββββββββββββββββββββ€
β β
ββ Performance issues? βββΊ Consider migration β
β β
ββ Bundle size issues? βββΊ Consider migration β
β β
ββ Working fine? βββΊ Stay with current SDK β
Instructions for Migration Analysis
When a user asks about migration, follow these steps:
Step 1: Analyze Current Codebase
Run the migration analysis script to detect:
- Which SDK version is currently used
- Anchor dependencies
- Third-party SDK dependencies
- Usage patterns that need migration
# Use the analyze-migration.sh script in scripts/
./scripts/analyze-migration.sh /path/to/project
Step 2: Check Dependencies
Look for these blocking dependencies:
- @coral-xyz/anchor or @project-serum/anchor - Wait for Anchor Kit support
- SDKs that haven't migrated (check their package.json)
Step 3: Assess Migration Complexity
Count occurrences of these patterns that need changes:
- new Connection(...) β createSolanaRpc(...)
- Keypair.fromSecretKey(...) β createKeyPairSignerFromBytes(...)
- new PublicKey(...) β address(...)
- new Transaction() β createTransactionMessage(...)
- Class-based patterns β Functional composition with pipe()
Step 4: Recommend Strategy
Based on findings, recommend:
- Full Migration: If no blockers and < 50 migration points
- Gradual Migration: If 50-200 migration points, use @solana/compat
- Wait: If Anchor-dependent or critical SDKs don't support Kit
- Hybrid: If only specific modules need Kit performance
API Migration Reference
See resources/api-mappings.md for complete mappings. Key conversions:
Connection β RPC
// v1
const connection = new Connection(url, 'confirmed');
const balance = await connection.getBalance(pubkey);
// Kit
const rpc = createSolanaRpc(url);
const { value: balance } = await rpc.getBalance(address).send();
Keypair β KeyPairSigner
// v1
const keypair = Keypair.fromSecretKey(secretKey);
console.log(keypair.publicKey.toBase58());
// Kit
const signer = await createKeyPairSignerFromBytes(secretKey);
console.log(signer.address);
Transaction Building
// v1
const tx = new Transaction().add(
SystemProgram.transfer({
fromPubkey: sender.publicKey,
toPubkey: recipient,
lamports: amount,
})
);
tx.recentBlockhash = blockhash;
tx.feePayer = sender.publicKey;
// Kit
const tx = pipe(
createTransactionMessage({ version: 0 }),
tx => setTransactionMessageFeePayer(sender.address, tx),
tx => setTransactionMessageLifetimeUsingBlockhash(blockhash, tx),
tx => appendTransactionMessageInstruction(
getTransferSolInstruction({
source: sender,
destination: address(recipient),
amount: lamports(BigInt(amount)),
}),
tx
),
);
Edge Cases & Gotchas
1. BigInt Conversion
Kit uses native BigInt everywhere. Watch for:
// WRONG - will fail
const amount = 1000000000;
// CORRECT
const amount = 1_000_000_000n;
// or
const amount = BigInt(1000000000);
// or use helper
const amount = lamports(1_000_000_000n);
2. Base58 Encoding Errors
Kit may require explicit encoding:
// If you see: "Encoded binary (base 58) data should be less than 128 bytes"
// Add encoding parameter:
await rpc.getAccountInfo(address, { encoding: 'base64' }).send();
3. Async Keypair Generation
Kit keypair creation is async (uses WebCrypto):
// v1 - synchronous
const keypair = Keypair.generate();
// Kit - MUST await
const keypair = await generateKeyPairSigner();
4. RPC Method Chaining
Kit RPC calls require .send():
// v1
const balance = await connection.getBalance(pubkey);
// Kit - don't forget .send()!
const { value: balance } = await rpc.getBalance(address).send();
5. PublicKey vs Address
These are different types and not interchangeable:
// Use @solana/compat for conversion
import { fromLegacyPublicKey, toLegacyPublicKey } from '@solana/compat';
const kitAddress = fromLegacyPublicKey(legacyPublicKey);
const legacyPubkey = toLegacyPublicKey(kitAddress);
6. Transaction Signing
Signing flow is different:
// v1
transaction.sign(keypair);
// or
const signed = await connection.sendTransaction(tx, [keypair]);
// Kit - use signer pattern
const signedTx = await signTransactionMessageWithSigners(txMessage);
const signature = await sendAndConfirmTransaction(signedTx);
7. Anchor Incompatibility
Anchor generates v1 types. If using Anchor:
// Keep @solana/web3.js for Anchor interactions
import { Connection, PublicKey } from '@solana/web3.js';
import { Program } from '@coral-xyz/anchor';
// Use Kit for non-Anchor parts if needed
// Bridge with @solana/compat
8. Subscription Handling
Kit uses AsyncIterators:
// v1
const subscriptionId = connection.onAccountChange(pubkey, callback);
connection.removeAccountChangeListener(subscriptionId);
// Kit - use AbortController
const abortController = new AbortController();
const notifications = await rpcSubscriptions
.accountNotifications(address)
.subscribe({ abortSignal: abortController.signal });
for await (const notification of notifications) {
// handle notification
}
// To unsubscribe:
abortController.abort();
9. VersionedTransaction Migration
// v1
const versionedTx = new VersionedTransaction(messageV0);
// Kit - transactions are versioned by default
const tx = createTransactionMessage({ version: 0 });
10. Lookup Tables
Address Lookup Tables work differently:
// v1
const lookupTable = await connection.getAddressLookupTable(tableAddress);
const messageV0 = new TransactionMessage({...}).compileToV0Message([lookupTable.value]);
// Kit
// Lookup tables are handled in transaction compilation
// See resources/lookup-tables-example.md
Alternative: Consider Gill
If Kit feels too low-level, consider Gill:
- Built on Kit primitives
- Higher-level abstractions
- Simpler API for common tasks
- Full Kit compatibility
import { createSolanaClient, sendSol } from 'gill';
const client = createSolanaClient({ rpcUrl });
await sendSol(client, { from: signer, to: recipient, amount: lamports(1n) });
Guidelines
- Always check Anchor compatibility before recommending Kit migration
- Recommend
@solana/compatfor gradual migrations - Bundle size benefits matter most for browser applications
- Performance benefits matter most for high-throughput backends
- Don't migrate stable, working code without clear benefits
- Test thoroughly - Kit has different error types and behaviors
Files in This Skill
solana-kit-migration/
βββ SKILL.md # This file
βββ scripts/
β βββ analyze-migration.sh # Codebase analysis script
β βββ detect-patterns.js # Pattern detection utility
βββ resources/
β βββ api-mappings.md # Complete API reference
β βββ compatibility-matrix.md # SDK compatibility info
β βββ package-comparison.md # Feature comparison
βββ examples/
β βββ v1-to-kit/ # Migration examples
β β βββ basic-transfer.md
β β βββ token-operations.md
β β βββ subscription-handling.md
β βββ mixed-codebase/ # Hybrid approach examples
β βββ anchor-with-kit.md
βββ docs/
βββ edge-cases.md # Detailed edge cases
Notes
- Kit was released as @solana/[email protected] on December 16, 2024
- It was later renamed to @solana/kit to avoid confusion
- The 1.x line is in maintenance mode but still widely used
- Migration tooling is evolving - check for updates regularly
# Supported AI Coding Agents
This skill is compatible with the SKILL.md standard and works with all major AI coding agents:
Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.