跳轉至

訂單生命週期

本教學將帶您了解 Sera 上限價單的完整生命週期 — 從下單到領取收益。

概覽

sequenceDiagram
    participant User
    participant API as Sera API
    participant Chain as Ethereum

    User->>API: POST /orders (signed order)
    API-->>User: order_id
    Note over API: Order is matched<br/>when counterparty found
    API->>Chain: Settlement on-chain
    User->>API: GET /orders/{id}
    API-->>User: Status: settled
    Note over User: Proceeds available<br/>in vault balance

步驟一:檢查伺服器時間

在建立簽名之前,與伺服器時鐘同步以避免到期問題:

const timeRes = await fetch('https://api.sera.cx/api/v1/system/time');
const { timestamp } = await timeRes.json();
console.log('Server time:', timestamp);
import requests

time_res = requests.get("https://api.sera.cx/api/v1/system/time")
server_time = time_res.json()["timestamp"]
print(f"Server time: {server_time}")

所有已簽名訂單都必須帶 expiration,而且 API 會強制執行 now < expiration <= now + 365 天 - 300 秒。請使用伺服器時間,而不是只依賴瀏覽器或本地系統時鐘。

步驟二:查詢可用代幣

取得支援的代幣清單以找到您需要的合約地址:

const tokensRes = await fetch('https://api.sera.cx/api/v1/tokens');
const { tokens } = await tokensRes.json();

// 查找 USDC 和 EURC 地址
const usdc = tokens.find(t => t.symbol === 'USDC');
const eurc = tokens.find(t => t.symbol === 'EURC');

步驟三:掛限價單

建構並簽署 EIP-712 Order,然後提交:

import { ethers } from 'ethers';
import { v4 as uuidv4 } from 'uuid';

// Generate a unique order ID
const orderId = uuidv4();
const { executor_id: executorId } = await fetch('https://api.sera.cx/api/v1/health')
  .then(r => r.json());
const rawOrderId = BigInt(`0x${orderId.replace(/-/g, '')}`);
const groupId = rawOrderId >> 16n;
const uuidInt = ((BigInt(executorId) << 252n) | (rawOrderId << 124n) | (groupId << 12n)).toString();

// 構造訂單。from_address 是市場基礎代幣,to_address 是報價代幣。
// 最終支出哪一邊由 side 決定。
const order = {
  owner_address: walletAddress,
  side: 'bid',                // Buy EURC with USDC
  amount: '1000.0',           // 1000 EURC
  price: '1.085',             // At 1.085 USDC per EURC
  order_type: 'limit',
  from_address: EURC_ADDRESS, // 市場基礎代幣,也是您要買入的代幣
  to_address: USDC_ADDRESS,   // 市場報價代幣,在 bid 中是您支出的代幣
  order_id: orderId,
  uuid_int: uuidInt,
  expiration: Math.floor(Date.now() / 1000) + 86400,  // 24 hours
};

// Sign with EIP-712 (see Authentication docs for full signing details)
const signature = await signOrder(signer, order);

// Submit the order
const response = await fetch('https://api.sera.cx/api/v1/orders', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ ...order, signature })
});

const result = await response.json();
console.log('Order placed:', result.order_id);

步驟四:監控訂單狀態

使用您的 API key 輪詢訂單狀態:

const statusRes = await fetch(
  `https://api.sera.cx/api/v1/orders/${orderId}`,
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY:YOUR_API_SECRET' } }
);

const status = await statusRes.json();
console.log('Status:', status.status);
// 外部狀態:"pending"、"matched"、"settled"、"cancelled"、"failed"
console.log('Filled:', status.filled_amount);
console.log('Signed uuid_int:', status.uuid_int);

步驟五:查詢餘額

訂單結算後,收益會出現在您的 Vault 餘額中:

const balanceRes = await fetch(
  'https://api.sera.cx/api/v1/balances?owner_address=' + walletAddress,
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY:YOUR_API_SECRET' } }
);

const balances = await balanceRes.json();
for (const bal of balances.balances) {
  console.log(`${bal.symbol}: vault_raw=${bal.vault_available}, frozen_raw=${bal.vault_frozen}, decimals=${bal.decimals}`);
}

GET /balances 現在回傳原始 uint256 十進位字串。顯示給使用者前,請搭配每一行的 decimals 欄位自行轉換。

步驟六:取消訂單(可選)

如果您想取消未成交或部分成交的訂單:

// Sign a CancelOrder message
const cancelSignature = await signCancelOrder(signer, walletAddress, status.uuid_int);

const cancelRes = await fetch('https://api.sera.cx/api/v1/orders/cancel', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    owner_address: walletAddress,
    order_id: orderId,
    uuid_int: status.uuid_int,
    signature: cancelSignature
  })
});

console.log('Cancelled:', await cancelRes.json());

Note

所有使用者都受 5 分鐘冷卻期限制 — 訂單必須至少存在 5 分鐘後才能取消。

步驟七:提取(可選)

將資金從 Vault 轉回錢包時,請使用即時提取流程:

  1. 呼叫 POST /withdraw 取得執行者聯簽。
  2. 呼叫 POST /withdraw/build 取得未簽名的 executeInstantWithdrawDualSig 交易。
  3. 在本地簽署該交易,然後透過 POST /withdraw/send 廣播。

如果 API 不可用,您仍可回退到鏈上的 emergencyWithdraw() 流程。

虛擬流動性訂單

VL 訂單的生命週期與標準限價單相同,但共用預算管理。當某個 VL 同胞訂單成交時,撮合引擎會自動修改或取消其餘同胞訂單,以維持在預算內。

主要差異:

  • 掛單 — 使用 POST /orders/vl/batch 取代 POST /orders
  • 取消 — 使用 POST /orders/vl/cancel 取消整批,或使用 POST /orders/cancel 取消單筆同胞訂單
  • 預算追蹤 — 系統在所有同胞訂單間追蹤共用的凍結餘額;任一同胞成交會減少其他同胞可用預算

完整指南請參見 虛擬流動性

訂單狀態摘要

狀態 含義 可取消?
pending 已提交、掛單中或部分成交
matched 所有腿在撮合引擎中已交叉,鏈上結算進行中
settled 已完全成交且鏈上確認
cancelled 已在完全成交前取消
failed 被拒絕或結算 revert 通常否;查看 errorerror_code

pending 可以表示尚未成交、部分成交後仍有剩餘數量,或已提交但尚未進入鏈上結算的訂單。前端應結合 filled_amountremaining_amountsettlement_summary/fills 以及 settlement_economics 判斷使用者資金變化。公共 API 不暴露協議價差收入或交易對手轉帳拆分。