mcpField
C
cryptorefills-x402

cryptorefills-x402

github.com/cryptorefills其他094 次安装9 周前更新
代码仓库

关于 cryptorefills-x402

cryptorefills-x402 是供 AI Agent 使用的技能,可通过 Cryptorefills 使用 USDC 购买数字商品,无需账户或 API 密钥。它支持 Base 和 Solana 支付流程,并提供支付证明校验及签名、支出保护措施。

主要功能

  1. 01浏览品牌与商品目录
  2. 02使用 USDC 下单
  3. 03选择 Base 或 Solana 结算
  4. 04验证签名支付要求
  5. 05跟踪订单交付

适用场景

  1. 01自主采购礼品卡
  2. 02开通旅行 eSIM
  3. 03发放程序化奖励
  4. 04进行注册表驱动的 Solana 支付

安装

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

$npx skills add https://github.com/cryptorefills/agents --skill cryptorefills-x402

安装后在 Claude Code 中输入/cryptorefills-x402确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
endpoints.md
protocol.md
troubleshooting.md

详细介绍

Cryptorefills x402 — 自主 Agent 商务

为持有加密货币钱包的 AI Agent 提供完全自主的购买功能。无需账户、OAuth 或 API 密钥,只需稳定币和签名密钥。

基于 x402 protocol 构建,将 HTTP 402 Payment Required 作为机器间支付标准。支持两种结算通道:Base(Ethereum L2 上的 USDC,默认)和 Solana(Solana 主网上的 USDC SPL,可选)。

如需在人类指导下使用多种支付方式进行购买,请改用 cryptorefills-buy。 如需仅浏览目录,请改用 cryptorefills-catalog。

选择结算通道

结算通道主机Phase-1 标头钱包资产原生 Gas
Base(默认)x402.cryptorefills.com无,或 X-Preferred-Network: base支持 EIP-712 的 EVM 钱包USDC 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913,链 ID 8453无 — Cryptorefills 负责中继
Solanax402.cryptorefills.comX-Preferred-Network: solanaSolana 密钥对USDC SPL 铸币地址 EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v无 — CDP facilitator 支付 SOL
Solana(主机固定)solana.x402.cryptorefills.com省略,或仅使用 solanaSolana 密钥对同上无

默认结算通道建议。 如果你的 Agent 在两种结算通道上都有钱包,且没有外部限制,请使用 Base — EIP-712 工具支持更广泛,支付窗口更长(约 15 分钟,Solana 约 60 秒),且与自 v1.0 起 EVM-only Agent 一直使用的合约完全一致。若 Agent 已在 Solana 上运行、需要避免使用 SOL,或注册表 / 市场(例如 pay-skills)要求默认使用 Solana 主网 402 挑战,则使用 Solana — 此时请使用 solana.x402.cryptorefills.com 主机,以固定结算通道,避免歧义。

何时启用

  • Agent 在 Base 上拥有钱包(USDC、EIP-712),或在 Solana 上拥有钱包(USDC SPL,可对 v0 交易进行部分签名)
  • 任务需要在没有人工支付交互的情况下自主购买
  • 不希望设置账户、执行 OAuth 流程或管理 API 密钥
  • 关键词:“用 USDC 购买”、“USDC SPL”、“自主购买”、“Agent 商务”、“x402 支付”、“程序化礼品卡”、“Solana mainnet-beta”、“partial-sign”、“VersionedTransaction”、“compute-budget”、“pay-skills registry”、“无需 SOL”、“无需 ETH”
  • 使用场景:自动采购礼品卡、配置旅行 eSIM、程序化奖励、由注册表驱动的 Solana 支付

要求

Base 结算通道
要求详情
Base 上的 USDC链 ID 8453,合约 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
EIP-712 签名为 transferWithAuthorization(EIP-3009)签署类型化数据
用于 Gas 的 ETH不需要 — Cryptorefills 会在链上中继授权
HTTP 客户端标准 REST API 调用
账户无需账户
Solana 结算通道
要求详情
Solana 主网上的 USDC SPL铸币地址 EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v,6 位小数
Solana 密钥对64 字节 Ed25519 密钥(Phantom / Solflare 导出格式均可)
Solana RPC 访问权限用于获取最新的 recentBlockhash。默认使用 https://api.mainnet-beta.solana.com;任何可靠的 RPC 均可
v0 交易签名按照规范的 3 条指令结构构建 VersionedTransaction,并进行部分签名 — 参见 protocol.md
用于 Gas 的 SOL不需要 — CDP facilitator 使用其资金池支付 SOL Gas
HTTP 客户端标准 REST API 调用
账户无需账户

