mcpField
S
solana-kit

solana-kit

github.com/sendaifun開発130346 回インストール13 週間前に更新
リポジトリ

solana-kit について

solana-kitは、`@solana/kit` JavaScript SDKでSolanaアプリを開発するためのスキルガイドです。Solana開発者向けに、関数型設計とTypeScriptの型を活用したRPC、アカウント、署名、トランザクションの手順を扱います。

主な機能

  1. 01HTTP RPCとWebSocket購読
  2. 02署名者と鍵生成のインターフェース
  3. 03関数合成によるトランザクション構築と署名
  4. 04トランザクション送信と確認
  5. 05アカウント取得と一括リクエスト
  6. 06TypeScript型とパッケージの案内

活用シーン

  1. 01`@solana/kit`を使ったSolanaアプリ開発
  2. 02署名済みトランザクションの構築と送信
  3. 03Solanaアカウントの単体・一括取得
  4. 04web3.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 開発ガイド

Anza のモダンでツリーシェイキング可能、依存関係ゼロの JavaScript SDK @solana/kit を使用して Solana アプリケーションを構築するための包括的なガイドです。

概要

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/rpcRPC クライアントの作成
@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:Compute Budget の追加
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:Lookup Table を使ったバージョン付きトランザクション
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);

Note:compat パッケージは、レガシー型から Kit の型へ変換します。逆方向に変換する場合は、レガシーオブジェクトを手動で構築する必要がある場合があります。

パフォーマンスベンチマーク

Kit は web3.js 1.x と比較して、大幅なパフォーマンス向上を実現します。

指標web3.js 1.x@solana/kit改善
キーペア生成~50ms~5ms10 倍高速
トランザクション署名~20ms~2ms10 倍高速
バンドルサイズ311KB226KB26%小型化
確認のレイテンシ~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

コメント