ccxt 4.0.88 → 4.0.90

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 (45) hide show
  1. package/CHANGELOG.md +139 -0
  2. package/README.md +3 -3
  3. package/dist/ccxt.browser.js +1014 -49
  4. package/dist/ccxt.browser.min.js +10 -10
  5. package/dist/cjs/ccxt.js +1 -1
  6. package/dist/cjs/src/base/Exchange.js +62 -0
  7. package/dist/cjs/src/bingx.js +1 -1
  8. package/dist/cjs/src/bitmex.js +1 -0
  9. package/dist/cjs/src/pro/binance.js +190 -15
  10. package/dist/cjs/src/pro/bitget.js +127 -0
  11. package/dist/cjs/src/pro/bitmex.js +46 -0
  12. package/dist/cjs/src/pro/bybit.js +130 -3
  13. package/dist/cjs/src/pro/coinbasepro.js +70 -0
  14. package/dist/cjs/src/pro/cryptocom.js +71 -0
  15. package/dist/cjs/src/pro/gate.js +29 -0
  16. package/dist/cjs/src/pro/kucoin.js +92 -3
  17. package/dist/cjs/src/pro/kucoinfutures.js +91 -5
  18. package/dist/cjs/src/pro/okx.js +82 -0
  19. package/js/ccxt.d.ts +1 -1
  20. package/js/ccxt.js +1 -1
  21. package/js/src/base/Exchange.d.ts +17 -0
  22. package/js/src/base/Exchange.js +62 -0
  23. package/js/src/bingx.js +1 -1
  24. package/js/src/bitmex.js +1 -0
  25. package/js/src/pro/binance.d.ts +3 -0
  26. package/js/src/pro/binance.js +190 -15
  27. package/js/src/pro/bitget.d.ts +4 -0
  28. package/js/src/pro/bitget.js +127 -0
  29. package/js/src/pro/bitmex.d.ts +1 -0
  30. package/js/src/pro/bitmex.js +46 -0
  31. package/js/src/pro/bybit.d.ts +3 -0
  32. package/js/src/pro/bybit.js +131 -4
  33. package/js/src/pro/coinbasepro.d.ts +2 -0
  34. package/js/src/pro/coinbasepro.js +71 -1
  35. package/js/src/pro/cryptocom.d.ts +3 -0
  36. package/js/src/pro/cryptocom.js +71 -0
  37. package/js/src/pro/gate.d.ts +1 -0
  38. package/js/src/pro/gate.js +29 -0
  39. package/js/src/pro/kucoin.d.ts +2 -0
  40. package/js/src/pro/kucoin.js +93 -4
  41. package/js/src/pro/kucoinfutures.d.ts +2 -0
  42. package/js/src/pro/kucoinfutures.js +92 -6
  43. package/js/src/pro/okx.d.ts +2 -0
  44. package/js/src/pro/okx.js +83 -1
  45. package/package.json +1 -1
@@ -16,10 +16,12 @@ class bitmex extends bitmex$1 {
16
16
  'watchMyTrades': true,
17
17
  'watchOHLCV': true,
18
18
  'watchOrderBook': true,
19
+ 'watchOrderBookForSymbols': true,
19
20
  'watchOrders': true,
20
21
  'watchTicker': true,
21
22
  'watchTickers': false,
22
23
  'watchTrades': true,
24
+ 'watchTradesForSymbols': true,
23
25
  },
24
26
  'urls': {
25
27
  'test': {
@@ -517,6 +519,7 @@ class bitmex extends bitmex$1 {
517
519
  stored.append(trades[j]);
518
520
  }
519
521
  client.resolve(stored, messageHash);
522
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, stored);
520
523
  }
521
524
  }
522
525
  async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
@@ -956,6 +959,47 @@ class bitmex extends bitmex$1 {
956
959
  const orderbook = await this.watch(url, messageHash, this.deepExtend(request, params), messageHash);
957
960
  return orderbook.limit();
958
961
  }
