@xapy/orderbook 0.1.22 → 0.1.23

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.
Files changed (80) hide show
  1. package/README.md +14 -9
  2. package/dist/exchanges/binance/index.cjs +21 -6
  3. package/dist/exchanges/binance/index.cjs.map +1 -1
  4. package/dist/exchanges/binance/index.d.cts +1 -1
  5. package/dist/exchanges/binance/index.d.ts +1 -1
  6. package/dist/exchanges/binance/index.js +21 -6
  7. package/dist/exchanges/binance/index.js.map +1 -1
  8. package/dist/exchanges/bingx/index.cjs +38 -11
  9. package/dist/exchanges/bingx/index.cjs.map +1 -1
  10. package/dist/exchanges/bingx/index.d.cts +1 -1
  11. package/dist/exchanges/bingx/index.d.ts +1 -1
  12. package/dist/exchanges/bingx/index.js +38 -11
  13. package/dist/exchanges/bingx/index.js.map +1 -1
  14. package/dist/exchanges/bitget/index.cjs +21 -6
  15. package/dist/exchanges/bitget/index.cjs.map +1 -1
  16. package/dist/exchanges/bitget/index.d.cts +1 -1
  17. package/dist/exchanges/bitget/index.d.ts +1 -1
  18. package/dist/exchanges/bitget/index.js +21 -6
  19. package/dist/exchanges/bitget/index.js.map +1 -1
  20. package/dist/exchanges/bybit/index.cjs +21 -6
  21. package/dist/exchanges/bybit/index.cjs.map +1 -1
  22. package/dist/exchanges/bybit/index.d.cts +1 -1
  23. package/dist/exchanges/bybit/index.d.ts +1 -1
  24. package/dist/exchanges/bybit/index.js +21 -6
  25. package/dist/exchanges/bybit/index.js.map +1 -1
  26. package/dist/exchanges/coinex/index.cjs +21 -6
  27. package/dist/exchanges/coinex/index.cjs.map +1 -1
  28. package/dist/exchanges/coinex/index.d.cts +1 -1
  29. package/dist/exchanges/coinex/index.d.ts +1 -1
  30. package/dist/exchanges/coinex/index.js +21 -6
  31. package/dist/exchanges/coinex/index.js.map +1 -1
  32. package/dist/exchanges/{bitmart → deribit}/index.cjs +174 -148
  33. package/dist/exchanges/deribit/index.cjs.map +1 -0
  34. package/dist/exchanges/deribit/index.d.cts +48 -0
  35. package/dist/exchanges/deribit/index.d.ts +48 -0
  36. package/dist/exchanges/{bitmart → deribit}/index.js +172 -146
  37. package/dist/exchanges/deribit/index.js.map +1 -0
  38. package/dist/exchanges/gate/index.cjs +21 -6
  39. package/dist/exchanges/gate/index.cjs.map +1 -1
  40. package/dist/exchanges/gate/index.d.cts +1 -1
  41. package/dist/exchanges/gate/index.d.ts +1 -1
  42. package/dist/exchanges/gate/index.js +21 -6
  43. package/dist/exchanges/gate/index.js.map +1 -1
  44. package/dist/exchanges/huobi/index.cjs +21 -6
  45. package/dist/exchanges/huobi/index.cjs.map +1 -1
  46. package/dist/exchanges/huobi/index.d.cts +1 -1
  47. package/dist/exchanges/huobi/index.d.ts +1 -1
  48. package/dist/exchanges/huobi/index.js +21 -6
  49. package/dist/exchanges/huobi/index.js.map +1 -1
  50. package/dist/exchanges/hyperliquid/index.cjs +21 -6
  51. package/dist/exchanges/hyperliquid/index.cjs.map +1 -1
  52. package/dist/exchanges/hyperliquid/index.d.cts +1 -1
  53. package/dist/exchanges/hyperliquid/index.d.ts +1 -1
  54. package/dist/exchanges/hyperliquid/index.js +21 -6
  55. package/dist/exchanges/hyperliquid/index.js.map +1 -1
  56. package/dist/exchanges/kucoin/index.cjs +21 -6
  57. package/dist/exchanges/kucoin/index.cjs.map +1 -1
  58. package/dist/exchanges/kucoin/index.d.cts +1 -1
  59. package/dist/exchanges/kucoin/index.d.ts +1 -1
  60. package/dist/exchanges/kucoin/index.js +21 -6
  61. package/dist/exchanges/kucoin/index.js.map +1 -1
  62. package/dist/exchanges/okx/index.cjs +21 -6
  63. package/dist/exchanges/okx/index.cjs.map +1 -1
  64. package/dist/exchanges/okx/index.d.cts +1 -1
  65. package/dist/exchanges/okx/index.d.ts +1 -1
  66. package/dist/exchanges/okx/index.js +21 -6
  67. package/dist/exchanges/okx/index.js.map +1 -1
  68. package/dist/index.cjs +189 -122
  69. package/dist/index.cjs.map +1 -1
  70. package/dist/index.d.cts +3 -3
  71. package/dist/index.d.ts +3 -3
  72. package/dist/index.js +189 -122
  73. package/dist/index.js.map +1 -1
  74. package/dist/{stream-L9MJjYbE.d.cts → stream-CO3LD9jf.d.cts} +1 -1
  75. package/dist/{stream-L9MJjYbE.d.ts → stream-CO3LD9jf.d.ts} +1 -1
  76. package/package.json +7 -6
  77. package/dist/exchanges/bitmart/index.cjs.map +0 -1
  78. package/dist/exchanges/bitmart/index.d.cts +0 -68
  79. package/dist/exchanges/bitmart/index.d.ts +0 -68
  80. package/dist/exchanges/bitmart/index.js.map +0 -1
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { B as BookEvent, O as OrderbookLevel, M as Market } from './stream-L9MJjYbE.cjs';
2
- export { C as ClientOptions, E as ExchangeName, a as Orderbook, b as OrderbookOptions, c as OrderbookStream, S as Side, d as StreamEvents } from './stream-L9MJjYbE.cjs';
1
+ import { B as BookEvent, O as OrderbookLevel, M as Market } from './stream-CO3LD9jf.cjs';
2
+ export { C as ClientOptions, E as ExchangeName, a as Orderbook, b as OrderbookOptions, c as OrderbookStream, S as Side, d as StreamEvents } from './stream-CO3LD9jf.cjs';
3
3
  export { BybitClient } from './exchanges/bybit/index.cjs';
