Questa pagina è una traduzione della community e ha solo scopo informativo; fa fede la versione originale in inglese.
Versione originale ↗

Sottoscrizioni

Questa pagina descrive la sottoscrizione ai flussi di dati tramite l'API WebSocket.

Messaggi di sottoscrizione

Per sottoscrivere flussi di dati specifici è necessario inviare un messaggio di sottoscrizione. Il formato del messaggio di sottoscrizione è il seguente:

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

L'ack della sottoscrizione fornisce uno snapshot dei dati precedenti per i dati di serie temporali (ad es. i fill dell'utente). Questi messaggi di snapshot sono contrassegnati con isSnapshot: true e possono essere ignorati se i messaggi precedenti sono già stati elaborati.

L'oggetto di sottoscrizione contiene i dettagli dello specifico flusso a cui si desidera sottoscriversi. Scegliere tra i seguenti tipi di sottoscrizione e fornire le proprietà corrispondenti:

  1. allMids: * Messaggio di sottoscrizione: { "type": "allMids", "dex": "<dex>" } * Formato dati: AllMids * Il campo dex rappresenta il perp dex da cui ricavare i mid. * Si noti che il campo dex è facoltativo. Se non viene fornito, viene utilizzato il primo perp dex. I mid spot sono inclusi solo con il primo perp dex.
  2. notification: * Messaggio di sottoscrizione: { "type": "notification", "user": "<address>" } * Formato dati: Notification
  3. webData3 : * Messaggio di sottoscrizione: { "type": "webData3", "user": "<address>" } * Formato dati: WebData3
  4. twapStates : * Messaggio di sottoscrizione: { "type": "twapStates", "user": "<address>", "dex": "<dex>" } * Formato dati: TwapStates
  5. clearinghouseState: * Messaggio di sottoscrizione: { "type": "clearinghouseState", "user": "<address>", "dex": "<dex>" } * Formato dati: ClearinghouseState
  6. openOrders: * Messaggio di sottoscrizione: { "type": "openOrders", "user": "<address>", "dex": "<dex>" } * Formato dati: OpenOrders
  7. candle: * Messaggio di sottoscrizione: { "type": "candle", "coin": "<coin_symbol>", "interval": "<candle_interval>" } * Intervalli supportati: "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "8h", "12h", "1d", "3d", "1w", "1M" * Formato dati: Candle[]
  8. l2Book: * Messaggio di sottoscrizione: { "type": "l2Book", "coin": "<coin_symbol>" } * Parametri facoltativi: nSigFigs: int, mantissa: int , fast: boolean (5 livelli se fast, 20 livelli se slow) * Formato dati: WsBook
  9. trades: * Messaggio di sottoscrizione: { "type": "trades", "coin": "<coin_symbol>" } * Formato dati: WsTrade[]
  10. orderUpdates:
    • Messaggio di sottoscrizione: { "type": "orderUpdates", "user": "<address>" }
    • Formato dati: WsOrder[]
  11. userEvents:
    • Messaggio di sottoscrizione: { "type": "userEvents", "user": "<address>" }
    • Formato dati: WsUserEvent
    • Nota: il nome del canale per i messaggi userEvents è "channel": "user"
  12. userFills:
    • Messaggio di sottoscrizione: { "type": "userFills", "user": "<address>" }
    • Parametro facoltativo: aggregateByTime: bool
    • Formato dati: WsUserFills
  13. userFundings:
    • Messaggio di sottoscrizione: { "type": "userFundings", "user": "<address>" }
    • Formato dati: WsUserFundings
  14. userNonFundingLedgerUpdates:
    • Messaggio di sottoscrizione: { "type": "userNonFundingLedgerUpdates", "user": "<address>" }
    • Formato dati: WsUserNonFundingLedgerUpdates
  15. activeAssetCtx:
    • Messaggio di sottoscrizione: { "type": "activeAssetCtx", "coin": "<coin_symbol>" }
    • Formato dati: WsActiveAssetCtx o WsActiveSpotAssetCtx
  16. activeAssetData: (supporta solo i perp)
    • Messaggio di sottoscrizione: { "type": "activeAssetData", "user": "<address>", "coin": "<coin_symbol>" }
    • Formato dati: WsActiveAssetData
  17. userTwapSliceFills:
    • Messaggio di sottoscrizione: { "type": "userTwapSliceFills", "user": "<address>" }
    • Formato dati: WsUserTwapSliceFills
  18. userTwapHistory:
    • Messaggio di sottoscrizione: { "type": "userTwapHistory", "user": "<address>" }
    • Formato dati: WsUserTwapHistory
  19. bbo :
    • Messaggio di sottoscrizione: { "type": "bbo", "coin": "<coin>" }
    • Formato dati: WsBbo
  20. spotState
    • Messaggio di sottoscrizione: { "type": "spotState", "user": "<address>", "isPortfolioMargin": bool }
    • Formato dati: WsSpotState
    • isPortfolioMargin è un argomento facoltativo
  21. allDexsClearinghouseState
    1. Messaggio di sottoscrizione: { "type": "allDexsClearinghouseState", "user": "<address>" }
    2. Formato dati: WsAllDexsClearinghouseState
  22. allDexsAssetCtxs
    1. Messaggio di sottoscrizione: { "type": "allDexsAssetCtxs" }
    2. Formato dati: WsAllDexsAssetCtxs
  23. outcomeMetaUpdates
    1. Messaggio di sottoscrizione: { "type": "outcomeMetaUpdates" }
    2. Formato dati: WsOutcomeMetaUpdates
  24. fastAssetCtxs
    1. { "method": "subscribe", "subscription": { "type": "fastAssetCtxs" } }
    2. Formato dati: WsFastAssetCtxs codificato in base64 e compresso
    3. Per leggere i dati, applicare nell'ordine:\ 1. decodificare da base64 in byte\ 2. decomprimere: un flusso DEFLATE grezzo (RFC 1951) — non è presente alcun wrapper zlib (RFC 1950) o gzip (RFC 1952). Python zlib.decompress(b, wbits=-15), browser new DecompressionStream("deflate-raw"), Node\ fflate.inflateSync\ 3. decodificare in UTF-8 e analizzare come JSON\ 4. Esempio per verificare la propria implementazione\ payload: "q1ZyCnFWsqpWyk0syg6oULJSsjQ3NTDQM1Wq1VFyDfFAkTI2MzXQMwJLVVRWWfmFuTiiyBuamOoZKdXWAgA="\ decoded: { "BTC": { "markPx": "97500.5" }, "ETH": { "markPx": "3650.25" }, "xyz:NVDA": { "markPx": "145.2" }}
    4. Il primo messaggio è uno snapshot; i messaggi successivi contengono solo i coin che sono stati aggiornati. I campi senza aggiornamenti vengono omessi.