支出保障措施

自主 Agent 使用真实资金消费时,需要严格的管控:

  • 开始前设置每个会话的消费限额(默认:每个会话最高 $100,每笔交易最高 $50 — 只有用户明确要求时才提高限额)。
  • 签名前核实 402 响应中的订单金额 — 切勿盲目签名。
  • 每种支付通道使用专用钱包,其中只存放所需数量的稳定币。
  • 切勿记录、暴露或分享钱包的私钥/密钥 — 使用环境变量或密钥管理器。
  • 记录每笔交易:order_id、产品、金额、钱包地址、支付通道、交易签名/哈希。
  • 签名金额不得超过 402 响应中的 maxAmountRequired。
  • 签名前验证 402 的真实性。 payTo 是每个会话的存款钱包 — 清单中不会列出存款钱包,因此无法使用允许列表。相反,每个 402 都携带 X-Payment-Required-Signature,这是由网关签名的 JWS(ES256)。使用清单中的 attestation.keys / attestation.jwks_uri 中的密钥验证它(与清单同源),并确保:iss == 你发送 POST 请求所用的源站,sid == X-Session-Id 标头,pr_sha256 == base64url(sha256(PAYMENT-REQUIRED 标头的原样值)), pay_to/network == 解码后的 accepts[0] 值,exp 为未来时间。**如果缺少该标头或任何检查未通过,请拒绝该 402,且不要签名。**完整操作步骤和 verify402() 代码片段:references/protocol.md → 验证 402 证明。

Solana 特定要求:

  • payTo 是 OWNER 公钥,绝不是 ATA。 根据 (payTo, mint) 推导收款方 ATA。若将 payTo 当作 ATA 来签署转账,操作会失败。
  • 部分签名之前,验证 extra.feePayer 与 PAYMENT-REQUIRED 中的值一致 — 并将其用作交易的 payerKey。
  • 部分签名前立即重新获取 recentBlockhash。 有效时间约为 60 秒;网关将 maxTimeoutSeconds 限制为 60 以提示这一点。在 Solana 上,不要在阶段 1 和阶段 2 之间插入用户提示。
  • 序列化之前,断言构建的交易恰好包含 3 条指令(compute-unit limit、compute-unit price、TransferChecked)。
  • 使用 SPL TransferChecked(标签 0x0c),而不要使用 Transfer(0x03)。 CDP 会以 unknown_error 拒绝普通 Transfer。

一般要求:

  • 礼品卡代码(voucher_code)与现金类似 — 妥善保管,绝不公开分享或写入日志。
  • 数字商品一经交付概不退款。
  • 条款:https://www.cryptorefills.com/terms/

每个主机均通过 /.well-known/x402.json 提供清单,并包含 attestation 区块(签名密钥、jwks_uri、验证流程)。请从你在阶段 1 中使用的同一主机读取清单 — attestation 中的 iss 必须与该源站一致,且 jwks_uri 必须与该源站同源。

阶段 2 始终发送到与阶段 1 相同的主机。 X-Session-Id 对应的会话绑定到特定主机;跨主机 POST 请求可能导致会话查找失败。

核心工作流

GET  /v1/brands          → discover brands
GET  /v1/catalog         → get products and prices
POST /v1/orders          → 402 + PAYMENT-REQUIRED + X-Session-Id + X-Payment-Required-Signature
   ↓ verify the attestation (JWS) — reject the 402 if it is missing or invalid
   ↓ sign (EIP-712 for Base, partial-sign v0 tx for Solana)
POST /v1/orders          → submit with PAYMENT-SIGNATURE [+ X-Session-Id] → 200
GET  /v1/orders/{id}     → poll until delivered

两种支付通道的流程、REST 合约以及订单/交付模式完全相同。只有阶段 1 的标头选择、PAYMENT-REQUIRED 中的 extra 区块以及签名原语不同。

分步说明

1. 浏览品牌
GET /v1/brands?country_code=us

返回该国家/地区可用的品牌。每个条目都包含 brand_name、family、category、min、max。

国家代码使用 ISO 3166-1 Alpha-2 小写格式(us、it、br),无论支付通道为何。如果从目录或购买技能(使用大写格式)获取国家代码,请先将其转换为小写,再用于 x402 端点。

