mcpField
W
wallet-policy

wallet-policy

github.com/starchild-ai-agent安全304.1k 次安装6 天前更新
代码仓库

关于 wallet-policy

wallet-policy 是用于编写 Privy 钱包安全策略的技能,可将自然语言要求转为规则并提交用户审核。它覆盖 EVM 与 Solana,并强调规则验证和签名确认后应用。

主要功能

  1. 01自然语言生成钱包策略
  2. 02支持 EVM 与 Solana
  3. 03按条件构建允许或拒绝规则
  4. 04提交策略供用户审核与签名
  5. 05说明默认拒绝等策略逻辑

适用场景

  1. 01限制交易接收地址
  2. 02设置交易金额上限
  3. 03限定可用链或合约
  4. 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 两次——分别使用 chain_type="ethereum" 和 chain_type="solana"。

重要——必须调用工具:

  • 每个策略请求都必须调用 wallet_propose_policy。绝不能以纯文本或代码块形式输出规则。
  • 对于涉及 EVM 和 Solana 的请求,必须调用该工具两次——每种 chain_type 各一次。
  • 该工具会根据 Privy API 架构验证规则。如果验证失败,请修正错误并重试。

策略引擎基础知识

在相关情况下,向用户说明以下基础知识:

  1. 默认全部允许——新钱包没有策略(允许所有交易)。策略为可选启用。附加策略后,系统会切换为默认拒绝:未匹配任何规则的请求都会被拒绝。空规则数组 = 拒绝所有操作。
  2. 拒绝优先——如果任何拒绝规则匹配,即使同时匹配允许规则,请求也会被阻止。
  3. 多个条件 = 与——单条规则中的所有条件都必须匹配,该规则才会触发。
  4. 多条规则 = 按顺序评估——第一个匹配的拒绝规则会阻止请求;否则,第一个匹配的允许规则会放行请求。
  5. Solana 按指令检查——Solana 交易中的每条指令都必须单独匹配一条允许规则。

构建策略规则

默认方案:通配符策略

对于任何链上服务(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 设置拒绝规则,可阻止最危险的操作(提取密钥)
  • * 通配符涵盖所有交易类型、签名方法和链,无需为特定服务设置规则

何时改用特定规则:仅当用户明确要求更严格的限制时(例如“只允许 1 ETH 以下的转账”“只允许在 Arbitrum 上进行交易”“只允许使用此特定合约地址”)。此时,请使用下方的规则构建参考。

构建自定义限制规则

如果用户希望进行更严格的控制,请明确服务需要进行哪些交易:

  • 会调用哪些合约地址?(to 字段)
  • 会在哪条链上运行?(chain_id)
  • 会发送多少价值?(以 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_sendTransactionEVM广播交易
eth_signTransactionEVM签名但不广播
eth_signTypedData_v4EVM签署 EIP-712 类型化数据
eth_signUserOperationEVM签署 ERC-4337 UserOperation
eth_sign7702AuthorizationEVMEIP-7702 授权
signTransactionSolana签署 Solana 交易
signAndSendTransactionSolana签名并广播
signTransactionBytesTron/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 逻辑。使用多条独立规则表示 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 主网"1"
Ethereum Sepolia"11155111"
Base"8453"
Optimism"10"
Arbitrum One"42161"
Polygon"137"
BSC"56"

常见 Solana 程序 ID

程序ID
System Program11111111111111111111111111111111
Token ProgramTokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
Token-2022TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
Associated TokenATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL
USDC MintEPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v

交互指南

  1. 先询问链 — 确定用户需要 EVM、Solana 还是两者的策略。
  2. 确认地址 — 如果用户说“允许向我的朋友转账”,请询问地址。
  3. 确认金额 — 在输出中将用户易读的金额(例如“1 ETH”)转换为 wei/lamports。
  4. 说明权衡 — 如果策略过于宽松,请提醒用户;如果过于严格,请指出会阻止哪些操作。
  5. 合理组合 — 在一条规则中使用多个条件表示 AND,使用多条规则表示 OR。
  6. 始终包含 deny-export — 除非用户明确需要导出密钥,否则建议添加 DENY exportPrivateKey 规则。
  7. 输出有效 JSON — 每个 json:policy 块都必须是有效且可解析的 JSON。仔细检查地址和值。
  8. 规则名称 ≤ 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)
  • 请勿将 Solana field_sources(solana_*)与 chain_type="ethereum" 搭配使用,反之亦然
  • 请勿使用小写的 action 值——始终使用 "ALLOW" 或 "DENY"
  • 请勿将 ethereum_transaction 或 ethereum_calldata field_sources 与 eth_signTypedData_v4 搭配使用——请改用 ethereum_typed_data_domain 或 ethereum_typed_data_message
  • 请勿将 ethereum_transaction field_sources 与 eth_sign7702Authorization 搭配使用——请改用 ethereum_7702_authorization
  • 除非用户明确要求更严格的限制,否则请勿为服务使用自定义限制规则——默认使用通配符策略

评论

支持 Markdown