即时兑换交易¶
即时兑换为希望立即以最佳可用价格交换代币的交易者提供即时执行。与限价单不同,即时兑换是 Fill-or-Kill 的 — 要么完全执行,要么被拒绝。
兑换流程¶
sequenceDiagram
participant User
participant API as Sera API
participant Chain as Ethereum
User->>API: POST /swap/quote
API-->>User: Quote (uuid, route_params)
User->>User: Sign route_params (EIP-712)
User->>API: POST /swap (uuid + signature)
API->>Chain: Settlement
Chain-->>API: Confirmation
API-->>User: Success (trade_id) 第 1 步:请求报价¶
const response = await fetch('https://api.sera.cx/api/v1/swap/quote', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
from_token: '0x1920...F88', // USDC address
to_token: '0xd3Bd...779', // EURC address
from_amount: '1000000000', // 1000 USDC (6 decimals)
owner_address: '0xYOUR_WALLET',
recipient: '0xYOUR_WALLET', // 接收输出代币的地址(可以是另一个钱包)
expiration: Math.floor(Date.now() / 1000) + 3600, // 1 hour
gas_mode: 'receive_less'
})
});
const quote = await response.json();
// quote.uuid — Unique quote identifier
// quote.route_params — EIP-712 parameters to sign
// quote.fee_breakdown — Gas 费用详情 (gas_cost_usd, gas_cost_from_token)
报价参数¶
| 参数 | 类型 | 说明 |
|---|---|---|
from_token | address | 输入代币的 ERC-20 地址 |
to_token | address | 输出代币的 ERC-20 地址 |
from_amount | string | 原始代币单位的金额(例如 "1000000000" 表示 1000 USDC) |
owner_address | address | 您的钱包地址 |
recipient | address | 输出代币的接收地址;可以是任意地址——设置为其他钱包即可将兑换输出发送给第三方。 |
expiration | integer | Unix 时间戳截止时间 |
gas_mode | string | "receive_less" 或 "pay_more" |
报价响应¶
响应包含:
uuid— 此报价的唯一标识符(提交时使用)route_params— 需要签名的 EIP-712 Intent 结构体字段fee_breakdown— Gas 费用详情:gas_cost_usd和gas_cost_from_tokenexpires_at— 报价过期时间(报价为一次性使用)
第 2 步:签署报价¶
使用您的钱包通过 EIP-712 类型化数据签名对 route_params 进行签名:
import { ethers } from 'ethers';
// The EIP-712 domain (get from /api/v1/tokens or contract)
const domain = {
name: 'Sera',
version: '1',
chainId: 11155111, // Sepolia
verifyingContract: '0x...' // Sera contract address
};
// The Intent type
const types = {
Intent: [
{ name: 'inputToken', type: 'address' },
{ name: 'outputToken', type: 'address' },
{ name: 'maxInputAmount', type: 'uint256' },
{ name: 'minOutputAmount', type: 'uint256' },
{ name: 'recipient', type: 'address' },
{ name: 'initialDepositAmount', type: 'uint256' },
{ name: 'uuid', type: 'uint256' },
{ name: 'deadline', type: 'uint48' },
]
};
const signature = await signer.signTypedData(domain, types, quote.route_params);
第 3 步:执行兑换¶
提交已签名的报价:
const result = await fetch('https://api.sera.cx/api/v1/swap', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
uuid: quote.uuid,
signature: signature
})
});
const swap = await result.json();
// swap.success — Whether the swap was accepted
// swap.trade_id — Unique trade identifier for tracking
Gas 模式¶
与限价单(需要以真实 ETH 支付 Gas)不同,兑换的 Gas 费用由服务器自动计入报价中。您无需持有 ETH 即可执行兑换 — Gas 被吸收到代币金额中。
请求报价时,您可以选择 Gas 费用的应用方式:
| 模式 | 行为 |
|---|---|
receive_less | Gas 费用从输出中扣除。您花费的恰好是 from_amount,但收到的略少。 |
pay_more | Gas 费用添加到输入中。您收到完整的报价金额,但花费的略多。 |
报价响应中的 fee_breakdown 显示确切的 Gas 费用,不会有意外。服务器会计算调整后的金额 — 您的前端只需按原样签署 route_params 即可。
多段路由¶
Sera 自动为您的兑换找到最优路由。如果直接交易对不存在或多跳路径能提供更好的定价,兑换会透明地通过中间货币路由。
例如,GBP → SGD 的兑换可能执行为:
- GBP → USD
- USD → SGD
这是原子性的 — 要么所有段都成功,要么全部不执行。
为什么 MEV 不是问题¶
Sera 的即时兑换并不是像公共 AMM 兑换那样执行的。报价生成、路由和撮合都在 Sera 的 Web2 引擎中链下完成,而 Ethereum 只作为最终结算层使用。
这意味着用户不会把一笔开放式市价兑换订单暴露到公共内存池中进行价格发现。相反,您会先请求报价,再签署精确的 route_params,然后结算要么在已签名的边界内执行,要么直接失败。
已签名的 Intent 包含 maxInputAmount、minOutputAmount、一次性 uuid 和 deadline。由于交易并不是在公共内存池中被发现和重新定价,常见的夹击攻击路径并不存在。
错误处理¶
| HTTP 状态码 | 含义 |
|---|---|
| 200 | 兑换已接受并正在处理 |
| 400 | 请求参数无效 |
| 410 | 报价已过期(请重新请求报价) |
| 429 | 超出频率限制(请等待后重试) |
| 503 | 服务暂时不可用 |