Trang này được dịch tự động. Bản gốc tiếng Anh là phiên bản chính thức. Đọc bằng tiếng Anh
Chuyển đến nội dung chính

WebSocket API

Truyền dữ liệu thời gian thực cho giao dịch quyền chọn Hypercall.

Tài liệu tham khảo tương tác

Xem Tài liệu tham khảo WebSocket API tương tác để có trải nghiệm duyệt tốt hơn với các ví dụ trực tiếp và chi tiết schema.

Đặc tả có thể đọc bằng máy

Tải đặc tả AsyncAPI để sử dụng theo hướng lập trình.

Kết nối

Kết nối tới wss://HOST/ws:

Các endpoint:

  • Production: wss://api.hypercall.xyz/ws
  • Local: ws://localhost:3000/ws
Trạng thái testnet

Testnet tạm thời bị vô hiệu hóa cho đến khi Hypercall có thêm testnet HYPE.

Nhận diện ví

Để nhận dữ liệu trên các kênh yêu cầu xác thực (lệnh, khớp lệnh, danh mục), hãy nhận diện ví của bạn sau khi kết nối bằng cách gửi một thông điệp Authenticate:

{"type": "Authenticate", "wallet": "0x1234..."}

Máy chủ phản hồi bằng xác nhận:

{"type": "Authenticated", "wallet": "0x1234..."}

Sau khi nhận được Authenticated, bạn có thể đăng ký các kênh yêu cầu xác thực. Nếu địa chỉ ví không hợp lệ, máy chủ phản hồi bằng một thông điệp Error và kết nối vẫn được giữ mở.

Đã lỗi thời: Xác thực bằng tham số truy vấn

Tham số truy vấn ?wallet= vẫn được hỗ trợ để tương thích ngược nhưng đã lỗi thời và sẽ bị loại bỏ trong một bản phát hành tương lai. Hãy ưu tiên phương pháp dựa trên thông điệp ở trên.

Tính sống của kết nối

Máy chủ thực thi một cơ chế heartbeat cho WebSocket:

  • Gửi một khung điều khiển Ping mỗi 20 giây
  • Chờ một khung Pong tương ứng trong vòng 60 giây
  • Đóng kết nối với mã đóng 1008 và lý do pong timeout nếu client ngừng phản hồi

Các cài đặt WebSocket của trình duyệt xử lý ping/pong một cách tự động. Nhiều thư viện websocket Rust, bao gồm tungstenitetokio-tungstenite, cũng xử lý ping/pong khung điều khiển giúp bạn. Hãy kiểm tra tài liệu thư viện của client trước khi thêm xử lý Pong thủ công. Các cài đặt tùy chỉnh hoặc raw socket phải phản hồi các khung Ping bằng Pong.

Khôi phục khi consumer chậm

Máy chủ đóng một kết nối /ws không thể xả hết dữ liệu gửi đi trong các ngưỡng an toàn đã cấu hình về số thông điệp, số byte đã mã hóa, tuổi hàng đợi, hoặc thời gian ghi socket. Khi kết nối vẫn có thể chấp nhận một khung đóng, máy chủ sử dụng mã 1008 và một lý do JSON gọn:

{"error":"slow_consumer","class":"ordered_public","cause":"message_age","recovery":"snapshot_resubscribe"}

Các trường lý do là:

TrườngÝ nghĩa
classLớp phân phối có khung vượt qua ranh giới an toàn.
causemessage_limit, byte_limit, message_age, hoặc write_timeout.
recoveryHành động tiếp theo bắt buộc, chẳng hạn như resubscribe, snapshot_resubscribe, portfolio_refetch, hoặc rest_reconcile.

Sau bất kỳ lần ngắt kết nối nào, hãy kết nối lại, nhận diện ví lần nữa khi cần, đăng ký lại, và đối chiếu trạng thái hiện tại trước khi xử lý các sự kiện mới. Các kênh công khai có thứ tự yêu cầu một snapshot mới. Các kênh sự kiện riêng tư yêu cầu đối chiếu qua bề mặt REST có thẩm quyền vì việc phát lại theo con trỏ (cursor) chưa khả dụng. Một kết nối bị đình trệ hoàn toàn có thể chấm dứt trước khi đọc được lý do đóng, nên client cũng phải sử dụng luồng khôi phục này cho một lần đóng không sạch.