2. 获取目录
GET /v1/catalog?country_code=us&brand_name=Amazon.com

返回包含 product_id、is_range、currency、price_usdc,以及 denomination(固定面值)或 min_value/max_value(范围面值)的商品。

  • 固定面值商品(is_range: false):直接使用 product_id。省略 product_value。面值是以 currency 计价的 denomination。
  • 范围面值商品(is_range: true):将 items[].product_value 设为所需金额,单位为品牌当地的 currency(不是美元)。例如,购买一张面值 €5、currency: "EUR" 的 Amazon.nl 礼品卡时,传入 product_value: 5。402 响应会提供实际结算所需的 USDC 金额(通常为 price_usdc 加减少量价差)。
下单前:检查稳定币余额

下单前,请确认所选通道上的钱包有足够的稳定币:

  • Base:在 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 上调用 balanceOf(walletAddress)。
  • Solana:在发送方 ATA 上调用 getTokenAccountBalance — getAssociatedTokenAddress(mint=EPjF…WEGGkZwyTDt1v, owner=agent)。无需 SOL 余额。

目录中的 price_usdc 仅供参考;确切金额会在 402 响应中确认。

3. 创建订单 — 阶段 1(获取付款要求)

Base(默认):

curl -X POST https://x402.cryptorefills.com/v1/orders \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "items": [{
      "product_id": "abc123",
      "beneficiary_account": "[email protected]",
      "product_value": 25
    }]
  }'
# → HTTP 402 with PAYMENT-REQUIRED, X-Session-Id and X-Payment-Required-Signature headers

Solana(通过标头启用):

curl -X POST https://x402.cryptorefills.com/v1/orders \
  -H "Content-Type: application/json" \
  -H "X-Preferred-Network: solana" \
  -d '<same body>'

Solana(固定主机):

curl -X POST https://solana.x402.cryptorefills.com/v1/orders \
  -H "Content-Type: application/json" \
  -d '<same body>'

范围面值商品必须提供 product_value;固定面值商品则省略。可选:添加 "callback_url": "https://...",以通过 webhook 接收交付通知,而不是轮询。

捕获以下三个响应标头:

  • PAYMENT-REQUIRED — 付款要求的 base64url 编码 JSON(各通道格式见下文)。
  • X-Session-Id — UUID。在阶段 2 中原样回传(Solana 必需,Base 可选)。
  • X-Payment-Required-Signature — 用于证明上述两个标头的 JWS(iss、sid、pr_sha256、pay_to、network、exp)。签名前先验证 — 参见 references/protocol.md。缺少该标头应视为 402 失败。
PAYMENT-REQUIRED — Base 示例
{
  "x402Version": 2,
  "accepts": [{
    "scheme": "exact",
    "network": "eip155:8453",
    "maxAmountRequired": "25000000",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "extra": { "name": "USD Coin", "version": "2", "decimals": 6 },
    "payTo": "0x...",
    "description": "$25.00 Amazon Gift Card"
  }],
  "expiresAt": 1830000000
}
与 Base 相比的 Solana 差异(完整 Solana 示例见 protocol.md)
BaseSolana
networkeip155:8453solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp(完整 CAIP-2)
assetEVM 合约SPL 铸币地址,base58 编码(USDC 为 EPjF…WEGGkZwyTDt1v)
extra{name, version, decimals}{feePayer} — 用作 payerKey
payTo收款钱包收款方 所有者 公钥(由 facilitator 端派生 ATA)
expiresAt 时间窗口约 15 分钟约 60 秒
4. 签署付款
Base — EIP-712 / EIP-3009

为 transferWithAuthorization 签署类型化数据。

Domain:Base 上的 USDC 合约。 Types:TransferWithAuthorization(address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce)。

字段值
from你的钱包地址
to402 响应中的 payTo
value402 响应中的 maxAmountRequired
validAfter0
validBefore402 响应中的 expiresAt(Unix 秒)
nonce随机 32 字节十六进制值

确切的 EIP-712 类型化数据结构见 references/protocol.md。

Solana — 部分签名 v0 交易

