mcpField
S
solana-kit

solana-kit

github.com/sendaifun开发130346 次安装13 周前更新
代码仓库

关于 solana-kit

solana-kit 是一份使用 `@solana/kit` JavaScript SDK 构建 Solana 应用的开发技能指南,面向 Solana 开发者。内容涵盖 RPC、账户、签名和交易流程,并采用函数式设计与 TypeScript 类型支持。

主要功能

  1. 01HTTP RPC 与 WebSocket 订阅
  2. 02签名者与密钥生成接口
  3. 03函数式构建和签署交易
  4. 04发送交易并等待确认
  5. 05获取账户及批量请求
  6. 06TypeScript 类型与包使用指南

适用场景

  1. 01使用 `@solana/kit` 开发 Solana 应用
  2. 02组合并发送已签名交易
  3. 03获取单个或多个 Solana 账户
  4. 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.md
troubleshooting.md
examples/create-token/
README.md
examples/fetch-accounts/
README.md
examples/subscriptions/
README.md
examples/transfer-sol/
README.md
resources/
api-quick-reference.md
packages-reference.md
templates/
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-subscriptionsWebSocket 订阅
@solana/signers签名接口
@solana/addresses地址工具
@solana/keys密钥生成
@solana/transactions交易编译
@solana/transaction-messages消息构建
@solana/accounts账户获取
@solana/codecs数据编码/解码
@solana/errors错误处理
程序软件包
软件包程序
@solana-program/systemSystem Program
@solana-program/tokenSPL Token
@solana-program/token-2022Token Extensions
@solana-program/memoMemo Program
@solana-program/compute-budgetCompute Budget
@solana-program/address-lookup-tableLookup 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

性能提示

  1. 仅导入所需内容——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";
    
  2. 复用 RPC 连接——不要为每个请求都创建连接

    // Create once
    const rpc = createSolanaRpc(endpoint);
    
    // Reuse everywhere
    await rpc.getBalance(addr1).send();
    await rpc.getBalance(addr2).send();
    
  3. 尽可能批量处理请求

    // Fetch multiple accounts in one request
    const accounts = await fetchEncodedAccounts(rpc, [addr1, addr2, addr3]);
    
  4. 谨慎使用 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 倍
包体积311KB226KB缩小 26%
确认延迟~400ms~200ms快约 200ms

基准测试数据来自 Triton One 的 Ping Thing 服务和 Solana Explorer 测试

速度更快的原因
  1. 原生 Ed25519:使用浏览器/运行时原生加密 API
  2. 零依赖:没有第三方库的开销
  3. 支持摇树优化:仅导入你使用的代码
  4. 无类:函数式设计有助于实现更好的优化

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