Hãy dùng các kết nối riêng biệt cho dữ liệu thị trường công khai tốc độ cao và cho các lệnh yêu cầu xác thực hoặc các luồng riêng tư. Các lớp phân phối chọn số liệu và hành vi khôi phục, nhưng các khung trên một kết nối vẫn dùng chung một đường ghi socket có thứ tự. Do đó một lần ghi công khai bị đình trệ có thể làm chậm các khung riêng tư sau đó trên cùng kết nối đó cho đến khi hạn chót ghi đóng nó lại.

Đăng ký kênh

Gửi một thông điệp JSON để đăng ký:

{"type": "Subscribe", "channel": "orderbook"}

Để hủy đăng ký:

{"type": "Unsubscribe", "channel": "orderbook"}

Bạn sẽ nhận được một xác nhận:

{"type": "Subscribed", "channel": "orderbook"}

Lọc theo symbol

Các kênh order_updatesfills hỗ trợ một bộ lọc symbols tùy chọn. Khi được cung cấp, máy chủ chỉ gửi các thông điệp có tài sản cơ sở khớp với một trong các symbol được chỉ định.

{"type": "Subscribe", "channel": "order_updates", "symbols": ["BTC"]}

Cả tài sản cơ sở đơn thuần ("BTC") và tên instrument đầy đủ ("BTC-20260131-100000-C") đều được chấp nhận. Để thêm nhiều symbol hơn, hãy gửi một Subscribe khác. Để loại bỏ các symbol cụ thể:

{"type": "Unsubscribe", "channel": "order_updates", "symbols": ["BTC"]}

Khi không có symbols nào được chỉ định, tất cả cập nhật cho ví của bạn sẽ được chuyển tiếp.

Lọc chuỗi quyền chọn

Kênh options_chain hỗ trợ lọc theo tài sản cơ sở, ngày đáo hạn, và loại quyền chọn:

{
"type": "Subscribe",
"channel": "options_chain",
"symbols": ["BTC-20260131-100000-C"],
"expiry": "2026-01-31",
"option_type": "call"
}
Bộ lọcGiá trịMặc định
symbolsMảng các symbol instrument đầy đủ (ví dụ, ["BTC-20260131-100000-C"])Tất cả instrument
expiryChuỗi ngày "YYYY-MM-DD"Tất cả ngày đáo hạn
option_type"call", "put", hoặc bỏ trống để lấy cả haiCả hai

Các kênh khả dụng

KênhYêu cầu xác thựcMô tả
orderbookKhôngCập nhật sổ lệnh L2 cho tất cả symbol
tradesKhôngLuồng giao dịch công khai
market_updatesKhôngThay đổi niêm yết thị trường (tạo/xóa/hết hạn)
options_chainKhôngCập nhật chuỗi quyền chọn theo gia tăng (có thể lọc theo symbols, expiry, option_type)
index_pricesKhôngGiá spot/chỉ số thời gian thực cho tất cả tài sản cơ sở
indicative_market_dataKhôngLuồng nhà cung cấp báo giá trong allowlist. Chưa khả dụng rộng rãi
order_updatesThay đổi trạng thái lệnh của bạn (có thể lọc theo symbol)
fillsCác lần khớp lệnh của bạn (có thể lọc theo symbol)
portfolioCập nhật vị thế và số dư của bạn
liquidationThay đổi trạng thái thanh lý của bạn
competitionTóm tắt PnL, thứ hạng, và thống kê cuối cùng của cuộc thi của bạn
competition_engagementThay đổi thứ hạng, khoảng cách tới hạng kế tiếp, và bảng xếp hạng cuối cùng
rfqBáo giá RFQ, cập nhật trạng thái, và thông báo khớp lệnh

Các loại thông điệp

Đặt lệnh (Yêu cầu xác thực)

Đặt một lệnh qua đường lệnh WebSocket.

{
"type": "PlaceOrder",
"wallet": "0x1234...",
"symbol": "BTC-20260131-100000-C",
"side": "Buy",
"size": "1",
"price": "100",
"tif": "gtc",
"route": "book_only",
"client_id": "my-order-1",
"nonce": 1000,
"signature": "0x..."
}
TrườngKiểuMô tả
walletstringĐịa chỉ ví sở hữu lệnh
symbolstringSymbol quyền chọn
sidestring"Buy" hoặc "Sell"
sizestringQuy mô hợp đồng, khớp chính xác với giá trị đã ký
pricestringGiá giới hạn, khớp chính xác với giá trị đã ký
tifstringTime-in-force tùy chọn, mặc định là "gtc"
routestringRoute tùy chọn. Dùng "book_only" cho các lệnh WebSocket nhận biết route. Route bỏ trống vẫn được chấp nhận cho đến ít nhất ngày 4 tháng 7, 2026.
client_idstringID lệnh của client tùy chọn
nonceintegerNonce ký duy nhất
signaturestringChữ ký EIP-712 PlaceOrder

