本頁面為社群翻譯版本,僅供參考;內容以英文原版為準。
查看英文原版 ↗

訂閱

本頁描述如何使用 WebSocket API 訂閱數據流。

訂閱消息

要訂閱特定的數據源,你需要發送一條訂閱消息。訂閱消息的格式如下:

{
  "method": "subscribe",
  "subscription": { ... }
}

訂閱確認(ack)會爲時間序列數據(例如用戶成交)提供先前數據的快照。這些快照消息帶有 isSnapshot: true 標記,如果之前的消息已被處理,則可以忽略。

訂閱對象包含你要訂閱的特定數據源的詳細資訊。從以下訂閱類型中選擇並提供相應的屬性:

  1. allMids: * 訂閱消息:{ "type": "allMids", "dex": "<dex>" } * 數據格式:AllMids * dex 欄位表示從中獲取中間價(mid)的永續合約 dex。 * 注意 dex 欄位是可選的。如果未提供,則使用第一個永續合約 dex。現貨中間價僅包含在第一個永續合約 dex 中。
  2. notification: * 訂閱消息:{ "type": "notification", "user": "<address>" } * 數據格式:Notification
  3. webData3 : * 訂閱消息:{ "type": "webData3", "user": "<address>" } * 數據格式:WebData3
  4. twapStates : * 訂閱消息:{ "type": "twapStates", "user": "<address>", "dex": "<dex>" } * 數據格式:TwapStates
  5. clearinghouseState: * 訂閱消息:{ "type": "clearinghouseState", "user": "<address>", "dex": "<dex>" } * 數據格式:ClearinghouseState
  6. openOrders: * 訂閱消息:{ "type": "openOrders", "user": "<address>", "dex": "<dex>" } * 數據格式:OpenOrders
  7. candle: * 訂閱消息:{ "type": "candle", "coin": "<coin_symbol>", "interval": "<candle_interval>" } * 支持的 K 線周期:"1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "8h", "12h", "1d", "3d", "1w", "1M" * 數據格式:Candle[]
  8. l2Book: * 訂閱消息:{ "type": "l2Book", "coin": "<coin_symbol>" } * 可選參數:nSigFigs: int、mantissa: int、fast: boolean(fast 爲 5 檔,slow 爲 20 檔) * 數據格式:WsBook
  9. trades: * 訂閱消息:{ "type": "trades", "coin": "<coin_symbol>" } * 數據格式:WsTrade[]
  10. orderUpdates:
    • 訂閱消息:{ "type": "orderUpdates", "user": "<address>" }
    • 數據格式:WsOrder[]
  11. userEvents:
    • 訂閱消息:{ "type": "userEvents", "user": "<address>" }
    • 數據格式:WsUserEvent
    • 注意:userEvents 消息的通道名爲 "channel": "user"
  12. userFills:
    • 訂閱消息:{ "type": "userFills", "user": "<address>" }
    • 可選參數:aggregateByTime: bool
    • 數據格式:WsUserFills
  13. userFundings:
    • 訂閱消息:{ "type": "userFundings", "user": "<address>" }
    • 數據格式:WsUserFundings
  14. userNonFundingLedgerUpdates:
    • 訂閱消息:{ "type": "userNonFundingLedgerUpdates", "user": "<address>" }
    • 數據格式:WsUserNonFundingLedgerUpdates
  15. activeAssetCtx:
    • 訂閱消息:{ "type": "activeAssetCtx", "coin": "<coin_symbol>" }
    • 數據格式:WsActiveAssetCtx 或 WsActiveSpotAssetCtx
  16. activeAssetData:(僅支持永續合約)
    • 訂閱消息:{ "type": "activeAssetData", "user": "<address>", "coin": "<coin_symbol>" }
    • 數據格式:WsActiveAssetData
  17. userTwapSliceFills:
    • 訂閱消息:{ "type": "userTwapSliceFills", "user": "<address>" }
    • 數據格式:WsUserTwapSliceFills
  18. userTwapHistory:
    • 訂閱消息:{ "type": "userTwapHistory", "user": "<address>" }
    • 數據格式:WsUserTwapHistory
  19. bbo :
    • 訂閱消息:{ "type": "bbo", "coin": "<coin>" }
    • 數據格式:WsBbo
  20. spotState
    • 訂閱消息:{ "type": "spotState", "user": "<address>", "isPortfolioMargin": bool }
    • 數據格式:WsSpotState
    • isPortfolioMargin 是可選參數
  21. allDexsClearinghouseState
    1. 訂閱消息:{ "type": "allDexsClearinghouseState", "user": "<address>" }
    2. 數據格式:WsAllDexsClearinghouseState
  22. allDexsAssetCtxs
    1. 訂閱消息:{ "type": "allDexsAssetCtxs" }
    2. 數據格式:WsAllDexsAssetCtxs
  23. outcomeMetaUpdates
    1. 訂閱消息:{ "type": "outcomeMetaUpdates" }
    2. 數據格式:WsOutcomeMetaUpdates
  24. fastAssetCtxs
    1. { "method": "subscribe", "subscription": { "type": "fastAssetCtxs" } }
    2. 數據格式:base64 編碼且壓縮過的 WsFastAssetCtxs
    3. 讀取數據請按順序執行:\ 1. base64 解碼爲字節\ 2. 解壓縮:原始 DEFLATE 流(RFC 1951)——沒有 zlib(RFC 1950)或 gzip(RFC 1952)包裝。Python 用 zlib.decompress(b, wbits=-15),瀏覽器用 new DecompressionStream("deflate-raw"),Node 用\ fflate.inflateSync\ 3. UTF-8 解碼並解析爲 JSON\ 4. 用於測試你的實現的示例\ payload:"q1ZyCnFWsqpWyk0syg6oULJSsjQ3NTDQM1Wq1VFyDfFAkTI2MzXQMwJLVVRWWfmFuTiiyBuamOoZKdXWAgA="\ 解碼後:{ "BTC": { "markPx": "97500.5" }, "ETH": { "markPx": "3650.25" }, "xyz:NVDA": { "markPx": "145.2" }}
    4. 第一條消息是快照,後續消息僅包含已更新的幣種。沒有更新的欄位會被省略。

