Подписки
Эта страница описывает подписку на потоки данных с помощью WebSocket API.
Сообщения подписки
Чтобы подписаться на определённые каналы данных, необходимо отправить сообщение подписки. Формат сообщения подписки следующий:
{
"method": "subscribe",
"subscription": { ... }
}
Подтверждение подписки (subscription ack) предоставляет снимок предыдущих данных для данных временных рядов (например, исполнений пользователя). Эти сообщения-снимки помечены isSnapshot: true и могут быть проигнорированы, если предыдущие сообщения уже были обработаны.
Объект subscription содержит детали конкретного канала, на который вы хотите подписаться. Выберите один из следующих типов подписки и укажите соответствующие свойства:
allMids: * Сообщение подписки:{ "type": "allMids", "dex": "<dex>" }* Формат данных:AllMids* Полеdexзадаёт перп-декс, из которого берутся средние цены (mids). * Обратите внимание, что полеdexнеобязательно. Если оно не указано, используется первый перп-декс. Средние цены спот включаются только вместе с первым перп-дексом.notification: * Сообщение подписки:{ "type": "notification", "user": "<address>" }* Формат данных:NotificationwebData3: * Сообщение подписки:{ "type": "webData3", "user": "<address>" }* Формат данных:WebData3twapStates: * Сообщение подписки:{ "type": "twapStates", "user": "<address>", "dex": "<dex>" }* Формат данных:TwapStatesclearinghouseState:* Сообщение подписки:{ "type": "clearinghouseState", "user": "<address>", "dex": "<dex>" }* Формат данных:ClearinghouseStateopenOrders: * Сообщение подписки:{ "type": "openOrders", "user": "<address>", "dex": "<dex>" }* Формат данных:OpenOrderscandle: * Сообщение подписки:{ "type": "candle", "coin": "<coin_symbol>", "interval": "<candle_interval>" }* Поддерживаемые интервалы: "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "8h", "12h", "1d", "3d", "1w", "1M" * Формат данных:Candle[]l2Book: * Сообщение подписки:{ "type": "l2Book", "coin": "<coin_symbol>" }* Необязательные параметры:nSigFigs: int,mantissa: int,fast: boolean(5 уровней при fast, 20 уровней при slow) * Формат данных:WsBooktrades: * Сообщение подписки:{ "type": "trades", "coin": "<coin_symbol>" }* Формат данных:WsTrade[]orderUpdates:- Сообщение подписки:
{ "type": "orderUpdates", "user": "<address>" } - Формат данных:
WsOrder[]
- Сообщение подписки:
userEvents:- Сообщение подписки:
{ "type": "userEvents", "user": "<address>" } - Формат данных:
WsUserEvent - Примечание: имя канала для сообщений
userEvents—"channel": "user"
- Сообщение подписки:
userFills:- Сообщение подписки:
{ "type": "userFills", "user": "<address>" } - Необязательный параметр:
aggregateByTime: bool - Формат данных:
WsUserFills
- Сообщение подписки:
userFundings:- Сообщение подписки:
{ "type": "userFundings", "user": "<address>" } - Формат данных:
WsUserFundings
- Сообщение подписки:
userNonFundingLedgerUpdates:- Сообщение подписки:
{ "type": "userNonFundingLedgerUpdates", "user": "<address>" } - Формат данных:
WsUserNonFundingLedgerUpdates
- Сообщение подписки:
activeAssetCtx:- Сообщение подписки:
{ "type": "activeAssetCtx", "coin": "<coin_symbol>" } - Формат данных:
WsActiveAssetCtxилиWsActiveSpotAssetCtx
- Сообщение подписки:
activeAssetData: (поддерживает только перпы)- Сообщение подписки:
{ "type": "activeAssetData", "user": "<address>", "coin": "<coin_symbol>" } - Формат данных:
WsActiveAssetData
- Сообщение подписки:
userTwapSliceFills:- Сообщение подписки:
{ "type": "userTwapSliceFills", "user": "<address>" } - Формат данных:
WsUserTwapSliceFills
- Сообщение подписки:
userTwapHistory:- Сообщение подписки:
{ "type": "userTwapHistory", "user": "<address>" } - Формат данных:
WsUserTwapHistory
- Сообщение подписки:
bbo:- Сообщение подписки:
{ "type": "bbo", "coin": "<coin>" } - Формат данных:
WsBbo
- Сообщение подписки:
spotState- Сообщение подписки:
{ "type": "spotState", "user": "<address>", "isPortfolioMargin": bool } - Формат данных:
WsSpotState isPortfolioMargin— необязательный аргумент
- Сообщение подписки:
allDexsClearinghouseState- Сообщение подписки:
{ "type": "allDexsClearinghouseState", "user": "<address>" } - Формат данных:
WsAllDexsClearinghouseState
- Сообщение подписки:
allDexsAssetCtxs- Сообщение подписки:
{ "type": "allDexsAssetCtxs" } - Формат данных:
WsAllDexsAssetCtxs
- Сообщение подписки:
outcomeMetaUpdates- Сообщение подписки:
{ "type": "outcomeMetaUpdates" } - Формат данных:
WsOutcomeMetaUpdates
- Сообщение подписки:
fastAssetCtxs- { "method": "subscribe", "subscription": { "type": "fastAssetCtxs" } }
- Формат данных: закодированный в base64 и сжатый
WsFastAssetCtxs - Чтобы прочитать данные, примените по порядку:\
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="\ decoded:{ "BTC": { "markPx": "97500.5" }, "ETH": { "markPx": "3650.25" }, "xyz:NVDA": { "markPx": "145.2" }} - Первое сообщение является снимком, последующие сообщения содержат только обновившиеся монеты. Поля без обновлений опускаются.
Адрес пользователя
Чтобы подписаться на данные счёта, связанные с основным или суб-счётом, необходимо передать фактический адрес этого счёта. Распространённая ошибка — использование адреса агентского кошелька, что приводит к пустому результату.
Форматы данных
Сервер отвечает на успешные подписки сообщением, содержащим свойство 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: Состояния клирингового дома по всем дексам для конкретного пользователяWsAllDexsAssetCtxs: Контексты активов по всем дексамWsOutcomeMetaUpdates: Изменения метаданных исходов
Для потоковых пользовательских конечных точек, таких как 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, и их использование соответствует соответствующим типам подписки.
Примеры
Вот несколько примеров подписки на различные каналы с помощью сообщений подписки:
- Подписаться на все средние цены:
json
{ "method": "subscribe", "subscription": { "type": "allMids" } }
2. Подписаться на уведомления для конкретного пользователя:
json
{ "method": "subscribe", "subscription": { "type": "notification", "user": "<address>" } }
3. Подписаться на веб-данные конкретного пользователя:
json
{ "method": "subscribe", "subscription": { "type": "webData3", "user": "<address>" } }
4. Подписаться на обновления свечей для конкретной монеты и интервала:
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
Чтобы отписаться от определённого канала данных в WebSocket API Hyperliquid, необходимо отправить сообщение отписки в следующем формате:
{
"method": "unsubscribe",
"subscription": { ... }
}
Объект subscription должен совпадать с исходным сообщением подписки, отправленным при подписке на канал. Это позволяет серверу определить конкретный канал, от которого вы хотите отписаться. Отправляя это сообщение отписки, вы сообщаете серверу прекратить отправку дальнейших обновлений для указанного канала.
Обратите внимание, что отписка от определённого канала не влияет на другие подписки, активные в этот момент. Чтобы отписаться от нескольких каналов, можно отправить несколько сообщений отписки, каждое с соответствующими деталями подписки.