962
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
963
+ /**
964
+ * @method
965
+ * @name bitmex#watchOrderBookForSymbols
966
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
967
+ * @param {string[]} symbols unified array of symbols
968
+ * @param {int} [limit] the maximum amount of order book entries to return
969
+ * @param {object} [params] extra parameters specific to the bitmex api endpoint
970
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
971
+ */
972
+ let table = undefined;
973
+ if (limit === undefined) {
974
+ table = this.safeString(this.options, 'watchOrderBookLevel', 'orderBookL2');
975
+ }
976
+ else if (limit === 25) {
977
+ table = 'orderBookL2_25';
978
+ }
979
+ else if (limit === 10) {
980
+ table = 'orderBookL10';
981
+ }
982
+ else {
983
+ throw new errors.ExchangeError(this.id + ' watchOrderBookForSymbols limit argument must be undefined (L2), 25 (L2) or 10 (L3)');
984
+ }
985
+ await this.loadMarkets();
986
+ symbols = this.marketSymbols(symbols);
987
+ const topics = [];
988
+ for (let i = 0; i < symbols.length; i++) {
989
+ const symbol = symbols[i];
990
+ const market = this.market(symbol);
991
+ const messageHash = table + ':' + market['id'];
992
+ topics.push(messageHash);
993
+ }
994
+ const messageHash = 'multipleOrderbook::' + symbols.join(',');
995
+ const url = this.urls['api']['ws'];
996
+ const request = {
997
+ 'op': 'subscribe',
998
+ 'args': topics,
999
+ };
1000
+ const orderbook = await this.watch(url, messageHash, this.deepExtend(request, params), messageHash);
1001
+ return orderbook.limit();
1002
+ }
959
1003
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
960
1004
  /**
961
1005
  * @method
@@ -1178,6 +1222,7 @@ class bitmex extends bitmex$1 {
1178
1222
  }
1179
1223
  const messageHash = table + ':' + marketId;
1180
1224
  client.resolve(orderbook, messageHash);
1225
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbook::', symbol, orderbook);
1181
1226
  }
1182
1227
  else {
1183
1228
  const numUpdatesByMarketId = {};
@@ -1209,6 +1254,7 @@ class bitmex extends bitmex$1 {
1209
1254
  const symbol = market['symbol'];
1210
1255
  const orderbook = this.orderbooks[symbol];
1211
1256
  client.resolve(orderbook, messageHash);
1257
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbook::', symbol, orderbook);
1212
1258
  }
1213
1259
  }
1214
1260
  }
@@ -15,11 +15,14 @@ class bybit extends bybit$1 {
15
15
  'watchBalance': true,
16
16
  'watchMyTrades': true,
17
17
  'watchOHLCV': true,
18
+ 'watchOHLCVForSymbols': true,
18
19
  'watchOrderBook': true,
20
+ 'watchOrderBookForSymbols': true,
19
21
  'watchOrders': true,
20
22
  'watchTicker': true,
21
23
  'watchTickers': false,
22
24
  'watchTrades': true,
25
+ 'watchTradesForSymbols': true,
23
26
  'watchPosition': undefined,
24
27
  },
25
28
  'urls': {
@@ -339,6 +342,46 @@ class bybit extends bybit$1 {
339
342
  }
340
343
  return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
341
344
  }
345
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
346
+ /**
347
+ * @method
348
+ * @name bybit#watchOHLCVForSymbols
349
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
350
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/kline
351
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/etp-kline
352
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
353
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
354
+ * @param {int} [limit] the maximum amount of candles to fetch
355
+ * @param {object} [params] extra parameters specific to the bybit api endpoint
356
+ * @returns {object} A list of candles ordered as timestamp, open, high, low, close, volume
357
+ */
358
+ await this.loadMarkets();
359
+ const topics = [];
360
+ const hashes = [];
361
+ let firstSymbol = undefined;
362
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
363
+ const data = symbolsAndTimeframes[i];
364
+ let symbol = this.safeString(data, 0);
365
+ const timeframe = this.safeString(data, 1);
366
+ const market = this.market(symbol);
367
+ symbol = market['symbol'];
368
+ if (i === 0) {
369
+ firstSymbol = market['symbol'];
370
+ }
371
+ const timeframeId = this.safeString(this.timeframes, timeframe, timeframe);
372
+ const topic = 'kline.' + timeframeId + '.' + market['id'];
373
+ topics.push(topic);
374
+ hashes.push(symbol + '#' + timeframe);
375
+ }
376
+ const messageHash = 'multipleOHLCV::' + hashes.join(',');
377
+ const url = this.getUrlByMarketType(firstSymbol, false, params);
378
+ const [symbol, timeframe, stored] = await this.watchTopics(url, messageHash, topics, params);
379
+ if (this.newUpdates) {
380
+ limit = stored.getLimit(symbol, limit);
381
+ }
382
+ const filtered = this.filterBySinceLimit(stored, since, limit, 0, true);
383
+ return this.createOHLCVObject(symbol, timeframe, filtered);
384
+ }
342
385
  handleOHLCV(client, message) {
343
386
  //
344
387
  // {
@@ -367,6 +410,7 @@ class bybit extends bybit$1 {
367
410
  const topicParts = topic.split('.');
368
411
  const topicLength = topicParts.length;
369
412
  const timeframeId = this.safeString(topicParts, 1);
413
+ const timeframe = this.findTimeframe(timeframeId);
370
414
  const marketId = this.safeString(topicParts, topicLength - 1);
371
415
  const isSpot = client.url.indexOf('spot') > -1;
372
416
  const marketType = isSpot ? 'spot' : 'contract';
@@ -376,11 +420,11 @@ class bybit extends bybit$1 {
376
420
  if (ohlcvsByTimeframe === undefined) {
377
421
  this.ohlcvs[symbol] = {};
378
422
  }
379
- let stored = this.safeValue(ohlcvsByTimeframe, timeframeId);
423
+ let stored = this.safeValue(ohlcvsByTimeframe, timeframe);
380
424
  if (stored === undefined) {
381
425
  const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
382
426
  stored = new Cache.ArrayCacheByTimestamp(limit);
383
- this.ohlcvs[symbol][timeframeId] = stored;
427
+ this.ohlcvs[symbol][timeframe] = stored;
384
428
  }
385
429
  for (let i = 0; i < data.length; i++) {
386
430
  const parsed = this.parseWsOHLCV(data[i]);
@@ -388,6 +432,7 @@ class bybit extends bybit$1 {
388
432
  }
389
433
  const messageHash = 'kline' + ':' + timeframeId + ':' + symbol;
390
434
  client.resolve(stored, messageHash);
435
+ this.resolveMultipleOHLCV(client, 'multipleOHLCV::', symbol, timeframe, stored);
391
436
  }
392
437
  parseWsOHLCV(ohlcv, market = undefined) {
393
438
  //
@@ -451,6 +496,48 @@ class bybit extends bybit$1 {
451
496
  const orderbook = await this.watchTopics(url, messageHash, topics, params);
452
497
  return orderbook.limit();
453
498
  }
499
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
500
+ /**
501
+ * @method
502
+ * @name bybit#watchOrderBook
503
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
504
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/orderbook
505
+ * @param {string[]} symbols unified array of symbols
506
+ * @param {int} [limit] the maximum amount of order book entries to return.
507
+ * @param {object} [params] extra parameters specific to the bybit api endpoint
508
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
509
+ */
510
+ await this.loadMarkets();
511
+ const symbolsLength = symbols.length;
512
+ if (symbolsLength === 0) {
513
+ throw new errors.ArgumentsRequired(this.id + ' watchOrderBookForSymbols() requires a non-empty array of symbols');
514
+ }
515
+ symbols = this.marketSymbols(symbols);
516
+ const url = this.getUrlByMarketType(symbols[0], false, params);
517
+ params = this.cleanParams(params);
518
+ const market = this.market(symbols[0]);
519
+ if (limit === undefined) {
520
+ limit = (market['spot']) ? 50 : 500;
521
+ }
522
+ else {
523
+ if (!market['spot']) {
524
+ // bybit only support limit 1, 50, 200, 500 for contract
525
+ if ((limit !== 1) && (limit !== 50) && (limit !== 200) && (limit !== 500)) {
526
+ throw new errors.BadRequest(this.id + ' watchOrderBookForSymbols() can only use limit 1, 50, 200 and 500.');
527
+ }
528
+ }
529
+ }
530
+ const topics = [];
531
+ for (let i = 0; i < symbols.length; i++) {
532
+ const symbol = symbols[i];
533
+ const market = this.market(symbol);
534
+ const topic = 'orderbook.' + limit.toString() + '.' + market['id'];
535
+ topics.push(topic);
536
+ }
537
+ const messageHash = 'multipleOrderbook::' + symbols.join(',');
538
+ const orderbook = await this.watchTopics(url, messageHash, topics, params);
539
+ return orderbook.limit();
540
+ }
454
541
  handleOrderBook(client, message) {
455
542
  //
456
543
  // {
@@ -513,6 +600,8 @@ class bybit extends bybit$1 {
513
600
  const messageHash = 'orderbook' + ':' + symbol;
514
601
  this.orderbooks[symbol] = orderbook;
515
602
  client.resolve(orderbook, messageHash);
603
+ // handle watchOrderBookForSymbols
604
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbook::', symbol, orderbook);
516
605
  }
517
606
  handleDelta(bookside, delta) {
518
607
  const bidAsk = this.parseBidAsk(delta, 0, 1);
@@ -548,6 +637,42 @@ class bybit extends bybit$1 {
548
637
  }
549
638
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
550
639
  }
640
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
641
+ /**
642
+ * @method
643
+ * @name bybit#watchTradesForSymbols
644
+ * @description get the list of most recent trades for a list of symbols
645
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/trade
646
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
647
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
648
+ * @param {int} [limit] the maximum amount of trades to fetch
649
+ * @param {object} [params] extra parameters specific to the bybit api endpoint
650
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
651
+ */
652
+ await this.loadMarkets();
653
+ symbols = this.marketSymbols(symbols);
654
+ const symbolsLength = symbols.length;
655
+ if (symbolsLength === 0) {
656
+ throw new errors.ArgumentsRequired(this.id + ' watchTradesForSymbols() requires a non-empty array of symbols');
657
+ }
658
+ const url = this.getUrlByMarketType(symbols[0], false, params);
659
+ const topics = [];
660
+ params = this.cleanParams(params);
661
+ for (let i = 0; i < symbols.length; i++) {
662
+ const symbol = symbols[i];
663
+ const market = this.market(symbol);
664
+ const topic = 'publicTrade.' + market['id'];
665
+ topics.push(topic);
666
+ }
667
+ const messageHash = 'multipleTrades::' + symbols.join(',');
668
+ const trades = await this.watchTopics(url, messageHash, topics, params);
669
+ if (this.newUpdates) {
670
+ const first = this.safeValue(trades, 0);
671
+ const tradeSymbol = this.safeString(first, 'symbol');
672
+ limit = trades.getLimit(tradeSymbol, limit);
673
+ }
674
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
675
+ }
551
676
  handleTrades(client, message) {
552
677
  //
553
678
  // {
@@ -589,6 +714,8 @@ class bybit extends bybit$1 {
589
714
  }
590
715
  const messageHash = 'trade' + ':' + symbol;
591
716
  client.resolve(stored, messageHash);
717
+ // handle watchTradesForSymbols part
718
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, stored);
592
719
  }
593
720
  parseWsTrade(trade, market = undefined) {
594
721
  //
@@ -704,7 +831,7 @@ class bybit extends bybit$1 {
704
831
  if (this.newUpdates) {
705
832
  limit = trades.getLimit(symbol, limit);
706
833
  }
707
- return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
834
+ return this.filterBySymbolSinceLimit(trades, symbol, since, limit, true);
708
835
  }
709
836
  handleMyTrades(client, message) {
710
837
  //
@@ -14,9 +14,11 @@ class coinbasepro extends coinbasepro$1 {
14
14
  'ws': true,
15
15
  'watchOHLCV': false,
16
16
  'watchOrderBook': true,
17
+ 'watchOrderBookForSymbols': true,
17
18
  'watchTicker': true,
18
19
  'watchTickers': true,
19
20
  'watchTrades': true,
21
+ 'watchTradesForSymbols': true,
20
22
  'watchBalance': false,
21
23
  'watchStatus': false,
22
24
  'watchOrders': true,
@@ -157,6 +159,33 @@ class coinbasepro extends coinbasepro$1 {
157
159
  }
158
160
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
159
161
  }
162
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
163
+ /**
164
+ * @method
165
+ * @name coinbase#watchTradesForSymbols
166
+ * @description get the list of most recent trades for a particular symbol
167
+ * @param {string} symbol unified symbol of the market to fetch trades for
168
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
169
+ * @param {int} [limit] the maximum amount of trades to fetch
170
+ * @param {object} [params] extra parameters specific to the coinbase api endpoint
171
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
172
+ */
173
+ const symbolsLength = symbols.length;
174
+ if (symbolsLength === 0) {
175
+ throw new errors.BadRequest(this.id + ' watchTradesForSymbols() requires a non-empty array of symbols');
176
+ }
177
+ await this.loadMarkets();
178
+ symbols = this.marketSymbols(symbols);
179
+ const name = 'matches';
180
+ const messageHash = 'multipleTrades::';
181
+ const trades = await this.subscribeMultiple(name, symbols, messageHash, params);
182
+ if (this.newUpdates) {
183
+ const first = this.safeValue(trades, 0);
184
+ const tradeSymbol = this.safeString(first, 'symbol');
185
+ limit = trades.getLimit(tradeSymbol, limit);
186
+ }
187
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
188
+ }
160
189
  async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
161
190
  /**
162
191
  * @method
@@ -241,6 +270,44 @@ class coinbasepro extends coinbasepro$1 {
241
270
  const orderbook = await this.watch(url, messageHash, this.extend(request, authentication), messageHash, subscription);
242
271
  return orderbook.limit();
243
272
  }
273
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
274
+ /**
275
+ * @method
276
+ * @name coinbasepro#watchOrderBookForSymbols
277
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
278
+ * @param {string[]} symbols unified array of symbols
279
+ * @param {int} [limit] the maximum amount of order book entries to return
280
+ * @param {object} [params] extra parameters specific to the coinbasepro api endpoint
281
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
282
+ */
283
+ const symbolsLength = symbols.length;
284
+ if (symbolsLength === 0) {
285
+ throw new errors.BadRequest(this.id + ' watchOrderBookForSymbols() requires a non-empty array of symbols');
286
+ }
287
+ const name = 'level2';
288
+ await this.loadMarkets();
289
+ symbols = this.marketSymbols(symbols);
290
+ const marketIds = this.marketIds(symbols);
291
+ const messageHash = 'multipleOrderbooks' + '::' + symbols.join(',');
292
+ const url = this.urls['api']['ws'];
293
+ const subscribe = {
294
+ 'type': 'subscribe',
295
+ 'product_ids': marketIds,
296
+ 'channels': [
297
+ name,
298
+ ],
299
+ };
300
+ const request = this.extend(subscribe, params);
301
+ const subscription = {
302
+ 'messageHash': messageHash,
303
+ 'symbols': symbols,
304
+ 'marketIds': marketIds,
305
+ 'limit': limit,
306
+ };
307
+ const authentication = this.authenticate();
308
+ const orderbook = await this.watch(url, messageHash, this.extend(request, authentication), messageHash, subscription);
309
+ return orderbook.limit();
310
+ }
244
311
  handleTrade(client, message) {
245
312
  //
246
313
  // {
@@ -273,6 +340,7 @@ class coinbasepro extends coinbasepro$1 {
273
340
  }
274
341
  tradesArray.append(trade);
275
342
  client.resolve(tradesArray, messageHash);
343
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, tradesArray);
276
344
  }
277
345
  return message;
278
346
  }