PlaceOrder qua WebSocket hiện gửi trực tiếp đến sổ lệnh. route="best_execution"route="rfq_only" bị từ chối trên WebSocket vì đường này chưa chạy định tuyến RPI/RFQ. Dùng POST /order cho best_execution.

Cập nhật sổ lệnh

Snapshot/cập nhật sổ lệnh L2 cho một symbol.

{
"type": "OrderbookUpdate",
"symbol": "BTC-20260131-100000-C",
"bids": [["95000.5", "10.5"], ["94999.0", "25.0"]],
"asks": [["95001.0", "8.0"], ["95002.5", "15.0"]],
"timestamp": 1737331200000
}
TrườngKiểuMô tả
symbolstringSymbol quyền chọn
bidsarrayCác mức giá mua dưới dạng tuple [price, size], size tính theo hợp đồng ở dạng dễ đọc
asksarrayCác mức giá bán dưới dạng tuple [price, size], size tính theo hợp đồng ở dạng dễ đọc
timestampintegerUnix timestamp (mili giây)

Giao dịch

Sự kiện giao dịch công khai.

{
"type": "Trade",
"symbol": "BTC-20260131-100000-C",
"price": "0.0523",
"size": "5.0",
"side": "buy",
"timestamp": 1737331200000
}
TrườngKiểuMô tả
symbolstringSymbol quyền chọn
pricestringGiá giao dịch tính bằng USD
sizestringQuy mô giao dịch tính bằng hợp đồng
sidestringPhía chủ động (buy hoặc sell)
timestampintegerUnix timestamp (mili giây)

Khớp lệnh (Yêu cầu xác thực)

Thông báo khớp lệnh giao dịch của bạn.

{
"type": "Fill",
"order_id": 12345,
"fill_id": 67890,
"symbol": "BTC-20260131-100000-C",
"side": "buy",
"price": "0.0523",
"size": "5.0",
"timestamp": 1737331200000,
"wallet_address": "0x1234...abcd",
"fee": "0",
"trade_id": 99999,
"is_taker": true
}
TrườngKiểuMô tả
order_idintegerID lệnh của bạn
fill_idintegerID khớp lệnh
symbolstringMã quyền chọn
sidestringChiều giao dịch (buy hoặc sell)
pricestringGiá khớp tính bằng USD
sizestringKhối lượng khớp tính bằng số hợp đồng
timestampintegerDấu thời gian Unix (mili giây)
wallet_addressstringĐịa chỉ ví của bạn
feestringPhí giao dịch được thu. Trả về 0 khi phí của sàn giao dịch launch venue bị tắt
trade_idintegerID giao dịch duy nhất
is_takerbooleanBạn có phải là bên taker hay không
builder_code_addressstring?Ví builder code (nếu có)
builder_code_feestring?Phí builder code. Trả về null khi phí của sàn giao dịch launch venue bị tắt

Cập nhật Danh mục (Đã xác thực)

Cập nhật luồng danh mục cho các vị thế, số dư, ký quỹ và các Greeks.

Ví dụ cập nhật Greeks:

{
"type": "PortfolioUpdate",
"timestamp": 1737331200000,
"per_leg": [
{
"symbol": "BTC-20260131-100000-C",
"quantity": "2.0",
"delta": 0.91,
"gamma": 0.003,
"theta": -0.12,
"vega": 0.44,
"iv": 0.63
}
],
"aggregate": {
"delta": 0.91,
"gamma": 0.003,
"theta": -0.12,
"vega": 0.44,
"iv": 0.63
}
}

Đối với danh mục trống, các cập nhật Greeks sử dụng:

  • per_leg: []
  • aggregate: null

Tóm tắt PnL Cuộc thi (Đã xác thực)

Cập nhật luồng cuộc thi để hiển thị PnL ở header/footer.

