mcpField
S
starknet-wallet

starknet-wallet

github.com/keep-starknet-strangeその他8138 回インストール3 週間前に更新
リポジトリ

starknet-wallet について

Starknet の AI エージェント向けウォレット管理スキルで、アカウント抽象化、残高確認、送金、コントラクト操作を扱います。Starknet MCP Server のツールを使い、日常的なオンチェーン操作やセッションキーのワークフローを支援します。

主な機能

  1. 01単一または複数トークンの残高確認
  2. 02Paymaster のガスレスモードに対応した送金
  3. 03コントラクトの読み取りと実行
  4. 04AVNU のスワップ見積もりと実行
  5. 05事前承認操作のためのセッションキー

活用シーン

  1. 01エージェントウォレットのトークン残高確認
  2. 02エージェントウォレットからのトークン送金
  3. 03セッションキーのポリシーに沿った自律操作
  4. 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.example
package.json
agents/
openai.yaml
scripts/
check-balance.ts
check-balances.ts
README.md
rpc-spec-version.ts

詳細

Starknet ウォレットスキル

ネイティブのアカウント抽象化をサポートし、AI エージェント向けに Starknet ウォレットを管理します。

使用する場面

  • エージェントのワークフロー用に Starknet アカウントを作成、入金、操作するとき。
  • エージェントのウォレットから残高の確認、送金、セッションキーの管理、コントラクトの呼び出しを行うとき。

使用しない場面

  • starknet-defi のほうが適している、DeFi 固有のルーティング、ステーキング、レンディングのフロー。
  • Cairo コントラクトの作成、デプロイのみの操作、セキュリティ監査。

クイックスタート

  1. SDK の依存関係をインストールし、Starknet RPC/アカウントの環境変数を設定します。
  2. スキルカタログを使用して、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

セッションキー(エージェントの自律性)

セッションキーを使うと、エージェントはアクションごとに人間の承認を得ることなく、事前承認済みのトランザクションを実行できます。

  1. 人間の所有者が、次のポリシーを設定してセッションキーを作成します。
    • 許可するコントラクトアドレスとメソッド
    • トランザクション/期間ごとの最大支出額
    • 有効期限のタイムスタンプ
  2. エージェントがセッションキーを使って自律的に操作します。
  3. 所有者はいつでも取り消せます。

リファレンス実装:Cartridge Controller

設定

変数用途デフォルト
STARKNET_RPC_URLStarknet JSON-RPC エンドポイント必須
STARKNET_ACCOUNT_ADDRESSエージェントのアカウントアドレス必須
STARKNET_PRIVATE_KEYエージェントの署名キー必須
AVNU_BASE_URLavnu API のベース URLhttps://starknet.api.avnu.fi
AVNU_PAYMASTER_URLavnu ペイマスターの URLhttps://starknet.paymaster.avnu.fi

エラー処理

エラー原因解決方法
INSUFFICIENT_BALANCEトークン残高が不足しています送金前に残高を確認してください
INVALID_NONCEノンスが一致しません新しいノンスで再試行してください
TRANSACTION_REVERTEDコントラクトの実行に失敗しましたcalldata と許可設定を確認してください
FEE_TRANSFER_FAILUREガス料金を支払えませんペイマスターを使うか、ETH/STRK を追加してください

参考資料

コメント