跳到主要内容

WebSocket API

Version: v1.0 Last Updated: 2026-01-06

概述

AXBlade 通过 WebSocket 连接提供实时数据流。WebSocket API 支持公开频道(市场数据)和私有频道(用户数据)。


连接 URL

环境WebSocket URL
主网wss://api.axblade.io/ws
测试网wss://testnet.axblade.io/ws
本地开发ws://localhost:8080/ws

消息格式

所有消息均为 JSON 格式。

客户端 → 服务器消息

interface ClientMessage {
type: string;
[key: string]: any;
}

服务器 → 客户端消息

interface ServerMessage {
type: string;
[key: string]: any;
}

认证

私有频道需要认证。支持两种方式:

方式 1: JWT Token

{
"type": "auth",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

或使用专用的 auth_token 消息:

{
"type": "auth_token",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

方式 2: EIP-712 签名

{
"type": "auth",
"address": "0xYourWalletAddress",
"signature": "0x...",
"timestamp": 1704067200
}

EIP-712 签名结构:

const types = {
WebSocketAuth: [
{ name: "wallet", type: "address" },
{ name: "timestamp", type: "uint256" }
]
};

const message = {
wallet: address.toLowerCase(),
timestamp: Math.floor(Date.now() / 1000)
};

认证响应

{
"type": "auth_result",
"success": true,
"message": null
}

失败时:

{
"type": "auth_result",
"success": false,
"message": "Invalid or expired token"
}

订阅

订阅频道

{
"type": "subscribe",
"channel": "ticker:HYPEUSDT"
}

私有频道可以包含 JWT token:

{
"type": "subscribe",
"channel": "positions",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

取消订阅

{
"type": "unsubscribe",
"channel": "ticker:HYPEUSDT"
}

订阅响应

{
"type": "subscribed",
"channel": "ticker:HYPEUSDT"
}

公开频道

Ticker 频道

实时价格和市场统计。

订阅:

{"type": "subscribe", "channel": "ticker:HYPEUSDT"}

消息:

{
"type": "ticker",
"symbol": "HYPEUSDT",
"last_price": "25.45",
"mark_price": "25.44",
"index_price": "25.43",
"price_change_24h": "0.50",
"price_change_percent_24h": "2.00",
"high_24h": "26.00",
"low_24h": "24.50",
"volume_24h": "1000000.00",
"volume_24h_usd": "25450000.00",
"open_interest_long": "5000000",
"open_interest_short": "4500000",
"open_interest_long_percent": "53",
"open_interest_short_percent": "47",
"available_liquidity_long": "1000000",
"available_liquidity_short": "950000",
"funding_rate_long_1h": "-0.0010%",
"funding_rate_short_1h": "+0.0010%"
}

更新间隔: 每 2 秒


Orderbook 频道

实时订单簿深度更新。

订阅:

{"type": "subscribe", "channel": "orderbook:HYPEUSDT"}

消息:

{
"type": "orderbook",
"symbol": "HYPEUSDT",
"bids": [
{"price": "25.45", "size": "100.5"},
{"price": "25.44", "size": "200.3"}
],
"asks": [
{"price": "25.46", "size": "150.2"},
{"price": "25.47", "size": "180.1"}
],
"timestamp": 1704067200000
}

更新间隔: 每 500ms(或有变化时)


Trades 频道

实时成交执行。

订阅:

{"type": "subscribe", "channel": "trades:HYPEUSDT"}

消息:

{
"type": "trade",
"id": "1704067200000-abc123",
"symbol": "HYPEUSDT",
"price": "25.45",
"amount": "10.5",
"side": "buy",
"timestamp": 1704067200000
}

更新: 实时(每笔成交)


K 线频道

实时 K 线数据。

订阅:

{"type": "subscribe", "channel": "kline:HYPEUSDT:1m"}

支持的周期:

  • 1m - 1 分钟
  • 5m - 5 分钟
  • 15m - 15 分钟
  • 30m - 30 分钟
  • 1h - 1 小时
  • 4h - 4 小时
  • 1d - 1 天

初始快照:

{
"type": "kline_snapshot",
"channel": "kline:HYPEUSDT:1m",
"data": {
"time": 1704067200,
"open": "25.40",
"high": "25.50",
"low": "25.38",
"close": "25.45",
"volume": "1000.5",
"quote_volume": "25450.75",
"trade_count": 150,
"is_final": true
}
}

更新消息:

{
"type": "kline",
"channel": "kline:HYPEUSDT:1m",
"data": {
"time": 1704067260,
"open": "25.45",
"high": "25.48",
"low": "25.44",
"close": "25.47",
"volume": "500.2",
"is_final": false
}
}

私有频道

私有频道需要认证。

Positions 频道

实时仓位更新。

订阅:

{"type": "subscribe", "channel": "positions"}

消息:

{
"type": "position",
"id": "550e8400-e29b-41d4-a716-446655440000",
"symbol": "HYPEUSDT",
"side": "long",
"size": "10.0",
"entry_price": "25.50",
"mark_price": "26.00",
"liquidation_price": "23.10",
"unrealized_pnl": "5.00",
"leverage": 10,
"margin": "25.50",
"updated_at": 1704067200000,
"event": "updated"
}

事件类型:

  • opened - 新仓位开启
  • updated - 仓位修改
  • closed - 仓位关闭
  • liquidated - 仓位清算

更新间隔: 每 5 秒 + 变化时实时推送


Orders 频道

实时订单更新。

订阅:

{"type": "subscribe", "channel": "orders"}

消息:

{
"type": "order",
"id": "550e8400-e29b-41d4-a716-446655440000",
"symbol": "HYPEUSDT",
"side": "buy",
"order_type": "limit",
"price": "25.50",
"amount": "10.0",
"filled_amount": "5.0",
"status": "partially_filled",
"updated_at": 1704067200000,
"event": "filled"
}

事件类型:

  • created - 订单创建
  • filled - 订单(部分)成交
  • cancelled - 订单取消

Balance 频道

实时余额更新。

订阅:

{"type": "subscribe", "channel": "balance"}

消息:

{
"type": "balance",
"token": "0x572E474C3Cf364D085760784F938A1Aa397a8B9b",
"symbol": "USDT",
"available": "1000.00",
"frozen": "100.00",
"total": "1100.00"
}

更新间隔: 每 5 秒 + 变化时实时推送


心跳

Ping/Pong

发送周期性 ping 消息保持连接:

客户端 Ping:

{"type": "ping"}

服务器 Pong:

{"type": "pong"}

服务器也响应 WebSocket 协议级别的 ping 帧。


错误消息

{
"type": "error",
"code": "AUTH_REQUIRED",
"message": "Authentication required for private channels"
}

错误码:

错误码描述
INVALID_MESSAGE解析 JSON 消息失败
AUTH_REQUIRED私有频道需要认证
INVALID_SIGNATUREEIP-712 签名验证失败
TIMESTAMP_EXPIRED认证时间戳过期 (5分钟有效期)
INVALID_CHANNEL未知频道格式

交易对标准化

WebSocket API 支持多种交易对格式:

输入格式标准化后
HYPEUSDTHYPEUSDT
HYPE-USDHYPEUSDT
HYPE-USDTHYPEUSDT
hypeusdtHYPEUSDT
HYPE/USDHYPEUSDT

连接限制

限制
每连接最大订阅数10
消息频率限制100 条/秒
连接超时30 秒(有心跳时)

TypeScript 示例

class AXBladeWebSocket {
private ws: WebSocket;
private jwtToken: string;
private subscriptions: Set<string> = new Set();

constructor(url: string, jwtToken: string) {
this.jwtToken = jwtToken;
this.ws = new WebSocket(url);
this.setupHandlers();
}

private setupHandlers() {
this.ws.onopen = () => {
console.log('已连接');
this.authenticate();
};

this.ws.onmessage = (event) => {
const message = JSON.parse(event.data);
this.handleMessage(message);
};

this.ws.onerror = (error) => {
console.error('WebSocket 错误:', error);
};

this.ws.onclose = () => {
console.log('已断开');
};
}

private authenticate() {
this.send({
type: 'auth_token',
token: this.jwtToken
});
}

private handleMessage(message: any) {
switch (message.type) {
case 'auth_result':
if (message.success) {
console.log('认证成功');
this.resubscribe();
} else {
console.error('认证失败:', message.message);
}
break;
case 'subscribed':
console.log('已订阅:', message.channel);
break;
case 'ticker':
console.log('行情:', message.symbol, message.last_price);
break;
case 'orderbook':
console.log('订单簿:', message.symbol, message.bids.length, 'bids');
break;
case 'trade':
console.log('成交:', message.symbol, message.price, message.amount);
break;
case 'position':
console.log('仓位:', message.symbol, message.side, message.unrealized_pnl);
break;
case 'order':
console.log('订单:', message.id, message.status);
break;
case 'balance':
console.log('余额:', message.symbol, message.available);
break;
case 'kline':
console.log('K线:', message.channel, message.data.close);
break;
case 'error':
console.error('错误:', message.code, message.message);
break;
}
}

subscribe(channel: string) {
this.subscriptions.add(channel);
this.send({ type: 'subscribe', channel });
}

unsubscribe(channel: string) {
this.subscriptions.delete(channel);
this.send({ type: 'unsubscribe', channel });
}

private resubscribe() {
for (const channel of this.subscriptions) {
this.send({ type: 'subscribe', channel });
}
}

private send(message: object) {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(message));
}
}

// 心跳
startHeartbeat(intervalMs: number = 15000) {
setInterval(() => {
this.send({ type: 'ping' });
}, intervalMs);
}

close() {
this.ws.close();
}
}

// 使用示例
const ws = new AXBladeWebSocket('wss://api.axblade.io/ws', jwtToken);

// 订阅公开频道
ws.subscribe('ticker:HYPEUSDT');
ws.subscribe('orderbook:HYPEUSDT');
ws.subscribe('trades:HYPEUSDT');
ws.subscribe('kline:HYPEUSDT:1m');

// 订阅私有频道(需要认证)
ws.subscribe('positions');
ws.subscribe('orders');
ws.subscribe('balance');

// 启动心跳
ws.startHeartbeat();

React Hook 示例

import { useEffect, useRef, useState, useCallback } from 'react';

interface TickerData {
symbol: string;
last_price: string;
price_change_percent_24h: string;
volume_24h_usd: string;
}

export function useAXBladeWebSocket(jwtToken: string | null) {
const ws = useRef<WebSocket | null>(null);
const [connected, setConnected] = useState(false);
const [authenticated, setAuthenticated] = useState(false);
const [ticker, setTicker] = useState<TickerData | null>(null);

const connect = useCallback(() => {
ws.current = new WebSocket('wss://api.axblade.io/ws');

ws.current.onopen = () => {
setConnected(true);
if (jwtToken) {
ws.current?.send(JSON.stringify({
type: 'auth_token',
token: jwtToken
}));
}
};

ws.current.onmessage = (event) => {
const message = JSON.parse(event.data);

if (message.type === 'auth_result') {
setAuthenticated(message.success);
} else if (message.type === 'ticker') {
setTicker(message);
}
};

ws.current.onclose = () => {
setConnected(false);
setAuthenticated(false);
};
}, [jwtToken]);

const subscribe = useCallback((channel: string) => {
if (ws.current?.readyState === WebSocket.OPEN) {
ws.current.send(JSON.stringify({ type: 'subscribe', channel }));
}
}, []);

const unsubscribe = useCallback((channel: string) => {
if (ws.current?.readyState === WebSocket.OPEN) {
ws.current.send(JSON.stringify({ type: 'unsubscribe', channel }));
}
}, []);

useEffect(() => {
connect();
return () => {
ws.current?.close();
};
}, [connect]);

return {
connected,
authenticated,
ticker,
subscribe,
unsubscribe
};
}

// 组件中使用
function TradingView() {
const { connected, ticker, subscribe } = useAXBladeWebSocket(jwtToken);

useEffect(() => {
if (connected) {
subscribe('ticker:HYPEUSDT');
}
}, [connected, subscribe]);

return (
<div>
{ticker && (
<div>
<span>{ticker.symbol}</span>
<span>${ticker.last_price}</span>
<span>{ticker.price_change_percent_24h}%</span>
</div>
)}
</div>
);
}

相关文档