{
"type": "CompetitionPnlSummary",
"wallet_address": "0x1234...abcd",
"lifetime_realized_pnl": "1250.50",
"active_competition": {
"competition_id": 7,
"competition_name": "Spring Sprint",
"competition_state": "active",
"rank": 12,
"pnl": "420.25",
"volume": "25000",
"efficiency": "0.01681",
"medal": null
},
"timestamp": 1737331200000
}

Khi không có cuộc thi nào đang diễn ra, active_competitionnull.

Cập nhật Lệnh (Đã xác thực)

Thông báo thay đổi trạng thái lệnh.

{
"type": "OrderUpdate",
"order_id": 12345,
"client_order_id": "my-order-1",
"status": "filled",
"filled_size": "10.0",
"remaining_size": "0",
"avg_fill_price": "0.0523"
}

Cập nhật Thị trường

Thay đổi về danh sách thị trường.

Thị trường Được tạo:

{
"type": "MarketUpdate",
"action": "Created",
"symbol": "BTC-20260131-100000-C",
"strike": "100000",
"is_call": true,
"underlying": "BTC",
"expiry": 1738281600,
"timestamp": 1737331200000
}

Thị trường Đã đáo hạn:

{
"type": "MarketUpdate",
"action": "Expired",
"symbol": "BTC-20260131-100000-C",
"strike": "100000",
"is_call": true,
"underlying": "BTC",
"expiry": 1738281600,
"timestamp": 1738281600000
}

Vị thế Đã đáo hạn (Đã xác thực)

Thông báo khi vị thế của bạn được thanh toán tại ngày đáo hạn.

{
"type": "PositionExpired",
"wallet_address": "0x1234...abcd",
"symbol": "BTC-20260131-100000-C",
"position_size": "10.0",
"settlement_price": "105000",
"settlement_value": "500.0",
"timestamp": 1738281600000
}

Thay đổi Trạng thái Thanh lý (Đã xác thực)

Thay đổi trạng thái thanh lý tài khoản của bạn.

{
"type": "LiquidationStateChange",
"wallet_address": "0x1234...abcd",
"previous_state": "Normal",
"new_state": "Warning",
"equity": "10000.0",
"mm_required": "9500.0",
"shortfall": "0",
"auction_id": null,
"timestamp": 1737331200000
}
Trạng tháiMô tả
NormalTài khoản đang lành mạnh
WarningSắp bị margin call
LiquidatingPhiên đấu giá thanh lý đang diễn ra

Cập nhật Giá Chỉ số

Giá spot/chỉ số được gộp theo lô cho tất cả các tài sản cơ sở.

{
"type": "IndexPriceUpdate",
"prices": [
{"underlying": "BTC", "price": "97250.50"},
{"underlying": "ETH", "price": "3200.00"},
{"underlying": "HYPE", "price": "28.50"}
],
"timestamp": 1737331200000
}
TrườngKiểuMô tả
pricesarrayMảng các mục {underlying, price} cho mỗi tài sản cơ sở được theo dõi
prices[].underlyingstringMã tài sản cơ sở (ví dụ: "BTC", "ETH")
prices[].pricestringGiá spot/chỉ số hiện tại tính bằng USD
timestampintegerDấu thời gian Unix (mili giây)

Dữ liệu Thị trường Tham khảo

Luồng nhà cung cấp báo giá trong danh sách được cho phép, với giá mua/giá bán tốt nhất được tổng hợp từ các nhà cung cấp báo giá đã đăng ký. Kênh này chưa được cung cấp rộng rãi. Hãy sử dụng dữ liệu thị trường REST và các kênh lệnh/khớp lệnh/danh mục đã xác thực, trừ khi Hypercall đã bật tính năng luồng nhà cung cấp báo giá cho tích hợp của bạn.

{
"type": "IndicativeMarketData",
"instrument": "BTC-20260131-100000-C",
"best_bid": "0.0520",
"best_ask": "0.0530",
"indicative_bid_size": "50.0",
"indicative_ask_size": "25.0",
"num_providers": 3,
"timestamp": 1737331200000
}
TrườngKiểuMô tả
instrumentstringMã quyền chọn
best_bidstringGiá mua tổng hợp tốt nhất (tùy chọn)
best_askstringGiá bán tổng hợp tốt nhất (tùy chọn)
bid_ivnumberBiến động ngụ ý của giá mua tốt nhất (tùy chọn)
ask_ivnumberBiến động ngụ ý của giá bán tốt nhất (tùy chọn)
indicative_bid_sizestringTổng khối lượng mua trên tất cả nhà cung cấp (tùy chọn)
indicative_ask_sizestringTổng khối lượng bán trên tất cả nhà cung cấp (tùy chọn)
num_providersintegerSố lượng nhà cung cấp báo giá đang hoạt động
timestampintegerDấu thời gian Unix (mili giây)