4
4
  export { BitgetClient } from './exchanges/bitget/index.cjs';
5
5
  export { GateClient } from './exchanges/gate/index.cjs';
@@ -10,7 +10,7 @@ export { OkxClient } from './exchanges/okx/index.cjs';
10
10
  export { BinanceClient } from './exchanges/binance/index.cjs';
11
11
  export { HyperliquidClient } from './exchanges/hyperliquid/index.cjs';
12
12
  export { KucoinClient } from './exchanges/kucoin/index.cjs';
13
- export { BitmartClient } from './exchanges/bitmart/index.cjs';
13
+ export { DeribitClient } from './exchanges/deribit/index.cjs';
14
14
 
15
15
  declare class ExchangeError extends Error {
16
16
  readonly exchange: string;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { B as BookEvent, O as OrderbookLevel, M as Market } from './stream-L9MJjYbE.js';
2
- export { C as ClientOptions, E as ExchangeName, a as Orderbook, b as OrderbookOptions, c as OrderbookStream, S as Side, d as StreamEvents } from './stream-L9MJjYbE.js';
1
+ import { B as BookEvent, O as OrderbookLevel, M as Market } from './stream-CO3LD9jf.js';
2
+ export { C as ClientOptions, E as ExchangeName, a as Orderbook, b as OrderbookOptions, c as OrderbookStream, S as Side, d as StreamEvents } from './stream-CO3LD9jf.js';
3
3
  export { BybitClient } from './exchanges/bybit/index.js';
4
4
  export { BitgetClient } from './exchanges/bitget/index.js';
5
5
  export { GateClient } from './exchanges/gate/index.js';
@@ -10,7 +10,7 @@ export { OkxClient } from './exchanges/okx/index.js';
10
10
  export { BinanceClient } from './exchanges/binance/index.js';
11
11
  export { HyperliquidClient } from './exchanges/hyperliquid/index.js';
12
12
  export { KucoinClient } from './exchanges/kucoin/index.js';
13
- export { BitmartClient } from './exchanges/bitmart/index.js';
13
+ export { DeribitClient } from './exchanges/deribit/index.js';
14
14
 
15
15
  declare class ExchangeError extends Error {
16
16
  readonly exchange: string;
package/dist/index.js CHANGED
@@ -323,6 +323,21 @@ async function fetchBybitOrderbook(opts) {
323
323
  var hasNativeWebSocket = typeof globalThis.WebSocket !== "undefined";
324
324
 
325
325
  // src/transport/ws.ts
326
+ function toError(value, fallback = "unknown error") {
327
+ if (value instanceof Error) {
328
+ return value.message ? value : new Error(`${value.name}: ${fallback}`);
329
+ }
330
+ if (typeof value === "string" && value) return new Error(value);
331
+ return new Error(fallback);
332
+ }
333
+ function normalizeWsError(ev) {
334
+ const detail = ev?.message || (ev?.error instanceof Error ? ev.error.message : void 0) || (typeof ev?.error === "string" ? ev.error : void 0);
335
+ return new Error(detail ? `WebSocket error: ${detail}` : "WebSocket error");
336
+ }
337
+ function describeClose(ev) {
338
+ if (ev?.reason) return ev.reason;
339
+ return ev?.code === void 0 ? "closed" : `closed (code ${ev.code})`;
340
+ }
326
341
  var cachedCtor = null;
327
342
  async function getWebSocketCtor() {
328
343
  if (cachedCtor) return cachedCtor;
@@ -370,7 +385,7 @@ var WSClient = class extends TypedEmitter {
370
385
  close: () => this.close()
371
386
  });
372
387
  } catch (err) {
373
- this.emit("error", err);
388
+ this.emit("error", toError(err, "onOpen handler failed"));
374
389
  }
375
390
  };
376
391
  ws.onmessage = (e) => {
@@ -378,21 +393,21 @@ var WSClient = class extends TypedEmitter {
378
393
  try {
379
394
  result = this.cfg.onMessage(e.data);
380
395
  } catch (err) {
381
- this.emit("error", err);
396
+ this.emit("error", toError(err, "onMessage handler failed"));
382
397
  return;
383
398
  }
384
399
  if (result && typeof result.catch === "function") {
385
400
  result.catch(
386
- (err) => this.emit("error", err)
401
+ (err) => this.emit("error", toError(err, "onMessage handler failed"))
387
402
  );
388
403
  }
389
404
  };
390
405
  ws.onerror = (e) => {
391
- this.emit("error", new Error(e?.message ?? "WebSocket error"));
406
+ this.emit("error", normalizeWsError(e));
392
407
  };
393
408
  ws.onclose = (e) => {
394
409
  this.stopPing();
395
- const reason = e?.reason ?? "closed";
410
+ const reason = describeClose(e);
396
411
  this.emit("close", reason);
397
412
  if (!this.closed) this.scheduleReconnect();
398
413
  };
@@ -432,7 +447,7 @@ var WSClient = class extends TypedEmitter {
432
447
  }
433
448
  this.emit("reconnecting", next.attempt, next.wait);
434
449
  setTimeout(() => {
435
- this.connect().catch((e) => this.emit("error", e));
450
+ this.connect().catch((e) => this.emit("error", toError(e, "reconnect failed")));
436
451
  }, next.wait);
437
452
  }
438
453
  };