构建 v0 VersionedTransaction,且必须恰好包含 3 条指令,并按以下顺序排列:ComputeBudget 设置计算单位上限(200_000 units)→ ComputeBudget 设置价格(1000 microLamports)→ SPL createTransferCheckedInstruction(标签 0x0c,不是 Transfer 的 0x03)。使用 mint = asset、senderAta = getAssociatedTokenAddress(mint, signer)、recipientAta = getAssociatedTokenAddress(mint, payTo)(其中 payTo 是所有者)、payerKey = extra.feePayer,以及从 Solana RPC 获取的最新 recentBlockhash。使用 tx.sign([signer]) 进行部分签名 — 为 CDP 保留 feePayer 签名槽位。序列化后不超过 1232 字节。

完整步骤见 references/protocol.md。

5. 完成订单 — 阶段 2

使用 PAYMENT-SIGNATURE 重新 POST 相同的请求体。回传阶段 1 中的 X-Session-Id(Solana 必需)。

Base
curl -X POST https://x402.cryptorefills.com/v1/orders \
  -H "Content-Type: application/json" \
  -H "PAYMENT-SIGNATURE: <base64url-encoded JSON>" \
  -d '<same body as phase 1>'
# → HTTP 200

PAYMENT-SIGNATURE 负载(然后对 JSON 进行 base64url 编码):

{
  "x402Version": 2,
  "scheme": "exact",
  "network": "eip155:8453",
  "payload": {
    "signature": "0x...",
    "authorization": {
      "from": "0xYourWallet",
      "to": "0xPayToAddress",
      "value": "25000000",
      "validAfter": "0",
      "validBefore": "1830000000",
      "nonce": "0xRandomBytes32"
    }
  }
}
Solana
curl -X POST https://x402.cryptorefills.com/v1/orders \
  -H "Content-Type: application/json" \
  -H "PAYMENT-SIGNATURE: <base64url-encoded JSON>" \
  -H "X-Session-Id: <UUID from Phase 1 response>" \
  -d '<same body as phase 1>'
# → HTTP 200

PAYMENT-SIGNATURE 载荷(对外层 JSON 进行 base64url 编码;内层 payload.transaction 为普通 base64):

{
  "x402Version": 2,
  "scheme": "exact",
  "network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
  "payload": {
    "transaction": "<plain-base64 of serialized v0 transaction>"
  }
}

编码规则。 对于两种支付通道,外层 PAYMENT-SIGNATURE 封装都使用 base64url 编码。只有 Solana 上的内层 payload.transaction 字段使用普通 base64(Solana 生态惯例;不透明地传递给支付协调方)。不要将两者统一处理。

服务端以 HTTP 200 响应:

{
  "order_id": "cr_abc123",
  "status": "processing",
  "estimated_delivery_seconds": 60,
  "poll_url": "/v1/orders/cr_abc123"
}
6. 跟踪交付状态
GET /v1/orders/{order_id}

每隔 5–10 秒轮询一次,直到 status 为 completed 或 failed。10 分钟后停止轮询,并报告订单可能卡住了——请通过 [email protected] 联系支持团队,并提供 order_id。

当 completed 时,deliveries 数组包含:

  • voucher_code — 礼品卡兑换码
  • pin — 如有要求则提供 PIN
  • url — 如适用则提供兑换 URL
  • brand_name、product_name — 购买的商品

示例:Solana 上的 €5 Amazon.nl 礼品卡

端到端验证各步骤的说明是否能够组合使用。真实数值,钱包地址已匿名化:

# 1. Discover Amazon.nl
curl 'https://x402.cryptorefills.com/v1/brands?country_code=nl' | jq '.[] | select(.family|test("Amazon"))'
#   → {"brand_name":"Amazon.nl","family":"Amazon.nl","category":"e-commerce", ...}

# 2. Find a range product priced in EUR
curl 'https://x402.cryptorefills.com/v1/catalog?country_code=nl&brand_name=Amazon.nl' | jq '.[0]'
#   → {"product_id":"amzn-nl-range","is_range":true,"currency":"EUR",
#      "min_value":5,"max_value":500,"price_usdc":"5.42", ...}
#   1 EUR isn't offered (min is 5 EUR) — pick 5 EUR.

# 3. Phase 1 — opt into Solana
curl -i -X POST https://x402.cryptorefills.com/v1/orders \
  -H "Content-Type: application/json" \
  -H "X-Preferred-Network: solana" \
  -d '{"email":"[email protected]",
       "items":[{"product_id":"amzn-nl-range",
                 "beneficiary_account":"[email protected]",
                 "product_value":5}]}'