Thay đổi Thứ hạng Cuộc thi (Đã xác thực)

Thông báo khi thứ hạng của bạn thay đổi trong một cuộc thi đang diễn ra.

{
"type": "CompetitionRankChange",
"wallet_address": "0x1234...abcd",
"competition_id": 7,
"from_rank": 15,
"to_rank": 12,
"delta_places": 3,
"pnl": "420.25",
"timestamp": 1737331200000
}

Cập nhật Khoảng cách Cuộc thi (Đã xác thực)

Khoảng cách đến thứ hạng ngay trên bạn.

{
"type": "CompetitionGapUpdate",
"wallet_address": "0x1234...abcd",
"competition_id": 7,
"rank": 12,
"next_rank": 11,
"gap_metric_value": "50.00",
"timestamp": 1737331200000
}

Thứ hạng Chung cuộc (Đã xác thực)

Được gửi khi một cuộc thi kết thúc kèm theo kết quả cuối cùng của bạn.

{
"type": "CompetitionFinalStanding",
"wallet_address": "0x1234...abcd",
"competition_id": 7,
"rank": 12,
"pnl": "420.25",
"volume": "25000",
"efficiency": "0.01681",
"medal": null,
"timestamp": 1737331200000
}

Báo giá RFQ (Đã xác thực)

Các báo giá nhận được để phản hồi cho yêu cầu RFQ mà bạn gửi.

{
"type": "RfqQuotes",
"rfq_id": "550e8400-e29b-41d4-a716-446655440000",
"quotes": [
{
"quote_id": "660e8400-e29b-41d4-a716-446655440001",
"net_premium": "52.30",
"expires_at": 1737331225000
}
],
"status": "quoted",
"taker_wallet": "0x1234...abcd"
}

Cập nhật Trạng thái RFQ (Đã xác thực)

Thay đổi trạng thái cho một RFQ mà bạn đã gửi.

{
"type": "RfqStatusUpdate",
"rfq_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "executed",
"taker_wallet": "0x1234...abcd"
}

Lỗi

Thông báo lỗi từ máy chủ.

{
"type": "Error",
"message": "Invalid channel: foobar"
}

Xác thực

Các kênh đã xác thực yêu cầu một tin nhắn định danh ví sau khi kết nối:

{"type": "Authenticate", "wallet": "0x1234567890abcdef..."}

Các tin nhắn trên các kênh đã xác thực được lọc để chỉ hiển thị dữ liệu cho ví của bạn. Không cần chữ ký cho các kết nối WebSocket.

Ví dụ: Python Client

import asyncio
import websockets
import json

async def main():
uri = "wss://api.hypercall.xyz/ws"

async with websockets.connect(uri) as ws:
# Identify the wallet before subscribing to authenticated channels.
await ws.send(json.dumps({
"type": "Authenticate",
"wallet": "0xYourWallet"
}))

# Subscribe to orderbook
await ws.send(json.dumps({
"type": "Subscribe",
"channel": "orderbook"
}))

# Subscribe to fills for BTC only
await ws.send(json.dumps({
"type": "Subscribe",
"channel": "fills",
"symbols": ["BTC"]
}))

# Listen for messages
async for message in ws:
data = json.loads(message)
print(f"Received: {data['type']}")

asyncio.run(main())

Ví dụ: TypeScript Client

const ws = new WebSocket("wss://api.hypercall.xyz/ws");

ws.onopen = () => {
ws.send(JSON.stringify({ type: "Authenticate", wallet: "0xYourWallet" }));

// Subscribe to channels
ws.send(JSON.stringify({ type: "Subscribe", channel: "orderbook" }));

// Subscribe to order updates filtered to BTC
ws.send(JSON.stringify({
type: "Subscribe",
channel: "order_updates",
symbols: ["BTC"],
}));
};

ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
console.log(`Received: ${msg.type}`);

if (msg.type === "OrderbookUpdate") {
console.log(`${msg.symbol}: ${msg.bids.length} bids, ${msg.asks.length} asks`);
}
};