strk20-wallet-api について
プライバシー対応ウォレットを使って STRK20 のプライベート dapp を構築するためのスキルです。機能検出、プライベート操作、Shadow Account、DeFi フローを扱い、アプリがプライベート状態に触れない設計を示します。
主な機能
- 01Wallet API の機能検出
- 02Shield とプライベート送金
- 03dapp ごとの Shadow Account
- 04アトミックなプライベート DeFi フロー
- 05ウォレットの同意とプライバシー指針
活用シーン
- 01dapp にプライベート送金を追加
- 02永続する仮名ポジションの構築
- 03プライベートスワップと DeFi 呼び出しの組み合わせ
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ odinfree/ strk20-skills --skill strk20-wallet-apiインストール後、Claude Code で/strk20-wallet-apiを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlreferences/starknet-wallet-api__avnu-private-swaps.mdstarknet-wallet-api__overview.mdstarknet-wallet-api__private-defi.mdstarknet-wallet-api__shadow-accounts.mdstarknet-wallet-api__starknet-js.mdstarknet-wallet-api__starknet-start-hook.md詳細
STRK20 Wallet API:プライベート Dapp
ほとんどのプライベート Dapp に推奨される方法です。Dapp はユーザーのプライバシー対応ウォレットに処理を依頼し、ウォレットが閲覧キー、ノートの検出、証明の生成、送信を処理します。アプリがプライベート状態を目にすることはありません。ユーザーに閲覧キーを求めないでください。
詳細なドキュメントは references/ にあります。以下のスニペットは、特に重要な部分です。
バージョンの基準。インストール前に確認してください
- STRK20 のコアサポートは starknet.js 10.4.0 で追加されました。安定版のシャドウアカウントサポートは、Wallet API 0.10.4 とともに starknet.js 10.8.0 で追加されました。
- starknet.js v5、v6、または v7 を使っている既存リポジトリの場合、10.4.0 への更新は破壊的変更を伴うため、STRK20 を組み込む前に独立したタスクとして計画してください。
- 安定性がテスト済みのシャドウアカウントの組み合わせは、
[email protected]、@starknet-io/[email protected]、および get-starknet discovery と wallet standard6.0.6です。これらをまとめて固定し、アップグレード時には接続とウォレットのテストを再実行してください。 - STRK20 のコアメソッドには Wallet API
>= 0.10.3、シャドウアカウントには Wallet API>= 0.10.4が必要です。ライブラリをアップグレードしても、接続中のウォレットに機能が追加されるわけではないため、実行時に通知されたバージョンを検出してください。 - ラッパーレイヤー:Starkzap のドキュメントには STRK20 サポートの記載がなく、starknet-react や starknetkit は starknet.js 10.4.0 への対応が遅れている可能性があります。すぐに置き換えられると約束する前に、npm で現在の互換性を確認してください。いずれの場合も、公式の agent-skill リポジトリによると、プラグインの接続先は starknet.js の
WalletAccountV6レベルです。
2 つの方法
- React Dapp の場合:Starknet Start の
useStrk20フックを使います。これは内部でWalletAccountV6を呼び出す便利なラッパーです。 - その他の場合、または接続や証明の処理をより細かく制御する必要がある場合:get-starknet v6 で接続した
WalletAccountV6を直接使います。
データ呼び出しではなく、バージョン照会で機能を検出する
const versions = await walletV6.supportedWalletApi(wallet)
const supported = versions.some((v) => compareVersions(v, "0.10.3") >= 0)
const supportsShadowAccounts = versions.some((v) => compareVersions(v, "0.10.4") >= 0)
機能検出のために strk20Balances を呼び出さないでください。これは残高を読み取るメソッドであり、アプリが見る理由のないデータへのアクセスを許可するユーザー同意のプロンプトを、ウォレットが表示するためです。
接続中のウォレットの型は、エクスポートされた機能サブパスからインポートしてください。パッケージのルートからインポートすると TS2459 が発生します。
import type { WalletWithStarknetFeatures } from "@starknet-io/get-starknet-wallet-standard/features"
アクション
STRK20_ACTION[] を作成し、ウォレットに渡します。
// Shield (deposit into the pool)
const actions: STRK20_ACTION[] = [{ type: "deposit", token: tokenAddress, amount }]
// Private transfer. No contract call, no event, no approval step.
const actions: STRK20_ACTION[] = [
{ type: "transfer", token: strkAddress, amount, recipient },
]
const { transaction_hash } = await account.strk20InvokeTransaction(actions)
送信時に UI が通知なく失敗するのを防ぐため、次の 2 点に注意してください。
waitForTransactionにアプリケーションのタイムアウトを設定してください。ペイマスター経由で中継されたハッシュが、選択した RPC に現れるまで時間がかかる場合があります。タイムアウトは「送信済みだが、まだ確認を確認できない」ことを意味します。そのため、エクスプローラーへのリンクを保持し、UI でポーリングを再開できるようにしてください。- 比較の前に felt アドレスを正規化してください。パディングの有無が異なる 16 進数文字列でも同じトークンまたはアカウントを表すことがあるため、
BigInt(left) === BigInt(right)で比較します。
シャドウアカウント:dapp ごとの安定した ID
シャドウアカウントを使うと、1 人のユーザーが (dappName, nonce) の各ペアに対して、決定論的な公開実行アカウントを導出できます。これは別のウォレットではありません。署名鍵はなく、正規の ShadowAccountAnonymizer だけがこのアカウントを通じて実行できます。新しいアドレスが必要な場合は、新しい nonce を使用してください。nonce を再利用すると同じアドレスが再利用され、公開アクティビティが関連付けられます。
import type {
STRK20_ACTION,
STRK20_SHADOW_ACCOUNT_INVOKE_ACTION,
} from "starknet"
const shadowAction: STRK20_SHADOW_ACCOUNT_INVOKE_ACTION = {
type: "shadow_account_invoke",
dapp_name: "myDapp",
nonce: "0x0",
calls: [dappContract.populate("stake", { amount: 1_000n })],
collect_policy: { type: "diff" },
}
const actions: STRK20_ACTION[] = [
{ type: "transfer", token: rewardToken, amount: "OPEN", recipient: userAddress },
shadowAction,
]
const commitment = await account.strk20ShadowAccountCommitment("myDapp", "0x0")
コミットメントの呼び出しはローカルで行われ、トランザクションは送信されません。nonce を省略すると、そのユーザーと dapp のすべてのシャドウアカウントで共有される部分コミットメントが取得されます。これを公開すると、dapp はそのグループを識別できるようになり、意図的にその dapp のコンテキスト内でアカウントが関連付けられます。
回収ポリシーによって、各オープンノートに戻される量が決まります。all はトークン残高の全額を回収し、diff はこのインタラクションによる増加分のみを回収し、exact は指定した量を回収します。1 つのポリシーが、そのアクションによって精算されるすべてのオープンノートに適用されます。
ほとんどの shadow_account_invoke リクエストでは、dapp_name と nonce だけが必要です。dapp が先にアドレスへ資金を入金する必要がある場合や、公開ポジションを読み取る必要がある場合は、nonce に依存しない部分コミットメントを取得し、正規アノニマイザーの get_shadow_accounts ビューを通じて解決してください。アドレス導出の内部処理を複製するより、このビューを優先してください。
const partial = await account.strk20ShadowAccountCommitment("myDapp")
const accounts = await anonymizer.get_shadow_accounts(partial, 0, 1, false)
const shadowAddress = accounts[0].address
2026-09-29 に確認された正規デプロイ先:
- Mainnet:
0x04f33230dc57855c6e7eabe66dfa0fde82c5458fd0e54827cdb7cb4c474888a7 - Sepolia:
0x010a2285310c107c731d997afc147afb7495daff6397c2d242133d9fe8d9b147
フローを構築する前に references/starknet-wallet-api__shadow-accounts.md を読み、リリース前に接続先ネットワークのデプロイ先を再確認してください。
このフローを表示する前に、接続済みウォレットの機能を確認してください。starknet.js だけを根拠にサポートされていると判断してはいけません。上記の一般的な 0.10.3 の確認だけでは、シャドウアカウントには不十分です。supportedWalletApi() が 0.10.4 以降の互換性のあるバージョンを提示していることを必須とし、コミットメントまたは invoke の呼び出しから未対応メソッドの応答が返された場合にも対処してください。このアカウントはメインウォレットへの直接的なつながりを隠します。ただし、そのアドレス、呼び出し、残高、ポジション、イベント、タイミングは引き続き公開されます。
- シールドには ERC-20 の
approveが必要であり、approveはトークン所有者として実行する必要があります。これはトランザクションが 2 つになることを意味しません。ペイマスターを使う場合、approveはsignMessageによって外部実行として承認され、入金と同じトランザクションに含まれます(invoke_and_apply_action)。ウォレットによってプロンプトが 1 つ表示されるか 2 つ表示されるかは、ウォレットの実装によります。対象のウォレットを確認し、表示される各ステップにラベルを付けてください。 - プライベート送金は、登録済みのプールユーザー間で行われます。初回利用時にウォレットが送信者を自動登録しますが、受取人も登録が必要であり、登録できるのは受取人本人だけです。受取人の登録を促す UX を設計してください。登録前に送金するフローでは、
strk20-anonymizer-contractsのエスクローパターンを確認してください。 - 送金でリテラル量
"OPEN"を指定すると、DeFi ヘルパーの出力が加算されるスロットであるオープンノートが作成されます。invoke の calldata 内で、ウォレットは 2 つのプレースホルダーを解決します。${openNoteIds[N]}(このトランザクション内の N 番目のオープンノートの ID)と${poolAddress}(プライバシープールのアドレス)です。 - プール手数料は、プライベート操作ごとに定額で適用されます。ハードコードせず、プールの
get_fee_amountから読み取ってください(公式の agent-skill リポジトリの作成時点では Mainnet で 4 STRK)。MAX 金額を事前入力する場合は手数料を差し引いてください。そうしないと、ユーザーが署名した後に操作が失敗します。ウォレットのフローでは現在、ガス手数料はスポンサーされていますが、プール手数料はスポンサーされません。
プライベート DeFi のエンドツーエンド処理(2 つのアクション、1 つのトランザクション)
const actions: STRK20_ACTION[] = [
// 1. Open the note the swap output will be credited into.
{ type: "transfer", token: tokenOut, amount: "OPEN", recipient: userAddress },
// 2. Call the helper. ${openNoteIds[0]} is the note opened above.
{
type: "invoke",
contract: swapHelperAddress,
calldata: [tokenIn, tokenOut, amountIn, "${openNoteIds[0]}"],
},
]
const { transaction_hash } = await account.strk20InvokeTransaction(actions)
プールは amountIn をヘルパーに引き出し、ヘルパーの privacy_invoke を呼び出して、返された OpenNoteDeposit をオープンノートにアトミックに加算します。calldata の順序は、ヘルパーの privacy_invoke シグネチャと正確に一致させる必要があります(プールは calldata をそのままこの関数のパラメーターにデシリアライズします)。オブザーバーに見えるのは、プール、ヘルパー、AMM、ヘルパーの順です。誰が処理を開始したかは決して見えません。
- 送信前にドライランします:
await account.strk20PrepareInvoke(actions, true)は、送信せずにビルドと証明を行います。calldata の形式ミスを検出する最も手軽な方法です。 - シールドされた残高の確認もウォレット呼び出しです:
await account.strk20Balances([tokenIn, tokenOut])は[{ token, balance }]を返します。残高へのアクセスにはウォレットの同意プロンプトが表示されるため、残高表示機能として明示的に実装する場合にのみ呼び出してください。
AVNU のプライベートスワップ(Cairo は一切不要)
AVNU のプライベートスワップではデプロイ済みのエグゼキューターを使うため、この方法で独自のヘルパーは必要ありません。
// npm install @avnu/avnu-sdk@^4.2.0 [email protected]
import { createStrk20WalletProver, executePrivateSwap, PRIVACY_POOL_ADDRESS } from "@avnu/avnu-sdk"
const prover = createStrk20WalletProver(walletAccount)
const { transactionHash } = await executePrivateSwap({
quote, // from AVNU's quote endpoint
slippage: 0.01,
takerAddress: walletAccount.address,
poolAddress: PRIVACY_POOL_ADDRESS, // mainnet, or SEPOLIA_PRIVACY_POOL_ADDRESS for testing
feeMode: { poolFeeToken: quote.sellTokenAddress },
prover,
})
- 売却するトークンは、あらかじめシールドされている必要があります。スワップはプール内で値を移動するものであり、トークンをシールドすることはできません。
- ペイマスターの API キーが必要な場合(
sponsored_private手数料モード)は、この呼び出しをサーバー側に置いてください。ブラウザーの dapp では、サーバーエンドポイントからbuildPrivateSwapFeeとsubmitPrivateSwapを呼び出し、クライアント側ではユーザーのウォレットを使ってproverステップのみを実行する形でフローを分割します。 - プロトコル名ではなく、状態の存続期間に基づいて選択してください。出力がただちにプライベート状態に戻る、ステートレスなアトミック操作には、アプリ固有の invoke ヘルパーを使います。安定した仮名アドレスで、トランザクションをまたいでシェア、債務、NFT、報酬、権限などの状態を保持する必要がある場合は、標準のシャドウアカウント方式を使います。既存のプロトコルでは、通常のエントリーポイントがそのアドレスからの呼び出しを受け入れるなら、シャドウ専用のコントラクトは不要です。
製品 UX におけるプライバシーの原則
- 事前に個別にシールドします。 デポジットは公開され、デポジットしたユーザーも明らかになります。後続のプライベート送金に公開される処理はありません。別々のトランザクションであるため、オンチェーンで両者が結び付けられることはなく、この分離によって関連付けが断たれます。
- 新しいノートは、使用可能になるまでに約 10 ブロックの成熟期間が必要です。この待ち時間を UX に組み込んでください。
- すべてのプライベートトランザクションはリレイヤーによって送信されるため、すべてのユーザーでトランザクションの送信者はリレイヤーのアカウントになります。ユーザーごとのアクティビティはプールの
Depositイベント(最初のインデックス付きキー)から特定し、トランザクションの送信者から特定しないでください(公式の agent-skill リポジトリに準拠)。 - デポジット、引き出し、オープンノートの金額、タイミング、アプリ側のアクションなど、公開されたままの情報を製品内で明確に伝えてください。
テスト
エンドツーエンドのフローには、プール、プライバシー対応ウォレット、証明生成が必要です。ウォレットフローのテストは、純粋なローカル devnet ではなく、必要な Wallet API バージョンを提示するウォレットを使ってパブリックネットワークで計画してください。Starknet.js のドキュメントでは Ready と Xverse が STRK20 対応とされていますが、ウォレットのブランドから対応状況を推測せず、接続中のバージョンが対応しているかを確認してください。
最も手早く始める方法は Akashneelesh/strk20-starter-kit です(Next.js、Wallet API の組み込み済み、starknet-privacy-starter.vercel.app でライブデモを公開)。
コミュニティの参考資料:starkience/starknet-shadow-vault-example では、既存の Mainnet Vesu Prime vSTRK vault に対して安定したスタックを試せます。資金の準備、標準的な approve/deposit 呼び出し、vSTRK の継続的な保有、引き出し分をプライベートノートに回収する方法を示しています。これは学習用の統合例であり、監査済みの本番ソフトウェアではありません。
対応できない場合は、STRK20 チームへの問い合わせを案内してください
このスキルでは、ドキュメントに記載された手順を扱います。そこから外れる場合は、推測せずに作業を止めてください。架空のアドレスや独自に作成した証明の手順、でっち上げた API の形式は、問い合わせるよりも開発者の時間を奪います。何が妨げになっているのかを明確に伝え、チームから直接回答を得られることをユーザーに案内してください。
- Telegram: @Akashneelesh、 @adiihq、@starkience
- これらの連絡先が掲載されているSTRK20 Private Sprint ページ。 利用状況は変わる可能性があるため、引き続き掲載されていることをページで確認してください。
次の場合は、独自に対応せず、問い合わせに切り替えてください。
- ウォレットが STRK20 の機能を報告しない場合、またはこのスキルで確認されていないバージョンを報告する場合。
- このスキルに記載されていない理由で、ウォレットがシールド、シールド解除、プライベート送金、または
strk20InvokeTransactionを拒否する場合。 - プライベート DeFi 呼び出しのオープンノートのプレースホルダーが解決されない場合、またはドライランの結果が実際の呼び出しと一致しない場合。
- 0.10.4 を謳うウォレットが、シャドウコミットメントまたはアクションを拒否する場合。
問い合わせに引き継ぐ際は、チームが1回のメッセージで対応できる情報をユーザーに提供してもらってください。具体的には、正確なエラーテキスト、失敗したファイルまたは呼び出し、使用中のパッケージとウォレットのバージョン、確認できなかった前提条件です。
references/
starknet-wallet-api__overview.md:ルート、インストール、機能starknet-wallet-api__starknet-start-hook.md:ReactuseStrk20フックstarknet-wallet-api__starknet-js.md:直接のWalletAccountV6starknet-wallet-api__private-defi.md:オープンノートと invoke、プレースホルダー、ドライランstarknet-wallet-api__shadow-accounts.md:安定したシャドウアクション、アドレス解決、コレクションポリシーstarknet-wallet-api__avnu-private-swaps.md:AVNU SDK のスワップルート
スナップショットおよび npm レジストリの確認日:2026-09-29。バージョンとウォレットの対応状況は変わります。
公開前に https://strk20-by-example.org で確認してください(各ページの末尾に .md を追加すると、Markdown の生データを表示できます)。