用戶地址

要訂閱與主帳戶或子帳戶關聯的帳戶數據,你必須傳入該帳戶的實際地址。一個常見的錯誤是使用代理錢包(agent wallet)的地址,這會導致返回空結果。

數據格式

伺服器會以包含 channel 屬性爲 "subscriptionResponse" 的消息回應成功的訂閱,其中 data 欄位提供原始訂閱內容。隨後伺服器將開始發送 channel 屬性爲相應訂閱類型(例如 "allMids")的消息,data 欄位提供所訂閱的數據。

data 欄位的格式取決於訂閱類型:

  • AllMids:所有中間價。
  • 格式:AllMids { mids: Record<string, string> }
  • Notification:通知消息。
  • 格式:Notification { notification: string }
  • WebData3:用戶的匯總資訊,主要用於前端。
  • 格式:WebData3
  • WsTrade[]:成交更新陣列。
  • 格式:WsTrade[]
  • WsBook:訂單簿快照更新。
  • 格式:WsBook { coin: string; levels: [Array<WsLevel>, Array<WsLevel>]; time: number; }
  • WsOrder:用戶訂單更新。
  • 格式:WsOrder[]
  • WsUserEvent:非訂單更新的用戶事件
  • 格式:WsUserEvent { "fills": [WsFill] | "funding": WsUserFunding | "liquidation": WsLiquidation | "nonUserCancel": [WsNonUserCancel] }
  • WsUserFills :成交快照,隨後是流式成交
  • WsUserFundings :資金費用快照,隨後是整點時的資金費用
  • WsUserNonFundingLedgerUpdates:不包含資金費用的賬本更新:提幣、充值、劃轉和清算
  • WsBbo :僅在某個區塊上 bbo 發生變化時發送的 bbo 更新
  • WsSpotState :現貨狀態更新。
  • WsAllDexsClearinghouseState :特定用戶在所有 dex 上的清算所狀態
  • WsAllDexsAssetCtxs :所有 dex 上的資產上下文
  • WsOutcomeMetaUpdates :outcome 元數據的變更

