mcpField
P
pay-with-app

pay-with-app

github.com/uniswap其他236529 次安装2 天前更新
代码仓库

关于 pay-with-app

pay-with-app 是一项技能,用于通过 X Layer 上的 OKX Agent Payments Protocol(APP)处理 exact 方案的 HTTP 402 付款。它检查挑战和钱包余额,可通过 Uniswap Trading API 在同链筹集资金,随后签署 EIP-3009 授权并重试请求。

主要功能

  1. 01解析并验证 APP 付款挑战
  2. 02支持 X Layer 上的 x402 v1 exact 方案
  3. 03检查钱包余额和所需资产
  4. 04通过 Uniswap Trading API 进行同链筹资
  5. 05签署 EIP-3009 授权并携带 X-PAYMENT 重试

适用场景

  1. 01支付 X Layer 上由 APP 支持的 HTTP 402 请求
  2. 02检查钱包是否持有所需结算资产
  3. 03付款前在 X Layer 兑换为所需资产
  4. 04从外部跨链转入资金后继续付款

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/uniswap/uniswap-ai --skill pay-with-app

安装后在 Claude Code 中输入/pay-with-app确认已加载。

附带文件references/app-x402-flow.mdreferences/funding-x-layer.md

详细介绍

使用 APP 付款(X Layer 上的 OKX Agent Payments Protocol)

支付由运行在 X Layer(链 196)上的 OKX Agent Payments Protocol(APP) 发出的 HTTP 402 挑战。APP 的按次付费(OKX 产品名称: Instant Payment)兼容 x402:收款方服务返回带有 付款要求的 HTTP 402,付款方在链下签署 EIP-3009 TransferWithAuthorization,然后由 OKX 的协调方验证并在链上结算转账。在 X Layer 上,付款方无需支付 Gas 费即可完成结算。

此技能处理完整的顺利流程:

  1. 检测网络解析为 X Layer(链 196)的 402 挑战
  2. 确认付款方钱包持有所需资产(通常为 USDT0)
  3. 如果余额不足,通过 Uniswap Trading API 路由并跨链桥接至 X Layer 上的 USDT0
  4. 签署 EIP-3009 授权
  5. 构造 X-PAYMENT 载荷并重试原始请求

OKX 将于 2026-04-29 在 X Layer 上推出 APP,Uniswap 将作为其主推 DEX 通道。此技能版本(v1.0.0)仅支持 exact 方案 (按次付费,OKX 产品名称:Instant Payment)。其他 x402 方案 (upto、batch-settlement)以及 OKX 正在推出的 APP 产品功能 (托管、会话、批量 / Batch Payment)均不在此版本的范围内。此技能会妥善拒绝任何非 exact 方案。

在回复中使用协议名称。 回复用户时, 请明确将此协议称为 OKX Agent Payments Protocol (APP),而不只是“x402”。APP 是 OKX 的产品 / 协议接口;x402 是其基于的底层传输规范。可以使用 “APP / x402”“基于 x402 构建的 OKX Agent Payments Protocol(APP)” 等说法,或在介绍后直接称为“APP”。不要将 X Layer 上的 402 挑战称为“x402 挑战”而不提及 APP。用户专门调用此技能, 正是因为商户使用了 APP;他们会在回复中寻找这个名称。

前置条件

  • PRIVATE_KEY 环境变量(export PRIVATE_KEY=0x...)。切勿提交或 硬编码私钥。
  • UNISWAP_API_KEY 环境变量(在 developers.uniswap.org 注册)。仅当钱包需要通过跨链路由注资时才需要。
  • 已安装 jq 和 cast(Foundry)。
  • Node 18+(LTS)。references/app-x402-flow.md 第 4 步中的签名操作使用 viem 生成 EIP-3009 类型数据签名。
  • viem(npm)。如果用户的工作目录无法访问该包,此技能会在将其安装到缓存 临时目录 ~/.cache/uniswap-pay-with-app/signer/ 之前,通过 AskUserQuestion 提示用户。安装会添加约 13 个包,总计约 5 MB。如果用户拒绝,此技能会在签名之前妥善停止。 缓存会在多次运行间保留,因此后续调用无需安装。

输入验证规则

