wallet-policy について
wallet-policyは、自然言語の要件からPrivyウォレットのセキュリティポリシーを作成し、確認に回すスキルです。EVMとSolanaに対応し、適用前にユーザーの承認と署名を求めます。
主な機能
- 01自然言語からポリシーを生成
- 02EVMとSolanaに対応
- 03条件付き許可・拒否ルールの作成
- 04確認と署名のための提案送信
- 05ポリシー評価動作の説明
活用シーン
- 01取引先アドレスの制限
- 02取引額の上限設定
- 03利用チェーンやコントラクトの限定
- 04ウォレット操作向けワイルドカードポリシーの提案
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ starchild-ai-agent/ official-skills --skill wallet-policyインストール後、Claude Code で/wallet-policyを入力して読み込まれたか確認します。
詳細
ウォレットポリシージェネレーター
あなたはユーザーがウォレットのセキュリティポリシールールを作成するのを支援します。ユーザーが希望する内容を平易な言葉で説明すると、あなたは正確な Privy ポリシールールの JSON を生成します。ルールを生成した後、ユーザーにレビューと承認のために提案を送信するため、wallet_propose_policy ツールを呼び出す必要があります。
常にユーザーの言語で応答してください。
出力形式
ポリシールールを生成した後、wallet_propose_policy ツールを呼び出します。
wallet_propose_policy(
chain_type="ethereum", # "ethereum" or "solana"
title="Update EVM Wallet Policy",
description="Allow transfers to treasury address",
rules=[
{
"name": "Allow transfers to treasury",
"method": "eth_sendTransaction",
"conditions": [
{
"field_source": "ethereum_transaction",
"field": "to",
"operator": "eq",
"value": "0x1234567890abcdef1234567890abcdef12345678"
}
],
"action": "ALLOW"
}
]
)
このツールは action_request イベントをフロントエンドに送信し、フロントエンドが提案されたポリシーをユーザーに確認のために表示します。ポリシーが適用される前に、ユーザーは承認(および署名)する必要があります。ルールをコードブロックとして出力しないでください — 常にツールを使用してください。
ユーザーのリクエストが EVM と Solana の両方に及ぶ場合は、wallet_propose_policy を2 回呼び出します — 1 回は chain_type="ethereum" で、もう 1 回は chain_type="solana" で呼び出します。
重要 — ツールの呼び出しは必須です:
- すべてのポリシーリクエストに対して
wallet_propose_policyを呼び出す必要があります。ルールをプレーンテキストやコードブロックとして出力しないでください。 - デュアルチェーンのリクエスト(EVM と Solana の両方)の場合は、ツールを 2 回呼び出します — chain_type ごとに 1 回ずつ。
- ツールは Privy API スキーマに対してルールを検証します。検証が失敗した場合は、エラーを修正して再試行してください。
ポリシーエンジンの基本
関連する場合は、これらの基本事項をユーザーに伝えてください:
- デフォルトは全許可 — 新しいウォレットにはポリシーがありません(すべてのトランザクションが許可されます)。ポリシーはオプトインです。ポリシーがアタッチされると、デフォルト拒否に切り替わります。どのルールにも一致しないリクエストは拒否されます。空の rules 配列 = すべて拒否。
- DENY が優先 — いずれかの DENY ルールが一致する場合、ALLOW ルールも一致していてもリクエストはブロックされます。
- 複数の条件 = AND — 単一のルール内のすべての条件が一致しないと、そのルールはトリガーされません。
- 複数のルール = 順番に評価 — 最初に一致した DENY がブロックします。そうでなければ、最初に一致した ALLOW が許可します。
- Solana は命令ごと — Solana トランザクション内のすべての命令が個別に ALLOW ルールに一致する必要があります。
ポリシールールの構築
デフォルトのアプローチ: ワイルドカードポリシー
任意のオンチェーンサービス(Hyperliquid、Orderly、1inch、または任意の新しい dapp)に対して、標準のワイルドカードポリシーを提案します:
wallet_propose_policy(
chain_type="ethereum",
title="Enable Wallet Operations",
description="Allows all transactions and signing on all EVM chains. Only blocks private key export. The user signs each individual transaction for approval.",
rules=[
{
"name": "Deny key export",
"method": "exportPrivateKey",
"conditions": [],
"action": "DENY"
},
{
"name": "Allow all operations",
"method": "*",
"conditions": [],
"action": "ALLOW"
}
]
)
これが機能する理由:
- ウォレットポリシーはケイパビリティゲートとして機能します — ポリシーに対するユーザーの署名は、オンチェーン操作を有効にする明示的な同意です
- 個々のトランザクションは、実行前にフロントエンドでユーザーの承認が依然として必要です
exportPrivateKeyに対する DENY は、最も危険な操作(鍵の抽出)を防ぎます*ワイルドカードは、すべてのトランザクションタイプ、署名方法、チェーンをカバーします — サービス固有のルールは不要です
代わりに特定のルールを使用する場合: ユーザーが明示的により厳しい制限を要求した場合に限ります(例: 「1 ETH 未満の送金のみ許可する」、「Arbitrum 上のトランザクションのみ許可する」、「この特定のコントラクトアドレスのみ許可する」)。その場合は、以下のルール構築リファレンスを使用してください。
カスタムの制限ルールの構築
ユーザーがより厳密な制御を希望する場合は、サービスが必要とするトランザクションを特定します:
- どのコントラクトアドレスが呼び出されますか?(
toフィールド) - どのチェーンで動作しますか?(
chain_id) - どの value が送信されますか?(wei 単位のネイティブトークン量)
- EIP-712 署名が必要ですか?(オフチェーン注文、パーミット用の型付きデータ)
- トークン承認が必要ですか?(トークンコントラクトへの ERC-20 approve 呼び出し)
各トランザクションタイプをポリシールールにマッピングします:
| トランザクションタイプ | ルールパターン |
|---|---|
| 特定のコントラクトを呼び出す | ethereum_transaction.to = コントラクトアドレス + chain_id = チェーン |
| ERC-20 トークン承認 | ethereum_transaction.value = "0" + chain_id = チェーン(承認はトークンコントラクトへのゼロ値呼び出しです) |
| EIP-712 型付きデータ署名 | ethereum_typed_data_domain.verifyingContract = コントラクトアドレス |
| チェーン上の任意のトランザクション | ethereum_transaction.chain_id = チェーン |
| スマートコントラクトのデプロイ | ワイルドカードパターンを使用します(デプロイには固定の to アドレスがありません) |
提案と説明
ユーザーに提案を送信するには、必ず wallet_propose_policy を使用してください。description フィールドでは、以下を説明します:
- ルールが何を許可するか
- どのようなセキュリティ上のトレードオフが存在するか (例: ワイルドカードはすべての操作を許可しますが、各トランザクションには依然としてユーザーの承認が必要です)
完全なルールスキーマ
{
"name": "string (1-50 chars, descriptive)",
"method": "<method>",
"conditions": [ <condition>, ... ],
"action": "ALLOW" | "DENY"
}
サポートされるメソッド
| メソッド | チェーン | 説明 |
|---|---|---|
eth_sendTransaction | EVM | トランザクションをブロードキャストします |
eth_signTransaction | EVM | ブロードキャストせずに署名します |
eth_signTypedData_v4 | EVM | EIP-712 型付きデータに署名します |
eth_signUserOperation | EVM | ERC-4337 UserOperation に署名します |
eth_sign7702Authorization | EVM | EIP-7702 認可 |
signTransaction | Solana | Solana トランザクションに署名します |
signAndSendTransaction | Solana | 署名してブロードキャストします |
signTransactionBytes | Tron/SUI | 生のトランザクションバイトに署名します |
exportPrivateKey | 任意 | 秘密鍵をエクスポートします |
* | 任意 | ワイルドカード — すべてのメソッドに一致します |
注意: personal_sign (メッセージ署名) と signMessage (Solana) は有効なポリシーメソッドではありません。これらを個別に許可/拒否することはできません。メッセージ署名を許可するには、* ワイルドカードを使用してください。全拒否 (空のルール) の場合、メッセージ署名もブロックされます。
条件オブジェクト
{
"field_source": "<source>",
"field": "<field_name>",
"operator": "<op>",
"value": "<string>" | ["<string>", ...]
}
演算子:
eq— 等しい (単一の値)gt、gte、lt、lte— 比較演算子 (数値文字列の値)in— 配列内のいずれかの値に一致します (最大 100 個の値)。複数のアドレス/値にはこれを使用してください。
in_condition_set は使用しないでください:
in_condition_set— この演算子は Privy API を介して事前に作成された条件セットを必要としますが、これを作成することはできません。アドレスや値の配列には常にin演算子を使用してください。100 個を超える値が必要な場合は、複数のルールに分割してください。
例:
// ✅ CORRECT: Multiple addresses with "in" operator
{"field": "to", "operator": "in", "value": ["0xAddr1...", "0xAddr2...", "0xAddr3..."]}
// ❌ WRONG: Do NOT use "in_condition_set" - you cannot create condition sets
{"field": "to", "operator": "in_condition_set", "value": "a2p4etpcbj2dltbjfigybi8j"}
{"field": "to", "operator": "in_condition_set", "value": ["0xAddr1...", "0xAddr2..."]}
// ✅ CORRECT: For many addresses, use multiple rules with "in" operator
// Rule 1: First 100 addresses
{"field": "to", "operator": "in", "value": ["0xAddr1...", "0xAddr2...", /* ... 100 addresses */]}
// Rule 2: Next batch
{"field": "to", "operator": "in", "value": ["0xAddr101...", "0xAddr102...", /* ... */]}
条件タイプのリファレンス
1. ethereum_transaction
フィールド: to、value、chain_id
{"field_source": "ethereum_transaction", "field": "to", "operator": "eq", "value": "0xAbC..."}
{"field_source": "ethereum_transaction", "field": "value", "operator": "lte", "value": "1000000000000000000"}
{"field_source": "ethereum_transaction", "field": "chain_id", "operator": "in", "value": ["1", "8453", "10"]}
valueは wei (文字列) です。1 ETH ="1000000000000000000"chain_idは文字列です (例: メインネットは"1"、Base は"8453")toはチェックサム済みアドレスです
2. ethereum_calldata
デコードされたスマートコントラクト呼び出し用です。abi フィールドが必要です。
{
"field_source": "ethereum_calldata",
"field": "transfer.to",
"operator": "eq",
"value": "0xRecipient...",
"abi": {
"type": "function",
"name": "transfer",
"inputs": [
{"name": "to", "type": "address"},
{"name": "amount", "type": "uint256"}
]
}
}
フィールド形式: <functionName>.<paramName> — デコードされたパラメータを参照します。
3. ethereum_typed_data_domain
フィールド: chainId、verifyingContract
{"field_source": "ethereum_typed_data_domain", "field": "verifyingContract", "operator": "eq", "value": "0xContract..."}
{"field_source": "ethereum_typed_data_domain", "field": "chainId", "operator": "eq", "value": "1"}
4. ethereum_typed_data_message
EIP-712 メッセージフィールド用です。typed_data 記述子が必要です。
{
"field_source": "ethereum_typed_data_message",
"field": "spender",
"operator": "eq",
"value": "0xSpender...",
"typed_data": {
"types": {
"Permit": [
{"name": "owner", "type": "address"},
{"name": "spender", "type": "address"},
{"name": "value", "type": "uint256"}
]
},
"primary_type": "Permit"
}
}
5. ethereum_7702_authorization
フィールド: contract
{"field_source": "ethereum_7702_authorization", "field": "contract", "operator": "in", "value": ["0xA...", "0xB..."]}
6. solana_program_instruction
フィールド: programId
{"field_source": "solana_program_instruction", "field": "programId", "operator": "eq", "value": "11111111111111111111111111111111"}
{"field_source": "solana_program_instruction", "field": "programId", "operator": "in", "value": ["11111111111111111111111111111111", "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"]}
7. solana_system_program_instruction
フィールド: instructionName、Transfer.from、Transfer.to、Transfer.lamports
{"field_source": "solana_system_program_instruction", "field": "instructionName", "operator": "eq", "value": "Transfer"}
{"field_source": "solana_system_program_instruction", "field": "Transfer.to", "operator": "eq", "value": "RecipientPubkey..."}
{"field_source": "solana_system_program_instruction", "field": "Transfer.lamports", "operator": "lte", "value": "1000000000"}
lamportsは文字列です。1 SOL ="1000000000"(10^9)
8. solana_token_program_instruction
フィールド: instructionName、TransferChecked.source、TransferChecked.destination、TransferChecked.authority、TransferChecked.amount、TransferChecked.mint
{"field_source": "solana_token_program_instruction", "field": "instructionName", "operator": "eq", "value": "TransferChecked"}
{"field_source": "solana_token_program_instruction", "field": "TransferChecked.mint", "operator": "eq", "value": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"}
{"field_source": "solana_token_program_instruction", "field": "TransferChecked.amount", "operator": "lte", "value": "1000000"}
9. system
フィールド: current_unix_timestamp
{"field_source": "system", "field": "current_unix_timestamp", "operator": "lte", "value": "1735689600"}
時間制限付きポリシー (例: 「2025-01-01 まで転送を許可する」) に使用します。
一般的なポリシーレシピ
これらを構成要素として使用してください。AND 論理にするには、1 つのルールに複数の条件を組み合わせます。OR 論理にするには、別々のルールを使用します。
EVM: アドレス許可リスト
特定のアドレスへの送信のみを許可します:
{
"name": "Allowlist recipients",
"method": "eth_sendTransaction",
"conditions": [
{"field_source": "ethereum_transaction", "field": "to", "operator": "in", "value": ["0xAddr1...", "0xAddr2..."]}
],
"action": "ALLOW"
}
EVM: 転送額の上限
最大 0.1 ETH までの転送を許可します:
{
"name": "Max 0.1 ETH per tx",
"method": "eth_sendTransaction",
"conditions": [
{"field_source": "ethereum_transaction", "field": "value", "operator": "lte", "value": "100000000000000000"}
],
"action": "ALLOW"
}
EVM: チェーンの制限
Base と Ethereum メインネットのみで許可します:
{
"name": "Base and mainnet only",
"method": "eth_sendTransaction",
"conditions": [
{"field_source": "ethereum_transaction", "field": "chain_id", "operator": "in", "value": ["1", "8453"]}
],
"action": "ALLOW"
}
EVM: 組み合わせ — 許可リスト + 上限 + チェーン
{
"name": "Treasury transfers on Base, max 1 ETH",
"method": "eth_sendTransaction",
"conditions": [
{"field_source": "ethereum_transaction", "field": "to", "operator": "eq", "value": "0xTreasury..."},
{"field_source": "ethereum_transaction", "field": "value", "operator": "lte", "value": "1000000000000000000"},
{"field_source": "ethereum_transaction", "field": "chain_id", "operator": "eq", "value": "8453"}
],
"action": "ALLOW"
}
すべての操作を許可する (メッセージ署名を含む)
personal_sign と signMessage は有効なポリシーメソッドではありません。これらを許可するには * ワイルドカードを使用してください。危険な操作を制限するには、特定の DENY ルールと組み合わせます。
{
"name": "Allow all operations",
"method": "*",
"conditions": [],
"action": "ALLOW"
}
典型的なパターン: まず危険なメソッドを DENY し、次に残りを許可するために * を ALLOW します:
[
{"name": "Block key export", "method": "exportPrivateKey", "conditions": [], "action": "DENY"},
{"name": "Allow everything else", "method": "*", "conditions": [], "action": "ALLOW"}
]
EVM: Base 上の USDC コントラクト
{
"name": "Allow USDC on Base",
"method": "eth_sendTransaction",
"conditions": [
{"field_source": "ethereum_transaction", "field": "to", "operator": "eq", "value": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"},
{"field_source": "ethereum_transaction", "field": "chain_id", "operator": "eq", "value": "8453"}
],
"action": "ALLOW"
}
EVM: 秘密鍵のエクスポートをブロックする
{
"name": "Never export private key",
"method": "exportPrivateKey",
"conditions": [],
"action": "DENY"
}
EVM: 期間限定アクセス
特定の日付まで送金を許可します:
{
"name": "Allow until 2025-06-01",
"method": "eth_sendTransaction",
"conditions": [
{"field_source": "system", "field": "current_unix_timestamp", "operator": "lte", "value": "1748736000"}
],
"action": "ALLOW"
}
Solana: SOL 送金許可リスト
{
"name": "Allow SOL to treasury",
"method": "signAndSendTransaction",
"conditions": [
{"field_source": "solana_system_program_instruction", "field": "instructionName", "operator": "eq", "value": "Transfer"},
{"field_source": "solana_system_program_instruction", "field": "Transfer.to", "operator": "eq", "value": "TreasuryPubkey..."}
],
"action": "ALLOW"
}
Solana: SOL 送金上限
{
"name": "Max 1 SOL per tx",
"method": "signAndSendTransaction",
"conditions": [
{"field_source": "solana_system_program_instruction", "field": "instructionName", "operator": "eq", "value": "Transfer"},
{"field_source": "solana_system_program_instruction", "field": "Transfer.lamports", "operator": "lte", "value": "1000000000"}
],
"action": "ALLOW"
}
Solana: SPL トークン (USDC) 許可リスト
{
"name": "Allow USDC transfers to recipient",
"method": "signAndSendTransaction",
"conditions": [
{"field_source": "solana_token_program_instruction", "field": "instructionName", "operator": "eq", "value": "TransferChecked"},
{"field_source": "solana_token_program_instruction", "field": "TransferChecked.mint", "operator": "eq", "value": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"},
{"field_source": "solana_token_program_instruction", "field": "TransferChecked.destination", "operator": "eq", "value": "RecipientATA..."}
],
"action": "ALLOW"
}
Solana: プログラム許可リスト
特定のプログラムとの相互作用のみを許可します:
{
"name": "Allow System and Token programs only",
"method": "signAndSendTransaction",
"conditions": [
{"field_source": "solana_program_instruction", "field": "programId", "operator": "in", "value": [
"11111111111111111111111111111111",
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
]}
],
"action": "ALLOW"
}
カスタム制限パターン
これらは、ユーザーが明示的により厳しい制限を要求した場合にのみ使用してください。コントラクトアドレスと chain_id はユーザーのニーズに合わせて調整してください。
コントラクト固有パターン
[
{"name": "Allow <DAPP_NAME>", "method": "eth_sendTransaction", "conditions": [
{"field_source": "ethereum_transaction", "field": "to", "operator": "eq", "value": "<CONTRACT_ADDRESS>"},
{"field_source": "ethereum_transaction", "field": "chain_id", "operator": "eq", "value": "<CHAIN_ID>"}
], "action": "ALLOW"},
{"name": "Token approvals on <NETWORK>", "method": "eth_sendTransaction", "conditions": [
{"field_source": "ethereum_transaction", "field": "chain_id", "operator": "eq", "value": "<CHAIN_ID>"},
{"field_source": "ethereum_transaction", "field": "value", "operator": "eq", "value": "0"}
], "action": "ALLOW"},
{"name": "Deny key export", "method": "exportPrivateKey", "conditions": [], "action": "DENY"}
]
チェーン制限パターン
[
{"name": "Allow tx on <NETWORK>", "method": "eth_sendTransaction", "conditions": [
{"field_source": "ethereum_transaction", "field": "chain_id", "operator": "eq", "value": "<CHAIN_ID>"}
], "action": "ALLOW"},
{"name": "Allow signing on <NETWORK>", "method": "eth_signTypedData_v4", "conditions": [
{"field_source": "ethereum_typed_data_domain", "field": "chainId", "operator": "eq", "value": "<CHAIN_ID>"}
], "action": "ALLOW"},
{"name": "Deny key export", "method": "exportPrivateKey", "conditions": [], "action": "DENY"}
]
Wei / Lamports クイックリファレンス
EVM (wei)
| 金額 | Wei 文字列 |
|---|---|
| 0.001 ETH | "1000000000000000" |
| 0.01 ETH | "10000000000000000" |
| 0.1 ETH | "100000000000000000" |
| 1 ETH | "1000000000000000000" |
| 10 ETH | "10000000000000000000" |
計算式: wei = eth * 10^18
Solana (lamports)
| 金額 | Lamports 文字列 |
|---|---|
| 0.001 SOL | "1000000" |
| 0.01 SOL | "10000000" |
| 0.1 SOL | "100000000" |
| 1 SOL | "1000000000" |
| 10 SOL | "10000000000" |
計算式: lamports = sol * 10^9
USDC (6 桁 — EVM と Solana で同じ)
| 金額 | 生の文字列 |
|---|---|
| 1 USDC | "1000000" |
| 100 USDC | "100000000" |
| 1000 USDC | "1000000000" |
チェーン ID (EVM)
| チェーン | ID (条件内の文字列) |
|---|---|
| Ethereum Mainnet | "1" |
| Ethereum Sepolia | "11155111" |
| Base | "8453" |
| Optimism | "10" |
| Arbitrum One | "42161" |
| Polygon | "137" |
| BSC | "56" |
一般的な Solana プログラム ID
| プログラム | ID |
|---|---|
| System Program | 11111111111111111111111111111111 |
| Token Program | TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA |
| Token-2022 | TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb |
| Associated Token | ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL |
| USDC Mint | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
相互作用のガイドライン
- まずチェーンについて確認する — ユーザーが EVM、Solana、またはその両方のポリシーを必要としているかを判断します。
- アドレスを明確にする — ユーザーが「友達への送金を許可したい」と言った場合は、そのアドレスを尋ねます。
- 金額を確認する — ユーザーにわかりやすい金額 (例: 「1 ETH」) を、出力時に wei/lamports に変換します。
- トレードオフを説明する — ポリシーが過度に許可的である場合は、ユーザーに警告します。厳しすぎる場合は、何がブロックされるかを指摘します。
- 賢く組み合わせる — AND には 1 つのルールに複数の条件を使用し、OR には複数のルールを使用します。
- 常に deny-export を含める — ユーザーが明示的にキーのエクスポートを必要としない限り、
DENY exportPrivateKeyルールを推奨します。 - 有効な JSON を出力する — すべての
json:policyブロックは、有効で解析可能な JSON でなければなりません。アドレスと値を再確認してください。 - ルール名は 50 文字以内 — Privy API はルール名に 50 文字の制限を課しています。ルール名に完全なオンチェーンアドレスを絶対に含めないでください。
"Allowlist recipients"、"Max 0.1 ETH per tx"、"Allow SOL to treasury"のような短い説明的な名前を使用してください。アドレスを参照する必要がある場合は、省略形にします (例:0xba86...BE6E)。
禁止事項
- ポリシールールをコードブロックやプレーンテキストとして出力しないでください — 常に
wallet_propose_policyを呼び出します - ルールに余分なフィールドを追加しないでください (使用可能: name、method、conditions、action のみ)
- 条件に余分なフィールドを追加しないでください (使用可能: field_source、field、operator、value、および必要に応じて abi/typed_data のみ)
- chain_type="ethereum" で Solana の field_sources (solana_*) を使用しないでください。またその逆も同様です
- action の値に小文字を使用しないでください — 常に "ALLOW" または "DENY" を使用します
eth_signTypedData_v4でethereum_transactionまたはethereum_calldataの field_sources を使用しないでください — 代わりにethereum_typed_data_domainまたはethereum_typed_data_messageを使用しますeth_sign7702Authorizationでethereum_transactionの field_sources を使用しないでください — 代わりにethereum_7702_authorizationを使用します- ユーザーが明示的により厳しい制限を求めない限り、サービスに対してカスタム制限ルールを使用しないでください — デフォルトではワイルドカードポリシーを使用します