关于 solana-kit
solana-kit 是一份使用 `@solana/kit` JavaScript SDK 构建 Solana 应用的开发技能指南,面向 Solana 开发者。内容涵盖 RPC、账户、签名和交易流程,并采用函数式设计与 TypeScript 类型支持。
主要功能
- 01HTTP RPC 与 WebSocket 订阅
- 02签名者与密钥生成接口
- 03函数式构建和签署交易
- 04发送交易并等待确认
- 05获取账户及批量请求
- 06TypeScript 类型与包使用指南
适用场景
- 01使用 `@solana/kit` 开发 Solana 应用
- 02组合并发送已签名交易
- 03获取单个或多个 Solana 账户
- 04从 web3.js 1.x 迁移到 Kit
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ sendaifun/ skills --skill solana-kit安装后在 Claude Code 中输入/solana-kit确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
docs/advanced-patterns.mdtroubleshooting.mdexamples/create-token/README.mdexamples/fetch-accounts/README.mdexamples/subscriptions/README.mdexamples/transfer-sol/README.mdresources/api-quick-reference.mdpackages-reference.mdtemplates/project-template.ts详细介绍
Solana Kit 开发指南
使用 @solana/kit 构建 Solana 应用的综合指南。@solana/kit 是 Anza 推出的现代化、支持摇树优化且零依赖的 JavaScript SDK。
概览
Solana Kit(前身为 web3.js 2.0)是对 Solana JavaScript SDK 的完整重写,具有以下特性:
- 支持摇树优化:仅打包你使用的代码(包体积减少 78%)
- 零依赖:无需第三方包
- 函数式设计:可组合,无类
- 加密速度提升 10 倍:原生支持 Ed25519
- TypeScript 优先:完整的类型安全
快速开始
安装
npm install @solana/kit
如需与特定程序交互:
npm install @solana-program/system @solana-program/token
最简示例
import {
createSolanaRpc,
createSolanaRpcSubscriptions,
generateKeyPairSigner,
lamports,
pipe,
createTransactionMessage,
setTransactionMessageFeePayer,
setTransactionMessageLifetimeUsingBlockhash,
appendTransactionMessageInstruction,
signTransactionMessageWithSigners,
sendAndConfirmTransactionFactory,
getSignatureFromTransaction,
} from "@solana/kit";
import { getTransferSolInstruction } from "@solana-program/system";
const LAMPORTS_PER_SOL = BigInt(1_000_000_000);
async function transferSol() {
// 1. Connect to RPC
const rpc = createSolanaRpc("https://api.devnet.solana.com");
const rpcSubscriptions = createSolanaRpcSubscriptions("wss://api.devnet.solana.com");
// 2. Create signers
const sender = await generateKeyPairSigner();
const recipient = await generateKeyPairSigner();
// 3. Get blockhash
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
// 4. Build transaction with pipe
const transactionMessage = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayer(sender.address, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
(tx) => appendTransactionMessageInstruction(
getTransferSolInstruction({
amount: lamports(LAMPORTS_PER_SOL / BigInt(10)), // 0.1 SOL
destination: recipient.address,
source: sender,
}),
tx
)
);
// 5. Sign
const signedTx = await signTransactionMessageWithSigners(transactionMessage);
// 6. Send and confirm
const sendAndConfirm = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
await sendAndConfirm(signedTx, { commitment: "confirmed" });
console.log("Signature:", getSignatureFromTransaction(signedTx));
}
核心概念
1. RPC 连接
Kit 将 HTTP 和 WebSocket 连接分开处理:
import { createSolanaRpc, createSolanaRpcSubscriptions } from "@solana/kit";
// HTTP for requests
const rpc = createSolanaRpc("https://api.devnet.solana.com");
// WebSocket for subscriptions
const rpcSubscriptions = createSolanaRpcSubscriptions("wss://api.devnet.solana.com");
// Make RPC calls
const slot = await rpc.getSlot().send();
const balance = await rpc.getBalance(address).send();
const { value: blockhash } = await rpc.getLatestBlockhash().send();
2. 签名者
Kit 使用签名者接口,而不是直接使用密钥对:
import {
generateKeyPairSigner,
createKeyPairSignerFromBytes,
address,
} from "@solana/kit";
// Generate new signer
const signer = await generateKeyPairSigner();
console.log("Address:", signer.address);
// From existing secret key (Uint8Array)
const existing = await createKeyPairSignerFromBytes(secretKeyBytes);
// Create address from string
const addr = address("11111111111111111111111111111111");
3. 使用 Pipe 构建交易
Kit 通过 pipe 实现函数式组合:
import {
pipe,
createTransactionMessage,
setTransactionMessageFeePayer,
setTransactionMessageLifetimeUsingBlockhash,
appendTransactionMessageInstruction,
appendTransactionMessageInstructions,
prependTransactionMessageInstructions,
} from "@solana/kit";
const tx = pipe(
createTransactionMessage({ version: 0 }), // Create v0 message
(tx) => setTransactionMessageFeePayer(payer.address, tx), // Set fee payer
(tx) => setTransactionMessageLifetimeUsingBlockhash(blockhash, tx), // Set lifetime
(tx) => appendTransactionMessageInstruction(instruction1, tx), // Add instruction
(tx) => appendTransactionMessageInstructions([instruction2, instruction3], tx), // Add multiple
);
4. 签署交易
import {
signTransactionMessageWithSigners,
partiallySignTransactionMessageWithSigners,
getSignatureFromTransaction,
} from "@solana/kit";
// Sign with all signers in the transaction
const signedTx = await signTransactionMessageWithSigners(transactionMessage);
// Partial signing (for multisig)
const partiallySignedTx = await partiallySignTransactionMessageWithSigners(
transactionMessage
);
// Get signature before sending
const signature = getSignatureFromTransaction(signedTx);
5. 发送交易
import {
sendAndConfirmTransactionFactory,
sendTransactionWithoutConfirmingFactory,
getBase64EncodedWireTransaction,
} from "@solana/kit";
// Send with confirmation (recommended)
const sendAndConfirm = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
await sendAndConfirm(signedTx, { commitment: "confirmed" });
// Send without waiting for confirmation
const send = sendTransactionWithoutConfirmingFactory({ rpc });
await send(signedTx, { commitment: "confirmed" });
// Manual encoding (low-level)
const encoded = getBase64EncodedWireTransaction(signedTx);
await rpc.sendTransaction(encoded, { encoding: "base64" }).send();
6. 获取账户
import {
fetchEncodedAccount,
fetchEncodedAccounts,
assertAccountExists,
} from "@solana/kit";
// Fetch single account
const account = await fetchEncodedAccount(rpc, address);
if (account.exists) {
console.log("Lamports:", account.lamports);
console.log("Owner:", account.programAddress);
console.log("Data:", account.data);
}
// Fetch multiple accounts
const accounts = await fetchEncodedAccounts(rpc, [addr1, addr2, addr3]);
// Assert account exists (throws if not)
assertAccountExists(account);
软件包参考
核心软件包
| 导入 | 描述 |
|---|---|
@solana/kit | 主软件包,包含下方列出的所有内容 |
独立软件包
| 软件包 | 用途 |
|---|---|
@solana/rpc | 创建 RPC 客户端 |
@solana/rpc-subscriptions | WebSocket 订阅 |
@solana/signers | 签名接口 |
@solana/addresses | 地址工具 |
@solana/keys | 密钥生成 |
@solana/transactions | 交易编译 |
@solana/transaction-messages | 消息构建 |
@solana/accounts | 账户获取 |
@solana/codecs | 数据编码/解码 |
@solana/errors | 错误处理 |
程序软件包
| 软件包 | 程序 |
|---|---|
@solana-program/system | System Program |
@solana-program/token | SPL Token |
@solana-program/token-2022 | Token Extensions |
@solana-program/memo | Memo Program |
@solana-program/compute-budget | Compute Budget |
@solana-program/address-lookup-table | Lookup Tables |
常见模式
模式 1:用于发送和确认的辅助函数
import {
signTransactionMessageWithSigners,
sendAndConfirmTransactionFactory,
getSignatureFromTransaction,
CompilableTransactionMessage,
TransactionMessageWithBlockhashLifetime,
Commitment,
} from "@solana/kit";
function createTransactionSender(rpc: Rpc, rpcSubscriptions: RpcSubscriptions) {
const sendAndConfirm = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
return async (
txMessage: CompilableTransactionMessage & TransactionMessageWithBlockhashLifetime,
commitment: Commitment = "confirmed"
) => {
const signedTx = await signTransactionMessageWithSigners(txMessage);
await sendAndConfirm(signedTx, { commitment, skipPreflight: false });
return getSignatureFromTransaction(signedTx);
};
}
// Usage
const sendTx = createTransactionSender(rpc, rpcSubscriptions);
const signature = await sendTx(transactionMessage);
模式 2:可复用的交易构建器
import {
pipe,
createTransactionMessage,
setTransactionMessageFeePayer,
setTransactionMessageLifetimeUsingBlockhash,
appendTransactionMessageInstructions,
IInstruction,
} from "@solana/kit";
async function buildTransaction(
rpc: Rpc,
feePayer: Address,
instructions: IInstruction[]
) {
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
return pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayer(feePayer, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
(tx) => appendTransactionMessageInstructions(instructions, tx)
);
}
模式 3:添加计算预算
import {
getSetComputeUnitLimitInstruction,
getSetComputeUnitPriceInstruction,
} from "@solana-program/compute-budget";
const computeInstructions = [
getSetComputeUnitLimitInstruction({ units: 200_000 }),
getSetComputeUnitPriceInstruction({ microLamports: 1000n }),
];
const tx = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayer(payer.address, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(blockhash, tx),
(tx) => prependTransactionMessageInstructions(computeInstructions, tx), // Prepend!
(tx) => appendTransactionMessageInstruction(mainInstruction, tx),
);
模式 4:使用查找表的版本化交易
import {
setTransactionMessageAddressLookupTable,
} from "@solana/kit";
// Fetch lookup table
const lookupTableAccount = await fetchAddressLookupTable(rpc, lookupTableAddress);
const tx = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayer(payer.address, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(blockhash, tx),
(tx) => setTransactionMessageAddressLookupTable(tx, lookupTableAccount),
(tx) => appendTransactionMessageInstructions(instructions, tx),
);
类型安全
Kit 提供全面的 TypeScript 类型:
import type {
Address,
Signature,
Lamports,
TransactionMessage,
Rpc,
RpcSubscriptions,
KeyPairSigner,
} from "@solana/kit";
// Addresses are branded strings
const addr: Address = address("11111111111111111111111111111111");
// Lamports are branded bigints
const amount: Lamports = lamports(1_000_000_000n);
// Type-safe RPC responses
const response = await rpc.getBalance(addr).send();
// response.value is typed as Lamports
性能提示
-
仅导入所需内容——Kit 支持摇树优化
// Good - only imports what's used import { createSolanaRpc, generateKeyPairSigner } from "@solana/kit"; // Also good - use subpackages for smaller bundles import { createSolanaRpc } from "@solana/rpc"; import { generateKeyPairSigner } from "@solana/signers"; -
复用 RPC 连接——不要为每个请求都创建连接
// Create once const rpc = createSolanaRpc(endpoint); // Reuse everywhere await rpc.getBalance(addr1).send(); await rpc.getBalance(addr2).send(); -
尽可能批量处理请求
// Fetch multiple accounts in one request const accounts = await fetchEncodedAccounts(rpc, [addr1, addr2, addr3]); -
谨慎使用 skipPreflight——速度更快,但不会进行模拟
await sendAndConfirm(tx, { commitment: "confirmed", skipPreflight: true });
错误处理
import { isSolanaError, SOLANA_ERROR__TRANSACTION_ERROR__INSUFFICIENT_FUNDS } from "@solana/errors";
try {
await sendAndConfirm(signedTx, { commitment: "confirmed" });
} catch (error) {
if (isSolanaError(error, SOLANA_ERROR__TRANSACTION_ERROR__INSUFFICIENT_FUNDS)) {
console.error("Not enough SOL for transaction");
} else if (isSolanaError(error)) {
console.error("Solana error:", error.context);
} else {
throw error;
}
}
从 web3.js 1.x 迁移
请参阅单独的迁移技能,或使用 @solana/compat 实现互操作:
import {
fromLegacyPublicKey,
fromLegacyKeypair,
fromVersionedTransaction,
fromLegacyTransactionInstruction,
} from "@solana/compat";
// Convert legacy PublicKey to Kit Address
const address = fromLegacyPublicKey(legacyPublicKey);
// Convert legacy Keypair to Kit CryptoKeyPair (async)
const keyPair = await fromLegacyKeypair(legacyKeypair);
// Convert legacy VersionedTransaction to Kit Transaction
const kitTransaction = fromVersionedTransaction(legacyVersionedTx);
// Convert legacy TransactionInstruction to Kit Instruction
const kitInstruction = fromLegacyTransactionInstruction(legacyInstruction);
注意:compat 软件包会将旧版类型转换为 Kit 类型。若要反向转换,你可能需要手动构建旧版对象。
性能基准
与 web3.js 1.x 相比,Kit 显著提升了性能:
| 指标 | web3.js 1.x | @solana/kit | 提升 |
|---|---|---|---|
| 密钥对生成 | ~50ms | ~5ms | 快 10 倍 |
| 交易签名 | ~20ms | ~2ms | 快 10 倍 |
| 包体积 | 311KB | 226KB | 缩小 26% |
| 确认延迟 | ~400ms | ~200ms | 快约 200ms |
基准测试数据来自 Triton One 的 Ping Thing 服务和 Solana Explorer 测试
速度更快的原因
- 原生 Ed25519:使用浏览器/运行时原生加密 API
- 零依赖:没有第三方库的开销
- 支持摇树优化:仅导入你使用的代码
- 无类:函数式设计有助于实现更好的优化
Resources
Skill Structure
solana-kit/
├── SKILL.md # This file
├── resources/
│ ├── packages-reference.md # Complete package documentation
│ └── api-quick-reference.md # Quick lookup table
├── examples/
│ ├── transfer-sol/ # Basic SOL transfer
│ ├── create-token/ # SPL token creation
│ ├── fetch-accounts/ # Account fetching & decoding
│ └── subscriptions/ # Real-time subscriptions
├── templates/
│ └── project-template.ts # Copy-paste starter
└── docs/
├── advanced-patterns.md # Complex patterns
└── troubleshooting.md # Common issues
评论
支持 Markdown