@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.js CHANGED
@@ -34,6 +34,7 @@ __export(index_exports, {
34
34
  FundingRateResponseSchema: () => FundingRateResponseSchema,
35
35
  FundingRateSchema: () => FundingRateSchema,
36
36
  Hip3Client: () => Hip3Client,
37
+ Hip4Client: () => Hip4Client,
37
38
  HyperliquidClient: () => HyperliquidClient,
38
39
  InstrumentArrayResponseSchema: () => InstrumentArrayResponseSchema,
39
40
  InstrumentResponseSchema: () => InstrumentResponseSchema,
@@ -71,6 +72,7 @@ __export(index_exports, {
71
72
  WsErrorSchema: () => WsErrorSchema,
72
73
  WsHistoricalBatchSchema: () => WsHistoricalBatchSchema,
73
74
  WsHistoricalDataSchema: () => WsHistoricalDataSchema,
75
+ WsOutcomeSettledSchema: () => WsOutcomeSettledSchema,
74
76
  WsPongSchema: () => WsPongSchema,
75
77
  WsReplayCompletedSchema: () => WsReplayCompletedSchema,
76
78
  WsReplayPausedSchema: () => WsReplayPausedSchema,
@@ -398,11 +400,22 @@ var WsChannelSchema = import_zod.z.enum([
398
400
  "lighter_candles",
399
401
  "lighter_open_interest",
400
402
  "lighter_funding",
403
+ "lighter_l3_orderbook",
401
404
  "hip3_orderbook",
402
405
  "hip3_trades",
403
406
  "hip3_candles",
404
407
  "hip3_open_interest",
405
- "hip3_funding"
408
+ "hip3_funding",
409
+ "hip3_liquidations",
410
+ "hip4_orderbook",
411
+ "hip4_trades",
412
+ "hip4_open_interest",
413
+ "l4_diffs",
414
+ "l4_orders",
415
+ "hip3_l4_diffs",
416
+ "hip3_l4_orders",
417
+ "hip4_l4_diffs",
418
+ "hip4_l4_orders"
406
419
  ]);
407
420
  var WsConnectionStateSchema = import_zod.z.enum(["connecting", "connected", "disconnected", "reconnecting"]);
408
421
  var WsSubscribedSchema = import_zod.z.object({
@@ -498,6 +511,14 @@ var WsStreamStoppedSchema = import_zod.z.object({
498
511
  type: import_zod.z.literal("stream_stopped"),
499
512
  snapshots_sent: import_zod.z.number()
500
513
  });
514
+ var WsOutcomeSettledSchema = import_zod.z.object({
515
+ type: import_zod.z.literal("outcome_settled"),
516
+ coin: import_zod.z.string(),
517
+ outcome_id: import_zod.z.number(),
518
+ side: import_zod.z.number(),
519
+ settlement_value: import_zod.z.number().optional(),
520
+ settlement_at: import_zod.z.string().optional()
521
+ });
501
522
  var WsServerMessageSchema = import_zod.z.discriminatedUnion("type", [
502
523
  WsSubscribedSchema,
503
524
  WsUnsubscribedSchema,
@@ -515,7 +536,8 @@ var WsServerMessageSchema = import_zod.z.discriminatedUnion("type", [
515
536
  WsStreamProgressSchema,
516
537
  WsHistoricalBatchSchema,
517
538
  WsStreamCompletedSchema,
518
- WsStreamStoppedSchema
539
+ WsStreamStoppedSchema,
540
+ WsOutcomeSettledSchema
519
541
  ]);
520
542
  var OrderBookResponseSchema = ApiResponseSchema(OrderBookSchema);
521
543
  var OrderBookArrayResponseSchema = ApiResponseSchema(import_zod.z.array(OrderBookSchema));
@@ -1065,16 +1087,26 @@ var TradesResource = class {
1065
1087
  /**
1066
1088
  * Get most recent trades for a symbol.
1067
1089
  *
1068
- * Note: This method is available for Lighter (client.lighter.trades.recent())
1069
- * and HIP-3 (client.hyperliquid.hip3.trades.recent()) which have real-time data
1070
- * ingestion. Hyperliquid uses hourly backfill so this endpoint is not available
1071
- * for Hyperliquid.
1090
+ * Note: This method is available on Lighter (`client.lighter.trades.recent()`),
1091
+ * HIP-3 (`client.hyperliquid.hip3.trades.recent()`), and HIP-4
1092
+ * (`client.hyperliquid.hip4.trades.recent()`) which have real-time ingestion.
1093
+ * Hyperliquid uses hourly S3 backfill and does NOT expose a recent endpoint —
1094
+ * calling `client.hyperliquid.trades.recent()` (or the legacy
1095
+ * `client.trades.recent()`) throws a structured `OxArchiveError` rather than
1096
+ * letting the request fail with an opaque JSON parse error.
1072
1097
  *
1073
1098
  * @param symbol - The symbol (e.g., 'BTC', 'ETH')
1074
1099
  * @param limit - Number of trades to return (default: 100)
1075
1100
  * @returns Array of recent trades
1101
+ * @throws {OxArchiveError} When called on the bare Hyperliquid namespace.
1076
1102
  */
1077
1103
  async recent(symbol, limit) {
1104
+ if (this.basePath === "/v1/hyperliquid" || this.basePath === "/v1") {
1105
+ throw new OxArchiveError(
1106
+ "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().",
1107
+ 404
1108
+ );
1109
+ }
1078
1110
  const response = await this.http.get(
1079
1111
  `${this.basePath}/trades/${this.coinTransform(symbol)}/recent`,
1080
1112
  { limit },
@@ -1179,6 +1211,61 @@ var Hip3InstrumentsResource = class {
1179
1211
  return response.data;
1180
1212
  }
1181
1213
  };
1214
+ var Hip4InstrumentsResource = class {
1215
+ constructor(http, basePath = "/v1/hyperliquid/hip4", coinTransform) {
1216
+ this.http = http;
1217
+ this.basePath = basePath;
1218
+ this.coinTransform = coinTransform || ((c) => encodeURIComponent(c));
1219
+ }
1220
+ coinTransform;
1221
+ async list() {
1222
+ const response = await this.http.get(
1223
+ `${this.basePath}/instruments`
1224
+ );
1225
+ return response.data;
1226
+ }
1227
+ async get(coin) {
1228
+ const response = await this.http.get(
1229
+ `${this.basePath}/instruments/${this.coinTransform(coin)}`
1230
+ );
1231
+ return response.data;
1232
+ }
1233
+ };
1234
+ var Hip4OutcomesResource = class {
1235
+ constructor(http, basePath = "/v1/hyperliquid/hip4") {
1236
+ this.http = http;
1237
+ this.basePath = basePath;
1238
+ }
1239
+ /** List per-outcome aggregates. `aggregatedOi` is omitted on list responses. */
1240
+ async list(params) {
1241
+ const response = await this.http.get(
1242
+ `${this.basePath}/outcomes`,
1243
+ params
1244
+ );
1245
+ return {
1246
+ data: response.data,
1247
+ nextCursor: response.meta.nextCursor
1248
+ };
1249
+ }
1250
+ /** Get a single outcome aggregate. Response includes `aggregatedOi`. */
1251
+ async get(outcomeId) {
1252
+ const response = await this.http.get(
1253
+ `${this.basePath}/outcomes/${outcomeId}`
1254
+ );
1255
+ return response.data;
1256
+ }
1257
+ /**
1258
+ * Look up an outcome aggregate by its synthesized slug. Accepts the
1259
+ * per-outcome slug (`btc-above-78213-may-04-0600`) OR a per-side slug
1260
+ * (`btc-above-78213-yes-may-04-0600`). Response includes `aggregatedOi`.
1261
+ */
1262
+ async getBySlug(slug) {
1263
+ const response = await this.http.get(
1264
+ `${this.basePath}/outcomes/by-slug/${slug}`
1265
+ );
1266
+ return response.data;
1267
+ }
1268
+ };
1182
1269
 
1183
1270
  // src/resources/funding.ts
1184
1271
  var FundingResource = class {
@@ -1371,7 +1458,7 @@ var DataQualityResource = class {
1371
1458
  /**
1372
1459
  * Get overall system health status
1373
1460
  *
1374
- * @returns StatusResponse with overall status, per-exchange status,
1461
+ * @returns StatusResponse with overall status, per-scope status,
1375
1462
  * per-data-type status, and active incident count
1376
1463
  *
1377
1464
  * @example
@@ -1390,9 +1477,9 @@ var DataQualityResource = class {
1390
1477
  // Coverage Endpoints
1391
1478
  // ===========================================================================
1392
1479
  /**
1393
- * Get data coverage summary for all exchanges
1480
+ * Get data coverage summary across venue APIs
1394
1481
  *
1395
- * @returns CoverageResponse with coverage info for all exchanges and data types
1482
+ * @returns CoverageResponse with coverage info for supported venue APIs and data types
1396
1483
  *
1397
1484
  * @example
1398
1485
  * ```typescript
@@ -1409,10 +1496,10 @@ var DataQualityResource = class {
1409
1496
  return this.http.get(`${this.basePath}/coverage`);
1410
1497
  }
1411
1498
  /**
1412
- * Get data coverage for a specific exchange
1499
+ * Get data coverage for a specific venue scope
1413
1500
  *
1414
- * @param exchange - Exchange name ('hyperliquid', 'lighter', or 'hip3')
1415
- * @returns ExchangeCoverage with coverage info for all data types on this exchange
1501
+ * @param exchange - Venue scope ('hyperliquid', 'lighter', 'hip3', or 'hip4')
1502
+ * @returns ExchangeCoverage with coverage info for all data types on this venue scope
1416
1503
  *
1417
1504
  * @example
1418
1505
  * ```typescript
@@ -1426,12 +1513,12 @@ var DataQualityResource = class {
1426
1513
  );
1427
1514
  }
1428
1515
  /**
1429
- * Get data coverage for a specific symbol on an exchange
1516
+ * Get data coverage for a specific symbol on a venue scope
1430
1517
  *
1431
1518
  * Includes gap detection, empirical data cadence, and hour-level historical coverage.
1432
1519
  * Supports optional time bounds for gap detection (default: last 30 days).
1433
1520
  *
1434
- * @param exchange - Exchange name ('hyperliquid', 'lighter', or 'hip3')
1521
+ * @param exchange - Venue scope ('hyperliquid', 'lighter', 'hip3', or 'hip4')
1435
1522
  * @param symbol - Symbol name (e.g., 'BTC', 'ETH', or HIP3 coins like 'xyz:XYZ100')
1436
1523
  * @param options - Optional time bounds for gap detection window
1437
1524
  * @returns SymbolCoverageResponse with per-data-type coverage including gaps, cadence, and historical coverage
@@ -1509,7 +1596,7 @@ var DataQualityResource = class {
1509
1596
  // Latency Endpoints
1510
1597
  // ===========================================================================
1511
1598
  /**
1512
- * Get current latency metrics for all exchanges
1599
+ * Get current latency metrics for supported venue APIs
1513
1600
  *
1514
1601
  * @returns LatencyResponse with WebSocket, REST API, and data freshness metrics
1515
1602
  *
@@ -1811,7 +1898,7 @@ var L2OrderBookResource = class {
1811
1898
  if (params?.timestamp != null) query.timestamp = params.timestamp;
1812
1899
  if (params?.depth != null) query.depth = params.depth;
1813
1900
  const resp = await this.http.get(
1814
- `${this.basePath}/orderbook/${encodeURIComponent(coin)}/l2`,
1901
+ `${this.basePath}/orderbook/${coin}/l2`,
1815
1902
  query
1816
1903
  );
1817
1904
  return resp.data;
@@ -1820,7 +1907,7 @@ var L2OrderBookResource = class {
1820
1907
  async history(symbol, params) {
1821
1908
  const coin = this.coinTransform(symbol);
1822
1909
  const resp = await this.http.get(
1823
- `${this.basePath}/orderbook/${encodeURIComponent(coin)}/l2/history`,
1910
+ `${this.basePath}/orderbook/${coin}/l2/history`,
1824
1911
  params
1825
1912
  );
1826
1913
  return {
@@ -1832,7 +1919,7 @@ var L2OrderBookResource = class {
1832
1919
  async diffs(symbol, params) {
1833
1920
  const coin = this.coinTransform(symbol);
1834
1921
  const resp = await this.http.get(
1835
- `${this.basePath}/orderbook/${encodeURIComponent(coin)}/l2/diffs`,
1922
+ `${this.basePath}/orderbook/${coin}/l2/diffs`,
1836
1923
  params
1837
1924
  );
1838
1925
  return {
@@ -1925,6 +2012,10 @@ var HyperliquidClient = class {
1925
2012
  * HIP-3 builder-deployed perpetuals (February 2026+)
1926
2013
  */
1927
2014
  hip3;
2015
+ /**
2016
+ * HIP-4 outcome markets (binary YES/NO; May 2026+)
2017
+ */
2018
+ hip4;
1928
2019
  http;
1929
2020
  constructor(http) {
1930
2021
  this.http = http;
@@ -1940,6 +2031,7 @@ var HyperliquidClient = class {
1940
2031
  this.l4Orderbook = new L4OrderBookResource(http, basePath);
1941
2032
  this.l2Orderbook = new L2OrderBookResource(http, basePath);
1942
2033
  this.hip3 = new Hip3Client(http);
2034
+ this.hip4 = new Hip4Client(http);
1943
2035
  }
1944
2036
  /**
1945
2037
  * Get per-symbol data freshness across all data types
@@ -2092,6 +2184,205 @@ var Hip3Client = class {
2092
2184
  };
2093
2185
  }
2094
2186
  };
2187
+ var Hip4Client = class {
2188
+ /**
2189
+ * HIP-4 per-side instruments (one row per `#N`).
2190
+ */
2191
+ instruments;
2192
+ /**
2193
+ * HIP-4 per-outcome aggregates (one row per outcome). HIP-4-specific, no HIP-3 analog.
2194
+ */
2195
+ outcomes;
2196
+ /**
2197
+ * L2 orderbook snapshots (Pro+).
2198
+ */
2199
+ orderbook;
2200
+ /**
2201
+ * Trade/fill history.
2202
+ */
2203
+ trades;
2204
+ /**
2205
+ * Open interest (per side).
2206
+ */
2207
+ openInterest;
2208
+ /**
2209
+ * Order history, flow, and TP/SL (Pro+).
2210
+ */
2211
+ orders;
2212
+ /**
2213
+ * L4 orderbook (snapshots, diffs, history).
2214
+ */
2215
+ l4Orderbook;
2216
+ /**
2217
+ * L2 full-depth orderbook (derived from L4).
2218
+ */
2219
+ l2Orderbook;
2220
+ http;
2221
+ constructor(http) {
2222
+ this.http = http;
2223
+ const basePath = "/v1/hyperliquid/hip4";
2224
+ const coinTransform = (c) => encodeURIComponent(c);
2225
+ this.instruments = new Hip4InstrumentsResource(http, basePath, coinTransform);
2226
+ this.outcomes = new Hip4OutcomesResource(http, basePath);
2227
+ this.orderbook = new OrderBookResource(http, basePath, coinTransform);
2228
+ this.trades = new TradesResource(http, basePath, coinTransform);
2229
+ this.openInterest = new OpenInterestResource(http, basePath, coinTransform);
2230
+ this.orders = new OrdersResource(http, basePath, coinTransform);
2231
+ this.l4Orderbook = new L4OrderBookResource(http, basePath, coinTransform);
2232
+ this.l2Orderbook = new L2OrderBookResource(http, basePath, coinTransform);
2233
+ }
2234
+ /** @internal Encode a HIP-4 coin for use in URL paths. */
2235
+ encodeCoin(coin) {
2236
+ return encodeURIComponent(coin);
2237
+ }
2238
+ /**
2239
+ * List per-outcome aggregates. `aggregatedOi` is omitted on list responses.
2240
+ */
2241
+ async listOutcomes(params) {
2242
+ return this.outcomes.list(params);
2243
+ }
2244
+ /**
2245
+ * Get a single outcome aggregate (includes `aggregatedOi`).
2246
+ */
2247
+ async getOutcome(outcomeId) {
2248
+ return this.outcomes.get(outcomeId);
2249
+ }
2250
+ /**
2251
+ * Look up an outcome aggregate by slug. Accepts the per-outcome slug
2252
+ * (e.g. `btc-above-78213-may-04-0600`) OR a per-side slug
2253
+ * (e.g. `btc-above-78213-yes-may-04-0600`). Includes `aggregatedOi`.
2254
+ */
2255
+ async getOutcomeBySlug(slug) {
2256
+ return this.outcomes.getBySlug(slug);
2257
+ }
2258
+ /**
2259
+ * List all per-side instruments (one row per `#N`).
2260
+ */
2261
+ async getInstruments() {
2262
+ return this.instruments.list();
2263
+ }
2264
+ /**
2265
+ * Get a single per-side instrument by coin (e.g. `#0`).
2266
+ */
2267
+ async getInstrument(coin) {
2268
+ return this.instruments.get(coin);
2269
+ }
2270
+ /**
2271
+ * Get current L2 orderbook snapshot for a HIP-4 coin (Pro+).
2272
+ * @param coin Coin string with leading `#` (e.g. `#0`).
2273
+ */
2274
+ async getOrderbook(coin, params) {
2275
+ return this.orderbook.get(coin, params);
2276
+ }
2277
+ /**
2278
+ * Get historical L2 orderbook snapshots for a HIP-4 coin (Pro+).
2279
+ */
2280
+ async getOrderbookHistory(coin, params) {
2281
+ return this.orderbook.history(coin, params);
2282
+ }
2283
+ /**
2284
+ * Get historical fills for a HIP-4 coin.
2285
+ */
2286
+ async getTrades(coin, params) {
2287
+ return this.trades.list(coin, params);
2288
+ }
2289
+ /**
2290
+ * Get most recent N fills for a HIP-4 coin (latest first).
2291
+ */
2292
+ async getTradesRecent(coin, limit) {
2293
+ return this.trades.recent(coin, limit);
2294
+ }
2295
+ /**
2296
+ * Get per-side open interest history for a HIP-4 coin.
2297
+ * Note: `markPrice` on the response is an implied probability (0..1), not USD.
2298
+ */
2299
+ async getOpenInterest(coin, params) {
2300
+ return this.openInterest.history(coin, params);
2301
+ }
2302
+ /**
2303
+ * Get current per-side open interest for a HIP-4 coin.
2304
+ * Note: `markPrice` on the response is an implied probability (0..1), not USD.
2305
+ */
2306
+ async getOpenInterestCurrent(coin) {
2307
+ return this.openInterest.current(coin);
2308
+ }
2309
+ /**
2310
+ * Get combined market summary for a HIP-4 coin.
2311
+ * @param coin Either bare numeric form (`'0'`) or `#`-prefixed form (`'#0'`). The SDK URL-encodes `#` so both work.
2312
+ */
2313
+ async getSummary(coin) {
2314
+ const response = await this.http.get(
2315
+ `/v1/hyperliquid/hip4/summary/${this.encodeCoin(coin)}`,
2316
+ void 0,
2317
+ this.http.validationEnabled ? CoinSummaryResponseSchema : void 0
2318
+ );
2319
+ return response.data;
2320
+ }
2321
+ /**
2322
+ * Get per-symbol data freshness across all HIP-4 data types.
2323
+ * @param coin Either bare numeric form (`'0'`) or `#`-prefixed form (`'#0'`). The SDK URL-encodes `#` so both work.
2324
+ */
2325
+ async getFreshness(coin) {
2326
+ const response = await this.http.get(
2327
+ `/v1/hyperliquid/hip4/freshness/${this.encodeCoin(coin)}`,
2328
+ void 0,
2329
+ this.http.validationEnabled ? CoinFreshnessResponseSchema : void 0
2330
+ );
2331
+ return response.data;
2332
+ }
2333
+ /**
2334
+ * Get mid-price history for a HIP-4 coin.
2335
+ * Note: returned `markPrice`/`midPrice` are probabilities (0..1), not USD.
2336
+ * @param coin Either bare numeric form (`'0'`) or `#`-prefixed form (`'#0'`). The SDK URL-encodes `#` so both work.
2337
+ */
2338
+ async getPrices(coin, params) {
2339
+ const response = await this.http.get(
2340
+ `/v1/hyperliquid/hip4/prices/${this.encodeCoin(coin)}`,
2341
+ params,
2342
+ this.http.validationEnabled ? PriceSnapshotArrayResponseSchema : void 0
2343
+ );
2344
+ return {
2345
+ data: response.data,
2346
+ nextCursor: response.meta.nextCursor
2347
+ };
2348
+ }
2349
+ /**
2350
+ * Get order lifecycle events for a HIP-4 coin (Pro+).
2351
+ */
2352
+ async getOrderHistory(coin, params) {
2353
+ return this.orders.history(coin, params);
2354
+ }
2355
+ /**
2356
+ * Get time-bucketed order-flow aggregates for a HIP-4 coin (Pro+).
2357
+ */
2358
+ async getOrderFlow(coin, params) {
2359
+ return this.orders.flow(coin, params);
2360
+ }
2361
+ /**
2362
+ * Get TP/SL orders for a HIP-4 coin (Pro+).
2363
+ */
2364
+ async getTpsl(coin, params) {
2365
+ return this.orders.tpsl(coin, params);
2366
+ }
2367
+ /**
2368
+ * Get full L4 reconstruction (current) for a HIP-4 coin (Pro+).
2369
+ */
2370
+ async getL4Orderbook(coin, params) {
2371
+ return this.l4Orderbook.get(coin, params);
2372
+ }
2373
+ /**
2374
+ * Get L4 diffs (event stream) for a HIP-4 coin (Pro+).
2375
+ */
2376
+ async getL4Diffs(coin, params) {
2377
+ return this.l4Orderbook.diffs(coin, params);
2378
+ }
2379
+ /**
2380
+ * Get L4 checkpoint history for a HIP-4 coin (Build+; hard cap limit=10).
2381
+ */
2382
+ async getL4History(coin, params) {
2383
+ return this.l4Orderbook.history(coin, params);
2384
+ }
2385
+ };
2095
2386
  var LighterClient = class {
2096
2387
  /**
2097
2388
  * Order book data (L2 snapshots)
@@ -2346,7 +2637,9 @@ var OxArchiveWs = class {
2346
2637
  streamCompleteHandlers = [];
2347
2638
  orderbookHandlers = [];
2348
2639
  tradesHandlers = [];
2640
+ liquidationsHandlers = [];
2349
2641
  gapHandlers = [];
2642
+ outcomeSettledHandlers = [];
2350
2643
  constructor(options) {
2351
2644
  this.options = {
2352
2645
  apiKey: options.apiKey,
@@ -2430,7 +2723,7 @@ var OxArchiveWs = class {
2430
2723
  const key = this.subscriptionKey(channel, coin);
2431
2724
  this.subscriptions.add(key);
2432
2725
  if (this.isConnected()) {
2433
- this.send({ op: "subscribe", channel, coin });
2726
+ this.send({ op: "subscribe", channel, symbol: coin });
2434
2727
  }
2435
2728
  }
2436
2729
  /**
@@ -2464,7 +2757,7 @@ var OxArchiveWs = class {
2464
2757
  const key = this.subscriptionKey(channel, coin);
2465
2758
  this.subscriptions.delete(key);
2466
2759
  if (this.isConnected()) {
2467
- this.send({ op: "unsubscribe", channel, coin });
2760
+ this.send({ op: "unsubscribe", channel, symbol: coin });
2468
2761
  }
2469
2762
  }
2470
2763
  /**
@@ -2491,6 +2784,49 @@ var OxArchiveWs = class {
2491
2784
  unsubscribeAllTickers() {
2492
2785
  this.unsubscribe("all_tickers");
2493
2786
  }
2787
+ /**
2788
+ * Subscribe to live liquidation events for a coin (Hyperliquid).
2789
+ *
2790
+ * Each message is a fill row with `is_liquidation: true`. Same wire shape as
2791
+ * trades. Live as of v1.6.0 (Hyperliquid + HIP-3 nodes); historical replay
2792
+ * also supported via `replay('liquidations', ...)`.
2793
+ */
2794
+ subscribeLiquidations(coin) {
2795
+ this.subscribe("liquidations", coin);
2796
+ }
2797
+ /** Unsubscribe from live liquidation events (Hyperliquid). */
2798
+ unsubscribeLiquidations(coin) {
2799
+ this.unsubscribe("liquidations", coin);
2800
+ }
2801
+ /**
2802
+ * Subscribe to live HIP-3 liquidation events for a coin.
2803
+ * Each message is a fill row with `is_liquidation: true`.
2804
+ */
2805
+ subscribeHip3Liquidations(coin) {
2806
+ this.subscribe("hip3_liquidations", coin);
2807
+ }
2808
+ /** Unsubscribe from live HIP-3 liquidation events. */
2809
+ unsubscribeHip3Liquidations(coin) {
2810
+ this.unsubscribe("hip3_liquidations", coin);
2811
+ }
2812
+ /**
2813
+ * Subscribe to a HIP-4 channel for a given outcome coin.
2814
+ *
2815
+ * @param channel One of `hip4_orderbook`, `hip4_trades`, `hip4_open_interest`,
2816
+ * `hip4_l4_diffs`, `hip4_l4_orders`.
2817
+ * @param coin HIP-4 coin (e.g. `'#0'` or `'0'`). The bare numeric form is
2818
+ * recommended; both are accepted by the backend.
2819
+ */
2820
+ subscribeHip4(channel, coin) {
2821
+ const fullChannel = channel.startsWith("hip4_") ? channel : `hip4_${channel}`;
2822
+ this.subscribe(fullChannel, coin);
2823
+ }
2824
+ /** Unsubscribe from a HIP-4 channel for a given outcome coin. Accepts the
2825
+ * short channel form (`'orderbook'`) or the full form (`'hip4_orderbook'`). */
2826
+ unsubscribeHip4(channel, coin) {
2827
+ const fullChannel = channel.startsWith("hip4_") ? channel : `hip4_${channel}`;
2828
+ this.unsubscribe(fullChannel, coin);
2829
+ }
2494
2830
  // ==========================================================================
2495
2831
  // Historical Replay (Option B) - Like Tardis.dev
2496
2832
  // ==========================================================================
@@ -2513,7 +2849,7 @@ var OxArchiveWs = class {
2513
2849
  this.send({
2514
2850
  op: "replay",
2515
2851
  channel,
2516
- coin,
2852
+ symbol: coin,
2517
2853
  start: options.start,
2518
2854
  end: options.end,
2519
2855
  speed: options.speed ?? 1,
@@ -2548,7 +2884,7 @@ var OxArchiveWs = class {
2548
2884
  this.send({
2549
2885
  op: "replay",
2550
2886
  channels,
2551
- coin,
2887
+ symbol: coin,
2552
2888
  start: options.start,
2553
2889
  end: options.end,
2554
2890
  speed: options.speed ?? 1,
@@ -2604,7 +2940,7 @@ var OxArchiveWs = class {
2604
2940
  this.send({
2605
2941
  op: "stream",
2606
2942
  channel,
2607
- coin,
2943
+ symbol: coin,
2608
2944
  start: options.start,
2609
2945
  end: options.end,
2610
2946
  batch_size: options.batchSize ?? 1e3,
@@ -2641,7 +2977,7 @@ var OxArchiveWs = class {
2641
2977
  this.send({
2642
2978
  op: "stream",
2643
2979
  channels,
2644
- coin,
2980
+ symbol: coin,
2645
2981
  start: options.start,
2646
2982
  end: options.end,
2647
2983
  batch_size: options.batchSize ?? 1e3,
@@ -2780,6 +3116,44 @@ var OxArchiveWs = class {
2780
3116
  onTrades(handler) {
2781
3117
  this.tradesHandlers.push(handler);
2782
3118
  }
3119
+ /**
3120
+ * Helper to handle live liquidation events for both `liquidations` and
3121
+ * `hip3_liquidations` channels. Each item is a fill row with
3122
+ * `is_liquidation: true`, surfaced as a `Trade` (the wire shape matches
3123
+ * trades exactly).
3124
+ *
3125
+ * @param handler Called with the channel, coin, and parsed Trade array.
3126
+ *
3127
+ * @example
3128
+ * ```typescript
3129
+ * ws.onLiquidations((channel, coin, fills) => {
3130
+ * for (const f of fills) {
3131
+ * console.log(`${channel} ${coin} liq: ${f.side} ${f.size}@${f.price}`);
3132
+ * }
3133
+ * });
3134
+ * ws.subscribeLiquidations('BTC');
3135
+ * ws.subscribeHip3Liquidations('hyna:BTC');
3136
+ * ```
3137
+ */
3138
+ onLiquidations(handler) {
3139
+ this.liquidationsHandlers.push(handler);
3140
+ }
3141
+ /**
3142
+ * Handle HIP-4 outcome settlement events. Pushed once per `(outcome_id, side)`
3143
+ * when the outcome flips to settled. After this event the server proactively
3144
+ * unsubscribes the client from every hip4_* subscription on the settled coin —
3145
+ * treat the event as a terminal signal for that coin.
3146
+ *
3147
+ * @example
3148
+ * ```typescript
3149
+ * ws.onOutcomeSettled((coin, outcomeId, side, value, at) => {
3150
+ * console.log(`${coin} (outcome ${outcomeId} side ${side}) settled to ${value} at ${at}`);
3151
+ * });
3152
+ * ```
3153
+ */
3154
+ onOutcomeSettled(handler) {
3155
+ this.outcomeSettledHandlers.push(handler);
3156
+ }
2783
3157
  // Private methods
2784
3158
  send(message) {
2785
3159
  if (this.ws?.readyState === WebSocket.OPEN) {
@@ -2907,16 +3281,28 @@ var OxArchiveWs = class {
2907
3281
  break;
2908
3282
  }
2909
3283
  case "data": {
2910
- if (message.channel === "orderbook") {
3284
+ if (message.channel === "orderbook" || message.channel === "hip3_orderbook" || message.channel === "hip4_orderbook" || message.channel === "lighter_orderbook") {
2911
3285
  const orderbook = transformOrderbook(message.coin, message.data);
2912
3286
  for (const handler of this.orderbookHandlers) {
2913
3287
  handler(message.coin, orderbook);
2914
3288
  }
2915
- } else if (message.channel === "trades") {
3289
+ } else if (message.channel === "trades" || message.channel === "hip3_trades" || message.channel === "hip4_trades" || message.channel === "lighter_trades") {
2916
3290
  const trades = transformTrades(message.coin, message.data);
2917
3291
  for (const handler of this.tradesHandlers) {
2918
3292
  handler(message.coin, trades);
2919
3293
  }
3294
+ } else if (message.channel === "liquidations" || message.channel === "hip3_liquidations") {
3295
+ const fills = transformTrades(message.coin, message.data);
3296
+ for (const handler of this.liquidationsHandlers) {
3297
+ handler(message.channel, message.coin, fills);
3298
+ }
3299
+ }
3300
+ break;
3301
+ }
3302
+ case "outcome_settled": {
3303
+ const msg = message;
3304
+ for (const handler of this.outcomeSettledHandlers) {
3305
+ handler(msg.coin, msg.outcome_id, msg.side, msg.settlement_value, msg.settlement_at);
2920
3306
  }
2921
3307
  break;
2922
3308
  }
@@ -3069,6 +3455,7 @@ var L4OrderBookReconstructor = class {
3069
3455
  FundingRateResponseSchema,
3070
3456
  FundingRateSchema,
3071
3457
  Hip3Client,
3458
+ Hip4Client,
3072
3459
  HyperliquidClient,
3073
3460
  InstrumentArrayResponseSchema,
3074
3461
  InstrumentResponseSchema,
@@ -3106,6 +3493,7 @@ var L4OrderBookReconstructor = class {
3106
3493
  WsErrorSchema,
3107
3494
  WsHistoricalBatchSchema,
3108
3495
  WsHistoricalDataSchema,
3496
+ WsOutcomeSettledSchema,
3109
3497
  WsPongSchema,
3110
3498
  WsReplayCompletedSchema,
3111
3499
  WsReplayPausedSchema,