solana-kit について
solana-kitは、`@solana/kit` JavaScript SDKでSolanaアプリを開発するためのスキルガイドです。Solana開発者向けに、関数型設計とTypeScriptの型を活用したRPC、アカウント、署名、トランザクションの手順を扱います。
主な機能
- 01HTTP RPCとWebSocket購読
- 02署名者と鍵生成のインターフェース
- 03関数合成によるトランザクション構築と署名
- 04トランザクション送信と確認
- 05アカウント取得と一括リクエスト
- 06TypeScript型とパッケージの案内
活用シーン
- 01`@solana/kit`を使ったSolanaアプリ開発
- 02署名済みトランザクションの構築と送信
- 03Solanaアカウントの単体・一括取得
- 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.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 開発ガイド
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/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: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
パフォーマンスのヒント
-
必要なものだけをインポートする - 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);
Note:compat パッケージは、レガシー型から Kit の型へ変換します。逆方向に変換する場合は、レガシーオブジェクトを手動で構築する必要がある場合があります。
パフォーマンスベンチマーク
Kit は web3.js 1.x と比較して、大幅なパフォーマンス向上を実現します。
| 指標 | 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