跳轉至

兌換交易

兌換為希望立即以最佳可用價格交換代幣的交易者提供即時執行。與限價單不同,兌換是 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)

步驟一:請求報價

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_usdgas_cost_from_token
  • expires_at — 報價到期時間(報價為一次性使用)

步驟二:簽署報價

使用錢包透過 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);

步驟三:執行兌換

提交已簽署的報價:

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 的兌換可能執行為:

  1. GBP → USD
  2. USD → SGD

這是原子性的 — 要麼所有段都成功,要麼全部不執行。

為什麼 MEV 不是問題

Sera 的兌換並不是像公共 AMM 兌換那樣執行的。報價生成、路由和撮合都在 Sera 的 Web2 引擎中鏈下完成,而 Ethereum 只作為最終結算層使用。

這意味著使用者不會把一筆開放式市價兌換訂單暴露到公共 mempool 中進行價格發現。相反,您會先請求報價,再簽署精確的 route_params,然後結算要麼在已簽署的邊界內執行,要麼直接失敗。

已簽署的 Intent 包含 maxInputAmountminOutputAmount、一次性 uuiddeadline。由於交易並不是在公共 mempool 中被發現和重新定價,常見的夾擊攻擊路徑並不存在。

錯誤處理

HTTP 狀態碼 含義
200 兌換已接受並正在處理
400 請求參數無效
410 報價已過期(請重新請求報價)
429 超過速率限制(等待後重試)
503 服務暫時不可用