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
@@ -1084,7 +1084,7 @@ class bitvavo extends bitvavo$1 {
1084
1084
  return messageHash;
1085
1085
  }
1086
1086
  checkMessageHashDoesNotExist(messageHash) {
1087
- const supressMultipleWsRequestsError = this.safeValue(this.options, 'supressMultipleWsRequestsError', false);
1087
+ const supressMultipleWsRequestsError = this.safeBool(this.options, 'supressMultipleWsRequestsError', false);
1088
1088
  if (!supressMultipleWsRequestsError) {
1089
1089
  const client = this.safeValue(this.clients, this.urls['api']['ws']);
1090
1090
  if (client !== undefined) {
@@ -939,7 +939,7 @@ class bybit extends bybit$1 {
939
939
  this.setPositionsCache(client, symbols);
940
940
  const cache = this.positions;
941
941
  const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', true);
942
- const awaitPositionsSnapshot = this.safeValue('watchPositions', 'awaitPositionsSnapshot', true);
942
+ const awaitPositionsSnapshot = this.safeBool('watchPositions', 'awaitPositionsSnapshot', true);
943
943
  if (fetchPositionsSnapshot && awaitPositionsSnapshot && cache === undefined) {
944
944
  const snapshot = await client.future('fetchPositionsSnapshot');
945
945
  return this.filterBySymbolsSinceLimit(snapshot, symbols, since, limit, true);
@@ -546,7 +546,7 @@ class coinex extends coinex$1 {
546
546
  }
547
547
  const url = this.urls['api']['ws'][type];
548
548
  const messageHash = 'ohlcv';
549
- const watchOHLCVWarning = this.safeValue(this.options, 'watchOHLCVWarning', true);
549
+ const watchOHLCVWarning = this.safeBool(this.options, 'watchOHLCVWarning', true);
550
550
  const client = this.safeValue(this.clients, url, {});
551
551
  const clientSub = this.safeValue(client, 'subscriptions', {});
552
552
  const existingSubscription = this.safeValue(clientSub, messageHash);
@@ -553,7 +553,7 @@ class cryptocom extends cryptocom$1 {
553
553
  const client = this.client(url);
554
554
  this.setPositionsCache(client, symbols);
555
555
  const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', true);
556
- const awaitPositionsSnapshot = this.safeValue('watchPositions', 'awaitPositionsSnapshot', true);
556
+ const awaitPositionsSnapshot = this.safeBool('watchPositions', 'awaitPositionsSnapshot', true);
557
557
  if (fetchPositionsSnapshot && awaitPositionsSnapshot && this.positions === undefined) {
558
558
  const snapshot = await client.future('fetchPositionsSnapshot');
559
559
  return this.filterBySymbolsSinceLimit(snapshot, symbols, since, limit, true);
@@ -16,10 +16,13 @@ class deribit extends deribit$1 {
16
16
  'watchTicker': true,
17
17
  'watchTickers': false,
18
18
  'watchTrades': true,
19
+ 'watchTradesForSymbols': true,
19
20
  'watchMyTrades': true,
20
21
  'watchOrders': true,
21
22
  'watchOrderBook': true,
23
+ 'watchOrderBookForSymbols': true,
22
24
  'watchOHLCV': true,
25
+ 'watchOHLCVForSymbols': true,
23
26
  },
24
27
  'urls': {
25
28
  'test': {
@@ -30,18 +33,31 @@ class deribit extends deribit$1 {
30
33
  },
31
34
  },
32
35
  'options': {
33
- 'timeframes': {
34
- '1m': 1,
35
- '3m': 3,
36
- '5m': 5,
37
- '15m': 15,
38
- '30m': 30,
39
- '1h': 60,
40
- '2h': 120,
41
- '4h': 180,
42
- '6h': 360,
43
- '12h': 720,
44
- '1d': '1D',
36
+ 'ws': {
37
+ 'timeframes': {
38
+ '1m': '1',
39
+ '3m': '3',
40
+ '5m': '5',
41
+ '15m': '15',
42
+ '30m': '30',
43
+ '1h': '60',
44
+ '2h': '120',
45
+ '4h': '180',
46
+ '6h': '360',
47
+ '12h': '720',
48
+ '1d': '1D',
49
+ },
50
+ // watchTrades replacement
51
+ 'watchTradesForSymbols': {
52
+ 'interval': '100ms', // 100ms, agg2, raw
53
+ },
54
+ // watchOrderBook replacement
55
+ 'watchOrderBookForSymbols': {
56
+ 'interval': '100ms',
57
+ 'useDepthEndpoint': false,
58
+ 'depth': '20',
59
+ 'group': 'none', // none, 1, 2, 5, 10, 25, 100, 250
60
+ },
45
61
  },
46
62
  'currencies': ['BTC', 'ETH', 'SOL', 'USDC'],
47
63
  },
@@ -221,27 +237,31 @@ class deribit extends deribit$1 {
221
237
  * @param {str} [params.interval] specify aggregation and frequency of notifications. Possible values: 100ms, raw
222
238
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
223
239
  */
224
- await this.loadMarkets();
225
- const market = this.market(symbol);
226
- const url = this.urls['api']['ws'];
227
- const interval = this.safeString(params, 'interval', '100ms');
228
- params = this.omit(params, 'interval');
229
- const channel = 'trades.' + market['id'] + '.' + interval;
240
+ params['callerMethodName'] = 'watchTrades';
241
+ return await this.watchTradesForSymbols([symbol], since, limit, params);
242
+ }
243
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
244
+ /**
245
+ * @method
246
+ * @name deribit#watchTradesForSymbols
247
+ * @description get the list of most recent trades for a list of symbols
248
+ * @see https://docs.deribit.com/#trades-instrument_name-interval
249
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
250
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
251
+ * @param {int} [limit] the maximum amount of trades to fetch
252
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
253
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
254
+ */
255
+ let interval = undefined;
256
+ [interval, params] = this.handleOptionAndParams(params, 'watchTradesForSymbols', 'interval', '100ms');
230
257
  if (interval === 'raw') {
231
258
  await this.authenticate();
232
259
  }
233
- const message = {
234
- 'jsonrpc': '2.0',
235
- 'method': 'public/subscribe',
236
- 'params': {
237
- 'channels': [channel],
238
- },
239
- 'id': this.requestId(),
240
- };
241
- const request = this.deepExtend(message, params);
242
- const trades = await this.watch(url, channel, request, channel, request);
260
+ const trades = await this.watchMultipleWrapper('trades', interval, symbols, params);
243
261
  if (this.newUpdates) {
244
- limit = trades.getLimit(symbol, limit);
262
+ const first = this.safeDict(trades, 0);
263
+ const tradeSymbol = this.safeString(first, 'symbol');
264
+ limit = trades.getLimit(tradeSymbol, limit);
245
265
  }
246
266
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
247
267
  }
@@ -267,26 +287,27 @@ class deribit extends deribit$1 {
267
287
  // }
268
288
  // }
269
289
  //
270
- const params = this.safeValue(message, 'params', {});
290
+ const params = this.safeDict(message, 'params', {});
271
291
  const channel = this.safeString(params, 'channel', '');
272
292
  const parts = channel.split('.');
273
293
  const marketId = this.safeString(parts, 1);
294
+ const interval = this.safeString(parts, 2);
274
295
  const symbol = this.safeSymbol(marketId);
275
296
  const market = this.safeMarket(marketId);
276
- const trades = this.safeValue(params, 'data', []);
277
- let stored = this.safeValue(this.trades, symbol);
278
- if (stored === undefined) {
297
+ const trades = this.safeList(params, 'data', []);
298
+ if (this.safeValue(this.trades, symbol) === undefined) {
279
299
  const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
280
- stored = new Cache.ArrayCache(limit);
281
- this.trades[symbol] = stored;
300
+ this.trades[symbol] = new Cache.ArrayCache(limit);
282
301
  }
302
+ const stored = this.trades[symbol];
283
303
  for (let i = 0; i < trades.length; i++) {
284
304
  const trade = trades[i];
285
305
  const parsed = this.parseTrade(trade, market);
286
306
  stored.append(parsed);
287
307
  }
288
308
  this.trades[symbol] = stored;
289
- client.resolve(this.trades[symbol], channel);
309
+ const messageHash = 'trades|' + symbol + '|' + interval;
310
+ client.resolve(this.trades[symbol], messageHash);
290
311
  }
291
312
  async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
292
313
  /**
@@ -375,7 +396,7 @@ class deribit extends deribit$1 {
375
396
  /**
376
397
  * @method
377
398
  * @name deribit#watchOrderBook
378
- * @see https://docs.deribit.com/#public-get_book_summary_by_instrument
399
+ * @see https://docs.deribit.com/#book-instrument_name-group-depth-interval
379
400
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
380
401
  * @param {string} symbol unified symbol of the market to fetch the order book for
381
402
  * @param {int} [limit] the maximum amount of order book entries to return
@@ -383,25 +404,39 @@ class deribit extends deribit$1 {
383
404
  * @param {string} [params.interval] Frequency of notifications. Events will be aggregated over this interval. Possible values: 100ms, raw
384
405
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
385
406
  */
386
- await this.loadMarkets();
387
- const market = this.market(symbol);
388
- const url = this.urls['api']['ws'];
389
- const interval = this.safeString(params, 'interval', '100ms');
390
- params = this.omit(params, 'interval');
407
+ params['callerMethodName'] = 'watchOrderBook';
408
+ return await this.watchOrderBookForSymbols([symbol], limit, params);
409
+ }
410
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
411
+ /**
412
+ * @method
413
+ * @name deribit#watchOrderBookForSymbols
414
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
415
+ * @see https://docs.deribit.com/#book-instrument_name-group-depth-interval
416
+ * @param {string[]} symbols unified array of symbols
417
+ * @param {int} [limit] the maximum amount of order book entries to return
418
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
419
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
420
+ */
421
+ let interval = undefined;
422
+ [interval, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'interval', '100ms');
391
423
  if (interval === 'raw') {
392
424
  await this.authenticate();
393
425
  }
394
- const channel = 'book.' + market['id'] + '.' + interval;
395
- const subscribe = {
396
- 'jsonrpc': '2.0',
397
- 'method': 'public/subscribe',
398
- 'params': {
399
- 'channels': [channel],
400
- },
401
- 'id': this.requestId(),
402
- };
403
- const request = this.deepExtend(subscribe, params);
404
- const orderbook = await this.watch(url, channel, request, channel);
426
+ let descriptor = '';
427
+ let useDepthEndpoint = undefined; // for more info, see comment in .options
428
+ [useDepthEndpoint, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'useDepthEndpoint', false);
429
+ if (useDepthEndpoint) {
430
+ let depth = undefined;
431
+ [depth, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'depth', '20');
432
+ let group = undefined;
433
+ [group, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'group', 'none');
434
+ descriptor = group + '.' + depth + '.' + interval;
435
+ }
436
+ else {
437
+ descriptor = interval;
438
+ }
439
+ const orderbook = await this.watchMultipleWrapper('book', descriptor, symbols, params);
405
440
  return orderbook.limit();
406
441
  }
407
442
  handleOrderBook(client, message) {
@@ -453,6 +488,20 @@ class deribit extends deribit$1 {
453
488
  const params = this.safeValue(message, 'params', {});
454
489
  const data = this.safeValue(params, 'data', {});
455
490
  const channel = this.safeString(params, 'channel');
491
+ const parts = channel.split('.');
492
+ let descriptor = '';
493
+ const partsLength = parts.length;
494
+ const isDetailed = partsLength === 5;
495
+ if (isDetailed) {
496
+ const group = this.safeString(parts, 2);
497
+ const depth = this.safeString(parts, 3);
498
+ const interval = this.safeString(parts, 4);
499
+ descriptor = group + '.' + depth + '.' + interval;
500
+ }
501
+ else {
502
+ const interval = this.safeString(parts, 2);
503
+ descriptor = interval;
504
+ }
456
505
  const marketId = this.safeString(data, 'instrument_name');
457
506
  const symbol = this.safeSymbol(marketId);
458
507
  const timestamp = this.safeInteger(data, 'timestamp');
@@ -469,7 +518,8 @@ class deribit extends deribit$1 {
469
518
  storedOrderBook['datetime'] = this.iso8601(timestamp);
470
519
  storedOrderBook['symbol'] = symbol;
471
520
  this.orderbooks[symbol] = storedOrderBook;
472
- client.resolve(storedOrderBook, channel);
521
+ const messageHash = 'book|' + symbol + '|' + descriptor;
522
+ client.resolve(storedOrderBook, messageHash);
473
523
  }
474
524
  cleanOrderBook(data) {
475
525
  const bids = this.safeValue(data, 'bids', []);
@@ -609,28 +659,32 @@ class deribit extends deribit$1 {
609
659
  * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
610
660
  */
611
661
  await this.loadMarkets();
612
- const market = this.market(symbol);
613
- const url = this.urls['api']['ws'];
614
- const timeframes = this.safeValue(this.options, 'timeframes', {});
615
- const interval = this.safeString(timeframes, timeframe);
616
- if (interval === undefined) {
617
- throw new errors.NotSupported(this.id + ' this interval is not supported, please provide one of the supported timeframes');
662
+ symbol = this.symbol(symbol);
663
+ const ohlcvs = await this.watchOHLCVForSymbols([[symbol, timeframe]], since, limit, params);
664
+ return ohlcvs[symbol][timeframe];
665
+ }
666
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
667
+ /**
668
+ * @method
669
+ * @name deribit#watchOHLCVForSymbols
670
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
671
+ * @see https://docs.deribit.com/#chart-trades-instrument_name-resolution
672
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
673
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
674
+ * @param {int} [limit] the maximum amount of candles to fetch
675
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
676
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
677
+ */
678
+ const symbolsLength = symbolsAndTimeframes.length;
679
+ if (symbolsLength === 0 || !Array.isArray(symbolsAndTimeframes[0])) {
680
+ throw new errors.ArgumentsRequired(this.id + " watchOHLCVForSymbols() requires a an array of symbols and timeframes, like [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]");
618
681
  }
619
- const channel = 'chart.trades.' + market['id'] + '.' + interval;
620
- const message = {
621
- 'jsonrpc': '2.0',
622
- 'method': 'public/subscribe',
623
- 'params': {
624
- 'channels': [channel],
625
- },
626
- 'id': this.requestId(),
627
- };
628
- const request = this.deepExtend(message, params);
629
- const ohlcv = await this.watch(url, channel, request, channel, request);
682
+ const [symbol, timeframe, candles] = await this.watchMultipleWrapper('chart.trades', undefined, symbolsAndTimeframes, params);
630
683
  if (this.newUpdates) {
631
- limit = ohlcv.getLimit(market['symbol'], limit);
684
+ limit = candles.getLimit(symbol, limit);
632
685
  }
633
- return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
686
+ const filtered = this.filterBySinceLimit(candles, since, limit, 0, true);
687
+ return this.createOHLCVObject(symbol, timeframe, filtered);
634
688
  }
635
689
  handleOHLCV(client, message) {
636
690
  //
@@ -651,13 +705,44 @@ class deribit extends deribit$1 {
651
705
  // }
652
706
  // }
653
707
  //
654
- const params = this.safeValue(message, 'params', {});
708
+ const params = this.safeDict(message, 'params', {});
655
709
  const channel = this.safeString(params, 'channel', '');
656
710
  const parts = channel.split('.');
657
711
  const marketId = this.safeString(parts, 2);
658
- const symbol = this.safeSymbol(marketId);
659
- const ohlcv = this.safeValue(params, 'data', {});
660
- const parsed = [
712
+ const rawTimeframe = this.safeString(parts, 3);
713
+ const market = this.safeMarket(marketId);
714
+ const symbol = market['symbol'];
715
+ const wsOptions = this.safeDict(this.options, 'ws', {});
716
+ const timeframes = this.safeDict(wsOptions, 'timeframes', {});
717
+ const unifiedTimeframe = this.findTimeframe(rawTimeframe, timeframes);
718
+ this.ohlcvs[symbol] = this.safeDict(this.ohlcvs, symbol, {});
719
+ if (this.safeValue(this.ohlcvs[symbol], unifiedTimeframe) === undefined) {
720
+ const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
721
+ this.ohlcvs[symbol][unifiedTimeframe] = new Cache.ArrayCacheByTimestamp(limit);
722
+ }
723
+ const stored = this.ohlcvs[symbol][unifiedTimeframe];
724
+ const ohlcv = this.safeDict(params, 'data', {});
725
+ // data contains a single OHLCV candle
726
+ const parsed = this.parseWsOHLCV(ohlcv, market);
727
+ stored.append(parsed);
728
+ this.ohlcvs[symbol][unifiedTimeframe] = stored;
729
+ const resolveData = [symbol, unifiedTimeframe, stored];
730
+ const messageHash = 'chart.trades|' + symbol + '|' + rawTimeframe;
731
+ client.resolve(resolveData, messageHash);
732
+ }
733
+ parseWsOHLCV(ohlcv, market = undefined) {
734
+ //
735
+ // {
736
+ // "c": "28909.0",
737
+ // "o": "28915.4",
738
+ // "h": "28915.4",
739
+ // "l": "28896.1",
740
+ // "v": "27.6919",
741
+ // "T": 1696687499999,
742
+ // "t": 1696687440000
743
+ // }
744
+ //
745
+ return [
661
746
  this.safeInteger(ohlcv, 'tick'),
662
747
  this.safeNumber(ohlcv, 'open'),
663
748
  this.safeNumber(ohlcv, 'high'),
@@ -665,14 +750,46 @@ class deribit extends deribit$1 {
665
750
  this.safeNumber(ohlcv, 'close'),
666
751
  this.safeNumber(ohlcv, 'volume'),
667
752
  ];
668
- let stored = this.safeValue(this.ohlcvs, symbol);
669
- if (stored === undefined) {
670
- const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
671
- stored = new Cache.ArrayCacheByTimestamp(limit);
753
+ }
754
+ async watchMultipleWrapper(channelName, channelDescriptor, symbolsArray = undefined, params = {}) {
755
+ await this.loadMarkets();
756
+ const url = this.urls['api']['ws'];
757
+ const rawSubscriptions = [];
758
+ const messageHashes = [];
759
+ const isOHLCV = (channelName === 'chart.trades');
760
+ const symbols = isOHLCV ? this.getListFromObjectValues(symbolsArray, 0) : symbolsArray;
761
+ this.marketSymbols(symbols, undefined, false);
762
+ for (let i = 0; i < symbolsArray.length; i++) {
763
+ const current = symbolsArray[i];
764
+ let market = undefined;
765
+ if (isOHLCV) {
766
+ market = this.market(current[0]);
767
+ const unifiedTf = current[1];
768
+ const rawTf = this.safeString(this.timeframes, unifiedTf, unifiedTf);
769
+ channelDescriptor = rawTf;
770
+ }
771
+ else {
772
+ market = this.market(current);
773
+ }
774
+ const message = channelName + '.' + market['id'] + '.' + channelDescriptor;
775
+ rawSubscriptions.push(message);
776
+ messageHashes.push(channelName + '|' + market['symbol'] + '|' + channelDescriptor);
672
777
  }
673
- stored.append(parsed);
674
- this.ohlcvs[symbol] = stored;
675
- client.resolve(stored, channel);
778
+ const request = {
779
+ 'jsonrpc': '2.0',
780
+ 'method': 'public/subscribe',
781
+ 'params': {
782
+ 'channels': rawSubscriptions,
783
+ },
784
+ 'id': this.requestId(),
785
+ };
786
+ const extendedRequest = this.deepExtend(request, params);
787
+ const maxMessageByteLimit = 32768 - 1; // 'Message Too Big: limit 32768B'
788
+ const jsonedText = this.json(extendedRequest);
789
+ if (jsonedText.length >= maxMessageByteLimit) {
790
+ throw new errors.ExchangeError(this.id + ' requested subscription length over limit, try to reduce symbols amount');
791
+ }
792
+ return await this.watchMultiple(url, messageHashes, extendedRequest, rawSubscriptions);
676
793
  }
677
794
  handleMessage(client, message) {
678
795
  //
@@ -822,7 +822,7 @@ class gate extends gate$1 {
822
822
  const client = this.client(url);
823
823
  this.setPositionsCache(client, type, symbols);
824
824
  const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', true);
825
- const awaitPositionsSnapshot = this.safeValue('watchPositions', 'awaitPositionsSnapshot', true);
825
+ const awaitPositionsSnapshot = this.safeBool('watchPositions', 'awaitPositionsSnapshot', true);
826
826
  const cache = this.safeValue(this.positions, type);
827
827
  if (fetchPositionsSnapshot && awaitPositionsSnapshot && cache === undefined) {
828
828
  return await client.future(type + ':fetchPositionsSnapshot');
@@ -196,7 +196,7 @@ class independentreserve extends independentreserve$1 {
196
196
  orderbook['timestamp'] = timestamp;
197
197
  orderbook['datetime'] = this.iso8601(timestamp);
198
198
  }
199
- const checksum = this.safeValue(this.options, 'checksum', true);
199
+ const checksum = this.safeBool(this.options, 'checksum', true);
200
200
  if (checksum && receivedSnapshot) {
201
201
  const storedAsks = orderbook['asks'];
202
202
  const storedBids = orderbook['bids'];
@@ -697,7 +697,7 @@ class kraken extends kraken$1 {
697
697
  }
698
698
  // don't remove this line or I will poop on your face
699
699
  orderbook.limit();
700
- const checksum = this.safeValue(this.options, 'checksum', true);
700
+ const checksum = this.safeBool(this.options, 'checksum', true);
701
701
  if (checksum) {
702
702
  const priceString = this.safeString(example, 0);
703
703
  const amountString = this.safeString(example, 1);
@@ -238,7 +238,7 @@ class kucoinfutures extends kucoinfutures$1 {
238
238
  const client = this.client(url);
239
239
  this.setPositionCache(client, symbol);
240
240
  const fetchPositionSnapshot = this.handleOption('watchPosition', 'fetchPositionSnapshot', true);
241
- const awaitPositionSnapshot = this.safeValue('watchPosition', 'awaitPositionSnapshot', true);
241
+ const awaitPositionSnapshot = this.safeBool('watchPosition', 'awaitPositionSnapshot', true);
242
242
  const currentPosition = this.getCurrentPosition(symbol);
243
243
  if (fetchPositionSnapshot && awaitPositionSnapshot && currentPosition === undefined) {
244
244
  const snapshot = await client.future('fetchPositionSnapshot:' + symbol);
@@ -500,10 +500,12 @@ class mexc extends mexc$1 {
500
500
  }
501
501
  }
502
502
  handleDelta(orderbook, delta) {
503
- const nonce = this.safeInteger(orderbook, 'nonce');
503
+ const existingNonce = this.safeInteger(orderbook, 'nonce');
504
504
  const deltaNonce = this.safeInteger2(delta, 'r', 'version');
505
- if (deltaNonce !== nonce && deltaNonce !== nonce + 1) {
506
- throw new errors.ExchangeError(this.id + ' handleOrderBook received an out-of-order nonce');
505
+ if (deltaNonce < existingNonce) {
506
+ // even when doing < comparison, this happens: https://app.travis-ci.com/github/ccxt/ccxt/builds/269234741#L1809
507
+ // so, we just skip old updates
508
+ return;
507
509
  }
508
510
  orderbook['nonce'] = deltaNonce;
509
511
  const asks = this.safeValue(delta, 'asks', []);
@@ -559,7 +559,7 @@ class okx extends okx$1 {
559
559
  const storedBids = orderbook['bids'];
560
560
  this.handleDeltas(storedAsks, asks);
561
561
  this.handleDeltas(storedBids, bids);
562
- const checksum = this.safeValue(this.options, 'checksum', true);
562
+ const checksum = this.safeBool(this.options, 'checksum', true);
563
563
  if (checksum) {
564
564
  const asksLength = storedAsks.length;
565
565
  const bidsLength = storedBids.length;
@@ -868,12 +868,10 @@ class whitebit extends whitebit$1 {
868
868
  if (!this.handleErrorMessage(client, message)) {
869
869
  return;
870
870
  }
871
- const result = this.safeValue(message, 'result', {});
872
- if (result !== undefined) {
873
- if (result === 'pong') {
874
- this.handlePong(client, message);
875
- return;
876
- }
871
+ const result = this.safeString(message, 'result');
872
+ if (result === 'pong') {
873
+ this.handlePong(client, message);
874
+ return;
877
875
  }
878
876
  const id = this.safeInteger(message, 'id');
879
877
  if (id !== undefined) {
@@ -629,7 +629,7 @@ class woo extends woo$1 {
629
629
  const client = this.client(url);
630
630
  this.setPositionsCache(client, symbols);
631
631
  const fetchPositionsSnapshot = this.handleOption('watchPositions', 'fetchPositionsSnapshot', true);
632
- const awaitPositionsSnapshot = this.safeValue('watchPositions', 'awaitPositionsSnapshot', true);
632
+ const awaitPositionsSnapshot = this.safeBool('watchPositions', 'awaitPositionsSnapshot', true);
633
633
  if (fetchPositionsSnapshot && awaitPositionsSnapshot && this.positions === undefined) {
634
634
  const snapshot = await client.future('fetchPositionsSnapshot');
635
635
  return this.filterBySymbolsSinceLimit(snapshot, symbols, since, limit, true);
@@ -1553,7 +1553,7 @@ class probit extends probit$1 {
1553
1553
  // ]
1554
1554
  // }
1555
1555
  //
1556
- const data = this.safeValue(response, 'data', {});
1556
+ const data = this.safeList(response, 'data', []);
1557
1557
  return this.parseTransactions(data, currency, since, limit);
1558
1558
  }
1559
1559
  parseTransaction(transaction, currency = undefined) {
@@ -1378,7 +1378,7 @@ class wavesexchange extends wavesexchange$1 {
1378
1378
  'amountAsset': amountAsset,
1379
1379
  'priceAsset': priceAsset,
1380
1380
  };
1381
- const sandboxMode = this.safeValue(this.options, 'sandboxMode', false);
1381
+ const sandboxMode = this.safeBool(this.options, 'sandboxMode', false);
1382
1382
  const chainId = (sandboxMode) ? 84 : 87;
1383
1383
  const body = {
1384
1384
  'senderPublicKey': this.apiKey,
@@ -490,7 +490,7 @@ class woo extends woo$1 {
490
490
  // ]
491
491
  // }
492
492
  //
493
- const resultResponse = this.safeValue(response, 'rows', {});
493
+ const resultResponse = this.safeList(response, 'rows', []);
494
494
  return this.parseTrades(resultResponse, market, since, limit);
495
495
  }
496
496
  parseTrade(trade, market = undefined) {
@@ -2334,7 +2334,7 @@ class woo extends woo$1 {
2334
2334
  else {
2335
2335
  this.checkRequiredCredentials();
2336
2336
  if (method === 'POST' && (path === 'algo/order' || path === 'order')) {
2337
- const isSandboxMode = this.safeValue(this.options, 'sandboxMode', false);
2337
+ const isSandboxMode = this.safeBool(this.options, 'sandboxMode', false);
2338
2338
  if (!isSandboxMode) {
2339
2339
  const applicationId = 'bc830de7-50f3-460b-9ee0-f430f83f9dad';
2340
2340
  const brokerId = this.safeString(this.options, 'brokerId', applicationId);
@@ -2653,7 +2653,17 @@ class woo extends woo$1 {
2653
2653
  return response;
2654
2654
  }
2655
2655
  async fetchLeverage(symbol, params = {}) {
2656
+ /**
2657
+ * @method
2658
+ * @name woo#fetchLeverage
2659
+ * @description fetch the set leverage for a market
2660
+ * @see https://docs.woo.org/#get-account-information-new
2661
+ * @param {string} symbol unified market symbol
2662
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2663
+ * @returns {object} a [leverage structure]{@link https://docs.ccxt.com/#/?id=leverage-structure}
2664
+ */
2656
2665
  await this.loadMarkets();
2666
+ const market = this.market(symbol);
2657
2667
  const response = await this.v3PrivateGetAccountinfo(params);
2658
2668
  //
2659
2669
  // {
@@ -2683,11 +2693,17 @@ class woo extends woo$1 {
2683
2693
  // "timestamp": 1673323685109
2684
2694
  // }
2685
2695
  //
2686
- const result = this.safeValue(response, 'data');
2687
- const leverage = this.safeNumber(result, 'leverage');
2696
+ const data = this.safeDict(response, 'data', {});
2697
+ return this.parseLeverage(data, market);
2698
+ }
2699
+ parseLeverage(leverage, market = undefined) {
2700
+ const leverageValue = this.safeInteger(leverage, 'leverage');
2688
2701
  return {
2689
- 'info': response,
2690
- 'leverage': leverage,
2702
+ 'info': leverage,
2703
+ 'symbol': market['symbol'],
2704
+ 'marginMode': undefined,
2705
+ 'longLeverage': leverageValue,
2706
+ 'shortLeverage': leverageValue,
2691
2707
  };
2692
2708
  }
2693
2709
  async setLeverage(leverage, symbol = undefined, params = {}) {
package/js/ccxt.d.ts CHANGED
@@ -2,9 +2,9 @@ import { Exchange } from './src/base/Exchange.js';
2
2
  import { Precise } from './src/base/Precise.js';
3
3
  import * as functions from './src/base/functions.js';
4
4
  import * as errors from './src/base/errors.js';
5
- import type { Market, Trade, Fee, Ticker, OrderBook, Order, Transaction, Tickers, Currency, Balance, DepositAddress, WithdrawalResponse, DepositAddressResponse, OHLCV, Balances, PartialBalances, Dictionary, MinMax, Position, FundingRateHistory, Liquidation, FundingHistory, MarginMode, Greeks } from './src/base/types.js';
5
+ import type { Market, Trade, Fee, Ticker, OrderBook, Order, Transaction, Tickers, Currency, Balance, DepositAddress, WithdrawalResponse, DepositAddressResponse, OHLCV, Balances, PartialBalances, Dictionary, MinMax, Position, FundingRateHistory, Liquidation, FundingHistory, MarginMode, Greeks, Leverage, Leverages } from './src/base/types.js';
6
6
  import { BaseError, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, NoChange } from './src/base/errors.js';
7
- declare const version = "4.2.56";
7
+ declare const version = "4.2.58";
8
8
  import ace from './src/ace.js';
9
9
  import alpaca from './src/alpaca.js';
10
10
  import ascendex from './src/ascendex.js';
@@ -501,5 +501,5 @@ declare const ccxt: {
501
501
  zaif: typeof zaif;
502
502
  zonda: typeof zonda;
503
503
  } & typeof functions & typeof errors;
504
- export { version, Exchange, exchanges, pro, Precise, functions, errors, BaseError, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, NoChange, Market, Trade, Fee, Ticker, OrderBook, Order, Transaction, Tickers, Currency, Balance, DepositAddress, WithdrawalResponse, DepositAddressResponse, OHLCV, Balances, PartialBalances, Dictionary, MinMax, Position, FundingRateHistory, Liquidation, FundingHistory, MarginMode, Greeks, ace, alpaca, ascendex, bequant, bigone, binance, binancecoinm, binanceus, binanceusdm, bingx, bit2c, bitbank, bitbay, bitbns, bitcoincom, bitfinex, bitfinex2, bitflyer, bitget, bithumb, bitmart, bitmex, bitopro, bitpanda, bitrue, bitso, bitstamp, bitteam, bitvavo, bl3p, blockchaincom, blofin, btcalpha, btcbox, btcmarkets, btcturk, bybit, cex, coinbase, coinbasepro, coincheck, coinex, coinlist, coinmate, coinmetro, coinone, coinsph, coinspot, cryptocom, currencycom, delta, deribit, digifinex, exmo, fmfwio, gate, gateio, gemini, hitbtc, hitbtc3, hollaex, htx, huobi, huobijp, idex, independentreserve, indodax, kraken, krakenfutures, kucoin, kucoinfutures, kuna, latoken, lbank, luno, lykke, mercado, mexc, ndax, novadax, oceanex, okcoin, okx, onetrading, p2b, paymium, phemex, poloniex, poloniexfutures, probit, timex, tokocrypto, upbit, wavesexchange, wazirx, whitebit, woo, yobit, zaif, zonda, };
504
+ export { version, Exchange, exchanges, pro, Precise, functions, errors, BaseError, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, NoChange, Market, Trade, Fee, Ticker, OrderBook, Order, Transaction, Tickers, Currency, Balance, DepositAddress, WithdrawalResponse, DepositAddressResponse, OHLCV, Balances, PartialBalances, Dictionary, MinMax, Position, FundingRateHistory, Liquidation, FundingHistory, MarginMode, Greeks, Leverage, Leverages, ace, alpaca, ascendex, bequant, bigone, binance, binancecoinm, binanceus, binanceusdm, bingx, bit2c, bitbank, bitbay, bitbns, bitcoincom, bitfinex, bitfinex2, bitflyer, bitget, bithumb, bitmart, bitmex, bitopro, bitpanda, bitrue, bitso, bitstamp, bitteam, bitvavo, bl3p, blockchaincom, blofin, btcalpha, btcbox, btcmarkets, btcturk, bybit, cex, coinbase, coinbasepro, coincheck, coinex, coinlist, coinmate, coinmetro, coinone, coinsph, coinspot, cryptocom, currencycom, delta, deribit, digifinex, exmo, fmfwio, gate, gateio, gemini, hitbtc, hitbtc3, hollaex, htx, huobi, huobijp, idex, independentreserve, indodax, kraken, krakenfutures, kucoin, kucoinfutures, kuna, latoken, lbank, luno, lykke, mercado, mexc, ndax, novadax, oceanex, okcoin, okx, onetrading, p2b, paymium, phemex, poloniex, poloniexfutures, probit, timex, tokocrypto, upbit, wavesexchange, wazirx, whitebit, woo, yobit, zaif, zonda, };
505
505
  export default ccxt;