@@ -1232,7 +1247,7 @@ function streamBingxOrderbook(opts) {
1232
1247
  const wsSymbol = opts.symbol.toUpperCase().replace("/", "-");
1233
1248
  const level = opts.depth ?? 20;
1234
1249
  const interval = opts.interval ?? "500ms";
1235
- const depthDataType = `${wsSymbol}@depth${level}@${interval}`;
1250
+ const depthDataType = isSpot ? `${wsSymbol}@depth${level}` : `${wsSymbol}@depth${level}@${interval}`;
1236
1251
  const tickerDataType = `${wsSymbol}@bookTicker`;
1237
1252
  const merger = new BookMerger();
1238
1253
  let ws = null;
@@ -1275,8 +1290,8 @@ function streamBingxOrderbook(opts) {
1275
1290
  };
1276
1291
  stream.emit("update", book);
1277
1292
  };
1278
- const handleDepth = (d) => {
1279
- const ts = d.T ?? d.ts ?? Date.now();
1293
+ const handleDepth = (d, frameTs) => {
1294
+ const ts = d.T ?? d.ts ?? frameTs ?? Date.now();
1280
1295
  const event = {
1281
1296
  kind: "snapshot",
1282
1297
  bids: d.bids.map(([p, s]) => ({ price: Number(p), size: Number(s) })),
@@ -1318,10 +1333,22 @@ function streamBingxOrderbook(opts) {
1318
1333
  } catch {
1319
1334
  return;
1320
1335
  }
1321
- if (msg.id && !msg.data) return;
1336
+ if (msg.id && !msg.data) {
1337
+ if (msg.code) {
1338
+ stream.emit(
1339
+ "error",
1340
+ new ExchangeError(
1341
+ "bingx",
1342
+ `subscribe failed (${msg.id}): ${msg.code}${msg.msg ? ` ${msg.msg}` : ""}`
1343
+ )
1344
+ );
1345
+ }
1346
+ return;
1347
+ }
1322
1348
  if (!msg.dataType || !msg.data) return;
1349
+ const frameTs = msg.ts ?? msg.timestamp;
1323
1350
  if (msg.dataType === depthDataType) {
1324
- handleDepth(msg.data);
1351
+ handleDepth(msg.data, frameTs);
1325
1352
  } else if (msg.dataType === tickerDataType) {
1326
1353
  handleTicker(msg.data);
1327
1354
  }
@@ -2620,98 +2647,88 @@ var KucoinClient = class {
2620
2647
  }
2621
2648
  };
2622
2649
 
2623
- // src/exchanges/bitmart/symbols.ts
2624
- var QUOTES6 = ["USDT", "USDC", "USD"];
2625
- function toBitmartSymbol(symbol) {
2650
+ // src/exchanges/deribit/symbols.ts
2651
+ function toDeribitSymbol(symbol, market) {
2626
2652
  const [base, quote] = symbol.split("/");
2627
2653
  if (!base || !quote) {
2628
2654
  throw new Error(`invalid symbol "${symbol}" \u2014 expected "BASE/QUOTE"`);
2629
2655
  }
2630
- return `${base}${quote}`.toUpperCase();
2631
- }
2632
- function fromBitmartSymbol(s) {
2633
- const upper = s.toUpperCase();
2634
- for (const q of QUOTES6) {
2635
- if (upper.endsWith(q) && upper.length > q.length) {
2636
- return `${upper.slice(0, -q.length)}/${q}`;
2637
- }
2656
+ const pair = `${base}_${quote}`.toUpperCase();
2657
+ if (market !== "perpetual") return pair;
2658
+ if (quote.toUpperCase() !== "USDC") {
2659
+ throw new Error(
2660
+ `deribit linear perpetuals are USDC-margined; got "${quote}" (inverse contracts like BTC-PERPETUAL are unsupported)`
2661
+ );
2638
2662
  }
2639
- return upper;
2663
+ return `${pair}-PERPETUAL`;
2664
+ }
2665
+ function fromDeribitSymbol(instrument) {
2666
+ let s = instrument.toUpperCase();
2667
+ if (s.endsWith("-PERPETUAL")) s = s.slice(0, -"-PERPETUAL".length);
2668
+ const [base, quote] = s.split("_");
2669
+ return base && quote ? `${base}/${quote}` : s;
2640
2670
  }
2641
2671
 
2642
- // src/exchanges/bitmart/rest.ts
2643
- var BASE8 = "https://api-cloud-v2.bitmart.com";
2644
- async function fetchBitmartOrderbook(opts) {
2645
- if (opts.market !== "perpetual") {
2646
- throw new ExchangeError(
2647
- "bitmart",
2648
- "spot is not supported \u2014 only USDT-M perpetual"
2649
- );
2650
- }
2651
- const symbol = toBitmartSymbol(opts.symbol);
2652
- const url = `${BASE8}/contract/public/depth?symbol=${symbol}`;
2672
+ // src/exchanges/deribit/rest.ts
2673
+ var BASE8 = "https://www.deribit.com";
2674
+ var ALLOWED_DEPTHS = [1, 5, 10, 20, 50, 100, 1e3, 1e4];
2675
+ function clampDepth(depth) {
2676
+ return ALLOWED_DEPTHS.find((d) => d >= depth) ?? ALLOWED_DEPTHS[ALLOWED_DEPTHS.length - 1];
2677
+ }
2678
+ async function fetchDeribitOrderbook(opts) {
2679
+ const instrument = toDeribitSymbol(opts.symbol, opts.market);
2680
+ const depth = clampDepth(opts.depth ?? 50);
2681
+ const url = `${BASE8}/api/v2/public/get_order_book?instrument_name=${instrument}&depth=${depth}`;
2653
2682
  const res = await httpJson({
2654
2683
  url,
2655
2684
  timeoutMs: opts.timeoutMs,
2656
2685
  transformUrl: opts.transformUrl
2657
2686
  });
2658
- if (res.code !== 1e3) {
2659
- throw new ExchangeError("bitmart", `${res.code}: ${res.message ?? ""}`);
2687
+ if (res.error) {
2688
+ throw new ExchangeError(
2689
+ "deribit",
2690
+ `${res.error.code}: ${res.error.message}`
2691
+ );
2660
2692
  }
2693
+ const r = res.result;
2694
+ if (!r) throw new ExchangeError("deribit", "empty orderbook response");
2661
2695
  return {
2662
- exchange: "bitmart",
2663
- symbol: fromBitmartSymbol(res.data.symbol),
2664
- market: "perpetual",
2665
- bids: parseLevels2(res.data.bids),
2666
- asks: parseLevels2(res.data.asks),
2667
- timestamp: res.data.timestamp,
2668
- sequence: res.data.timestamp
2696
+ exchange: "deribit",
2697
+ symbol: fromDeribitSymbol(r.instrument_name ?? instrument),
2698
+ market: opts.market,
2699
+ bids: r.bids.map(([price, size]) => ({ price, size })),
2700
+ asks: r.asks.map(([price, size]) => ({ price, size })),
2701
+ timestamp: r.timestamp,
2702
+ sequence: r.change_id
2669
2703
  };
2670
2704
  }
2671
- function parseLevels2(rows) {
2672
- const out = [];
2673
- for (const row of rows) {
2674
- out.push({ price: Number(row[0]), size: Number(row[1]) });
2675
- }
2676
- return out;
2677
- }
2678
2705
 
2679
- // src/exchanges/bitmart/ws.ts
2680
- var WS_FUTURES4 = "wss://openapi-ws-v2.bitmart.com/api?protocol=1.1";
2681
- function streamBitmartOrderbook(opts) {
2682
- if (opts.market !== "perpetual") {
2683
- throw new ExchangeError(
2684
- "bitmart",
2685
- "spot is not supported \u2014 only USDT-M perpetual"
2686
- );
2687
- }
2688
- const symbol = toBitmartSymbol(opts.symbol);
2689
- const level = snapLevel(opts.depth);
2690
- const interval = opts.interval ?? "200ms";
2691
- const channelArg = `futures/depthAll${level}:${symbol}@${interval}`;
2706
+ // src/exchanges/deribit/ws.ts
2707
+ var WS_PUBLIC3 = "wss://www.deribit.com/ws/api/v2";
2708
+ var HEARTBEAT_SECONDS = 30;
2709
+ function streamDeribitOrderbook(opts) {
2710
+ const instrument = toDeribitSymbol(opts.symbol, opts.market);
2711
+ const channel = `book.${instrument}.${opts.interval ?? "100ms"}`;
2692
2712
  const merger = new BookMerger();
2693
2713
  let ws = null;
2714
+ let sock = null;
2715
+ let recovering = false;
2694
2716
  const stream = new OrderbookStream(() => ws?.close());
2695
- const subscribePayload = JSON.stringify({
2696
- action: "subscribe",
2697
- args: [channelArg]
2698
- });
2699
- const pingPayload = () => JSON.stringify({ action: "ping" });
2700
- const handleFrame = (frame) => {
2701
- if (frame.symbol !== symbol) return;
2702
- const event = {
2703
- kind: "snapshot",
2704
- bids: parseLevels3(frame.bids),
2705
- asks: parseLevels3(frame.asks),
2706
- sequence: frame.ms_t,
2707
- timestamp: frame.ms_t
2708
- };
2709
- const r = merger.apply(event);
2710
- if (!r.ok) return;
2717
+ let nextId = 1;
2718
+ const subscribeIds = /* @__PURE__ */ new Set();
2719
+ const rpc = (method, params) => {
2720
+ const id = nextId++;
2721
+ sock?.send(JSON.stringify({ jsonrpc: "2.0", id, method, params }));
2722
+ return id;
2723
+ };
2724
+ const subscribe = () => {
2725
+ subscribeIds.add(rpc("public/subscribe", { channels: [channel] }));
2726
+ };
2727
+ const emit = (r) => {
2711
2728
  const book = {
2712
- exchange: "bitmart",
2713
- symbol: fromBitmartSymbol(symbol),
2714
- market: "perpetual",
2729
+ exchange: "deribit",
2730
+ symbol: fromDeribitSymbol(instrument),
2731
+ market: opts.market,
2715
2732
  bids: r.bids,
2716
2733
  asks: r.asks,
2717
2734
  timestamp: r.timestamp,
@@ -2719,41 +2736,101 @@ function streamBitmartOrderbook(opts) {
2719
2736
  };
2720
2737
  stream.emit("update", book);
2721
2738
  };
2722
- const handlePayload = (text) => {
2739
+ const resync = () => {
2740
+ if (recovering) return;
2741
+ recovering = true;
2742
+ merger.reset();
2743
+ rpc("public/unsubscribe", { channels: [channel] });
2744
+ subscribe();
2745
+ };
2746
+ const toLevels = (entries) => entries.map(([action, price, amount]) => ({
2747
+ price,
2748
+ size: action === "delete" ? 0 : amount
2749
+ }));
2750
+ const buildEvent2 = (d) => {
2751
+ const bids = toLevels(d.bids);
2752
+ const asks = toLevels(d.asks);
2753
+ if (d.type === "snapshot") {
2754
+ return {
2755
+ kind: "snapshot",
2756
+ bids,
2757
+ asks,
2758
+ sequence: d.change_id,
2759
+ timestamp: d.timestamp
2760
+ };
2761
+ }
2762
+ return {
2763
+ kind: "delta",
2764
+ bids,
2765
+ asks,
2766
+ sequence: d.change_id,
2767
+ prevSequence: d.prev_change_id,
2768
+ timestamp: d.timestamp
2769
+ };
2770
+ };
2771
+ const handleData = (d) => {
2772
+ if (d.type === "snapshot") recovering = false;
2773
+ else if (recovering) return;
2774
+ const r = merger.apply(buildEvent2(d));
2775
+ if (r.ok) {
2776
+ emit(r);
2777
+ } else if (r.reason === "gap" || r.reason === "no-snapshot") {
2778
+ resync();
2779
+ }
2780
+ };
2781
+ const onMessage = (raw) => {
2782
+ if (typeof raw !== "string") return;
2723
2783
  let msg;
2724
2784
  try {
2725
- msg = JSON.parse(text);
2785
+ msg = JSON.parse(raw);
2726
2786
  } catch {
2727
2787
  return;
2728
2788
  }
2729
- if (msg.action === "subscribe" || msg.action === "pong") return;
2730
- if (msg.errorCode) {
2731
- stream.emit(
2732
- "error",
2733
- new Error(`bitmart: ${msg.errorCode} ${msg.errorMessage ?? ""}`)
2734
- );
2789
+ if (msg.method === "heartbeat") {
2790
+ if (msg.params?.type === "test_request") rpc("public/test", {});
2735
2791
  return;
2736
2792
  }
2737
- if (msg.group !== channelArg || !msg.data) return;
2738
- handleFrame(msg.data);
2739
- };
2740
- const onMessage = async (raw) => {
2741
- if (typeof raw === "string") {
2742
- handlePayload(raw);
2793
+ if (msg.method === "subscription") {
2794
+ if (msg.params?.channel !== channel || !msg.params.data) return;
2795
+ handleData(msg.params.data);
2743
2796
  return;
2744
2797
  }
2745
- const inflate = await getGzipInflate();
2746
- handlePayload(inflate(raw));
2798
+ if (msg.id !== void 0) {
2799
+ if (msg.error) {
2800
+ stream.emit(
2801
+ "error",
2802
+ new ExchangeError(
2803
+ "deribit",
2804
+ `${msg.error.code}: ${msg.error.message}`
2805
+ )
2806
+ );
2807
+ return;
2808
+ }
2809
+ if (subscribeIds.delete(msg.id)) {
2810
+ const channels = Array.isArray(msg.result) ? msg.result : [];
2811
+ if (!channels.includes(channel)) {
2812
+ stream.emit(
2813
+ "error",
2814
+ new ExchangeError(
2815
+ "deribit",
2816
+ `subscribe rejected for "${channel}" \u2014 unknown instrument or interval`
2817
+ )
2818
+ );
2819
+ }
2820
+ }
2821
+ }
2747
2822
  };
2748
2823
  ws = new WSClient({
2749
- url: WS_FUTURES4,
2750
- onOpen: (sock) => {
2824
+ url: WS_PUBLIC3,
2825
+ onOpen: (handle) => {
2826
+ sock = handle;
2751
2827
  merger.reset();
2752
- sock.send(subscribePayload);
2828
+ recovering = false;
2829
+ subscribeIds.clear();
2830
+ rpc("public/set_heartbeat", { interval: HEARTBEAT_SECONDS });
2831
+ subscribe();
2753
2832
  },
2754
- onMessage,
2755
- pingIntervalMs: 15e3,
2756
- pingPayload
2833
+ onMessage
2757
2834
  });
2758
2835
  ws.on("open", () => stream.emit("connected"));
2759
2836
  ws.on("close", (r) => stream.emit("disconnected", r));
@@ -2762,21 +2839,10 @@ function streamBitmartOrderbook(opts) {
2762
2839
  ws.connect().catch((e) => stream.emit("error", e));
2763
2840
  return stream;
2764
2841
  }
2765
- function snapLevel(depth) {
2766
- if (depth === 5) return 5;
2767
- if (depth === 20) return 20;
2768
- return 50;
2769
- }
2770
- function parseLevels3(rows) {
2771
- if (!rows) return [];
2772
- const out = [];
2773
- for (const r of rows) out.push({ price: Number(r.price), size: Number(r.vol) });
2774
- return out;
2775
- }
2776
2842
 
2777
- // src/exchanges/bitmart/index.ts
2778
- var BitmartClient = class {
2779
- exchange = "bitmart";
2843
+ // src/exchanges/deribit/index.ts
2844
+ var DeribitClient = class {
2845
+ exchange = "deribit";
2780
2846
  transformUrl;
2781
2847
  timeoutMs;
2782
2848
  constructor(opts = {}) {
@@ -2785,7 +2851,7 @@ var BitmartClient = class {
2785
2851
  }
2786
2852
  fetchOrderbook(symbol, opts = {}) {
2787
2853
  const { pair, market } = parseSymbol(symbol);
2788
- return fetchBitmartOrderbook({
2854
+ return fetchDeribitOrderbook({
2789
2855
  symbol: pair,
2790
2856
  market,
2791
2857
  depth: opts.depth,
@@ -2793,17 +2859,18 @@ var BitmartClient = class {
2793
2859
  transformUrl: this.transformUrl
2794
2860
  });
2795
2861
  }
2796
- streamOrderbook(symbol, _opts = {}) {
2862
+ streamOrderbook(symbol, opts = {}) {
2797
2863
  const { pair, market } = parseSymbol(symbol);
2798
- return streamBitmartOrderbook({
2864
+ return streamDeribitOrderbook({
2799
2865
  symbol: pair,
2800
2866
  market,
2867
+ depth: opts.depth,
2801
2868
  transformUrl: this.transformUrl,
2802
2869
  timeoutMs: this.timeoutMs
2803
2870
  });
2804
2871
  }
2805
2872
  };
2806
2873
 
2807
- export { Backoff, BinanceClient, BingxClient, BitgetClient, BitmartClient, BookMerger, BybitClient, CoinexClient, ExchangeError, GateClient, HuobiClient, HyperliquidClient, KucoinClient, OkxClient, OrderbookStream, RateLimitError, SequenceGapError, parseSymbol };
2874
+ export { Backoff, BinanceClient, BingxClient, BitgetClient, BookMerger, BybitClient, CoinexClient, DeribitClient, ExchangeError, GateClient, HuobiClient, HyperliquidClient, KucoinClient, OkxClient, OrderbookStream, RateLimitError, SequenceGapError, parseSymbol };
2808
2875
  //# sourceMappingURL=index.js.map
2809
2876
  //# sourceMappingURL=index.js.map