ccxt 4.2.57 → 4.2.59

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 (110) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/README.md +4 -5
  3. package/build.sh +1 -1
  4. package/cleanup.sh +3 -0
  5. package/dist/ccxt.browser.js +772 -497
  6. package/dist/ccxt.browser.min.js +7 -7
  7. package/dist/cjs/ccxt.js +1 -1
  8. package/dist/cjs/src/alpaca.js +90 -88
  9. package/dist/cjs/src/base/Exchange.js +24 -1
  10. package/dist/cjs/src/binance.js +43 -30
  11. package/dist/cjs/src/bingx.js +15 -4
  12. package/dist/cjs/src/bitget.js +72 -57
  13. package/dist/cjs/src/bitmex.js +13 -29
  14. package/dist/cjs/src/bitrue.js +24 -15
  15. package/dist/cjs/src/blofin.js +25 -2
  16. package/dist/cjs/src/bybit.js +11 -3
  17. package/dist/cjs/src/coinbase.js +24 -14
  18. package/dist/cjs/src/currencycom.js +15 -5
  19. package/dist/cjs/src/delta.js +14 -1
  20. package/dist/cjs/src/gate.js +1 -1
  21. package/dist/cjs/src/hitbtc.js +12 -1
  22. package/dist/cjs/src/krakenfutures.js +22 -7
  23. package/dist/cjs/src/kuna.js +14 -11
  24. package/dist/cjs/src/lbank.js +1 -1
  25. package/dist/cjs/src/mexc.js +20 -20
  26. package/dist/cjs/src/okx.js +32 -2
  27. package/dist/cjs/src/phemex.js +1 -1
  28. package/dist/cjs/src/pro/alpaca.js +1 -1
  29. package/dist/cjs/src/pro/binance.js +1 -1
  30. package/dist/cjs/src/pro/bitfinex2.js +1 -1
  31. package/dist/cjs/src/pro/bitget.js +1 -1
  32. package/dist/cjs/src/pro/bitmart.js +51 -89
  33. package/dist/cjs/src/pro/bitvavo.js +1 -1
  34. package/dist/cjs/src/pro/bybit.js +1 -1
  35. package/dist/cjs/src/pro/coinex.js +1 -1
  36. package/dist/cjs/src/pro/cryptocom.js +1 -1
  37. package/dist/cjs/src/pro/deribit.js +201 -84
  38. package/dist/cjs/src/pro/gate.js +1 -1
  39. package/dist/cjs/src/pro/independentreserve.js +1 -1
  40. package/dist/cjs/src/pro/kraken.js +1 -1
  41. package/dist/cjs/src/pro/kucoinfutures.js +1 -1
  42. package/dist/cjs/src/pro/mexc.js +5 -3
  43. package/dist/cjs/src/pro/okx.js +1 -1
  44. package/dist/cjs/src/pro/whitebit.js +4 -6
  45. package/dist/cjs/src/pro/woo.js +1 -1
  46. package/dist/cjs/src/probit.js +1 -1
  47. package/dist/cjs/src/wavesexchange.js +1 -1
  48. package/dist/cjs/src/woo.js +22 -6
  49. package/js/ccxt.d.ts +3 -3
  50. package/js/ccxt.js +1 -1
  51. package/js/src/alpaca.js +90 -88
  52. package/js/src/base/Exchange.d.ts +6 -4
  53. package/js/src/base/Exchange.js +24 -1
  54. package/js/src/base/types.d.ts +9 -0
  55. package/js/src/binance.d.ts +3 -2
  56. package/js/src/binance.js +43 -30
  57. package/js/src/bingx.d.ts +3 -2
  58. package/js/src/bingx.js +15 -4
  59. package/js/src/bitget.d.ts +3 -2
  60. package/js/src/bitget.js +72 -57
  61. package/js/src/bitmex.d.ts +3 -3
  62. package/js/src/bitmex.js +13 -29
  63. package/js/src/bitrue.js +24 -15
  64. package/js/src/blofin.d.ts +3 -2
  65. package/js/src/blofin.js +25 -2
  66. package/js/src/bybit.d.ts +3 -6
  67. package/js/src/bybit.js +11 -3
  68. package/js/src/coinbase.js +24 -14
  69. package/js/src/currencycom.d.ts +3 -2
  70. package/js/src/currencycom.js +15 -5
  71. package/js/src/delta.d.ts +3 -2
  72. package/js/src/delta.js +14 -1
  73. package/js/src/gate.js +1 -1
  74. package/js/src/hitbtc.d.ts +3 -2
  75. package/js/src/hitbtc.js +12 -1
  76. package/js/src/krakenfutures.d.ts +3 -2
  77. package/js/src/krakenfutures.js +22 -7
  78. package/js/src/kuna.js +14 -11
  79. package/js/src/lbank.js +1 -1
  80. package/js/src/mexc.d.ts +3 -13
  81. package/js/src/mexc.js +20 -20
  82. package/js/src/okx.d.ts +3 -2
  83. package/js/src/okx.js +32 -2
  84. package/js/src/phemex.js +1 -1
  85. package/js/src/pro/alpaca.js +1 -1
  86. package/js/src/pro/binance.js +1 -1
  87. package/js/src/pro/bitfinex2.js +1 -1
  88. package/js/src/pro/bitget.js +1 -1
  89. package/js/src/pro/bitmart.d.ts +2 -2
  90. package/js/src/pro/bitmart.js +51 -89
  91. package/js/src/pro/bitvavo.js +1 -1
  92. package/js/src/pro/bybit.js +1 -1
  93. package/js/src/pro/coinex.js +1 -1
  94. package/js/src/pro/cryptocom.js +1 -1
  95. package/js/src/pro/deribit.d.ts +5 -0
  96. package/js/src/pro/deribit.js +202 -85
  97. package/js/src/pro/gate.js +1 -1
  98. package/js/src/pro/independentreserve.js +1 -1
  99. package/js/src/pro/kraken.js +1 -1
  100. package/js/src/pro/kucoinfutures.js +1 -1
  101. package/js/src/pro/mexc.js +6 -4
  102. package/js/src/pro/okx.js +1 -1
  103. package/js/src/pro/whitebit.js +4 -6
  104. package/js/src/pro/woo.js +1 -1
  105. package/js/src/probit.js +1 -1
  106. package/js/src/wavesexchange.js +1 -1
  107. package/js/src/woo.d.ts +3 -5
  108. package/js/src/woo.js +22 -6
  109. package/package.json +1 -1
  110. package/skip-tests.json +8 -3
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import deribitRest from '../deribit.js';
9
- import { NotSupported, ExchangeError } from '../base/errors.js';
9
+ import { NotSupported, ExchangeError, ArgumentsRequired } from '../base/errors.js';
10
10
  import { ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
11
11
  import { sha256 } from '../static_dependencies/noble-hashes/sha256.js';
12
12
  // ---------------------------------------------------------------------------
@@ -19,10 +19,13 @@ export default class deribit extends deribitRest {
19
19
  'watchTicker': true,
20
20
  'watchTickers': false,
21
21
  'watchTrades': true,
22
+ 'watchTradesForSymbols': true,
22
23
  'watchMyTrades': true,
23
24
  'watchOrders': true,
24
25
  'watchOrderBook': true,
26
+ 'watchOrderBookForSymbols': true,
25
27
  'watchOHLCV': true,
28
+ 'watchOHLCVForSymbols': true,
26
29
  },
27
30
  'urls': {
28
31
  'test': {
@@ -33,18 +36,31 @@ export default class deribit extends deribitRest {
33
36
  },
34
37
  },
35
38
  'options': {
36
- 'timeframes': {
37
- '1m': 1,
38
- '3m': 3,
39
- '5m': 5,
40
- '15m': 15,
41
- '30m': 30,
42
- '1h': 60,
43
- '2h': 120,
44
- '4h': 180,
45
- '6h': 360,
46
- '12h': 720,
47
- '1d': '1D',
39
+ 'ws': {
40
+ 'timeframes': {
41
+ '1m': '1',
42
+ '3m': '3',
43
+ '5m': '5',
44
+ '15m': '15',
45
+ '30m': '30',
46
+ '1h': '60',
47
+ '2h': '120',
48
+ '4h': '180',
49
+ '6h': '360',
50
+ '12h': '720',
51
+ '1d': '1D',
52
+ },
53
+ // watchTrades replacement
54
+ 'watchTradesForSymbols': {
55
+ 'interval': '100ms', // 100ms, agg2, raw
56
+ },
57
+ // watchOrderBook replacement
58
+ 'watchOrderBookForSymbols': {
59
+ 'interval': '100ms',
60
+ 'useDepthEndpoint': false,
61
+ 'depth': '20',
62
+ 'group': 'none', // none, 1, 2, 5, 10, 25, 100, 250
63
+ },
48
64
  },
49
65
  'currencies': ['BTC', 'ETH', 'SOL', 'USDC'],
50
66
  },
@@ -224,27 +240,31 @@ export default class deribit extends deribitRest {
224
240
  * @param {str} [params.interval] specify aggregation and frequency of notifications. Possible values: 100ms, raw
225
241
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
226
242
  */
227
- await this.loadMarkets();
228
- const market = this.market(symbol);
229
- const url = this.urls['api']['ws'];
230
- const interval = this.safeString(params, 'interval', '100ms');
231
- params = this.omit(params, 'interval');
232
- const channel = 'trades.' + market['id'] + '.' + interval;
243
+ params['callerMethodName'] = 'watchTrades';
244
+ return await this.watchTradesForSymbols([symbol], since, limit, params);
245
+ }
246
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
247
+ /**
248
+ * @method
249
+ * @name deribit#watchTradesForSymbols
250
+ * @description get the list of most recent trades for a list of symbols
251
+ * @see https://docs.deribit.com/#trades-instrument_name-interval
252
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
253
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
254
+ * @param {int} [limit] the maximum amount of trades to fetch
255
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
256
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
257
+ */
258
+ let interval = undefined;
259
+ [interval, params] = this.handleOptionAndParams(params, 'watchTradesForSymbols', 'interval', '100ms');
233
260
  if (interval === 'raw') {
234
261
  await this.authenticate();
235
262
  }
236
- const message = {
237
- 'jsonrpc': '2.0',
238
- 'method': 'public/subscribe',
239
- 'params': {
240
- 'channels': [channel],
241
- },
242
- 'id': this.requestId(),
243
- };
244
- const request = this.deepExtend(message, params);
245
- const trades = await this.watch(url, channel, request, channel, request);
263
+ const trades = await this.watchMultipleWrapper('trades', interval, symbols, params);
246
264
  if (this.newUpdates) {
247
- limit = trades.getLimit(symbol, limit);
265
+ const first = this.safeDict(trades, 0);
266
+ const tradeSymbol = this.safeString(first, 'symbol');
267
+ limit = trades.getLimit(tradeSymbol, limit);
248
268
  }
249
269
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
250
270
  }
@@ -270,26 +290,27 @@ export default class deribit extends deribitRest {
270
290
  // }
271
291
  // }
272
292
  //
273
- const params = this.safeValue(message, 'params', {});
293
+ const params = this.safeDict(message, 'params', {});
274
294
  const channel = this.safeString(params, 'channel', '');
275
295
  const parts = channel.split('.');
276
296
  const marketId = this.safeString(parts, 1);
297
+ const interval = this.safeString(parts, 2);
277
298
  const symbol = this.safeSymbol(marketId);
278
299
  const market = this.safeMarket(marketId);
279
- const trades = this.safeValue(params, 'data', []);
280
- let stored = this.safeValue(this.trades, symbol);
281
- if (stored === undefined) {
300
+ const trades = this.safeList(params, 'data', []);
301
+ if (this.safeValue(this.trades, symbol) === undefined) {
282
302
  const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
283
- stored = new ArrayCache(limit);
284
- this.trades[symbol] = stored;
303
+ this.trades[symbol] = new ArrayCache(limit);
285
304
  }
305
+ const stored = this.trades[symbol];
286
306
  for (let i = 0; i < trades.length; i++) {
287
307
  const trade = trades[i];
288
308
  const parsed = this.parseTrade(trade, market);
289
309
  stored.append(parsed);
290
310
  }
291
311
  this.trades[symbol] = stored;
292
- client.resolve(this.trades[symbol], channel);
312
+ const messageHash = 'trades|' + symbol + '|' + interval;
313
+ client.resolve(this.trades[symbol], messageHash);
293
314
  }
294
315
  async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
295
316
  /**
@@ -380,7 +401,7 @@ export default class deribit extends deribitRest {
380
401
  /**
381
402
  * @method
382
403
  * @name deribit#watchOrderBook
383
- * @see https://docs.deribit.com/#public-get_book_summary_by_instrument
404
+ * @see https://docs.deribit.com/#book-instrument_name-group-depth-interval
384
405
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
385
406
  * @param {string} symbol unified symbol of the market to fetch the order book for
386
407
  * @param {int} [limit] the maximum amount of order book entries to return
@@ -388,25 +409,39 @@ export default class deribit extends deribitRest {
388
409
  * @param {string} [params.interval] Frequency of notifications. Events will be aggregated over this interval. Possible values: 100ms, raw
389
410
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
390
411
  */
391
- await this.loadMarkets();
392
- const market = this.market(symbol);
393
- const url = this.urls['api']['ws'];
394
- const interval = this.safeString(params, 'interval', '100ms');
395
- params = this.omit(params, 'interval');
412
+ params['callerMethodName'] = 'watchOrderBook';
413
+ return await this.watchOrderBookForSymbols([symbol], limit, params);
414
+ }
415
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
416
+ /**
417
+ * @method
418
+ * @name deribit#watchOrderBookForSymbols
419
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
420
+ * @see https://docs.deribit.com/#book-instrument_name-group-depth-interval
421
+ * @param {string[]} symbols unified array of symbols
422
+ * @param {int} [limit] the maximum amount of order book entries to return
423
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
424
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
425
+ */
426
+ let interval = undefined;
427
+ [interval, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'interval', '100ms');
396
428
  if (interval === 'raw') {
397
429
  await this.authenticate();
398
430
  }
399
- const channel = 'book.' + market['id'] + '.' + interval;
400
- const subscribe = {
401
- 'jsonrpc': '2.0',
402
- 'method': 'public/subscribe',
403
- 'params': {
404
- 'channels': [channel],
405
- },
406
- 'id': this.requestId(),
407
- };
408
- const request = this.deepExtend(subscribe, params);
409
- const orderbook = await this.watch(url, channel, request, channel);
431
+ let descriptor = '';
432
+ let useDepthEndpoint = undefined; // for more info, see comment in .options
433
+ [useDepthEndpoint, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'useDepthEndpoint', false);
434
+ if (useDepthEndpoint) {
435
+ let depth = undefined;
436
+ [depth, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'depth', '20');
437
+ let group = undefined;
438
+ [group, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'group', 'none');
439
+ descriptor = group + '.' + depth + '.' + interval;
440
+ }
441
+ else {
442
+ descriptor = interval;
443
+ }
444
+ const orderbook = await this.watchMultipleWrapper('book', descriptor, symbols, params);
410
445
  return orderbook.limit();
411
446
  }
412
447
  handleOrderBook(client, message) {
@@ -458,6 +493,20 @@ export default class deribit extends deribitRest {
458
493
  const params = this.safeValue(message, 'params', {});
459
494
  const data = this.safeValue(params, 'data', {});
460
495
  const channel = this.safeString(params, 'channel');
496
+ const parts = channel.split('.');
497
+ let descriptor = '';
498
+ const partsLength = parts.length;
499
+ const isDetailed = partsLength === 5;
500
+ if (isDetailed) {
501
+ const group = this.safeString(parts, 2);
502
+ const depth = this.safeString(parts, 3);
503
+ const interval = this.safeString(parts, 4);
504
+ descriptor = group + '.' + depth + '.' + interval;
505
+ }
506
+ else {
507
+ const interval = this.safeString(parts, 2);
508
+ descriptor = interval;
509
+ }
461
510
  const marketId = this.safeString(data, 'instrument_name');
462
511
  const symbol = this.safeSymbol(marketId);
463
512
  const timestamp = this.safeInteger(data, 'timestamp');
@@ -474,7 +523,8 @@ export default class deribit extends deribitRest {
474
523
  storedOrderBook['datetime'] = this.iso8601(timestamp);
475
524
  storedOrderBook['symbol'] = symbol;
476
525
  this.orderbooks[symbol] = storedOrderBook;
477
- client.resolve(storedOrderBook, channel);
526
+ const messageHash = 'book|' + symbol + '|' + descriptor;
527
+ client.resolve(storedOrderBook, messageHash);
478
528
  }
479
529
  cleanOrderBook(data) {
480
530
  const bids = this.safeValue(data, 'bids', []);
@@ -614,28 +664,32 @@ export default class deribit extends deribitRest {
614
664
  * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
615
665
  */
616
666
  await this.loadMarkets();
617
- const market = this.market(symbol);
618
- const url = this.urls['api']['ws'];
619
- const timeframes = this.safeValue(this.options, 'timeframes', {});
620
- const interval = this.safeString(timeframes, timeframe);
621
- if (interval === undefined) {
622
- throw new NotSupported(this.id + ' this interval is not supported, please provide one of the supported timeframes');
667
+ symbol = this.symbol(symbol);
668
+ const ohlcvs = await this.watchOHLCVForSymbols([[symbol, timeframe]], since, limit, params);
669
+ return ohlcvs[symbol][timeframe];
670
+ }
671
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
672
+ /**
673
+ * @method
674
+ * @name deribit#watchOHLCVForSymbols
675
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
676
+ * @see https://docs.deribit.com/#chart-trades-instrument_name-resolution
677
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
678
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
679
+ * @param {int} [limit] the maximum amount of candles to fetch
680
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
681
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
682
+ */
683
+ const symbolsLength = symbolsAndTimeframes.length;
684
+ if (symbolsLength === 0 || !Array.isArray(symbolsAndTimeframes[0])) {
685
+ throw new ArgumentsRequired(this.id + " watchOHLCVForSymbols() requires a an array of symbols and timeframes, like [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]");
623
686
  }
624
- const channel = 'chart.trades.' + market['id'] + '.' + interval;
625
- const message = {
626
- 'jsonrpc': '2.0',
627
- 'method': 'public/subscribe',
628
- 'params': {
629
- 'channels': [channel],
630
- },
631
- 'id': this.requestId(),
632
- };
633
- const request = this.deepExtend(message, params);
634
- const ohlcv = await this.watch(url, channel, request, channel, request);
687
+ const [symbol, timeframe, candles] = await this.watchMultipleWrapper('chart.trades', undefined, symbolsAndTimeframes, params);
635
688
  if (this.newUpdates) {
636
- limit = ohlcv.getLimit(market['symbol'], limit);
689
+ limit = candles.getLimit(symbol, limit);
637
690
  }
638
- return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
691
+ const filtered = this.filterBySinceLimit(candles, since, limit, 0, true);
692
+ return this.createOHLCVObject(symbol, timeframe, filtered);
639
693
  }
640
694
  handleOHLCV(client, message) {
641
695
  //
@@ -656,13 +710,44 @@ export default class deribit extends deribitRest {
656
710
  // }
657
711
  // }
658
712
  //
659
- const params = this.safeValue(message, 'params', {});
713
+ const params = this.safeDict(message, 'params', {});
660
714
  const channel = this.safeString(params, 'channel', '');
661
715
  const parts = channel.split('.');
662
716
  const marketId = this.safeString(parts, 2);
663
- const symbol = this.safeSymbol(marketId);
664
- const ohlcv = this.safeValue(params, 'data', {});
665
- const parsed = [
717
+ const rawTimeframe = this.safeString(parts, 3);
718
+ const market = this.safeMarket(marketId);
719
+ const symbol = market['symbol'];
720
+ const wsOptions = this.safeDict(this.options, 'ws', {});
721
+ const timeframes = this.safeDict(wsOptions, 'timeframes', {});
722
+ const unifiedTimeframe = this.findTimeframe(rawTimeframe, timeframes);
723
+ this.ohlcvs[symbol] = this.safeDict(this.ohlcvs, symbol, {});
724
+ if (this.safeValue(this.ohlcvs[symbol], unifiedTimeframe) === undefined) {
725
+ const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
726
+ this.ohlcvs[symbol][unifiedTimeframe] = new ArrayCacheByTimestamp(limit);
727
+ }
728
+ const stored = this.ohlcvs[symbol][unifiedTimeframe];
729
+ const ohlcv = this.safeDict(params, 'data', {});
730
+ // data contains a single OHLCV candle
731
+ const parsed = this.parseWsOHLCV(ohlcv, market);
732
+ stored.append(parsed);
733
+ this.ohlcvs[symbol][unifiedTimeframe] = stored;
734
+ const resolveData = [symbol, unifiedTimeframe, stored];
735
+ const messageHash = 'chart.trades|' + symbol + '|' + rawTimeframe;
736
+ client.resolve(resolveData, messageHash);
737
+ }
738
+ parseWsOHLCV(ohlcv, market = undefined) {
739
+ //
740
+ // {
741
+ // "c": "28909.0",
742
+ // "o": "28915.4",
743
+ // "h": "28915.4",
744
+ // "l": "28896.1",
745
+ // "v": "27.6919",
746
+ // "T": 1696687499999,
747
+ // "t": 1696687440000
748
+ // }
749
+ //
750
+ return [
666
751
  this.safeInteger(ohlcv, 'tick'),
667
752
  this.safeNumber(ohlcv, 'open'),
668
753
  this.safeNumber(ohlcv, 'high'),
@@ -670,14 +755,46 @@ export default class deribit extends deribitRest {
670
755
  this.safeNumber(ohlcv, 'close'),
671
756
  this.safeNumber(ohlcv, 'volume'),
672
757
  ];
673
- let stored = this.safeValue(this.ohlcvs, symbol);
674
- if (stored === undefined) {
675
- const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
676
- stored = new ArrayCacheByTimestamp(limit);
758
+ }
759
+ async watchMultipleWrapper(channelName, channelDescriptor, symbolsArray = undefined, params = {}) {
760
+ await this.loadMarkets();
761
+ const url = this.urls['api']['ws'];
762
+ const rawSubscriptions = [];
763
+ const messageHashes = [];
764
+ const isOHLCV = (channelName === 'chart.trades');
765
+ const symbols = isOHLCV ? this.getListFromObjectValues(symbolsArray, 0) : symbolsArray;
766
+ this.marketSymbols(symbols, undefined, false);
767
+ for (let i = 0; i < symbolsArray.length; i++) {
768
+ const current = symbolsArray[i];
769
+ let market = undefined;
770
+ if (isOHLCV) {
771
+ market = this.market(current[0]);
772
+ const unifiedTf = current[1];
773
+ const rawTf = this.safeString(this.timeframes, unifiedTf, unifiedTf);
774
+ channelDescriptor = rawTf;
775
+ }
776
+ else {
777
+ market = this.market(current);
778
+ }
779
+ const message = channelName + '.' + market['id'] + '.' + channelDescriptor;
780
+ rawSubscriptions.push(message);
781
+ messageHashes.push(channelName + '|' + market['symbol'] + '|' + channelDescriptor);
677
782
  }
678
- stored.append(parsed);
679
- this.ohlcvs[symbol] = stored;
680
- client.resolve(stored, channel);
783
+ const request = {
784
+ 'jsonrpc': '2.0',
785
+ 'method': 'public/subscribe',
786
+ 'params': {
787
+ 'channels': rawSubscriptions,
788
+ },
789
+ 'id': this.requestId(),
790
+ };
791
+ const extendedRequest = this.deepExtend(request, params);
792
+ const maxMessageByteLimit = 32768 - 1; // 'Message Too Big: limit 32768B'
793
+ const jsonedText = this.json(extendedRequest);
794
+ if (jsonedText.length >= maxMessageByteLimit) {
795
+ throw new ExchangeError(this.id + ' requested subscription length over limit, try to reduce symbols amount');
796
+ }
797
+ return await this.watchMultiple(url, messageHashes, extendedRequest, rawSubscriptions);
681
798
  }
682
799
  handleMessage(client, message) {
683
800
  //
@@ -825,7 +825,7 @@ export default class gate extends gateRest {
825
825
  const client = this.client(url);
826
826
  this.setPositionsCache(client, type, symbols);
827
827
  const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', true);
828
- const awaitPositionsSnapshot = this.safeValue('watchPositions', 'awaitPositionsSnapshot', true);
828
+ const awaitPositionsSnapshot = this.safeBool('watchPositions', 'awaitPositionsSnapshot', true);
829
829
  const cache = this.safeValue(this.positions, type);
830
830
  if (fetchPositionsSnapshot && awaitPositionsSnapshot && cache === undefined) {
831
831
  return await client.future(type + ':fetchPositionsSnapshot');
@@ -199,7 +199,7 @@ export default class independentreserve extends independentreserveRest {
199
199
  orderbook['timestamp'] = timestamp;
200
200
  orderbook['datetime'] = this.iso8601(timestamp);
201
201
  }
202
- const checksum = this.safeValue(this.options, 'checksum', true);
202
+ const checksum = this.safeBool(this.options, 'checksum', true);
203
203
  if (checksum && receivedSnapshot) {
204
204
  const storedAsks = orderbook['asks'];
205
205
  const storedBids = orderbook['bids'];
@@ -700,7 +700,7 @@ export default class kraken extends krakenRest {
700
700
  }
701
701
  // don't remove this line or I will poop on your face
702
702
  orderbook.limit();
703
- const checksum = this.safeValue(this.options, 'checksum', true);
703
+ const checksum = this.safeBool(this.options, 'checksum', true);
704
704
  if (checksum) {
705
705
  const priceString = this.safeString(example, 0);
706
706
  const amountString = this.safeString(example, 1);
@@ -241,7 +241,7 @@ export default class kucoinfutures extends kucoinfuturesRest {
241
241
  const client = this.client(url);
242
242
  this.setPositionCache(client, symbol);
243
243
  const fetchPositionSnapshot = this.handleOption('watchPosition', 'fetchPositionSnapshot', true);
244
- const awaitPositionSnapshot = this.safeValue('watchPosition', 'awaitPositionSnapshot', true);
244
+ const awaitPositionSnapshot = this.safeBool('watchPosition', 'awaitPositionSnapshot', true);
245
245
  const currentPosition = this.getCurrentPosition(symbol);
246
246
  if (fetchPositionSnapshot && awaitPositionSnapshot && currentPosition === undefined) {
247
247
  const snapshot = await client.future('fetchPositionSnapshot:' + symbol);
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import mexcRest from '../mexc.js';
9
- import { ExchangeError, AuthenticationError } from '../base/errors.js';
9
+ import { AuthenticationError } from '../base/errors.js';
10
10
  import { ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
11
11
  import { sha256 } from '../static_dependencies/noble-hashes/sha256.js';
12
12
  // ---------------------------------------------------------------------------
@@ -503,10 +503,12 @@ export default class mexc extends mexcRest {
503
503
  }
504
504
  }
505
505
  handleDelta(orderbook, delta) {
506
- const nonce = this.safeInteger(orderbook, 'nonce');
506
+ const existingNonce = this.safeInteger(orderbook, 'nonce');
507
507
  const deltaNonce = this.safeInteger2(delta, 'r', 'version');
508
- if (deltaNonce !== nonce && deltaNonce !== nonce + 1) {
509
- throw new ExchangeError(this.id + ' handleOrderBook received an out-of-order nonce');
508
+ if (deltaNonce < existingNonce) {
509
+ // even when doing < comparison, this happens: https://app.travis-ci.com/github/ccxt/ccxt/builds/269234741#L1809
510
+ // so, we just skip old updates
511
+ return;
510
512
  }
511
513
  orderbook['nonce'] = deltaNonce;
512
514
  const asks = this.safeValue(delta, 'asks', []);
package/js/src/pro/okx.js CHANGED
@@ -562,7 +562,7 @@ export default class okx extends okxRest {
562
562
  const storedBids = orderbook['bids'];
563
563
  this.handleDeltas(storedAsks, asks);
564
564
  this.handleDeltas(storedBids, bids);
565
- const checksum = this.safeValue(this.options, 'checksum', true);
565
+ const checksum = this.safeBool(this.options, 'checksum', true);
566
566
  if (checksum) {
567
567
  const asksLength = storedAsks.length;
568
568
  const bidsLength = storedBids.length;
@@ -871,12 +871,10 @@ export default class whitebit extends whitebitRest {
871
871
  if (!this.handleErrorMessage(client, message)) {
872
872
  return;
873
873
  }
874
- const result = this.safeValue(message, 'result', {});
875
- if (result !== undefined) {
876
- if (result === 'pong') {
877
- this.handlePong(client, message);
878
- return;
879
- }
874
+ const result = this.safeString(message, 'result');
875
+ if (result === 'pong') {
876
+ this.handlePong(client, message);
877
+ return;
880
878
  }
881
879
  const id = this.safeInteger(message, 'id');
882
880
  if (id !== undefined) {
package/js/src/pro/woo.js CHANGED
@@ -632,7 +632,7 @@ export default class woo extends wooRest {
632
632
  const client = this.client(url);
633
633
  this.setPositionsCache(client, symbols);
634
634
  const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', true);
635
- const awaitPositionsSnapshot = this.safeValue('watchPositions', 'awaitPositionsSnapshot', true);
635
+ const awaitPositionsSnapshot = this.safeBool('watchPositions', 'awaitPositionsSnapshot', true);
636
636
  if (fetchPositionsSnapshot && awaitPositionsSnapshot && this.positions === undefined) {
637
637
  const snapshot = await client.future('fetchPositionsSnapshot');
638
638
  return this.filterBySymbolsSinceLimit(snapshot, symbols, since, limit, true);
package/js/src/probit.js CHANGED
@@ -1556,7 +1556,7 @@ export default class probit extends Exchange {
1556
1556
  // ]
1557
1557
  // }
1558
1558
  //
1559
- const data = this.safeValue(response, 'data', {});
1559
+ const data = this.safeList(response, 'data', []);
1560
1560
  return this.parseTransactions(data, currency, since, limit);
1561
1561
  }
1562
1562
  parseTransaction(transaction, currency = undefined) {
@@ -1381,7 +1381,7 @@ export default class wavesexchange extends Exchange {
1381
1381
  'amountAsset': amountAsset,
1382
1382
  'priceAsset': priceAsset,
1383
1383
  };
1384
- const sandboxMode = this.safeValue(this.options, 'sandboxMode', false);
1384
+ const sandboxMode = this.safeBool(this.options, 'sandboxMode', false);
1385
1385
  const chainId = (sandboxMode) ? 84 : 87;
1386
1386
  const body = {
1387
1387
  'senderPublicKey': this.apiKey,
package/js/src/woo.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import Exchange from './abstract/woo.js';
2
- import type { TransferEntry, Balances, Currency, FundingRateHistory, Int, Market, OHLCV, Order, OrderBook, OrderSide, OrderType, Str, Strings, Trade, Transaction } from './base/types.js';
2
+ import type { TransferEntry, Balances, Currency, FundingRateHistory, Int, Market, OHLCV, Order, OrderBook, OrderSide, OrderType, Str, Strings, Trade, Transaction, Leverage } from './base/types.js';
3
3
  /**
4
4
  * @class woo
5
5
  * @augments Exchange
@@ -158,10 +158,8 @@ export default class woo extends Exchange {
158
158
  fetchFundingRates(symbols?: Strings, params?: {}): Promise<any>;
159
159
  fetchFundingRateHistory(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<FundingRateHistory[]>;
160
160
  setPositionMode(hedged: boolean, symbol?: Str, params?: {}): Promise<any>;
161
- fetchLeverage(symbol: string, params?: {}): Promise<{
162
- info: any;
163
- leverage: number;
164
- }>;
161
+ fetchLeverage(symbol: string, params?: {}): Promise<Leverage>;
162
+ parseLeverage(leverage: any, market?: any): Leverage;
165
163
  setLeverage(leverage: Int, symbol?: Str, params?: {}): Promise<any>;
166
164
  fetchPosition(symbol?: Str, params?: {}): Promise<import("./base/types.js").Position>;
167
165
  fetchPositions(symbols?: Strings, params?: {}): Promise<import("./base/types.js").Position[]>;
package/js/src/woo.js CHANGED
@@ -493,7 +493,7 @@ export default class woo extends Exchange {
493
493
  // ]
494
494
  // }
495
495
  //
496
- const resultResponse = this.safeValue(response, 'rows', {});
496
+ const resultResponse = this.safeList(response, 'rows', []);
497
497
  return this.parseTrades(resultResponse, market, since, limit);
498
498
  }
499
499
  parseTrade(trade, market = undefined) {
@@ -2337,7 +2337,7 @@ export default class woo extends Exchange {
2337
2337
  else {
2338
2338
  this.checkRequiredCredentials();
2339
2339
  if (method === 'POST' && (path === 'algo/order' || path === 'order')) {
2340
- const isSandboxMode = this.safeValue(this.options, 'sandboxMode', false);
2340
+ const isSandboxMode = this.safeBool(this.options, 'sandboxMode', false);
2341
2341
  if (!isSandboxMode) {
2342
2342
  const applicationId = 'bc830de7-50f3-460b-9ee0-f430f83f9dad';
2343
2343
  const brokerId = this.safeString(this.options, 'brokerId', applicationId);
@@ -2656,7 +2656,17 @@ export default class woo extends Exchange {
2656
2656
  return response;
2657
2657
  }
2658
2658
  async fetchLeverage(symbol, params = {}) {
2659
+ /**
2660
+ * @method
2661
+ * @name woo#fetchLeverage
2662
+ * @description fetch the set leverage for a market
2663
+ * @see https://docs.woo.org/#get-account-information-new
2664
+ * @param {string} symbol unified market symbol
2665
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2666
+ * @returns {object} a [leverage structure]{@link https://docs.ccxt.com/#/?id=leverage-structure}
2667
+ */
2659
2668
  await this.loadMarkets();
2669
+ const market = this.market(symbol);
2660
2670
  const response = await this.v3PrivateGetAccountinfo(params);
2661
2671
  //
2662
2672
  // {
@@ -2686,11 +2696,17 @@ export default class woo extends Exchange {
2686
2696
  // "timestamp": 1673323685109
2687
2697
  // }
2688
2698
  //
2689
- const result = this.safeValue(response, 'data');
2690
- const leverage = this.safeNumber(result, 'leverage');
2699
+ const data = this.safeDict(response, 'data', {});
2700
+ return this.parseLeverage(data, market);
2701
+ }
2702
+ parseLeverage(leverage, market = undefined) {
2703
+ const leverageValue = this.safeInteger(leverage, 'leverage');
2691
2704
  return {
2692
- 'info': response,
2693
- 'leverage': leverage,
2705
+ 'info': leverage,
2706
+ 'symbol': market['symbol'],
2707
+ 'marginMode': undefined,
2708
+ 'longLeverage': leverageValue,
2709
+ 'shortLeverage': leverageValue,
2694
2710
  };
2695
2711
  }
2696
2712
  async setLeverage(leverage, symbol = undefined, params = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccxt",
3
- "version": "4.2.57",
3
+ "version": "4.2.59",
4
4
  "description": "A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges",
5
5
  "unpkg": "dist/ccxt.browser.js",
6
6
  "type": "module",