#   → HTTP/1.1 402
#      X-Session-Id: 3f9c1a8b-...           ← capture, echo on Phase 2
#      PAYMENT-REQUIRED: <base64url JSON>   ← decode for accepts[0]
#      X-Payment-Required-Signature: <JWS>  ← verify first (protocol.md → Verifying the 402 attestation)
#
#   accepts[0] decoded:
#     network:           solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp
#     asset:             EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
#     maxAmountRequired: "5420000"          ← 5.42 USDC
#     payTo:             <owner pubkey>     ← derive recipient ATA from this
#     extra.feePayer:    <CDP pubkey>       ← use as transaction.payerKey
// 4. Decode PAYMENT-REQUIRED, verify budget, build the partial-signed v0 tx
import {ComputeBudgetProgram, Connection, Keypair, PublicKey,
        TransactionMessage, VersionedTransaction} from '@solana/web3.js';
import {createTransferCheckedInstruction, getAssociatedTokenAddress} from '@solana/spl-token';
import bs58 from 'bs58';

// 4a. Parse the 402 response
const paymentRequired = JSON.parse(
  Buffer.from(phase1Headers['payment-required'], 'base64url').toString());
const sessionId = phase1Headers['x-session-id'];
const {payTo, asset, maxAmountRequired, extra} = paymentRequired.accepts[0];

// 4b. Spending-safeguard checks BEFORE signing
const SPEND_LIMIT_ATOMIC = BigInt(50_000_000);              // $50 = 50e6 atomic USDC
if (BigInt(maxAmountRequired) > SPEND_LIMIT_ATOMIC) throw new Error('over budget');
if (asset !== 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v') throw new Error('wrong mint');

// 4c. Build the transaction
const signer       = Keypair.fromSecretKey(bs58.decode(process.env.SOLANA_SIGNER_KEY));
const conn         = new Connection('https://api.mainnet-beta.solana.com', 'confirmed');
const mint         = new PublicKey(asset);
const owner        = new PublicKey(payTo);                  // OWNER, not an ATA
const feePayer     = new PublicKey(extra.feePayer);         // CDP signs this slot

const senderAta    = await getAssociatedTokenAddress(mint, signer.publicKey);
const recipientAta = await getAssociatedTokenAddress(mint, owner);
const {blockhash}  = await conn.getLatestBlockhash('finalized');  // 'finalized' is older but accepted by all validators — reduces timing sensitivity

const message = new TransactionMessage({
  payerKey:        feePayer,
  recentBlockhash: blockhash,
  instructions: [
    ComputeBudgetProgram.setComputeUnitLimit({units: 200_000}),
    ComputeBudgetProgram.setComputeUnitPrice({microLamports: 1000}),
    createTransferCheckedInstruction(senderAta, mint, recipientAta,
                                     signer.publicKey, BigInt(maxAmountRequired), 6),
  ],
}).compileToV0Message();

const tx = new VersionedTransaction(message);
tx.sign([signer]);                                    // partial — leaves feePayer slot
// Assert on the pre-compilation array — MessageV0 exposes `compiledInstructions`, not `instructions`.
// Reading `tx.message.instructions` throws TypeError. Use the source array passed to TransactionMessage.
if (message.version !== 0) throw new Error('expected v0 message');
if (tx.message.compiledInstructions.length !== 3) throw new Error('expected exactly 3 instructions');
if (tx.serialize().length > 1232) throw new Error('tx too large');

const txB64       = Buffer.from(tx.serialize()).toString('base64');     // inner: plain base64
const inner       = {x402Version: 2, scheme: 'exact',
                     network: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
                     payload: {transaction: txB64}};
const headerValue = Buffer.from(JSON.stringify(inner)).toString('base64url');  // outer: base64url
# 5. Phase 2 — same host as Phase 1, echo X-Session-Id from step 3
curl -X POST https://x402.cryptorefills.com/v1/orders \
  -H "Content-Type: application/json" \
  -H "PAYMENT-SIGNATURE: <headerValue from step 4c>" \
  -H "X-Session-Id: <sessionId from step 4a>" \
  -d '<same body as Phase 1>'
#   → HTTP/1.1 200
#      {"order_id":"cr_xxx","status":"processing","poll_url":"/v1/orders/cr_xxx", ...}

# 6. Poll
curl https://x402.cryptorefills.com/v1/orders/cr_xxx
#   → {"status":"completed",
#      "deliveries":[{"voucher_code":"XXXX-YYYY-ZZZZ","brand_name":"Amazon.nl", ...}]}

如果步骤 1–6 无法适用于你的场景,失败情况已记录在 references/troubleshooting.md 中。

字段名称映射(x402 与 MCP)

如果在 x402 和 MCP 技能之间切换,请注意以下字段名称差异:

概念x402(本技能)MCP(cryptorefills-buy)
礼品卡代码voucher_codedeliverable.pin_code
PINpin(单独字段)包含在 pin_code 中
订单状态status(单个字段)order_state + payment_state
订单 ID 格式带 cr_ 前缀UUID

关键注意事项

两种支付通道
  • 国家代码:x402 端点使用小写(us,而非 US)。MCP 技能使用大写——端点不同,规则也不同。
  • 品牌名称:区分大小写——请使用 /v1/brands 响应中的准确值。
  • X-Preferred-Network 值:区分大小写,必须为小写——仅限 base 或 solana。在多支付通道主机上,Base 或 Solana(首字母大写)会返回 400 invalid_network。
  • 金额精度:使用 402 中的准确 maxAmountRequired,不要四舍五入或修改。
  • 外层编码:两种支付通道的 PAYMENT-SIGNATURE 外层封装都使用 base64url 编码(与网关的解码器一致)。
  • 不要混用支付通道:会话在阶段 1 选定的支付通道上固定。不要尝试在阶段 2 切换支付通道。
  • 阶段 2 使用相同主机:将阶段 2 的 POST 请求发送到阶段 1 使用的同一主机。会话与主机绑定。
  • 未签名的 402:如果 402 没有 X-Payment-Required-Signature,或其签名未通过任何一项检查,都必须拒绝——绝不能以“TLS 连接看起来没问题”为由继续处理。对收到的 PAYMENT-REQUIRED 标头字符串进行哈希;不要重新序列化解码后的 JSON。
Base
  • USDC 合约:在 Base 上必须准确为 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913。
  • 链 ID:必须为 8453(Base 主网)。链不正确 = 签名无效。
  • 支付超时:402 的 expiresAt 字段提供截止时间(约 15 分钟)。请在过期前签名并重新提交。
  • Nonce:每笔交易必须唯一。使用加密安全的随机 32 字节值。
  • EIP-712 域:必须与 Base 上 USDC 合约的域分隔符一致。
Solana
  • 网络字符串:必须使用完整的 CAIP-2 solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp,不能使用 "solana" 或 "solana-mainnet"。
  • **payTo 是 OWNER 公钥,不是 ATA。**协调方会根据 (owner, mint) 推导收款方 ATA。
  • **使用 TransferChecked(0x0c),不要使用 Transfer(0x03)。**CDP 会以 unknown_error 拒绝后者。
  • 必须恰好有 3 条指令,且顺序如下:ComputeBudget 设置限制、ComputeBudget 设置价格、TransferChecked。CDP 要求指令数量为 3 至 6 条。
  • payerKey = PAYMENT-REQUIRED 中的 extra.feePayer。CDP 会在结算时为该账户签名并支付 SOL Gas 费。
  • 交易数据包限制:1232 字节。规范的 3 条指令结构完全符合限制。
  • 区块哈希有效窗口:约 60 秒。部分签名前立即重新获取;Phase 1 和 Phase 2 之间不要插入用户提示。
  • 在 Phase 2 中回传 Phase 1 响应中的 X-Session-Id——这是必需的(SPL 交易是不透明的,因此网关没有其他方式查找会话)。
  • 内部编码:PAYMENT-SIGNATURE JSON 中的 payload.transaction 是普通 base64(Solana 惯例)——只有外层封装使用 base64url。

参考资料

只有在需要了解本技能文件之外的详细信息时,才加载参考资料。

文件在以下情况下加载……内容
references/protocol.md需要确切的签名方法——Base 的 EIP-712 域和类型,或 Solana 的完整 VersionedTransaction 构建方法——或需要验证 402 证明两阶段流程、请求头、各支付通道的 PAYMENT-REQUIRED 结构、X-Payment-Required-Signature 验证(verify402)、Base EIP-712 / EIP-3009 详情、Solana 三指令方法
references/endpoints.md需要 API 调用的确切请求 / 响应架构REST API 参考、主机表、完整请求头列表、错误响应代码
references/troubleshooting.md请求失败或返回意外状态各支付通道的错误目录和恢复方法

评论

支持 Markdown