Indirizzo utente

Per sottoscrivere i dati dell'account associati a un account principale o a un subaccount, è necessario passare l'indirizzo effettivo di tale account. Un errore comune è utilizzare l'indirizzo del wallet agente, che produce un risultato vuoto.

Formati dei dati

Il server risponde alle sottoscrizioni riuscite con un messaggio contenente la proprietà channel impostata su "subscriptionResponse", insieme al campo data che fornisce la sottoscrizione originale. Il server inizierà quindi a inviare messaggi con la proprietà channel impostata sul tipo di sottoscrizione corrispondente, ad es. "allMids", e con il campo data che fornisce i dati sottoscritti.

Il formato del campo data dipende dal tipo di sottoscrizione:

  • AllMids: tutti i prezzi mid.
  • Formato: AllMids { mids: Record<string, string> }
  • Notification: un messaggio di notifica.
  • Formato: Notification { notification: string }
  • WebData3: informazioni aggregate su un utente, utilizzate principalmente dal frontend.
  • Formato: WebData3
  • WsTrade[]: un array di aggiornamenti delle operazioni.
  • Formato: WsTrade[]
  • WsBook: aggiornamenti dello snapshot del book degli ordini.
  • Formato: WsBook { coin: string; levels: [Array<WsLevel>, Array<WsLevel>]; time: number; }
  • WsOrder: aggiornamenti degli ordini dell'utente.
  • Formato: WsOrder[]
  • WsUserEvent: eventi utente che non sono aggiornamenti degli ordini
  • Formato: WsUserEvent { "fills": [WsFill] | "funding": WsUserFunding | "liquidation": WsLiquidation | "nonUserCancel": [WsNonUserCancel] }
  • WsUserFills : snapshot dei fill seguito dai fill in streaming
  • WsUserFundings : snapshot dei pagamenti di funding seguito dai pagamenti di funding a ogni ora
  • WsUserNonFundingLedgerUpdates: aggiornamenti del ledger che non includono i pagamenti di funding: prelievi, depositi, trasferimenti e liquidazioni
  • WsBbo : aggiornamenti Bbo inviati solo se il bbo cambia in un blocco
  • WsSpotState : aggiornamento dello stato spot.
  • WsAllDexsClearinghouseState : stati del clearinghouse su tutti i dex per un utente specifico
  • WsAllDexsAssetCtxs : contesti degli asset su tutti i dex
  • WsOutcomeMetaUpdates : modifiche ai metadati degli outcome