對於 WsUserFills、WsUserFundings 等流式用戶端點,第一條消息帶有 isSnapshot: true,後續的流式更新帶有 isSnapshot: false。

數據類型定義

以下是 WebSocket API 中使用的數據類型定義:

interface WsTrade {
  coin: string;
  side: string;
  px: string;
  sz: string;
  hash: string;
  time: number;
  // tid is 50-bit hash of (buyer_oid, seller_oid). 
  // For a globally unique trade id, use (block_time, coin, tid)
  tid: number;  
  users: [string, string] // [buyer, seller]
}

// Snapshot feed, pushed on each block that is at least 0.5 since last push
interface WsBook {
  coin: string;
  levels: [Array<WsLevel>, Array<WsLevel>];
  time: number;
}

interface WsBbo {
  coin: string;
  time: number;
  bbo: [WsLevel | null, WsLevel | null];
}

interface WsLevel {
  px: string; // price
  sz: string; // size
  n: number; // number of orders
}

interface Notification {
  notification: string;
}

interface AllMids {
  mids: Record<string, string>;
}

interface Candle {
  t: number; // open millis
  T: number; // close millis
  s: string; // coin
  i: string; // interval
  o: number; // open price
  c: number; // close price
  h: number; // high price
  l: number; // low price
  v: number; // volume (base unit)
  n: number; // number of trades
}

type WsUserEvent = {"fills": WsFill[]} | {"funding": WsUserFunding} | {"liquidation": WsLiquidation} | {"nonUserCancel" :WsNonUserCancel[]};

interface WsUserFills {
  isSnapshot?: boolean;
  user: string;
  fills: Array<WsFill>;
}

interface WsFill {
  coin: string;
  px: string; // price
  sz: string; // size
  side: string;
  time: number;
  startPosition: string;
  dir: string; // used for frontend display
  closedPnl: string;
  hash: string; // L1 transaction hash
  oid: number; // order id
  crossed: boolean; // whether order crossed the spread (was taker)
  fee: string; // negative means rebate
  tid: number; // unique trade id
  liquidation?: FillLiquidation;
  feeToken: string; // the token the fee was paid in
  builderFee?: string; // amount paid to builder, also included in fee
}

interface FillLiquidation {
  liquidatedUser?: string;
  markPx: number;
  method: "market" | "backstop";
}

interface WsUserFunding {
  time: number;
  coin: string;
  usdc: string;
  szi: string;
  fundingRate: string;
}

interface WsLiquidation {
  lid: number;
  liquidator: string;
  liquidated_user: string;
  liquidated_ntl_pos: string;
  liquidated_account_value: string;
}

interface WsNonUserCancel {
  coin: String;
  oid: number;
}

interface WsOrder {
  order: WsBasicOrder;
  status: string; // See https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#query-order-status-by-oid-or-cloid for a list of possible values
  statusTimestamp: number;
}

interface WsBasicOrder {
  coin: string;
  side: string;
  limitPx: string;
  sz: string;
  oid: number;
  timestamp: number;
  origSz: string;
  cloid: string | undefined;
}

interface WsActiveAssetCtx {
  coin: string;
  ctx: PerpsAssetCtx;
}

interface WsActiveSpotAssetCtx {
  coin: string;
  ctx: SpotAssetCtx;
}

type SharedAssetCtx = {
  dayNtlVlm: number;
  prevDayPx: number;
  markPx: number;
  midPx?: number;
};

type PerpsAssetCtx = SharedAssetCtx & {
  funding: number;
  openInterest: number;
  oraclePx: number;
};

type SpotAssetCtx = SharedAssetCtx & {
  circulatingSupply: number;
};

interface WsActiveAssetData {
  user: string;
  coin: string;
  leverage: Leverage;
  maxTradeSzs: [number, number];
  availableToTrade: [number, number];
}

