帳戶端點¶
取得餘額¶
取得帳戶的錢包和 Vault 合併餘額。
身份驗證: 需要 API Key
查詢參數¶
| 參數 | 類型 | 必填 | 說明 |
|---|---|---|---|
owner_address | address | 是 | 必須與已驗證的 API key 擁有者相符 |
include_zero | boolean | 否 | 預設 false:過濾普通零餘額記錄,但保留有恢復、同步或限制狀態的零餘額記錄。true 包含全部白名單代幣。 |
回應¶
{
"owner_address": "0x...",
"balances": [
{
"token": "0x965d4b4546716e416e950bc30467d128455d2d0e",
"symbol": "USDC",
"decimals": 6,
"wallet_balance": "1250000000",
"vault_available": "400000000",
"vault_frozen": "100000000",
"vault_total": "500000000",
"total": "1750000000",
"chain_verified": null,
"spendability_status": null,
"restriction_reason": null,
"recovery_status": null,
"projection_present": null,
"recovery_version": null,
"balance_sync_hint": null,
"coverage_block_number": null,
"coverage_block_hash": null,
"coverage_checked_at": null,
"verification_status": null,
"generation": null,
"snapshot_block_number": null,
"snapshot_block_hash": null,
"snapshot_policy_digest": null,
"projection_updated_at": null,
"vault_spendable": null
}
],
"updated_at": "2026-04-15T09:12:34.567890+00:00",
"wallet_balance_available": true,
"vault_balance_available": true
}
| 欄位 | 類型 | 說明 |
|---|---|---|
token | address | ERC-20 合約地址 |
symbol | string | 代幣代號 |
decimals | integer | 該代幣的精度,用於將原始字串轉成人類可讀值 |
wallet_balance | string | 使用者錢包餘額(原始 uint256 十進位字串) |
vault_available | string | 已提交帳務的可用餘額,不一定可花(原始 uint256 字串)。 |
vault_frozen | string | Vault 中凍結在未完成訂單中的餘額(原始 uint256 十進位字串) |
vault_total | string | vault_available + vault_frozen |
total | string | wallet_balance + vault_total |
wallet_balance_available | boolean | 如果錢包餘額 RPC 呼叫失敗則為 false |
金額欄位為原始 uint256 十進位字串,使用 decimals 換算;可花資格與鏈上觀察可用性需要分別判斷。
可交易金額與恢復狀態¶
vault_spendable 非 null 時表示本次回傳的可花金額。vault_available 是已提交帳務中的可用金額;恢復或限制期間它可以大於零,而 vault_spendable 為 "0"。餘額讀取不授權下單,最終准入仍會重新檢查資格。舊版餘額模式下新增的逐資產狀態欄位可以為 null;不能把 null 當成零或資格證明。
| 欄位 | 類型 | 含義 |
|---|---|---|
vault_spendable | string / null | 資格檢查後的原始可花金額;帳務餘額為正時仍可能為零。 |
spendability_status | string / null | 可花資格狀態,包括 ready、local_covered、restricted、sync_required、current_coverage_required。 |
restriction_reason | string / null | 限制原因;未回報原因時為 null。 |
recovery_status | string / null | 恢復狀態,包括 ready、pending、draining、recovering、proven、blocked。 |
projection_present | boolean / null | 是否存在該資產的已提交帳務投影。 |
recovery_version | string / null | 不透明恢復版本;同步時傳入目前值。 |
balance_sync_hint | string / null | none:未觀察到差異;check_required:鏈上與帳務有差異;unknown:缺少新鮮鏈上觀察。它不是花費授權。 |
coverage_block_number / coverage_block_hash | integer / string / null | 目前覆蓋證據的區塊識別。 |
coverage_checked_at | string / null | 覆蓋核驗的 ISO 時間;讀取快取不會延長此證明的有效期。 |
verification_status | string / null | 帳務快照驗證狀態,例如 verified 或 unverified;不能單獨決定可否花費。 |
generation | integer / null | 帳務快照代次。 |
snapshot_block_number / snapshot_block_hash | integer / string / null | 帳務快照對應的區塊識別。 |
snapshot_policy_digest | string / null | 快照關聯的策略摘要。 |
projection_updated_at | string / null | 帳務投影更新的 ISO 時間;不是鏈頂或本次核驗時間。 |
外層 vault_balance_available 表示 Vault 鏈上觀察是否可用且新鮮,即使 balances=[] 也有意義;它不同於快照 verification_status。local_covered 行可能已有可花金額,但歷史 verification_status="unverified"。projection_updated_at 不代表證明的新鮮度。遇到未知狀態應重新整理,不能假定資金可花。
例如 vault_available="400000000"、vault_spendable="0"、spendability_status="restricted"、recovery_status="recovering" 可以同時成立。恢復狀態為 pending/draining/recovering/proven/blocked、資格為 restricted/sync_required/current_coverage_required、balance_sync_hint="check_required",或已有投影且同步提示為 unknown 時,零餘額行仍會保留。恢復流程見餘額同步。
範例¶
import requests
balances = requests.get(
"https://api.testnet.sera.cx/api/v1/balances",
params={"owner_address": "0x..."},
headers={"Authorization": "Bearer sera_key:secret"},
timeout=10,
).json()["balances"]
for bal in balances:
print(f"{bal['symbol']}: available={bal['vault_available']}, frozen={bal['vault_frozen']}")
const response = await fetch(
"https://api.testnet.sera.cx/api/v1/balances?owner_address=0x...",
{ headers: { "Authorization": "Bearer sera_key:secret" } },
);
const { balances } = await response.json();
for (const bal of balances) {
console.log(`${bal.symbol}: available=${bal.vault_available}, frozen=${bal.vault_frozen}`);
}
請求餘額同步¶
身份驗證: 需要 API Key,owner_address 必須屬於該 Key。先讀取 GET /api/v1/config → capabilities.balances.sync_enabled。這是帳務同步請求,不是充值或付款。
請求¶
{
"owner_address": "0x1111111111111111111111111111111111111111",
"token_address": "0x965d4b4546716e416e950bc30467d128455d2d0e",
"expected_recovery_version": null
}
owner_address 與 token_address 為 0x 前綴的 20 位元組十六進位地址字串,會正規化為小寫。三個欄位均必填,拒絕額外欄位。先查詢餘額,將該資產的 recovery_version 作為 expected_recovery_version:沒有版本時明確傳 null,否則傳 64 位小寫十六進位字串。不能省略或自行產生版本。
回應¶
HTTP 202:
{
"status": "queued",
"recovery_status": "pending",
"recovery_version": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
status 為 queued 或 already_pending;recovery_status 為 pending、draining、recovering 或 proven。輪詢 GET balances 查看進度和可花資格;202 與 proven 本身不授權交易。不要為解決同步延遲而重複充值。
| HTTP | detail.code / 處理 |
|---|---|
| 400 | unknown_token:使用登錄表中的代幣 |
| 409 | balance_sync_unavailable:目前部署不接受同步 |
| 409 | balance_recovery_blocked:查看回傳原因及餘額狀態,不要盲目重試 |
| 409 | balance_sync_version_changed:重新查詢餘額,再決定是否用目前版本重試 |
錯誤可能帶可為空的 detail.recovery_version 與 detail.reason:vault_below_frozen、frozen_reservation_differs、chain_event_conflict、chain_snapshot_integrity_error 或 account_recovery_blocked。還需處理 401/403、422、429 和通用 503。屬於 transfer 限流組(目前 2 req/s)。回應未知時先查詢餘額再重試;完成對帳前保留已提交版本。
充值輔助端點¶
請先透過 GET /config 取得目前的 vault_address 與 sor_address。現在的充值流程使用三個輔助端點:
- 若不使用 permit,先呼叫
POST /approve建構 ERC-20 授權交易。 - 呼叫
POST /deposit建構depositFund(...)或depositFundWithPermit(...)。 - 本地簽名後,透過
POST /tx/send廣播授權或充值交易。
如果代幣支援 EIP-2612,您可以在 POST /deposit 中直接傳入 permit_signature 與 permit_deadline,從而跳過單獨的授權交易。若需要在客戶端探測 permit 能力,請使用 GET /permit/metadata。
充值與提款可用性¶
顯示操作前讀取 /config:capabilities.deposits.enabled、.deposits.restriction_reason、.withdrawals.instant_enabled 與 .balances.sync_enabled。充值記帳暫停時,/deposit 及 /tx/send 的充值分支回傳 409、detail.code="deposit_accounting_paused",包括已簽名但尚未廣播的充值。不要建立另一筆充值,應等待能力恢復。此守衛不表示 /tx/send 的 approve 分支也被同樣拒絕。
建構充值交易¶
身份驗證: 需要 API Key
請求主體¶
{
"token": "0x965d4b4546716e416e950bc30467d128455d2d0e",
"owner": "0x...",
"amount": "1000000000",
"permit_signature": "0x...",
"permit_deadline": 1713254400,
"permit_amount": "1000000000"
}
| 欄位 | 類型 | 必填 | 說明 |
|---|---|---|---|
token | address | 是 | 要充值的 ERC-20 代幣地址 |
owner | address | 是 | 充值人地址,必須與已驗證 API Key 的擁有者相符 |
amount | string | 是 | 原始 uint256 代幣數量 |
permit_signature | hex string | 否 | 用於內聯授權的 EIP-2612 permit 簽名;支援標準 65 位元組與緊湊 64 位元組兩種十六進位編碼 |
permit_deadline | integer | 否 | permit 中簽名使用的截止時間 |
permit_amount | string | 否 | permit 的原始授權額度;省略時預設等於 amount |
未提供 permit 欄位時,建構器會產生 depositFund(token, owner, amount);提供 permit 欄位時,則會改為產生 depositFundWithPermit(...)。
回應¶
{
"tx": {
"to": "0x83475A1bD98a8DC2DCd507A747e4DC85da241D6e",
"data": "0x...",
"value": "0x0",
"chainId": "0xaa36a7",
"nonce": "0x2b",
"gas": "0x13880",
"type": "0x2",
"maxFeePerGas": "0x...",
"maxPriorityFeePerGas": "0x..."
}
}
建構授權交易¶
身份驗證: 需要 API Key
請求主體¶
{
"token": "0x965d4b4546716e416e950bc30467d128455d2d0e",
"owner": "0x...",
"spender": "0x3c7945840bAE0d7e7f3824Ebccef1962629250F0",
"amount": "1000000000"
}
spender 只能是 GET /config 回傳的即時 Vault 或 SOR 地址;其他目標都會被拒絕。
回應¶
{
"tx": {
"to": "0x965d4b4546716e416e950bc30467d128455d2d0e",
"data": "0x...",
"value": "0x0",
"chainId": "0xaa36a7",
"nonce": "0x2a",
"gas": "0xc350",
"type": "0x2",
"maxFeePerGas": "0x...",
"maxPriorityFeePerGas": "0x..."
}
}
廣播已簽名的授權或充值交易¶
身份驗證: 需要 API Key
請求主體¶
回應¶
POST /tx/send 只接受函式選擇器與目標地址組合位於允許清單內的已簽名授權 / 充值交易。
對於 approve,編碼後的 spender 還必須是 GET /config 回傳的即時 Vault 或 SOR 地址。如果提交的是 EIP-7702 的 type-4 交易,則每個授權 delegate 都必須位於當前部署的允許清單內,否則請求會被拒絕。
提取(共簽名)¶
請求伺服器共簽名以進行即時提取。Sera 的智慧合約要求即時提取需要兩個簽名 — 您的簽名和伺服器的簽名 — 以防止未經授權的提取。這是一個三步驟流程:取得共簽名、建構交易、然後廣播。
第一步:取得伺服器共簽名¶
身份驗證: EIP-712 WithdrawIntent 簽名
請求主體¶
{
"intent": {
"user": "0x...",
"tokens": ["0x965d4b4546716e416e950bc30467d128455d2d0e"],
"amounts": ["1000000000"],
"recipient": "0x...",
"deadline": "1704153600",
"uuid": "123456789"
},
"user_signature": "0x..."
}
| 欄位 | 類型 | 說明 |
|---|---|---|
intent.user | address | 提取使用者的錢包 |
intent.tokens | address[] | 要提取的代幣地址(1-20) |
intent.amounts | string[] | 每種代幣的金額(原始單位) |
intent.recipient | address | 代幣接收地址 |
intent.deadline | string | Unix 秒數的 uint256 字串。POST /withdraw 要求在未來且最多領先 600 秒;請讀取 GET /config 的 limits.withdraw.cosignature_max_ttl_seconds。 |
intent.uuid | string | 用於防止重放的唯一識別碼(uint256 字串) |
user_signature | string | EIP-712 WithdrawIntent 簽名 |
tokens 與 amounts 長度必須相等,且包含 1 至 20 項;每個 amount 必須為正 uint256 字串。
回應¶
第二步:建構提取交易¶
身份驗證: 可選
請求主體¶
{
"intent": {
"user": "0x...",
"tokens": ["0x965d4b4546716e416e950bc30467d128455d2d0e"],
"amounts": ["1000000000"],
"recipient": "0x...",
"deadline": "1704153600",
"uuid": "123456789"
},
"user_signature": "0x...",
"executor": "0x...",
"executor_signature": "0x..."
}
| 欄位 | 類型 | 說明 |
|---|---|---|
intent | object | 與第一步相同的 WithdrawIntent |
user_signature | string | 您的 EIP-712 簽名 |
executor | address | 第一步回應中的聯合簽名地址 executor_address |
executor_signature | string | 第一步取得的伺服器共簽名 |
回應¶
{
"tx": {
"to": "0x...",
"data": "0x...",
"value": "0x0",
"chainId": "0xaa36a7",
"nonce": "0x2c",
"gas": "0x249f0",
"type": "0x2",
"maxFeePerGas": "0x...",
"maxPriorityFeePerGas": "0x..."
}
}
第三步:廣播已簽名交易¶
身份驗證: 可選
請求主體¶
回應¶
POST /withdraw/send 只接受呼叫 executeInstantWithdrawDualSig(...) 且目標合約為來自 GET /config 的當前 Sera 合約地址的已簽名交易。如果提交的是 EIP-7702 的 type-4 交易,則每個授權 delegate 都必須位於當前部署的允許清單內,否則請求會被拒絕。
使用錢包簽署第二步的交易,然後將已簽名的十六進位提交到此端點。
緊急提取¶
API 不可用時,可使用 Sera 的鏈上兩步流程:
- 調用
emergencyWithdraw(token, amount)發起請求,金額須為正且不超過當前 Vault 餘額。 - 至少等待 7,200 個區塊(按每塊 12 秒估算約 24 小時)。
- 在請求區塊 + 7,200 至 + 14,400(含邊界)執行,使用相同代幣及
0 < amount <= 請求金額,當前餘額仍須足夠。 - 成功後會刪除整個請求,即使只提取部分金額。超過 14,400 區塊窗口後,再次調用會創建新請求並重新等待。
完整規則見 Sera.sol 合約參考。
ERC-20 轉帳¶
無需自己的 RPC 連線即可建構和廣播 ERC-20 代幣轉帳。僅接受 /tokens 註冊表中列出的代幣。
建構轉帳¶
身份驗證: 需要 API Key
請求主體¶
{
"token": "0x965d4b4546716e416e950bc30467d128455d2d0e",
"to": "0x...",
"amount": "1000000000",
"from_address": "0x..."
}
| 欄位 | 類型 | 必填 | 說明 |
|---|---|---|---|
token | address | 是 | ERC-20 代幣合約地址(必須在代幣註冊表中) |
to | address | 是 | 接收者地址 |
amount | string | 是 | 以原始代幣單位表示的金額 |
from_address | address | 是 | 發送者錢包地址 |
回應¶
{
"tx": {
"to": "0x...",
"data": "0x...",
"value": "0x0",
"chainId": "0xaa36a7",
"nonce": "0x2d",
"gas": "0xea60",
"type": "0x2",
"maxFeePerGas": "0x...",
"maxPriorityFeePerGas": "0x..."
}
}
廣播轉帳¶
身份驗證: 需要 API Key
請求主體¶
| 欄位 | 類型 | 必填 | 說明 |
|---|---|---|---|
raw_tx | string | 是 | 已簽名的交易十六進位(0x 前綴) |
回應¶
餘額覈驗與提款錯誤¶
chain_verified=true 描述舊版模式對快取 Vault 金額的鏈上糾正,不能概括已提交帳務的驗證狀態;請結合上方狀態欄位。null 不代表剛完成核驗。分別檢查 wallet_balance_available、vault_balance_available 與 updated_at。
GET /api/v2/balances 是相同查詢參數與回應的別名。所有餘額金額均爲 raw 整數字串。
POST /withdraw 同時回傳 executor_address 和 executor_signature,構建 /withdraw/build 時必須把該地址作爲 executor 傳入。聯合簽名截止時間最多領先 600 秒,即使通用簽名意圖模型允許更長時間。409 且 detail.error_code="WITHDRAW_UNAVAILABLE" 表示即時提款准入拒絕,請刷新餘額/訂單後再決定是否重試。受保護賬戶操作還可能回傳 COMPLIANCE_BLOCKED。
交易簽名與廣播規則¶
POST /transfer要求from_address與 API Key 所有者一致。/transfer/send只接受向已登記代幣合約調用transfer(...),原始交易簽名者也必須是該所有者。/tx/send同樣要求外層交易簽名者與 API Key 所有者一致;充值 calldata 中的 owner 也必須一致。充值 permit 在廣播前會重新檢查代幣、Vault spender、金額、當前 nonce 與 deadline;過時的 permit 需要重新獲取元數據並簽名。/withdraw/send要求原始交易簽名者等於intent.user,不能替換爲第三方付費者。若攜帶 API Key,所有者也必須一致。廣播前會再次篩查用戶與接收方。- 構建接口回傳未簽名交易。回傳
tx_hash表示提交給 RPC,不表示已成功打包或餘額已最終變化;請檢查交易收據並刷新餘額。