@0xarchive/sdk 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -305,11 +305,22 @@ var WsChannelSchema = z.enum([
305
305
  "lighter_candles",
306
306
  "lighter_open_interest",
307
307
  "lighter_funding",
308
+ "lighter_l3_orderbook",
308
309
  "hip3_orderbook",
309
310
  "hip3_trades",
310
311
  "hip3_candles",
311
312
  "hip3_open_interest",
312
- "hip3_funding"
313
+ "hip3_funding",
314
+ "hip3_liquidations",
315
+ "hip4_orderbook",
316
+ "hip4_trades",
317
+ "hip4_open_interest",
318
+ "l4_diffs",
319
+ "l4_orders",
320
+ "hip3_l4_diffs",
321
+ "hip3_l4_orders",
322
+ "hip4_l4_diffs",
323
+ "hip4_l4_orders"
313
324
  ]);
314
325
  var WsConnectionStateSchema = z.enum(["connecting", "connected", "disconnected", "reconnecting"]);
315
326
  var WsSubscribedSchema = z.object({
@@ -405,6 +416,14 @@ var WsStreamStoppedSchema = z.object({
405
416
  type: z.literal("stream_stopped"),
406
417
  snapshots_sent: z.number()
407
418
  });
419
+ var WsOutcomeSettledSchema = z.object({
420
+ type: z.literal("outcome_settled"),
421
+ coin: z.string(),
422
+ outcome_id: z.number(),
423
+ side: z.number(),
424
+ settlement_value: z.number().optional(),
425
+ settlement_at: z.string().optional()
426
+ });
408
427
  var WsServerMessageSchema = z.discriminatedUnion("type", [
409
428
  WsSubscribedSchema,
410
429
  WsUnsubscribedSchema,
@@ -422,7 +441,8 @@ var WsServerMessageSchema = z.discriminatedUnion("type", [
422
441
  WsStreamProgressSchema,
423
442
  WsHistoricalBatchSchema,
424
443
  WsStreamCompletedSchema,
425
- WsStreamStoppedSchema
444
+ WsStreamStoppedSchema,
445
+ WsOutcomeSettledSchema
426
446
  ]);
427
447
  var OrderBookResponseSchema = ApiResponseSchema(OrderBookSchema);
428
448
  var OrderBookArrayResponseSchema = ApiResponseSchema(z.array(OrderBookSchema));
@@ -972,16 +992,26 @@ var TradesResource = class {
972
992
  /**
973
993
  * Get most recent trades for a symbol.
974
994
  *
975
- * Note: This method is available for Lighter (client.lighter.trades.recent())
976
- * and HIP-3 (client.hyperliquid.hip3.trades.recent()) which have real-time data
977
- * ingestion. Hyperliquid uses hourly backfill so this endpoint is not available
978
- * for Hyperliquid.
995
+ * Note: This method is available on Lighter (`client.lighter.trades.recent()`),
996
+ * HIP-3 (`client.hyperliquid.hip3.trades.recent()`), and HIP-4
997
+ * (`client.hyperliquid.hip4.trades.recent()`) which have real-time ingestion.
998
+ * Hyperliquid uses hourly S3 backfill and does NOT expose a recent endpoint —
999
+ * calling `client.hyperliquid.trades.recent()` (or the legacy
1000
+ * `client.trades.recent()`) throws a structured `OxArchiveError` rather than
1001
+ * letting the request fail with an opaque JSON parse error.
979
1002
  *
980
1003
  * @param symbol - The symbol (e.g., 'BTC', 'ETH')
981
1004
  * @param limit - Number of trades to return (default: 100)
982
1005
  * @returns Array of recent trades
1006
+ * @throws {OxArchiveError} When called on the bare Hyperliquid namespace.
983
1007
  */
984
1008
  async recent(symbol, limit) {
1009
+ if (this.basePath === "/v1/hyperliquid" || this.basePath === "/v1") {
1010
+ throw new OxArchiveError(
1011
+ "trades.recent() is not available on Hyperliquid (no real-time ingestion). Use client.hyperliquid.trades.list(symbol, { start, end }) with a time range, or call recent() on a real-time namespace: client.hyperliquid.hip3.trades.recent(), client.hyperliquid.hip4.trades.recent(), or client.lighter.trades.recent().",
1012
+ 404
1013
+ );
1014
+ }
985
1015
  const response = await this.http.get(
986
1016
  `${this.basePath}/trades/${this.coinTransform(symbol)}/recent`,
987
1017
  { limit },
@@ -1086,6 +1116,61 @@ var Hip3InstrumentsResource = class {
1086
1116
  return response.data;
1087
1117
  }
1088
1118
  };
1119
+ var Hip4InstrumentsResource = class {
1120
+ constructor(http, basePath = "/v1/hyperliquid/hip4", coinTransform) {
1121
+ this.http = http;
1122
+ this.basePath = basePath;
1123
+ this.coinTransform = coinTransform || ((c) => encodeURIComponent(c));
1124
+ }
1125
+ coinTransform;
1126
+ async list() {
1127
+ const response = await this.http.get(
1128
+ `${this.basePath}/instruments`
1129
+ );
1130
+ return response.data;
1131
+ }
1132
+ async get(coin) {
1133
+ const response = await this.http.get(
1134
+ `${this.basePath}/instruments/${this.coinTransform(coin)}`
1135
+ );
1136
+ return response.data;
1137
+ }
1138
+ };
1139
+ var Hip4OutcomesResource = class {
1140
+ constructor(http, basePath = "/v1/hyperliquid/hip4") {
1141
+ this.http = http;
1142
+ this.basePath = basePath;
1143
+ }
1144
+ /** List per-outcome aggregates. `aggregatedOi` is omitted on list responses. */
1145
+ async list(params) {
1146
+ const response = await this.http.get(
1147
+ `${this.basePath}/outcomes`,
1148
+ params
1149
+ );
1150
+ return {
1151
+ data: response.data,
1152
+ nextCursor: response.meta.nextCursor
1153
+ };
1154
+ }
1155
+ /** Get a single outcome aggregate. Response includes `aggregatedOi`. */
1156
+ async get(outcomeId) {
1157
+ const response = await this.http.get(
1158
+ `${this.basePath}/outcomes/${outcomeId}`
1159
+ );
1160
+ return response.data;
1161
+ }
1162
+ /**
1163
+ * Look up an outcome aggregate by its synthesized slug. Accepts the
1164
+ * per-outcome slug (`btc-above-78213-may-04-0600`) OR a per-side slug
1165
+ * (`btc-above-78213-yes-may-04-0600`). Response includes `aggregatedOi`.
1166
+ */
1167
+ async getBySlug(slug) {
1168
+ const response = await this.http.get(
1169
+ `${this.basePath}/outcomes/by-slug/${slug}`
1170
+ );
1171
+ return response.data;
1172
+ }
1173
+ };
1089
1174
 
1090
1175
  // src/resources/funding.ts
1091
1176
  var FundingResource = class {
@@ -1278,7 +1363,7 @@ var DataQualityResource = class {
1278
1363
  /**
1279
1364
  * Get overall system health status
1280
1365
  *
1281
- * @returns StatusResponse with overall status, per-exchange status,
1366
+ * @returns StatusResponse with overall status, per-scope status,
1282
1367
  * per-data-type status, and active incident count
1283
1368
  *
1284
1369
  * @example
@@ -1297,9 +1382,9 @@ var DataQualityResource = class {
1297
1382
  // Coverage Endpoints
1298
1383
  // ===========================================================================
1299
1384
  /**
1300
- * Get data coverage summary for all exchanges
1385
+ * Get data coverage summary across venue APIs
1301
1386
  *
1302
- * @returns CoverageResponse with coverage info for all exchanges and data types
1387
+ * @returns CoverageResponse with coverage info for supported venue APIs and data types
1303
1388
  *
1304
1389
  * @example
1305
1390
  * ```typescript
@@ -1316,10 +1401,10 @@ var DataQualityResource = class {
1316
1401
  return this.http.get(`${this.basePath}/coverage`);
1317
1402
  }
1318
1403
  /**
1319
- * Get data coverage for a specific exchange
1404
+ * Get data coverage for a specific venue scope
1320
1405
  *
1321
- * @param exchange - Exchange name ('hyperliquid', 'lighter', or 'hip3')
1322
- * @returns ExchangeCoverage with coverage info for all data types on this exchange
1406
+ * @param exchange - Venue scope ('hyperliquid', 'lighter', 'hip3', or 'hip4')
1407
+ * @returns ExchangeCoverage with coverage info for all data types on this venue scope
1323
1408
  *
1324
1409
  * @example
1325
1410
  * ```typescript
@@ -1333,12 +1418,12 @@ var DataQualityResource = class {
1333
1418
  );
1334
1419
  }
1335
1420
  /**
1336
- * Get data coverage for a specific symbol on an exchange
1421
+ * Get data coverage for a specific symbol on a venue scope
1337
1422
  *
1338
1423
  * Includes gap detection, empirical data cadence, and hour-level historical coverage.
1339
1424
  * Supports optional time bounds for gap detection (default: last 30 days).
1340
1425
  *
1341
- * @param exchange - Exchange name ('hyperliquid', 'lighter', or 'hip3')
1426
+ * @param exchange - Venue scope ('hyperliquid', 'lighter', 'hip3', or 'hip4')
1342
1427
  * @param symbol - Symbol name (e.g., 'BTC', 'ETH', or HIP3 coins like 'xyz:XYZ100')
1343
1428
  * @param options - Optional time bounds for gap detection window
1344
1429
  * @returns SymbolCoverageResponse with per-data-type coverage including gaps, cadence, and historical coverage
@@ -1416,7 +1501,7 @@ var DataQualityResource = class {
1416
1501
  // Latency Endpoints
1417
1502
  // ===========================================================================
1418
1503
  /**
1419
- * Get current latency metrics for all exchanges
1504
+ * Get current latency metrics for supported venue APIs
1420
1505
  *
1421
1506
  * @returns LatencyResponse with WebSocket, REST API, and data freshness metrics
1422
1507
  *
@@ -1718,7 +1803,7 @@ var L2OrderBookResource = class {
1718
1803
  if (params?.timestamp != null) query.timestamp = params.timestamp;
1719
1804
  if (params?.depth != null) query.depth = params.depth;
1720
1805
  const resp = await this.http.get(
1721
- `${this.basePath}/orderbook/${encodeURIComponent(coin)}/l2`,
1806
+ `${this.basePath}/orderbook/${coin}/l2`,
1722
1807
  query
1723
1808
  );
1724
1809
  return resp.data;
@@ -1727,7 +1812,7 @@ var L2OrderBookResource = class {
1727
1812
  async history(symbol, params) {
1728
1813
  const coin = this.coinTransform(symbol);
1729
1814
  const resp = await this.http.get(
1730
- `${this.basePath}/orderbook/${encodeURIComponent(coin)}/l2/history`,
1815
+ `${this.basePath}/orderbook/${coin}/l2/history`,
1731
1816
  params
1732
1817
  );
1733
1818
  return {
@@ -1739,7 +1824,7 @@ var L2OrderBookResource = class {
1739
1824
  async diffs(symbol, params) {
1740
1825
  const coin = this.coinTransform(symbol);
1741
1826
  const resp = await this.http.get(
1742
- `${this.basePath}/orderbook/${encodeURIComponent(coin)}/l2/diffs`,
1827
+ `${this.basePath}/orderbook/${coin}/l2/diffs`,
1743
1828
  params
1744
1829
  );
1745
1830
  return {
@@ -1832,6 +1917,10 @@ var HyperliquidClient = class {
1832
1917
  * HIP-3 builder-deployed perpetuals (February 2026+)
1833
1918
  */
1834
1919
  hip3;
1920
+ /**
1921
+ * HIP-4 outcome markets (binary YES/NO; May 2026+)
1922
+ */
1923
+ hip4;
1835
1924
  http;
1836
1925
  constructor(http) {
1837
1926
  this.http = http;
@@ -1847,6 +1936,7 @@ var HyperliquidClient = class {
1847
1936
  this.l4Orderbook = new L4OrderBookResource(http, basePath);
1848
1937
  this.l2Orderbook = new L2OrderBookResource(http, basePath);
1849
1938
  this.hip3 = new Hip3Client(http);
1939
+ this.hip4 = new Hip4Client(http);
1850
1940
  }
1851
1941
  /**
1852
1942
  * Get per-symbol data freshness across all data types
@@ -1999,6 +2089,205 @@ var Hip3Client = class {
1999
2089
  };
2000
2090
  }
2001
2091
  };
2092
+ var Hip4Client = class {
2093
+ /**
2094
+ * HIP-4 per-side instruments (one row per `#N`).
2095
+ */
2096
+ instruments;
2097
+ /**
2098
+ * HIP-4 per-outcome aggregates (one row per outcome). HIP-4-specific, no HIP-3 analog.
2099
+ */
2100
+ outcomes;
2101
+ /**
2102
+ * L2 orderbook snapshots (Pro+).
2103
+ */
2104
+ orderbook;
2105
+ /**
2106
+ * Trade/fill history.
2107
+ */
2108
+ trades;
2109
+ /**
2110
+ * Open interest (per side).
2111
+ */
2112
+ openInterest;
2113
+ /**
2114
+ * Order history, flow, and TP/SL (Pro+).
2115
+ */
2116
+ orders;
2117
+ /**
2118
+ * L4 orderbook (snapshots, diffs, history).
2119
+ */
2120
+ l4Orderbook;
2121
+ /**
2122
+ * L2 full-depth orderbook (derived from L4).
2123
+ */
2124
+ l2Orderbook;
2125
+ http;
2126
+ constructor(http) {
2127
+ this.http = http;
2128
+ const basePath = "/v1/hyperliquid/hip4";
2129
+ const coinTransform = (c) => encodeURIComponent(c);
2130
+ this.instruments = new Hip4InstrumentsResource(http, basePath, coinTransform);
2131
+ this.outcomes = new Hip4OutcomesResource(http, basePath);
2132
+ this.orderbook = new OrderBookResource(http, basePath, coinTransform);
2133
+ this.trades = new TradesResource(http, basePath, coinTransform);
2134
+ this.openInterest = new OpenInterestResource(http, basePath, coinTransform);
2135
+ this.orders = new OrdersResource(http, basePath, coinTransform);
2136
+ this.l4Orderbook = new L4OrderBookResource(http, basePath, coinTransform);
2137
+ this.l2Orderbook = new L2OrderBookResource(http, basePath, coinTransform);
2138
+ }
2139
+ /** @internal Encode a HIP-4 coin for use in URL paths. */
2140
+ encodeCoin(coin) {
2141
+ return encodeURIComponent(coin);
2142
+ }
2143
+ /**
2144
+ * List per-outcome aggregates. `aggregatedOi` is omitted on list responses.
2145
+ */
2146
+ async listOutcomes(params) {
2147
+ return this.outcomes.list(params);
2148
+ }
2149
+ /**
2150
+ * Get a single outcome aggregate (includes `aggregatedOi`).
2151
+ */
2152
+ async getOutcome(outcomeId) {
2153
+ return this.outcomes.get(outcomeId);
2154
+ }
2155
+ /**
2156
+ * Look up an outcome aggregate by slug. Accepts the per-outcome slug
2157
+ * (e.g. `btc-above-78213-may-04-0600`) OR a per-side slug
2158
+ * (e.g. `btc-above-78213-yes-may-04-0600`). Includes `aggregatedOi`.
2159
+ */
2160
+ async getOutcomeBySlug(slug) {
2161
+ return this.outcomes.getBySlug(slug);
2162
+ }
2163
+ /**
2164
+ * List all per-side instruments (one row per `#N`).
2165
+ */
2166
+ async getInstruments() {
2167
+ return this.instruments.list();
2168
+ }
2169
+ /**
2170
+ * Get a single per-side instrument by coin (e.g. `#0`).
2171
+ */
2172
+ async getInstrument(coin) {
2173
+ return this.instruments.get(coin);
2174
+ }
2175
+ /**
2176
+ * Get current L2 orderbook snapshot for a HIP-4 coin (Pro+).
2177
+ * @param coin Coin string with leading `#` (e.g. `#0`).
2178
+ */
2179
+ async getOrderbook(coin, params) {
2180
+ return this.orderbook.get(coin, params);
2181
+ }
2182
+ /**
2183
+ * Get historical L2 orderbook snapshots for a HIP-4 coin (Pro+).
2184
+ */
2185
+ async getOrderbookHistory(coin, params) {
2186
+ return this.orderbook.history(coin, params);
2187
+ }
2188
+ /**
2189
+ * Get historical fills for a HIP-4 coin.
2190
+ */
2191
+ async getTrades(coin, params) {
2192
+ return this.trades.list(coin, params);
2193
+ }
2194
+ /**
2195
+ * Get most recent N fills for a HIP-4 coin (latest first).
2196
+ */
2197
+ async getTradesRecent(coin, limit) {
2198
+ return this.trades.recent(coin, limit);
2199
+ }
2200
+ /**
2201
+ * Get per-side open interest history for a HIP-4 coin.
2202
+ * Note: `markPrice` on the response is an implied probability (0..1), not USD.
2203
+ */
2204
+ async getOpenInterest(coin, params) {
2205
+ return this.openInterest.history(coin, params);
2206
+ }
2207
+ /**
2208
+ * Get current per-side open interest for a HIP-4 coin.
2209
+ * Note: `markPrice` on the response is an implied probability (0..1), not USD.
2210
+ */
2211
+ async getOpenInterestCurrent(coin) {
2212
+ return this.openInterest.current(coin);
2213
+ }
2214
+ /**
2215
+ * Get combined market summary for a HIP-4 coin.
2216
+ * @param coin Either bare numeric form (`'0'`) or `#`-prefixed form (`'#0'`). The SDK URL-encodes `#` so both work.
2217
+ */
2218
+ async getSummary(coin) {
2219
+ const response = await this.http.get(
2220
+ `/v1/hyperliquid/hip4/summary/${this.encodeCoin(coin)}`,
2221
+ void 0,
2222
+ this.http.validationEnabled ? CoinSummaryResponseSchema : void 0
2223
+ );
2224
+ return response.data;
2225
+ }
2226
+ /**
2227
+ * Get per-symbol data freshness across all HIP-4 data types.
2228
+ * @param coin Either bare numeric form (`'0'`) or `#`-prefixed form (`'#0'`). The SDK URL-encodes `#` so both work.
2229
+ */
2230
+ async getFreshness(coin) {
2231
+ const response = await this.http.get(
2232
+ `/v1/hyperliquid/hip4/freshness/${this.encodeCoin(coin)}`,
2233
+ void 0,
2234
+ this.http.validationEnabled ? CoinFreshnessResponseSchema : void 0
2235
+ );
2236
+ return response.data;
2237
+ }
2238
+ /**
2239
+ * Get mid-price history for a HIP-4 coin.
2240
+ * Note: returned `markPrice`/`midPrice` are probabilities (0..1), not USD.
2241
+ * @param coin Either bare numeric form (`'0'`) or `#`-prefixed form (`'#0'`). The SDK URL-encodes `#` so both work.
2242
+ */
2243
+ async getPrices(coin, params) {
2244
+ const response = await this.http.get(
2245
+ `/v1/hyperliquid/hip4/prices/${this.encodeCoin(coin)}`,
2246
+ params,
2247
+ this.http.validationEnabled ? PriceSnapshotArrayResponseSchema : void 0
2248
+ );
2249
+ return {
2250
+ data: response.data,
2251
+ nextCursor: response.meta.nextCursor
2252
+ };
2253
+ }
2254
+ /**
2255
+ * Get order lifecycle events for a HIP-4 coin (Pro+).
2256
+ */
2257
+ async getOrderHistory(coin, params) {
2258
+ return this.orders.history(coin, params);
2259
+ }
2260
+ /**
2261
+ * Get time-bucketed order-flow aggregates for a HIP-4 coin (Pro+).
2262
+ */
2263
+ async getOrderFlow(coin, params) {
2264
+ return this.orders.flow(coin, params);
2265
+ }
2266
+ /**
2267
+ * Get TP/SL orders for a HIP-4 coin (Pro+).
2268
+ */
2269
+ async getTpsl(coin, params) {
2270
+ return this.orders.tpsl(coin, params);
2271
+ }
2272
+ /**
2273
+ * Get full L4 reconstruction (current) for a HIP-4 coin (Pro+).
2274
+ */
2275
+ async getL4Orderbook(coin, params) {
2276
+ return this.l4Orderbook.get(coin, params);
2277
+ }
2278
+ /**
2279
+ * Get L4 diffs (event stream) for a HIP-4 coin (Pro+).
2280
+ */
2281
+ async getL4Diffs(coin, params) {
2282
+ return this.l4Orderbook.diffs(coin, params);
2283
+ }
2284
+ /**
2285
+ * Get L4 checkpoint history for a HIP-4 coin (Build+; hard cap limit=10).
2286
+ */
2287
+ async getL4History(coin, params) {
2288
+ return this.l4Orderbook.history(coin, params);
2289
+ }
2290
+ };
2002
2291
  var LighterClient = class {
2003
2292
  /**
2004
2293
  * Order book data (L2 snapshots)
@@ -2253,7 +2542,9 @@ var OxArchiveWs = class {
2253
2542
  streamCompleteHandlers = [];
2254
2543
  orderbookHandlers = [];
2255
2544
  tradesHandlers = [];
2545
+ liquidationsHandlers = [];
2256
2546
  gapHandlers = [];
2547
+ outcomeSettledHandlers = [];
2257
2548
  constructor(options) {
2258
2549
  this.options = {
2259
2550
  apiKey: options.apiKey,
@@ -2337,7 +2628,7 @@ var OxArchiveWs = class {
2337
2628
  const key = this.subscriptionKey(channel, coin);
2338
2629
  this.subscriptions.add(key);
2339
2630
  if (this.isConnected()) {
2340
- this.send({ op: "subscribe", channel, coin });
2631
+ this.send({ op: "subscribe", channel, symbol: coin });
2341
2632
  }
2342
2633
  }
2343
2634
  /**
@@ -2371,7 +2662,7 @@ var OxArchiveWs = class {
2371
2662
  const key = this.subscriptionKey(channel, coin);
2372
2663
  this.subscriptions.delete(key);
2373
2664
  if (this.isConnected()) {
2374
- this.send({ op: "unsubscribe", channel, coin });
2665
+ this.send({ op: "unsubscribe", channel, symbol: coin });
2375
2666
  }
2376
2667
  }
2377
2668
  /**
@@ -2398,6 +2689,49 @@ var OxArchiveWs = class {
2398
2689
  unsubscribeAllTickers() {
2399
2690
  this.unsubscribe("all_tickers");
2400
2691
  }
2692
+ /**
2693
+ * Subscribe to live liquidation events for a coin (Hyperliquid).
2694
+ *
2695
+ * Each message is a fill row with `is_liquidation: true`. Same wire shape as
2696
+ * trades. Live as of v1.6.0 (Hyperliquid + HIP-3 nodes); historical replay
2697
+ * also supported via `replay('liquidations', ...)`.
2698
+ */
2699
+ subscribeLiquidations(coin) {
2700
+ this.subscribe("liquidations", coin);
2701
+ }
2702
+ /** Unsubscribe from live liquidation events (Hyperliquid). */
2703
+ unsubscribeLiquidations(coin) {
2704
+ this.unsubscribe("liquidations", coin);
2705
+ }
2706
+ /**
2707
+ * Subscribe to live HIP-3 liquidation events for a coin.
2708
+ * Each message is a fill row with `is_liquidation: true`.
2709
+ */
2710
+ subscribeHip3Liquidations(coin) {
2711
+ this.subscribe("hip3_liquidations", coin);
2712
+ }
2713
+ /** Unsubscribe from live HIP-3 liquidation events. */
2714
+ unsubscribeHip3Liquidations(coin) {
2715
+ this.unsubscribe("hip3_liquidations", coin);
2716
+ }
2717
+ /**
2718
+ * Subscribe to a HIP-4 channel for a given outcome coin.
2719
+ *
2720
+ * @param channel One of `hip4_orderbook`, `hip4_trades`, `hip4_open_interest`,
2721
+ * `hip4_l4_diffs`, `hip4_l4_orders`.
2722
+ * @param coin HIP-4 coin (e.g. `'#0'` or `'0'`). The bare numeric form is
2723
+ * recommended; both are accepted by the backend.
2724
+ */
2725
+ subscribeHip4(channel, coin) {
2726
+ const fullChannel = channel.startsWith("hip4_") ? channel : `hip4_${channel}`;
2727
+ this.subscribe(fullChannel, coin);
2728
+ }
2729
+ /** Unsubscribe from a HIP-4 channel for a given outcome coin. Accepts the
2730
+ * short channel form (`'orderbook'`) or the full form (`'hip4_orderbook'`). */
2731
+ unsubscribeHip4(channel, coin) {
2732
+ const fullChannel = channel.startsWith("hip4_") ? channel : `hip4_${channel}`;
2733
+ this.unsubscribe(fullChannel, coin);
2734
+ }
2401
2735
  // ==========================================================================
2402
2736
  // Historical Replay (Option B) - Like Tardis.dev
2403
2737
  // ==========================================================================
@@ -2420,7 +2754,7 @@ var OxArchiveWs = class {
2420
2754
  this.send({
2421
2755
  op: "replay",
2422
2756
  channel,
2423
- coin,
2757
+ symbol: coin,
2424
2758
  start: options.start,
2425
2759
  end: options.end,
2426
2760
  speed: options.speed ?? 1,
@@ -2455,7 +2789,7 @@ var OxArchiveWs = class {
2455
2789
  this.send({
2456
2790
  op: "replay",
2457
2791
  channels,
2458
- coin,
2792
+ symbol: coin,
2459
2793
  start: options.start,
2460
2794
  end: options.end,
2461
2795
  speed: options.speed ?? 1,
@@ -2511,7 +2845,7 @@ var OxArchiveWs = class {
2511
2845
  this.send({
2512
2846
  op: "stream",
2513
2847
  channel,
2514
- coin,
2848
+ symbol: coin,
2515
2849
  start: options.start,
2516
2850
  end: options.end,
2517
2851
  batch_size: options.batchSize ?? 1e3,
@@ -2548,7 +2882,7 @@ var OxArchiveWs = class {
2548
2882
  this.send({
2549
2883
  op: "stream",
2550
2884
  channels,
2551
- coin,
2885
+ symbol: coin,
2552
2886
  start: options.start,
2553
2887
  end: options.end,
2554
2888
  batch_size: options.batchSize ?? 1e3,
@@ -2687,6 +3021,44 @@ var OxArchiveWs = class {
2687
3021
  onTrades(handler) {
2688
3022
  this.tradesHandlers.push(handler);
2689
3023
  }
3024
+ /**
3025
+ * Helper to handle live liquidation events for both `liquidations` and
3026
+ * `hip3_liquidations` channels. Each item is a fill row with
3027
+ * `is_liquidation: true`, surfaced as a `Trade` (the wire shape matches
3028
+ * trades exactly).
3029
+ *
3030
+ * @param handler Called with the channel, coin, and parsed Trade array.
3031
+ *
3032
+ * @example
3033
+ * ```typescript
3034
+ * ws.onLiquidations((channel, coin, fills) => {
3035
+ * for (const f of fills) {
3036
+ * console.log(`${channel} ${coin} liq: ${f.side} ${f.size}@${f.price}`);
3037
+ * }
3038
+ * });
3039
+ * ws.subscribeLiquidations('BTC');
3040
+ * ws.subscribeHip3Liquidations('hyna:BTC');
3041
+ * ```
3042
+ */
3043
+ onLiquidations(handler) {
3044
+ this.liquidationsHandlers.push(handler);
3045
+ }
3046
+ /**
3047
+ * Handle HIP-4 outcome settlement events. Pushed once per `(outcome_id, side)`
3048
+ * when the outcome flips to settled. After this event the server proactively
3049
+ * unsubscribes the client from every hip4_* subscription on the settled coin —
3050
+ * treat the event as a terminal signal for that coin.
3051
+ *
3052
+ * @example
3053
+ * ```typescript
3054
+ * ws.onOutcomeSettled((coin, outcomeId, side, value, at) => {
3055
+ * console.log(`${coin} (outcome ${outcomeId} side ${side}) settled to ${value} at ${at}`);
3056
+ * });
3057
+ * ```
3058
+ */
3059
+ onOutcomeSettled(handler) {
3060
+ this.outcomeSettledHandlers.push(handler);
3061
+ }
2690
3062
  // Private methods
2691
3063
  send(message) {
2692
3064
  if (this.ws?.readyState === WebSocket.OPEN) {
@@ -2814,16 +3186,28 @@ var OxArchiveWs = class {
2814
3186
  break;
2815
3187
  }
2816
3188
  case "data": {
2817
- if (message.channel === "orderbook") {
3189
+ if (message.channel === "orderbook" || message.channel === "hip3_orderbook" || message.channel === "hip4_orderbook" || message.channel === "lighter_orderbook") {
2818
3190
  const orderbook = transformOrderbook(message.coin, message.data);
2819
3191
  for (const handler of this.orderbookHandlers) {
2820
3192
  handler(message.coin, orderbook);
2821
3193
  }
2822
- } else if (message.channel === "trades") {
3194
+ } else if (message.channel === "trades" || message.channel === "hip3_trades" || message.channel === "hip4_trades" || message.channel === "lighter_trades") {
2823
3195
  const trades = transformTrades(message.coin, message.data);
2824
3196
  for (const handler of this.tradesHandlers) {
2825
3197
  handler(message.coin, trades);
2826
3198
  }
3199
+ } else if (message.channel === "liquidations" || message.channel === "hip3_liquidations") {
3200
+ const fills = transformTrades(message.coin, message.data);
3201
+ for (const handler of this.liquidationsHandlers) {
3202
+ handler(message.channel, message.coin, fills);
3203
+ }
3204
+ }
3205
+ break;
3206
+ }
3207
+ case "outcome_settled": {
3208
+ const msg = message;
3209
+ for (const handler of this.outcomeSettledHandlers) {
3210
+ handler(msg.coin, msg.outcome_id, msg.side, msg.settlement_value, msg.settlement_at);
2827
3211
  }
2828
3212
  break;
2829
3213
  }
@@ -2975,6 +3359,7 @@ export {
2975
3359
  FundingRateResponseSchema,
2976
3360
  FundingRateSchema,
2977
3361
  Hip3Client,
3362
+ Hip4Client,
2978
3363
  HyperliquidClient,
2979
3364
  InstrumentArrayResponseSchema,
2980
3365
  InstrumentResponseSchema,
@@ -3012,6 +3397,7 @@ export {
3012
3397
  WsErrorSchema,
3013
3398
  WsHistoricalBatchSchema,
3014
3399
  WsHistoricalDataSchema,
3400
+ WsOutcomeSettledSchema,
3015
3401
  WsPongSchema,
3016
3402
  WsReplayCompletedSchema,
3017
3403
  WsReplayPausedSchema,