EVM 链与账户
Sparky 在 EVM 链上结算。本页说明身份模型、登录方式,以及"每条链一套部署"对接入方意味着什么。
1. 支持的网络
| 网络 | Chain ID | 部署 | 备注 |
|---|---|---|---|
| Avalanche C-Chain | 43114 | 主网 | 主结算链 |
| Arbitrum One | 42161 | 主网 | |
| BNB Chain | 56 | 主网 | |
| Avalanche Fuji | 43113 | 测试网 | 测试 USDT,无实际价值 |
| Arbitrum Sepolia | 421614 | 测试网 | 测试 USDT,无实际价值 |
每个网络由独立的后端进程服务,有各自的 Base URL(见 Base URL)。部署所结算的链由其 CHAIN_ID / RPC_URL 配置固定,并体现在 GET /api/v1/auth/nonce/{address} 返回的 EIP-712 domain 中。
2. 账户身份 = EOA 地址
你在 Sparky 的账户就是你的钱包地址,没有单独的用户 ID:
- 余额、持仓、订单、API Key 与推荐数据都以小写 EOA 地址为键。
/fapi/v2/balance的accountAlias恒为"default"—— 一个钱包地址对应且仅对应一个账户。- 两套引擎(Orderly 网关与 Sparky 自研)使用同一 EOA;Orderly 侧按地址派生
account_id,自研侧直接鉴权。
按链隔离
因为每条链都是独立部署:
- **余额按链隔离。**充入 Avalanche Vault 只会记入你的 Avalanche 账户。
- **持仓与订单按链隔离。**没有跨链保证金。
- **API Key 按链隔离。**在你交易的每套部署上分别创建(每账户每部署最多 30 个)。
- 推荐码按链隔离。
想要统一身份,在各链使用同一私钥即可;后端从不把各部署关联起来。
3. 登录(EIP-712 → JWT)
原生 /api/v1/* 使用对 EIP-712 typed data 签名换取的 JWT。/fapi/* 不使用 JWT —— 它使用用 JWT 创建的 API Key(见 API Keys)。
客户端 ──① GET /api/v1/auth/nonce/{address} ──▶ nonce + typed_data
──② 用钱包对 typed_data 签名(链下)
──③ POST /api/v1/auth/login {address, signature, timestamp} ──▶ { token, expires_at }
3.1 获取 nonce 与 typed data
GET /api/v1/auth/nonce/{address}
{
"nonce": 1,
"typed_data": {
"types": {
"EIP712Domain": [
{ "name": "name", "type": "string" },
{ "name": "version", "type": "string" },
{ "name": "chainId", "type": "uint256" },
{ "name": "verifyingContract", "type": "address" }
],
"Login": [
{ "name": "wallet", "type": "address" },
{ "name": "nonce", "type": "uint256" },
{ "name": "timestamp", "type": "uint256" }
]
},
"domain": {
"name": "AXBlade",
"version": "1",
"chainId": 43114,
"verifyingContract": "0x0000000000000000000000000000000000000000"
},
"primaryType": "Login",
"message": {
"wallet": "0xYourWalletAddress",
"nonce": 1,
"timestamp": 1700000000
}
}
}
domain.name 是为签名兼容保留的历史标识;请始终从该响应读取 domain 而不要硬编码。chainId 即部署所在链。
3.2 签名
// ethers.js v6
const { types, domain, message } = typed_data;
const { EIP712Domain, ...signTypes } = types; // ethers 会自动加上 domain 类型
const signature = await signer.signTypedData(domain, signTypes, message);
3.3 换取 JWT
POST /api/v1/auth/login
Content-Type: application/json
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
address | string | 是 | 钱包地址 |
signature | string | 是 | 0x 开头的 EIP-712 签名 |
timestamp | number | 是 | 必须等于 typed_data.message.timestamp(Unix 秒);与服务器时间相差超过 300 秒返回 TIMESTAMP_EXPIRED |
{ "token": "eyJhbGciOiJIUzI1NiIs...", "expires_at": 1700086400 }
之后每个 /api/v1/* 请求携带 Authorization: Bearer <token>;expires_at 过后重新登录。
3.4 Privy 内嵌钱包
Sparky Web 端采用基于 Privy 的产品模型:用户以邮箱、Google 或外部钱包登录,Privy 生成内嵌 EOA,前端用 Privy access token 通过 POST /api/v1/auth/privy-login 换取 Sparky JWT。对这类会话,下单、撤单、TP/SL 与平仓只由 JWT 授权 —— 请求体里的 signature 字段是为兼容保留的历史字段,Privy 会话不再依赖它。
程序化接入方通常跳过 Privy,直接用上面的 EIP-712 流程登录,再为 /fapi 创建 API Key。
4. 该用哪套接口
| 你是… | 使用 | 鉴权 |
|---|---|---|
| 机器人 / 做市商 / SDK 用户 | /fapi/v1/*、/fapi/v2/*、/futures/data/* | X-MBX-APIKEY + HMAC-SHA256 |
| 需要充提或推荐的前端 / 脚本 | /api/v1/* | Authorization: Bearer <JWT> |
| 只读公开行情 | /fapi/v1/* 或 /api/v1/markets/* 均可 | 无 |
API Key 不能提现。提现与推荐操作始终需要钱包派生的 JWT。