错误与速率限制
Allswap API 的所有错误都会返回简洁 JSON 信封。error 字符串给机器处理;可选的 detail 和 upstream 字段用于定位 provider 侧失败。
错误信封
{
"error": "unknown originAsset/destinationAsset",
"detail": "originAsset or destinationAsset is not available in /v1/assets",
"upstream": {
"status": 404,
"path": "POST /aggregate/quotes"
}
}常见错误码
| 错误码 | HTTP | 含义 | 可以重试? |
|---|---|---|---|
origin not allowed | 403 | 请求 Origin 不在允许列表。 | 否 |
body too large | 413 | POST 请求体超过允许大小。 | 先修 |
unknown originAsset/destinationAsset | 400 | 某个 CAIP-19 资产 ID 不在可路由资产列表中。 | 先修 |
no provider supports this pair | 404 | 当前没有 provider 能路由这组 originAsset 到 destinationAsset。 | 否 |
amount_too_low | 400 | 低于该交易对的 provider 最小可交易金额。 | 先修 |
amount_too_high | 400 | 超过该交易对当前流动性上限。 | 先修 |
providerId required (route_A | route_B) | 400 | 创建订单需要传入报价预览中选定的 provider。 | 先修 |
missing txHash | 400 | 提交入金记录时必须提供源链交易哈希。 | 先修 |
order not found | 404 | 订单 ID 不存在,或当前调用方不可见。 | 否 |
order already in terminal state | 410 | 订单已经是 SUCCESS、REFUNDED 或 FAILED。 | 否 |
rate limit exceeded | 429 | 请求预算已耗尽。降低频率后再试。 | 退避 |
upstream timeout | 504 | 路由 provider 未在超时内响应。 | 退避 |
upstream error | 502 | 路由 provider 返回了非预期错误。 | 退避 |
internal error | 500 | Allswap 内部处理失败。联系支持时请附上响应详情。 | 退避 |
速率限制
每个密钥有两个限制:每分钟请求数(RPM,控制突发)和 每月报价次数(档位月配额)。具体档位数字见 定价页。
每条响应都包含当前 RPM 桶的状态:
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 248
X-RateLimit-Reset: 1718983261当你打到 0,下一次请求返回 429 rate_limited,带 Retry-After header(秒)。务必遵守。
重试策略
按类别推荐做法:
- 输入问题(
unknown originAsset/destinationAsset、providerId required、missing txHash):先修请求;重复提交同一 payload 只会浪费配额。 - 不支持的交易对:不要立即重试。刷新
/v1/assets或/v1/swappable-targets,仍不可用就从 UI 中移除该路线。 - 429 rate limit:等待后再试。用服务端节流,避免单个用户耗尽整个集成的共享预算。
- 5xx / upstream 失败:带抖动的指数退避。建议 base = 500ms、cap = 8s、最多重试 4 次。
- 订单终态:订单进入
SUCCESS、REFUNDED或FAILED后,新用户动作应创建新订单。
参考:退避伪代码
async function withRetry<T>(fn: () => Promise<T>): Promise<T> {
let attempt = 0;
while (true) {
try {
return await fn();
} catch (err: any) {
const code = err?.body?.error?.code;
const status = err?.status;
if (status === 429) {
const wait = Number(err.headers["retry-after"] ?? 1) * 1000;
await sleep(wait);
continue;
}
const retriable = code === "upstream_timeout" || code === "internal_error";
if (!retriable || attempt >= 4) throw err;
const base = Math.min(8000, 500 * 2 ** attempt);
const jitter = Math.random() * base * 0.3;
await sleep(base + jitter);
attempt++;
}
}
}