interface WsTwapSliceFill {
  fill: WsFill;
  twapId: number;
}

interface WsUserTwapSliceFills {
  isSnapshot?: boolean;
  user: string;
  twapSliceFills: Array<WsTwapSliceFill>;
}

interface TwapState {
  coin: string;
  user: string;
  side: string;
  sz: number;
  executedSz: number;
  executedNtl: number;
  minutes: number;
  reduceOnly: boolean;
  randomize: boolean;
  timestamp: number;
}

type TwapStatus = "activated" | "terminated" | "finished" | "error";
interface WsTwapHistory {
  state: TwapState;
  status: {
    status: TwapStatus;
    description: string;
  };
  time: number;
}

interface WsUserTwapHistory {
  isSnapshot?: boolean;
  user: string;
  history: Array<WsTwapHistory>;
}

// Additional undocumented fields in WebData3 will be removed on a future update
interface WebData3 {
  userState: {
    agentAddress: string | null;
    agentValidUntil: number | null;
    serverTime: number;
    cumLedger: number;
    isVault: boolean;
    user: string;
    optOutOfSpotDusting?: boolean;
    dexAbstractionEnabled?: boolean;
  };
  perpDexStates: Array<PerpDexState>;
}

interface PerpDexState {
  totalVaultEquity: number;
  perpsAtOpenInterestCap?: Array<string>;
  leadingVaults?: Array<LeadingVault>;
}

interface LeadingVault {
  address: string;
  name: string;
}

interface ClearinghouseState {
  dex: string;
  user: string;
  clearinghouseState: InnerClearinghouseState;
}

interface InnerClearinghouseState {
  assetPositions: Array<AssetPosition>;
  marginSummary: MarginSummary;
  crossMarginSummary: MarginSummary;
  crossMaintenanceMarginUsed: number;
  withdrawable: number;
}

interface MarginSummary {
  accountValue: number;
  totalNtlPos: number;
  totalRawUsd: number;
  totalMarginUsed: number;
}

interface AssetPosition { type: "oneWay"; position: Position }

interface OpenOrders {
  dex: string;
  user: string;
  orders: Array<Order>;
}

interface TwapStates {
  dex: string;
  user: string;
  states: Array<[number, TwapState]>;
}

interface WsSpotState {
  user: string;
  spotState: SpotState;
}

interface SpotState {
  balances: Array<UserBalance>;
}

interface UserBalance {
  coin: string;
  token?: number;
  hold: string;
  total: string;
  entryNtl: string;
}

interface WsAllDexsClearinghouseState {
  user: string;
  clearinghouseStates: Array<[string, InnerClearinghouseState]>;
}

interface WsAllDexsAssetCtxs {
  ctxs: Array<[string, Array<PerpsAssetCtx>]>;
}

type WsOutcomeMetaUpdates = [WsOutcomeMetaUpdate];

type WsOutcomeMetaUpdate =
  | { outcomeCreated: OutcomeSpec }
  | { outcomeSettled: number }
  | { questionUpdated: QuestionSpec }
  | { questionSettled: number };

type OutcomeSpec = {
  outcome: number;
  name: string;
  description: string;
  sideSpecs: [OutcomeSideSpec, OutcomeSideSpec];
};

type OutcomeSideSpec = {
  name: string;
};

type QuestionSpec = {
  question: number;
  name: string;
  description: string;
  fallbackOutcome: number;
  namedOutcomes: number[];
  settledNamedOutcomes: number[];
};

type FFastAssetCtx = {
  markPx?: number;
  midPx?: number | null;
};
type WsFastAssetCtxs = Record<string, FFastAssetCtx>;
WsUserNonFundingLedgerUpdates
interface WsUserNonFundingLedgerUpdate {
  time: number;
  hash: string;
  delta: WsLedgerUpdate;
}