Per gli endpoint utente in streaming come WsUserFills,WsUserFundings il primo messaggio ha isSnapshot: true e i successivi aggiornamenti in streaming hanno isSnapshot: false.

Definizioni dei tipi di dati

Di seguito sono riportate le definizioni dei tipi di dati utilizzati nell'API WebSocket:

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;
}

Si noti che i tipi di dati sopra riportati sono in formato TypeScript e che il loro utilizzo corrisponde ai rispettivi tipi di sottoscrizione.

Esempi

Di seguito alcuni esempi di sottoscrizione a flussi diversi tramite i messaggi di sottoscrizione:

  1. Sottoscrizione a tutti i prezzi mid:

json { "method": "subscribe", "subscription": { "type": "allMids" } } 2. Sottoscrizione alle notifiche per un utente specifico:

json { "method": "subscribe", "subscription": { "type": "notification", "user": "<address>" } } 3. Sottoscrizione ai dati web per un utente specifico:

json { "method": "subscribe", "subscription": { "type": "webData3", "user": "<address>" } } 4. Sottoscrizione agli aggiornamenti delle candele per un coin e un intervallo specifici:

json { "method": "subscribe", "subscription": { "type": "candle", "coin": "<coin_symbol>", "interval": "<candle_interval>" } } 5. Sottoscrizione agli aggiornamenti del book degli ordini per un coin specifico:

json { "method": "subscribe", "subscription": { "type": "l2Book", "coin": "<coin_symbol>" } } 6. Sottoscrizione alle operazioni per un coin specifico:

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

Annullamento della sottoscrizione ai flussi WebSocket

Per annullare la sottoscrizione a uno specifico flusso di dati sull'API WebSocket di Hyperliquid, è necessario inviare un messaggio di annullamento con il seguente formato:

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

L'oggetto subscription deve corrispondere al messaggio di sottoscrizione originale inviato al momento della sottoscrizione al flusso. Ciò consente al server di identificare lo specifico flusso da cui si desidera annullare la sottoscrizione. Inviando questo messaggio di annullamento, si comunica al server di interrompere l'invio di ulteriori aggiornamenti per il flusso specificato.

Si noti che l'annullamento della sottoscrizione a uno specifico flusso non influisce sulle altre sottoscrizioni eventualmente attive in quel momento. Per annullare la sottoscrizione a più flussi, è possibile inviare più messaggi di annullamento, ciascuno con i dettagli di sottoscrizione appropriati.

Fonte ufficiale: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions
Istantanea della fonte: · Mirror generato: · Traduzione della community; fa fede la versione inglese
Traduzione non ufficiale della community della documentazione Hyperliquid. Contenuti © Hyperliquid; fa fede la versione inglese. Fonte: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions