starknet-wallet について
Starknet の AI エージェント向けウォレット管理スキルで、アカウント抽象化、残高確認、送金、コントラクト操作を扱います。Starknet MCP Server のツールを使い、日常的なオンチェーン操作やセッションキーのワークフローを支援します。
主な機能
- 01単一または複数トークンの残高確認
- 02Paymaster のガスレスモードに対応した送金
- 03コントラクトの読み取りと実行
- 04AVNU のスワップ見積もりと実行
- 05事前承認操作のためのセッションキー
活用シーン
- 01エージェントウォレットのトークン残高確認
- 02エージェントウォレットからのトークン送金
- 03セッションキーのポリシーに沿った自律操作
- 04スワップ見積もりの取得とトークン交換
MCP 対応
Starknet MCP Server は、残高、送金、コントラクト呼び出し、スワップ、エージェント ID 登録のツールを MCP クライアントに公開します。このスキルでは MCP クライアント経由でのツール呼び出し方も示します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ keep-starknet-strange/ starknet-agentic --skill starknet-walletインストール後、Claude Code で/starknet-walletを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
.env.examplepackage.jsonagents/openai.yamlscripts/check-balance.tscheck-balances.tsREADME.mdrpc-spec-version.ts詳細
Starknet ウォレットスキル
ネイティブのアカウント抽象化をサポートし、AI エージェント向けに Starknet ウォレットを管理します。
使用する場面
- エージェントのワークフロー用に Starknet アカウントを作成、入金、操作するとき。
- エージェントのウォレットから残高の確認、送金、セッションキーの管理、コントラクトの呼び出しを行うとき。
使用しない場面
starknet-defiのほうが適している、DeFi 固有のルーティング、ステーキング、レンディングのフロー。- Cairo コントラクトの作成、デプロイのみの操作、セキュリティ監査。
クイックスタート
- SDK の依存関係をインストールし、Starknet RPC/アカウントの環境変数を設定します。
- スキルカタログを使用して、DeFi、デプロイ、監査などの関連モジュールに移動します。
前提条件
npm install starknet@^10.8.0 @avnu/avnu-sdk@^4.2.0
環境変数:
STARKNET_RPC_URL=https://starknet-mainnet.g.alchemy.com/v2/YOUR_KEY
STARKNET_ACCOUNT_ADDRESS=0x...
STARKNET_PRIVATE_KEY=0x...
AVNU_BASE_URL=https://starknet.api.avnu.fi (optional)
AVNU_PAYMASTER_URL=https://starknet.paymaster.avnu.fi (optional)
AVNU_PAYMASTER_API_KEY=your_key (optional, for free gas)
利用可能な MCP ツール
Starknet MCP Server は、ウォレット操作用に以下のツールを提供します。
| ツール | 用途 | 主な機能 |
|---|---|---|
starknet_get_balance | 単一トークンの残高を確認 | シンプルで高速なクエリ |
starknet_get_balances | 複数トークンの残高を確認 | バッチクエリ(最大 200 トークン)、単一の RPC 呼び出し |
starknet_transfer | トークンを送金 | ガスレスモード(ペイマスター)に対応 |
starknet_call_contract | コントラクトの状態を読み取る | ビュー関数を呼び出す |
starknet_invoke_contract | コントラクト関数を実行 | 書き込み操作、ガスレスに対応 |
starknet_swap | トークンスワップを実行 | AVNU 連携、最適価格のルーティング |
starknet_get_quote | スワップ見積もりを取得 | スワップ前の価格推定 |
starknet_register_agent | エージェントの ID を登録 | ERC-8004 オンチェーン ID |
残高ツールの詳細
starknet_get_balance(単一トークン)
1 つのトークンの残高を照会します。シンプルなケースで使用します。
入力:
token(必須):トークンのシンボル(ETH、STRK、USDC、USDT)またはコントラクトアドレスaddress(任意):ウォレットアドレス(デフォルトはエージェントのアドレス)
レスポンス:
{
"address": "0x...",
"token": "ETH",
"tokenAddress": "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7",
"balance": "1.5",
"raw": "1500000000000000000",
"decimals": 18
}
starknet_get_balances(複数トークン)
1 回の RPC 呼び出しで複数トークンの残高を照会します。ポートフォリオの表示により効率的です。
入力:
tokens(必須):トークンのシンボルまたはアドレスの配列(最大 200)address(任意):ウォレットアドレス
レスポンス:
{
"address": "0x...",
"balances": [
{ "token": "ETH", "tokenAddress": "0x...", "balance": "1.5", "raw": "...", "decimals": 18 },
{ "token": "USDC", "tokenAddress": "0x...", "balance": "100", "raw": "...", "decimals": 6 }
],
"tokensQueried": 2,
"method": "balance_checker"
}
使用する場面:
- starknet_get_balance:単一トークンの残高をすばやく確認
- starknet_get_balances:ポートフォリオの概要、複数トークンの操作
基本操作
残高を確認(単一トークン)
シンプルな単一トークンのクエリには、starknet_get_balance MCP ツールを使用します。
// Via MCP tool (recommended)
const result = await mcpClient.callTool({
name: "starknet_get_balance",
arguments: {
address: "0x...", // Account address
token: "ETH", // Symbol (ETH, STRK, USDC, USDT) or contract address
}
});
// Returns: { address, token, tokenAddress, balance, raw, decimals }
starknet.js を直接使用:
import { RpcProvider, Contract } from "starknet";
const provider = new RpcProvider({ nodeUrl: process.env.STARKNET_RPC_URL });
// ETH balance (starknet.js v10 uses an options object for Contract)
const ethAddress = "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7";
const ethContract = new Contract({
abi: erc20Abi,
address: ethAddress,
providerOrAccount: provider,
});
// starknet.js parses a Cairo 1 u256 return value to bigint (no low/high struct)
const balance: bigint = await ethContract.balanceOf(accountAddress);
// Format: (balance / 10n ** 18n).toString() for whole units
複数の残高を確認(バッチ)
効率的な複数トークンのクエリには、starknet_get_balances を使用します(RPC 呼び出しは 1 回)。
// Via MCP tool (recommended for multiple tokens)
const result = await mcpClient.callTool({
name: "starknet_get_balances",
arguments: {
address: "0x...",
tokens: ["ETH", "STRK", "USDC", "USDT"], // Up to 200 tokens
}
});
// Returns:
// {
// address: "0x...",
// balances: [
// { token: "ETH", tokenAddress: "0x...", balance: "1.5", raw: "1500000000000000000", decimals: 18 },
// { token: "STRK", tokenAddress: "0x...", balance: "100", raw: "100000000000000000000", decimals: 18 },
// ...
// ],
// tokensQueried: 4,
// method: "balance_checker" // Uses BalanceChecker contract for efficiency
// }
BalanceChecker コントラクトを使って starknet.js を直接使用:
import { RpcProvider, Contract } from "starknet";
const provider = new RpcProvider({ nodeUrl: process.env.STARKNET_RPC_URL });
// BalanceChecker contract (returns non-zero balances only)
const BALANCE_CHECKER_ADDRESS = "0x031ce64a666fbf9a2b1b2ca51c2af60d9a76d3b85e5fbfb9d5a8dbd3fedc9716";
const BALANCE_CHECKER_ABI = [
{
type: "struct",
name: "core::integer::u256",
members: [
{ name: "low", type: "core::integer::u128" },
{ name: "high", type: "core::integer::u128" },
],
},
{
type: "struct",
name: "governance::balance_checker::NonZeroBalance",
members: [
{ name: "token", type: "core::starknet::contract_address::ContractAddress" },
{ name: "balance", type: "core::integer::u256" },
],
},
{
type: "function",
name: "get_balances",
inputs: [
{ name: "address", type: "core::starknet::contract_address::ContractAddress" },
{ name: "tokens", type: "core::array::Span::<core::starknet::contract_address::ContractAddress>" },
],
outputs: [{ type: "core::array::Span::<governance::balance_checker::NonZeroBalance>" }],
state_mutability: "view",
},
];
const balanceChecker = new Contract({
abi: BALANCE_CHECKER_ABI,
address: BALANCE_CHECKER_ADDRESS,
providerOrAccount: provider,
});
// Query multiple tokens at once
const tokens = [
"0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7", // ETH
"0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d", // STRK
"0x033068f6539f8e6e6b131e6b2b814e6c34a5224bc66947c47dab9dfee93b35fb", // USDC
"0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8", // USDC.e (legacy bridged USDC)
];
const result = await balanceChecker.get_balances(accountAddress, tokens);
// Parse response (only non-zero balances returned)
for (const item of result) {
const tokenAddr = "0x" + BigInt(item.token).toString(16).padStart(64, "0");
const balance = BigInt(item.balance); // starknet.js converts u256 to bigint
console.log(`${tokenAddr}: ${balance}`);
}
用途に応じた使い分け:
starknet_get_balance:単一トークン、シンプルなユースケースstarknet_get_balances:複数トークン、ポートフォリオ表示、より効率的
トークンを送金
任意でガスレスモードを指定して、starknet_transfer MCP ツールを使用します。
// Via MCP tool (recommended)
const result = await mcpClient.callTool({
name: "starknet_transfer",
arguments: {
recipient: "0x...",
token: "STRK", // Symbol or contract address
amount: "10.5", // Human-readable amount
gasfree: false, // Optional: use paymaster
}
});
// Returns: { transactionHash, recipient, token, amount, gasfree }
ガスレス送金(ETH/STRK の代わりにトークンでガス代を支払う):
// Pay gas in USDC instead of ETH/STRK
const result = await mcpClient.callTool({
name: "starknet_transfer",
arguments: {
recipient: "0x...",
token: "STRK",
amount: "100",
gasfree: true,
gasToken: "USDC", // Gas paid in USDC
}
});
starknet.js を直接使用:
import { Account, RpcProvider, CallData, cairo, ETransactionVersion } from "starknet";
const provider = new RpcProvider({ nodeUrl: process.env.STARKNET_RPC_URL });
const address = process.env.STARKNET_ACCOUNT_ADDRESS;
const privateKey = process.env.STARKNET_PRIVATE_KEY;
if (!address || !privateKey) throw new Error("Set STARKNET_ACCOUNT_ADDRESS and STARKNET_PRIVATE_KEY");
// starknet.js v10: Account uses an options object; provider calls go through account.provider
const account = new Account({
provider,
address,
signer: privateKey,
transactionVersion: ETransactionVersion.V3,
});
const tokenAddress = "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d"; // STRK
// Use cairo.uint256() instead of uint256.bnToUint256()
const { transaction_hash } = await account.execute({
contractAddress: tokenAddress,
entrypoint: "transfer",
calldata: CallData.compile({
recipient: recipientAddress,
amount: cairo.uint256(amountInWei),
}),
});
await account.provider.waitForTransaction(transaction_hash);
手数料を見積もる
const estimatedFee = await account.estimateInvokeFee({
contractAddress: tokenAddress,
entrypoint: "transfer",
calldata: CallData.compile({
recipient: recipientAddress,
amount: cairo.uint256(amountInWei),
}),
});
// estimatedFee.overall_fee -- total fee in STRK (V3 transactions)
コントラクトとのやり取り
コントラクトの状態を読み取る(ビュー関数):
// Via MCP tool
const result = await mcpClient.callTool({
name: "starknet_call_contract",
arguments: {
contractAddress: "0x...",
entrypoint: "balanceOf",
calldata: [accountAddress],
}
});
コントラクトに書き込む(状態を変更する関数):
// Via MCP tool with gasless option
const result = await mcpClient.callTool({
name: "starknet_invoke_contract",
arguments: {
contractAddress: "0x...",
entrypoint: "approve",
calldata: [spenderAddress, ...uint256Amount],
gasfree: true, // Optional: use paymaster
gasToken: "USDC", // Optional: pay gas in token
}
});
マルチコール(バッチトランザクション)
// Execute multiple operations in a single transaction
const { transaction_hash } = await account.execute([
{
contractAddress: tokenA,
entrypoint: "approve",
calldata: CallData.compile({
spender: routerAddress,
amount: cairo.uint256(amount),
}),
},
{
contractAddress: routerAddress,
entrypoint: "swap",
calldata: CallData.compile({ /* swap params */ }),
},
]);
ガスレス送金(トークンでガス代を支払う) - SDK v4 + PaymasterRpc
import { getQuotes, executeSwap } from "@avnu/avnu-sdk";
import { PaymasterRpc } from "starknet";
// SDK v4: Use PaymasterRpc from starknet.js
// Mainnet: https://starknet.paymaster.avnu.fi
// Sepolia: https://sepolia.paymaster.avnu.fi
const paymaster = new PaymasterRpc({
nodeUrl: process.env.AVNU_PAYMASTER_URL || "https://starknet.paymaster.avnu.fi",
});
// Any swap can be made gasless by adding paymaster option
const result = await executeSwap({
provider: account,
quote: bestQuote,
slippage: 0.01,
executeApprove: true,
paymaster: {
active: true,
provider: paymaster,
params: {
version: "0x1",
feeMode: {
mode: "default",
gasToken: usdcAddress, // Pay gas in USDC instead of ETH/STRK
},
},
},
});
トークンの解決
MCP サーバーは TokenService を使用して、トークンのシンボルとアドレスを解決します。静的トークン(ETH、STRK、USDC、USDT)は常に利用できます。その他のトークンについては、サービスが avnu SDK からメタデータを取得します。
import { fetchTokenByAddress, fetchTokens, fetchVerifiedTokenBySymbol } from '@avnu/avnu-sdk';
// Get token by symbol (undefined if not a verified/unruggable token)
const lords = await fetchVerifiedTokenBySymbol('LORDS');
if (!lords) throw new Error('LORDS not found in avnu token list');
console.log(lords.address, lords.decimals); // 0x0124aeb..., 18
// Get token by address (any token)
const token = await fetchTokenByAddress('0x...');
console.log(token.symbol, token.name, token.decimals);
// Get verified tokens (returns Page<Token>; tokens are in `content`)
const page = await fetchTokens({ tags: ['Verified'], size: 100 });
page.content.forEach(t => console.log(t.symbol, t.address));
ネットワークへの問い合わせなしで利用できる静的トークン:ETH、STRK、USDC、USDT
セッションキー(エージェントの自律性)
セッションキーを使うと、エージェントはアクションごとに人間の承認を得ることなく、事前承認済みのトランザクションを実行できます。
- 人間の所有者が、次のポリシーを設定してセッションキーを作成します。
- 許可するコントラクトアドレスとメソッド
- トランザクション/期間ごとの最大支出額
- 有効期限のタイムスタンプ
- エージェントがセッションキーを使って自律的に操作します。
- 所有者はいつでも取り消せます。
リファレンス実装:Cartridge Controller
設定
| 変数 | 用途 | デフォルト |
|---|---|---|
STARKNET_RPC_URL | Starknet JSON-RPC エンドポイント | 必須 |
STARKNET_ACCOUNT_ADDRESS | エージェントのアカウントアドレス | 必須 |
STARKNET_PRIVATE_KEY | エージェントの署名キー | 必須 |
AVNU_BASE_URL | avnu API のベース URL | https://starknet.api.avnu.fi |
AVNU_PAYMASTER_URL | avnu ペイマスターの URL | https://starknet.paymaster.avnu.fi |
エラー処理
| エラー | 原因 | 解決方法 |
|---|---|---|
INSUFFICIENT_BALANCE | トークン残高が不足しています | 送金前に残高を確認してください |
INVALID_NONCE | ノンスが一致しません | 新しいノンスで再試行してください |
TRANSACTION_REVERTED | コントラクトの実行に失敗しました | calldata と許可設定を確認してください |
FEE_TRANSFER_FAILURE | ガス料金を支払えません | ペイマスターを使うか、ETH/STRK を追加してください |