@@ -743,6 +811,7 @@ class coinbasepro extends coinbasepro$1 {
743
811
  orderbook['datetime'] = undefined;
744
812
  orderbook['symbol'] = symbol;
745
813
  client.resolve(orderbook, messageHash);
814
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbooks::', symbol, orderbook);
746
815
  }
747
816
  else if (type === 'l2update') {
748
817
  const orderbook = this.orderbooks[symbol];
@@ -764,6 +833,7 @@ class coinbasepro extends coinbasepro$1 {
764
833
  orderbook['timestamp'] = timestamp;
765
834
  orderbook['datetime'] = this.iso8601(timestamp);
766
835
  client.resolve(orderbook, messageHash);
836
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbooks::', symbol, orderbook);
767
837
  }
768
838
  }
769
839
  handleSubscriptionStatus(client, message) {
@@ -17,7 +17,9 @@ class cryptocom extends cryptocom$1 {
17
17
  'watchTickers': false,
18
18
  'watchMyTrades': true,
19
19
  'watchTrades': true,
20
+ 'watchTradesForSymbols': true,
20
21
  'watchOrderBook': true,
22
+ 'watchOrderBookForSymbols': true,
21
23
  'watchOrders': true,
22
24
  'watchOHLCV': true,
23
25
  'createOrderWs': true,
@@ -71,6 +73,30 @@ class cryptocom extends cryptocom$1 {
71
73
  const orderbook = await this.watchPublic(messageHash, params);
72
74
  return orderbook.limit();
73
75
  }
76
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
77
+ /**
78
+ * @method
79
+ * @name cryptocom#watchOrderBook
80
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
81
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#book-instrument_name
82
+ * @param {string[]} symbols unified array of symbols
83
+ * @param {int} [limit] the maximum amount of order book entries to return
84
+ * @param {object} [params] extra parameters specific to the cryptocom api endpoint
85
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
86
+ */
87
+ await this.loadMarkets();
88
+ symbols = this.marketSymbols(symbols);
89
+ const topics = [];
90
+ for (let i = 0; i < symbols.length; i++) {
91
+ const symbol = symbols[i];
92
+ const market = this.market(symbol);
93
+ const messageHash = 'book' + '.' + market['id'];
94
+ topics.push(messageHash);
95
+ }
96
+ const messageHash = 'multipleOrderbooks::' + symbols.join(',');
97
+ const orderbook = await this.watchPublicMultiple(messageHash, topics, params);
98
+ return orderbook.limit();
99
+ }
74
100
  handleOrderBookSnapshot(client, message) {
75
101
  // full snapshot
76
102
  //
@@ -110,6 +136,7 @@ class cryptocom extends cryptocom$1 {
110
136
  orderbook.reset(snapshot);
111
137
  this.orderbooks[symbol] = orderbook;
112
138
  client.resolve(orderbook, messageHash);
139
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbooks::', symbol, orderbook);
113
140
  }
114
141
  async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
115
142
  /**
@@ -133,6 +160,36 @@ class cryptocom extends cryptocom$1 {
133
160
  }
134
161
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
135
162
  }
163
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
164
+ /**
165
+ * @method
166
+ * @name cryptocom#watchTradesForSymbols
167
+ * @description get the list of most recent trades for a particular symbol
168
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#trade-instrument_name
169
+ * @param {string} symbol unified symbol of the market to fetch trades for
170
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
171
+ * @param {int} [limit] the maximum amount of trades to fetch
172
+ * @param {object} [params] extra parameters specific to the cryptocom api endpoint
173
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
174
+ */
175
+ await this.loadMarkets();
176
+ symbols = this.marketSymbols(symbols);
177
+ const topics = [];
178
+ for (let i = 0; i < symbols.length; i++) {
179
+ const symbol = symbols[i];
180
+ const market = this.market(symbol);
181
+ const messageHash = 'trade' + '.' + market['id'];
182
+ topics.push(messageHash);
183
+ }
184
+ const messageHash = 'multipleTrades::' + symbols.join(',');
185
+ const trades = await this.watchPublicMultiple(messageHash, topics, params);
186
+ if (this.newUpdates) {
187
+ const first = this.safeValue(trades, 0);
188
+ const tradeSymbol = this.safeString(first, 'symbol');
189
+ limit = trades.getLimit(tradeSymbol, limit);
190
+ }
191
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
192
+ }
136
193
  handleTrades(client, message) {
137
194
  //
138
195
  // {
@@ -179,6 +236,7 @@ class cryptocom extends cryptocom$1 {
179
236
  const channelReplaced = channel.replace('.' + marketId, '');
180
237
  client.resolve(stored, symbolSpecificMessageHash);
181
238
  client.resolve(stored, channelReplaced);
239
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, stored);
182
240
  }
183
241
  async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
184
242
  /**
@@ -574,6 +632,19 @@ class cryptocom extends cryptocom$1 {
574
632
  const message = this.extend(request, params);
575
633
  return await this.watch(url, messageHash, message, messageHash);
576
634
  }
635
+ async watchPublicMultiple(messageHash, topics, params = {}) {
636
+ const url = this.urls['api']['ws']['public'];
637
+ const id = this.nonce();
638
+ const request = {
639
+ 'method': 'subscribe',
640
+ 'params': {
641
+ 'channels': topics,
642
+ },
643
+ 'nonce': id,
644
+ };
645
+ const message = this.extend(request, params);
646
+ return await this.watch(url, messageHash, message, messageHash);
647
+ }
577
648
  async watchPrivateRequest(nonce, params = {}) {
578
649
  await this.authenticate();
579
650
  const url = this.urls['api']['ws']['private'];
@@ -16,6 +16,7 @@ class gate extends gate$1 {
16
16
  'watchTicker': true,
17
17
  'watchTickers': true,
18
18
  'watchTrades': true,
19
+ 'watchTradesForSymbols': true,
19
20
  'watchMyTrades': true,
20
21
  'watchOHLCV': true,
21
22
  'watchBalance': true,
@@ -394,6 +395,33 @@ class gate extends gate$1 {
394
395
  }
395
396
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
396
397
  }
398
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
399
+ /**
400
+ * @method
401
+ * @name gate#watchTradesForSymbols
402
+ * @description get the list of most recent trades for a particular symbol
403
+ * @param {string} symbol unified symbol of the market to fetch trades for
404
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
405
+ * @param {int} [limit] the maximum amount of trades to fetch
406
+ * @param {object} [params] extra parameters specific to the gate api endpoint
407
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
408
+ */
409
+ await this.loadMarkets();
410
+ symbols = this.marketSymbols(symbols);
411
+ const marketIds = this.marketIds(symbols);
412
+ const market = this.market(symbols[0]);
413
+ const messageType = this.getTypeByMarket(market);
414
+ const channel = messageType + '.trades';
415
+ const messageHash = 'multipleTrades::' + symbols.join(',');
416
+ const url = this.getUrlByMarket(market);
417
+ const trades = await this.subscribePublic(url, messageHash, marketIds, channel, params);
418
+ if (this.newUpdates) {
419
+ const first = this.safeValue(trades, 0);
420
+ const tradeSymbol = this.safeString(first, 'symbol');
421
+ limit = trades.getLimit(tradeSymbol, limit);
422
+ }
423
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
424
+ }
397
425
  handleTrades(client, message) {
398
426
  //
399
427
  // {
@@ -428,6 +456,7 @@ class gate extends gate$1 {
428
456
  cachedTrades.append(trade);
429
457
  const hash = 'trades:' + symbol;
430
458
  client.resolve(cachedTrades, hash);
459
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, cachedTrades);
431
460
  }
432
461
  }
433
462
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {