跳转至

Exact Output 兑换

Exact Output 从接收者必须收到的金额出发计算报价。当前流程使用钱包资金和固定输入扣款,要求 gas_mode="pay_more"、funding_policy="wallet_fixed_exact_output",不使用已有 Vault 余额支付这笔兑换。整数取整后,成功到账金额可能高于目标;实际结果以确认金额为准。

可用性取决于目标部署。临时 503 不能证明执行失败,请保留请求身份并遵循下方重试规则。

请求报价

POST /api/v1/swap/exact-output/quote

身份验证: 无。

请求体

{
  "quote_uuid": "client-quote-001",
  "from_token": "0x1111111111111111111111111111111111111111",
  "to_token": "0x2222222222222222222222222222222222222222",
  "to_amount": "1000000",
  "max_from_amount": "1200000",
  "owner_address": "0x3333333333333333333333333333333333333333",
  "recipient": "0x3333333333333333333333333333333333333333",
  "expiration": 1800000000,
  "gas_mode": "pay_more",
  "funding_policy": "wallet_fixed_exact_output"
}
以上地址仅为占位示例,请选择已注册代币。使用 GET /api/v1/system/time 设置未来截止时间,并预留报价、签名和执行时间。

字段 必填 说明
quote_uuid 否 1–64 个不含空格的可见 ASCII 字符;省略时生成 UUID。建议自行提供并保存,以便识别报价重试
from_token、to_token 是 不同、非零、严格小写的 0x EVM 地址
owner_address、recipient 是 非零小写签名/付款钱包与接收钱包
to_amount 是 目标输出金额,正 uint256 十进制 raw 字符串
max_from_amount 否 包含报价 gas 费用的最大钱包输入扣款,正 raw 字符串
expiration 是 Unix 秒数整数,0 < expiration < 2**48;报价后必须留有执行时间
gas_mode 是 pay_more
funding_policy 是 wallet_fixed_exact_output

额外字段、浮点金额和非规范 raw 字符串会被拒绝。报价有效期最长 30 秒,且至少早于路由截止时间 30 秒结束;请始终使用返回的 expires_at。

响应

字段 说明
quote_uuid 执行和状态查询使用的标识符
execution_flow exact_output_fok_v1
status quoted
expires_at 报价过期的 Unix 秒数
funding_policy、gas_mode 已接受的资金与 gas 选项
route_params 必须原样签名的 EIP-712 Intent 字段;其中 uuid 是签名 uint256,不是 quote_uuid
signing_domain 本次报价应使用的 EIP-712 域
permit 资金授权元数据,沿用 Swap 的 permit/approve 分支
fee_breakdown.quoted_gas_fee_input_raw 以输入代币 raw 单位计价的 gas 费
fee_breakdown.wallet_debit_raw 固定的钱包总扣款
fee_breakdown.expected_recipient_output_raw 预期输出,不低于 to_amount
fee_breakdown.confirmed_recipient_output_raw 报价时为 null
fee_breakdown.gas_fee_usd gas 的美元成本,十进制字符串

route_params.maxInputAmount 和 initialDepositAmount 均等于固定钱包扣款。minOutputAmount 是请求的目标金额。使用 Intent 类型和本次报价的 signing_domain,原样签署所有返回字段。

执行

POST /api/v1/swap/exact-output

身份验证: EIP-712 Intent 签名。如携带 API Key,必须属于报价所有者。

请求体

{
  "quote_uuid": "client-quote-001",
  "signature": "0x...",
  "permit_signature": "0x...",
  "permit_deadline": 1800000000
}
quote_uuid 和 signature 必填。只有已存报价要求且支持 EIP-2612 permit 时,才提交 permit_signature / permit_deadline。否则完成 approve 流程并省略这两个字段;多余的 permit 字段会被拒绝。

待确认执行返回 HTTP 202;其他正常 HTTP 响应使用 200。HTTP 200 本身不表示交易成功,必须检查 status。

查询状态

GET /api/v1/swap/exact-output/{quote_uuid}
GET /api/v1/swap/exact-output?quote_uuid=client-quote-001

身份验证: 需要 API Key,结果仅对报价所有者可见。自定义或不透明 ID 优先使用查询参数形式,并由 HTTP 客户端编码参数。路径形式仅适用于单路径段 ID:合法的 a/b 即使编码为 a%2Fb 也可能因路由解码返回 404,不能据此认定报价不存在。

状态 含义
quoted 报价存在且仍有效,尚无确认的执行结果
expired 未执行报价已失效
pending 执行结果尚未确定
succeeded 成功结算已确认
failed 执行已进入终态失败

报价/过期响应包含 quote_uuid、execution_flow、status。执行记录持久化后,还包含 order_id、route_uuid、intent_hash、transaction_hash、error_code、confirmed_recipient_output_raw、confirmed_actual_input_cost_raw;待确认时相关确认字段可能为 null。最终记账应使用确认字段,不能使用报价估计值。

重试与错误

  • 报价重试使用同一 quote_uuid 和完全相同的报价字段。相同 ID 绑定不同请求会返回 409;过期身份不能作为新报价复用。
  • 发送前保存完整执行请求体。超时、503 或 pending 后查询原 ID,必要时重试完全相同的签名请求。改变签名字节或 permit 内容会与已认领执行冲突;编码说明见下文。
  • 执行结果未知时,不要创建新报价 ID 替代原执行。关闭新报价/执行准入时,状态读取仍保留。

pending 可能包含服务在确认尚未广播交易后,对临时提交失败进行的自动重试,也可能表示提交或链上恢复结果尚不确定。这两种情况都不要求客户端创建新报价或重新签署替代 Intent;应持续查询原 quote_uuid,直到得到终态结果。

HTTP 含义 / 处理
400 Intent/permit 签名无效、多余 permit 或资金预检失败
401 状态查询缺少或使用无效 API Key
404 报价不存在
409 报价/执行身份冲突;部分准入前 permit nonce 冲突需重新报价
410 计划或报价过期
422 请求无效、超出输入上限或类型化报价拒绝
429 限流;存在 Retry-After 时遵循该值
503 临时不可用或关闭新准入;保留 ID 并查询状态

类型化 4xx 使用 detail.code,例如 EXACT_OUTPUT_QUOTE_CONFLICT、EXACT_OUTPUT_EXECUTION_CONFLICT、EXACT_OUTPUT_PLAN_EXPIRED、EXACT_OUTPUT_INPUT_CAP_EXCEEDED。共用的 Swap 预检错误也可能使用 detail.error_code 或字符串。5xx 通常返回通用 503 响应,不能依赖内部 EXACT_OUTPUT_* 码一定出现在该响应中。

Intent 与 permit 长度限制见签名编码。为保持兼容,应保存并原样重试签名请求:新执行认领将等价的十六进制编码规范化为签名字节,但改变签名字节或签名内容会改变执行身份;历史认领仍可能使用原字符串指纹。同时遵守整体请求体上限。