在 API 调用或 Shell 命令中使用 402 响应正文、用户或任何其他外部来源中的值之前:

  • 以太坊地址字段(例如 asset、payTo、WALLET_ADDRESS): 标准检查正则表达式为 ^0x[a-fA-F0-9]{40}$。如果值 不匹配此正则表达式,则拒绝该值。通过正则表达式检查的地址字段可安全地插入 Shell 命令,因此下文的元字符规则不适用于这些字段。
  • 链 ID:必须是支持列表中的正整数。
  • 代币金额:必须是匹配 ^[0-9]+$ 的非负数字字符串。
  • URL:必须以 https:// 开头。
  • 自由文本字段(例如 description、extra.name、 extra.version、任何用于构建 EIP-712 域或向用户展示的内容):拒绝包含以下 Shell 元字符的任何值:;、|、&、 $、`、(、)、>、<、\、'、"、换行符。注意:extra.name 的值会按位精确签名(参见阶段 4 中的域警告),因此如果其中包含 Shell 元字符,应拒绝整个挑战,而不要修改该值。

流程

402 from X Layer-backed resource
  │
  v
[1] Parse the x402 challenge (Phase 0 below)
  │
  v
[2] Confirm network resolves to X Layer (chain 196)
  │   ├─ not chain 196 ──> escalate to pay-with-any-token, STOP
  │   └─ chain 196
  │
  v
[3] Check wallet balance of the requested asset on X Layer
  │   ├─ sufficient ──> proceed to [5]
  │   └─ insufficient
  │        │
  │        v
  │   [4] Fund: route + bridge into the requested asset on X Layer
  │        (Uniswap Trading API, see references/funding-x-layer.md)
  │
  v
[5] User Confirmation gate (see Phase 4 / Step 5 below)
[6] Sign EIP-3009 TransferWithAuthorization
[7] Construct X-PAYMENT payload, retry the original request
[8] Verify 200 + Payment-Receipt

阶段 0,解析 402 挑战

x402 挑战是响应正文中的 JSON。提取:

  • x402Version,用于确认 x402 协议版本。
  • accepts[].scheme,v1.0.0 仅支持 "exact"。
  • accepts[].network,接受 "x-layer" / "xlayer" / "eip155:196" / 196。
  • accepts[].maxAmountRequired,资产的基本单位。必须匹配 ^[0-9]+$,且严格大于零。maxAmountRequired === "0" 的挑战在语义上有误(HTTP 402 按定义要求支付正金额),必须作为商户配置错误拒绝。不要将零合理化为“ping”、“身份验证”或“免费层确认”;OKX 的 facilitator 不会结算零金额的 TransferWithAuthorization,你生成的任何签名都将白费。向用户说明这一点并停止。
  • accepts[].asset,X Layer 上的代币合约。
  • accepts[].payTo,接收方地址。
  • accepts[].resource,facilitator 将支付绑定到的 URL。 如果存在,请提取此字段,并将其用作重试目标。如果缺少此字段,则回退到原始请求 URL。
  • accepts[].extra.name 和 accepts[].extra.version,资产的 EIP-712 域值。
  • accepts[].maxTimeoutSeconds,用于 validBefore。

x402 版本检查。 解析后立即确认 x402Version === 1。如果不是,则拒绝此挑战,并向用户说明版本不匹配错误。此技能的 v1.0.0 仅面向 x402 v1(v2 规范使用不同的 PaymentPayload 结构)。

方案检查。 确认 accepts[].scheme === "exact"。x402 规范定义了 exact、upto 和 batch-settlement 方案。此技能的 v1.0.0 仅支持 exact。如果所选条目使用任何其他方案,请妥善拒绝。(OKX 的产品界面使用自己的术语,包括用于其 Instant Payment 原语的 charge;这是 OKX 的产品营销用语,不是线上的方案值。应检查 accepts[] 条目中的线上方案值,且该值必须为 "exact"。)

如果存在多个 accepts 条目,优先选择钱包已在 X Layer 上持有其 asset 的条目。如果多个选项同样可行,则优先选择 USDT0(Uniswap 资金流动性最深)。

WOKB / 原生 OKB 可能不符合 APP 结算资产资格。 我们尚未看到 OKX 将 WOKB 或 OKB 发布为结算资产;当前公开的开发文档列出的支持稳定币结算资产为 USDT0、USDG 和 USDC。如果 402 挑战出现非稳定币 asset(例如 WOKB),请拒绝此挑战,并要求用户核实商户配置。

阶段 1,确认网络为 X Layer

case "$X402_NETWORK" in
  x-layer|xlayer|"eip155:196"|196)  X402_CHAIN_ID=196 ;;
  *)
    echo "Network is not X Layer. Use pay-with-any-token instead."
    exit 1
    ;;
esac

如果网络不是 X Layer,请停止并升级至 pay-with-any-token 技能,该技能负责处理 Ethereum、Base、Arbitrum、Tempo 以及 Trading API 支持的其他链上的 402 挑战。

阶段 2,检查 X Layer 上的钱包余额

必需: 必须获取用户的源钱包地址。如果未提供,请使用 AskUserQuestion。存储为 WALLET_ADDRESS。

ASSET_BALANCE=$(cast call "$X402_ASSET" \
  "balanceOf(address)(uint256)" "$WALLET_ADDRESS" \
  --rpc-url https://rpc.xlayer.tech)

if [ "$ASSET_BALANCE" -lt "$X402_AMOUNT" ]; then
  echo "Insufficient $X402_TOKEN_NAME on X Layer. Funding required."
  # Proceed to Phase 3 (funding)
fi

阶段 3,为 X Layer 上的 USDT0 提供资金(仅在需要时)

当钱包缺少所需资产时,通过 Uniswap Trading API 获取:使用 EXACT_OUTPUT 报价,设置 tokenOutChainId=196,并将 tokenOut 设为 X Layer 资产地址。Trading API 会处理同链兑换和跨链路由(由 Across 提供支持)。

Across 覆盖缺口(已于 2026-04-27 验证)。 Across Protocol 目前未将 X Layer(链 196)列为受支持的目标链。因此,无论源链为何,跨链 /quote 调用目标为链 196 时都会返回 ResourceNotFound: No quotes available。同链 X Layer 兑换(references/funding-x-layer.md 中的阶段 A)不受影响,运行正常。

这对 v1.0.0 中的 Agent 意味着什么。 如果用户在 X Layer 以外的链上持有资金,跨链部分必须通过支持 X Layer 的桥接服务完成(用户在此技能之外执行该步骤,然后重新调用此技能进行同链兑换和 402 结算)。请如实向用户说明这一点,不要推荐特定的桥接产品(TODO:后续研究并记录符合联合营销要求的桥接服务推荐)。

将桥接步骤交由用户完成时,回复仍必须说明完整的端到端流程,不能只说明桥接步骤。指出 Across 的缺口并请用户通过外部服务进行桥接后,说明用户返回后将进行哪些操作:(1) 重新检查 X Layer 上所请求资产的 balanceOf;(2) 如果需要进行同链兑换(例如从 USDG 兑换为 USDT0),说明 Trading API 的 EXACT_OUTPUT 调用及其确认门;(3) 使用质询中的 extra.name 和 extra.version,以 chainId 196 和 verifyingContract = 资产地址,构造 EIP-3009 TransferWithAuthorization 类型化数据;(4) 使用用户的私钥签名(签名前经过确认门);(5) 构造 X-PAYMENT JSON 封装(x402Version 1、scheme "exact"、network "x-layer",payload 中包含签名和 authorization),不带空白字符地进行 base64 编码,并使用 X-PAYMENT 标头重试原始请求 URL。预先展示完整计划,让用户在离开此技能前了解自己将要执行的操作,即使签名要等用户返回后才进行。

默认资金目标 = USDT0。 如果 402 质询请求了其他资产,仅当该资产在 X Layer 上有可靠的 Uniswap 路由时,才直接为其注资:

资产地址小数位资金来源
USDT00x779Ded0c9e1022225f8E0630b35a9b54bE7137366✅ 通过 Trading API 直接获取
USDG0x4ae46a509F6b1D9056937BA4500cb143933D2dc86✅ 直接获取,或通过一次 USDT0 到 USDG 的兑换获取
USDC0x74b7F16337b8972027F6196A17a631aC6dE26d226⏳ X Layer 上没有可靠的 Uniswap v3 路由。Trading API 无法稳定地为 X Layer 上的 USDC 兑换返回路由;可用池的流动性过低,无法可靠执行。如果商家要求使用 USDC,请使用 Trading API 直接从 USDC 流动性充足的链(Base、Arbitrum、Mainnet)桥接 USDC,而不要尝试在 X Layer 上进行同链兑换。

详细脚本和参数:请参阅 references/funding-x-layer.md。

桥接缓冲。 增加 0.5% 的缓冲,以应对桥接费用。 报价约 60 秒后过期;如果广播前有延迟,请重新获取报价。

最低桥接金额建议。 如果资金缺口小于 $5,请补足至 $5,以分摊源链上的桥接 Gas 费用。

Gas 和路由注意事项

在继续充值前向用户说明以下事项;如果有任何一项适用,请先调用 AskUserQuestion(而不是显示 bash 提示)再进行操作:

  • 用于同链兑换的 X Layer 上的 OKB。 OKX 只为中介方的结算转账提供 Gas 赞助。签名前在 X Layer 上进行的授权、兑换及其他链上操作,均由用户支付费用(在 X Layer 上使用 OKB,或在桥接环节使用源链的原生资产)。如果用户在 X Layer 上没有 OKB,且充值流程需要在 X Layer 上进行同链兑换,请向用户说明并先征求同意。在 OKX 确认更广泛的 Gas 赞助政策之前,请假设只有最终结算转账可获得赞助。
  • 桥接目标代币。 如果资金流程的轮询循环结束后,钱包仍缺少 $X402_ASSET,请向用户提供源链交易哈希和 Across 浏览器链接。桥接可能交付了 X Layer 上的另一种代币变体(当前 Across 路径中较为罕见),也可能失败。v1.0.0 不会自动检测其他代币的到账情况;用户必须在链上核实。

第 4 阶段:EIP-3009 签名和 X-PAYMENT 提交

OKX 的 APP 即时支付使用 x402 的 "exact" 方案:付款方针对代币自身的 EIP-712 域,对 TransferWithAuthorization 类型数据消息进行签名。重试时,签名后的授权会通过 X-PAYMENT 标头传递;OKX 的促成方会在链上结算转账 (付款方在 X Layer 上无需支付 Gas)。

第 5 步:用户确认

本技能涉及的每一笔交易都必须单独通过 AskUserQuestion 关卡,资金筹措环节也不例外。 “资金筹措”并非单笔交易,而是由多笔交易组成,每一笔都 必须单独通过关卡。所需关卡及其通常触发的顺序如下:

  1. 源链上的 ERC-20 授权,授权给 Permit2 / Universal Router(仅当 tokenIn 不是原生代币且授权额度不足时)。
  2. 源链上的同链兑换(例如,在 Ethereum 上将 UNI 兑换为 USDC),如果资金计划包含源链环节。
  3. 向跨链通道提交桥接(Across、OKX bridge 等)。如果桥接步骤由用户在本技能之外发起,则关卡问题改为:“你准备好离开本技能、执行桥接,并在资金到账 X Layer 后重新调用了吗?”。
  4. X Layer 上的同链兑换(例如,将 USDG 兑换为 USDT0),如果资金 计划包含目标链环节。
  5. 对 402 结算进行 EIP-3009 TransferWithAuthorization 签名。

每个关卡都使用 AskUserQuestion Agent 工具(不要使用 read -p、 不要向 bash 提示符执行 echo,也不要在回复中打印“(是/否)”),并且在继续之前 等待用户回复。每个关卡向用户展示的摘要必须包含:

  • 操作(授权、兑换、桥接、签署 EIP-3009 授权)。
  • 金额和代币(兑换和桥接的输入和输出金额)。
  • 源链和目标链(两者不同时)。
  • 接收方(EIP-3009 步骤中的 payTo)。
  • 支付所绑定的资源 URL。
  • 预估 Gas(如适用)。

常见失败模式。 在回复中描述多步骤资金计划时,不要把多笔交易合并成一个确认问题,例如“是否继续进行资金筹措和付款?”每笔交易都必须在即将执行时单独通过关卡。事先一次性确认“是”并不代表用户同意之后的交易;这些交易执行时,用户还没有看到实际金额、Gas 和接收方。

每个关卡都必须获得明确确认。每个关卡彼此独立。 绝不要自动提交,即使用户之前已预先授权此会话、 调用或钱包。流程中较早时的“是”不能沿用;对多步骤计划回答“是”,也不代表对其中 每笔单独交易都回答了“是”。

响应中正确的确认门应是什么样子。 无论你是在实时执行此技能,还是以文本描述计划,每个交易步骤都必须以独立的、带标签的“确认门”区块呈现,并包含结构化摘要和明确的 AskUserQuestion 调用。每个确认门都要照原样使用此模板。不要将确认门压缩成一行。不要用被动语态描述确认门(例如“我们将在签署前确认”)。应将确认门展示为一个独立操作。

模板(每个确认门都要使用,即使只有一个):

### Confirmation Gate N: <Action name>

| Field        | Value                                    |
| ------------ | ---------------------------------------- |
| Action       | <approve / swap / bridge / sign EIP-3009>|
| Amount in    | <amount + symbol on source chain>        |
| Amount out   | <amount + symbol on destination chain>   |
| Source chain | <chain name + id>                        |
| Dest chain   | <chain name + id>                        |
| Recipient    | <address>                                |
| Resource URL | <url the payment is bound to>            |
| Est. gas     | <amount + token>                         |

Then call AskUserQuestion("Proceed with <action>?")
and BLOCK on the user's reply. If anything other than an explicit
"yes", stop and report.

如果响应只列出字段,却没有 AskUserQuestion("Proceed?") + block 步骤,就不算确认门,即使内容看起来很完整。将每个确认门命名为独立步骤,并在继续前等待用户回复。

哪些情况不算确认门。 输出一个 bash 脚本,在标准输出中打印 "⚠️ CONFIRMATION REQUIRED" 和 "(yes/no)",然后继续执行 echo "Signing...",这不算确认门,因为无论用户输入什么,脚本都会继续执行。正确的确认门应使用 AskUserQuestion 工具(或者,若用户明确选择仅使用 shell 的模式,则使用实际阻塞的 read -p,并在脚本中明确设置 yes/no 分支)。如有疑问,优先使用 AskUserQuestion。

共享钱包的竞态问题。 如果钱包是共享的(例如,多个 Agent 同时使用同一密钥),余额可能会在检查余额与提交之间被耗尽。确认时也要重新检查 balanceOf。

步骤 6,签署并提交

关于域构造、nonce 生成、使用 viem 签署、载荷组装和重试的详细步骤,请参阅 references/app-x402-flow.md。重试时,如果质询中存在 accepts[].resource,则将其对应的 URL 作为目标;否则使用原始请求 URL。

域警告。 verifyingContract 是代币合约,不是单独的验证器。使用质询 extra 字段中的 name 和 version,不要假定默认值。不同代币的域值各不相同。域不正确会导致签名被 facilitator 拒绝,并再次返回 402。

extra.name 的 UTF-8 必须逐字节精确匹配。 EIP-712 域哈希要求字节完全一致。extra 中的 name 字段必须原样传递质询中的字节。不要对其进行规范化,不要将其转换为小写,不要用 ASCII T(U+0054)替换 Unicode ₮(U+20AE),也不要合并 Unicode 形式(NFC 与 NFD)。例如,质询返回 "USD₮0" 时,签名时必须使用 "USD₮0";若将其读取为 "USDT0",生成的签名将被 facilitator 拒绝,并再次返回 402。将 extra.name 的原始字节直接传入 EIP-712 域。

错误处理

情况操作
402 挑战中没有 network 字段检查挑战正文;如果 chainId 对应 196,则使用此技能;否则转交给 pay-with-any-token
网络不是链 196转交给 pay-with-any-token
x402Version !== 1明确拒绝;提示版本不匹配错误。此技能的 v1.0.0 仅针对 x402 v1。
accepts[].scheme !== "exact"明确拒绝;v1.0.0 仅支持 exact 方案。其他 x402 方案(upto、batch-settlement)不在支持范围内。
accepts[].maxAmountRequired === "0"明确拒绝,并指出商户配置错误。HTTP 402 要求正数付款;OKX 的 facilitator 不会结算零金额转账。不要签名,也不要将零金额解释为 ping、身份验证检查或免费套餐。
APP 请求在 X Layer 上使用 USDC明确说明注意事项:USDC 在 X Layer 上没有可靠的 Uniswap v3 路由。建议直接从流动性充足的链(Base、Arbitrum、Mainnet)跨链转入 USDC,或询问 USDT0。
X Layer 上资产不足触发资金充值流程(阶段 3)
Trading API 返回 400记录请求和响应;检查金额格式及地址校验和
Trading API 返回 429退避并使用指数延迟重试
报价已过期重新获取报价;不要重复使用旧的 permitData
跨链桥超时检查 Across 跨链桥浏览器;不要重新提交
EIP-3009 签名被拒(重试时返回 402)根据 extra 验证域的 name / version(逐字节精确匹配,包括任何非 ASCII 字符),检查 validBefore 是否仍有效,并确认 nonce 尚未使用
重试时金额不匹配使用实际资产链上的 decimals() 重新计算基本单位;不要假定为 6
链上结算回滚(transferFrom 失败)在重试时重新检查 balanceOf;签名与提交之间余额可能已被转走(共享钱包、并发 Agent 或手动转账)。重试前向用户说明情况。
用户询问托管 / 会话 / 批处理 / upto说明此版本的技能仅涵盖即时付款(exact 方案)。其他功能不在 v1.0.0 的支持范围内;OKX 发布相关功能后,将在后续 v1.x 版本中跟进。

关键地址和参考资料

X Layer(链 196)
  • 链 ID:196
  • 公共 RPC:https://rpc.xlayer.tech
  • USDT0:0x779Ded0c9e1022225f8E0630b35a9b54bE713736(精度 6)
  • USDG:0x4ae46a509F6b1D9056937BA4500cb143933D2dc8(精度 6)
  • USDC:0x74b7F16337b8972027F6196A17a631aC6dE26d22(精度 6,在 X Layer 上没有可靠的 Uniswap 路由; 请从流动性充足的链桥接)
  • WOKB(包装原生代币):0xe538905cf8410324e03A5A23C1c177a474D59b2b (精度 18)
  • Uniswap V3 工厂合约:0x4B2ab38DBF28D31D467aA8993f6c2585981D6804
  • SwapRouter02:0x4f0C28f5926AFDA16bf2506D5D9e57Ea190f9bcA
  • Universal Router 2.1: 0xDa00aE15d3A71466517129255255db7c0c0956d3
  • QuoterV2:0xD1b797D92d87B688193A2B976eFc8D577D204343
  • Permit2:0x000000000022D473030F116dDEE9F6B43aC78BA3
  • USDT0/USDG 池:0x0cBe0dBE1400e57f371a38BD3b9bC80F7C3676dA
  • USDT0/WOKB 池:0x63d62734847E55A266FCa4219A9aD0a02D5F6e02
Uniswap Trading API
  • 基础 URL:https://trade-api.gateway.uniswap.org/v1
  • 请求头:x-api-key: $UNISWAP_API_KEY
  • 请求头:x-universal-router-version: 2.1.1
  • 支持的链包括 1、8453、42161、10、137、130、196 等 (请参阅 Trading API 支持链文档)。

X Layer 上的链上 Universal Router 合约标记为 2.1 (部署地址为上文的 0xDa00aE15d3A71466517129255255db7c0c0956d3)。Trading API 要求请求头的值为 2.1.1,这是 API 内部使用的版本字符串,用于指向同一个 Universal Router 2.1 合约的路由路径。这两个版本字符串分别指代相关但不同的内容; 请勿用其中一个替换另一个。

OKX APP
  • APP 概览 / 开发文档: https://web3.okx.com/onchainos/dev-docs/payments/x402-introduction
  • OKX onchainos-skills 仓库:https://github.com/okx/onchainos-skills
  • x402 规范:https://github.com/coinbase/x402

相关技能

  • pay-with-any-token,用于处理 X Layer 以外链上的 HTTP 402 挑战的同级技能(Ethereum、Base、 Arbitrum、Tempo 等)。对于非 X Layer 挑战,请使用该技能。
  • swap-integration,完整的 Uniswap 兑换集成参考(Trading API、Universal Router、Permit2)。

评论

支持 Markdown