type WsLedgerUpdate = 
  | WsDeposit
  | WsWithdraw 
  | WsInternalTransfer 
  | WsSubAccountTransfer 
  | WsLedgerLiquidation 
  | WsVaultDelta 
  | WsVaultWithdrawal
  | WsVaultLeaderCommission
  | WsSpotTransfer
  | WsAccountClassTransfer
  | WsSpotGenesis
  | WsRewardsClaim;

interface WsDeposit {
  type: "deposit";
  usdc: number;
}

interface WsWithdraw {
  type: "withdraw";
  usdc: number;
  nonce: number;
  fee: number;
}

interface WsInternalTransfer {
  type: "internalTransfer";
  usdc: number;
  user: string;
  destination: string;
  fee: number;
}

interface WsSubAccountTransfer {
  type: "subAccountTransfer";
  usdc: number;
  user: string;
  destination: string;
}

interface WsLedgerLiquidation {
  type: "liquidation";
  // NOTE: for isolated positions this is the isolated account value
  accountValue: number;
  leverageType: "Cross" | "Isolated";
  liquidatedPositions: Array<LiquidatedPosition>;
}

interface LiquidatedPosition {
  coin: string;
  szi: number;
}

interface WsVaultDelta {
  type: "vaultCreate" | "vaultDeposit" | "vaultDistribution";
  vault: string;
  usdc: number;
}

interface WsVaultWithdrawal {
  type: "vaultWithdraw";
  vault: string;
  user: string;
  requestedUsd: number;
  commission: number;
  closingCost: number;
  basis: number;
  netWithdrawnUsd: number;
}

interface WsVaultLeaderCommission {
  type: "vaultLeaderCommission";
  user: string;
  usdc: number;
}

interface WsSpotTransfer = {
  type: "spotTransfer";
  token: string;
  amount: number;
  usdcValue: number;
  user: string;
  destination: string;
  fee: number;
}

interface WsAccountClassTransfer = {
  type: "accountClassTransfer";
  usdc: number;
  toPerp: boolean;
}

interface WsSpotGenesis = {
  type: "spotGenesis";
  token: string;
  amount: number;
}

interface WsRewardsClaim = {
  type: "rewardsClaim";
  amount: number;
}

請注意,上述數據類型爲 TypeScript 格式,其用法與各自的訂閱類型相對應。

示例

以下是用訂閱消息訂閱不同數據源的幾個示例:

  1. 訂閱所有中間價:

json { "method": "subscribe", "subscription": { "type": "allMids" } } 2. 訂閱特定用戶的通知:

json { "method": "subscribe", "subscription": { "type": "notification", "user": "<address>" } } 3. 訂閱特定用戶的 web 數據:

json { "method": "subscribe", "subscription": { "type": "webData3", "user": "<address>" } } 4. 訂閱特定幣種和周期的 K 線更新:

json { "method": "subscribe", "subscription": { "type": "candle", "coin": "<coin_symbol>", "interval": "<candle_interval>" } } 5. 訂閱特定幣種的訂單簿更新:

json { "method": "subscribe", "subscription": { "type": "l2Book", "coin": "<coin_symbol>" } } 6. 訂閱特定幣種的成交:

json { "method": "subscribe", "subscription": { "type": "trades", "coin": "<coin_symbol>" } }

取消訂閱 WebSocket 數據流

要取消訂閱 Hyperliquid WebSocket API 上的特定數據源,你需要發送如下格式的取消訂閱消息:

{
  "method": "unsubscribe",
  "subscription": { ... }
}

subscription 對象應與訂閱該數據源時發送的原始訂閱消息一致。這樣伺服器才能識別你要取消訂閱的特定數據源。通過發送此取消訂閱消息,你告知伺服器停止發送該數據源的後續更新。

請注意,取消訂閱某個特定數據源不會影響你當時已激活的其他訂閱。要取消訂閱多個數據源,你可以發送多條取消訂閱消息,每條消息包含相應的訂閱詳情。

英文官方來源: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions
原文擷取日期: · 鏡像建置日期: · 社群翻譯,以英文原版為準
非官方社群鏡像與翻譯,內容版權歸 Hyperliquid 所有,以英文原版為準。 來源: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions