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
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import bybitRest from '../bybit.js';
9
- import { AuthenticationError, ExchangeError, BadRequest } from '../base/errors.js';
9
+ import { AuthenticationError, ExchangeError, BadRequest, 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
  // ---------------------------------------------------------------------------
@@ -18,11 +18,14 @@ export default class bybit extends bybitRest {
18
18
  'watchBalance': true,
19
19
  'watchMyTrades': true,
20
20
  'watchOHLCV': true,
21
+ 'watchOHLCVForSymbols': true,
21
22
  'watchOrderBook': true,
23
+ 'watchOrderBookForSymbols': true,
22
24
  'watchOrders': true,
23
25
  'watchTicker': true,
24
26
  'watchTickers': false,
25
27
  'watchTrades': true,
28
+ 'watchTradesForSymbols': true,
26
29
  'watchPosition': undefined,
27
30
  },
28
31
  'urls': {
@@ -342,6 +345,46 @@ export default class bybit extends bybitRest {
342
345
  }
343
346
  return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
344
347
  }
348
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
349
+ /**
350
+ * @method
351
+ * @name bybit#watchOHLCVForSymbols
352
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
353
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/kline
354
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/etp-kline
355
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
356
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
357
+ * @param {int} [limit] the maximum amount of candles to fetch
358
+ * @param {object} [params] extra parameters specific to the bybit api endpoint
359
+ * @returns {object} A list of candles ordered as timestamp, open, high, low, close, volume
360
+ */
361
+ await this.loadMarkets();
362
+ const topics = [];
363
+ const hashes = [];
364
+ let firstSymbol = undefined;
365
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
366
+ const data = symbolsAndTimeframes[i];
367
+ let symbol = this.safeString(data, 0);
368
+ const timeframe = this.safeString(data, 1);
369
+ const market = this.market(symbol);
370
+ symbol = market['symbol'];
371
+ if (i === 0) {
372
+ firstSymbol = market['symbol'];
373
+ }
374
+ const timeframeId = this.safeString(this.timeframes, timeframe, timeframe);
375
+ const topic = 'kline.' + timeframeId + '.' + market['id'];
376
+ topics.push(topic);
377
+ hashes.push(symbol + '#' + timeframe);
378
+ }
379
+ const messageHash = 'multipleOHLCV::' + hashes.join(',');
380
+ const url = this.getUrlByMarketType(firstSymbol, false, params);
381
+ const [symbol, timeframe, stored] = await this.watchTopics(url, messageHash, topics, params);
382
+ if (this.newUpdates) {
383
+ limit = stored.getLimit(symbol, limit);
384
+ }
385
+ const filtered = this.filterBySinceLimit(stored, since, limit, 0, true);
386
+ return this.createOHLCVObject(symbol, timeframe, filtered);
387
+ }
345
388
  handleOHLCV(client, message) {
346
389
  //
347
390
  // {
@@ -370,6 +413,7 @@ export default class bybit extends bybitRest {
370
413
  const topicParts = topic.split('.');
371
414
  const topicLength = topicParts.length;
372
415
  const timeframeId = this.safeString(topicParts, 1);
416
+ const timeframe = this.findTimeframe(timeframeId);
373
417
  const marketId = this.safeString(topicParts, topicLength - 1);
374
418
  const isSpot = client.url.indexOf('spot') > -1;
375
419
  const marketType = isSpot ? 'spot' : 'contract';
@@ -379,11 +423,11 @@ export default class bybit extends bybitRest {
379
423
  if (ohlcvsByTimeframe === undefined) {
380
424
  this.ohlcvs[symbol] = {};
381
425
  }
382
- let stored = this.safeValue(ohlcvsByTimeframe, timeframeId);
426
+ let stored = this.safeValue(ohlcvsByTimeframe, timeframe);
383
427
  if (stored === undefined) {
384
428
  const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
385
429
  stored = new ArrayCacheByTimestamp(limit);
386
- this.ohlcvs[symbol][timeframeId] = stored;
430
+ this.ohlcvs[symbol][timeframe] = stored;
387
431
  }
388
432
  for (let i = 0; i < data.length; i++) {
389
433
  const parsed = this.parseWsOHLCV(data[i]);
@@ -391,6 +435,7 @@ export default class bybit extends bybitRest {
391
435
  }
392
436
  const messageHash = 'kline' + ':' + timeframeId + ':' + symbol;
393
437
  client.resolve(stored, messageHash);
438
+ this.resolveMultipleOHLCV(client, 'multipleOHLCV::', symbol, timeframe, stored);
394
439
  }
395
440
  parseWsOHLCV(ohlcv, market = undefined) {
396
441
  //
@@ -454,6 +499,48 @@ export default class bybit extends bybitRest {
454
499
  const orderbook = await this.watchTopics(url, messageHash, topics, params);
455
500
  return orderbook.limit();
456
501
  }
502
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
503
+ /**
504
+ * @method
505
+ * @name bybit#watchOrderBook
506
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
507
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/orderbook
508
+ * @param {string[]} symbols unified array of symbols
509
+ * @param {int} [limit] the maximum amount of order book entries to return.
510
+ * @param {object} [params] extra parameters specific to the bybit api endpoint
511
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
512
+ */
513
+ await this.loadMarkets();
514
+ const symbolsLength = symbols.length;
515
+ if (symbolsLength === 0) {
516
+ throw new ArgumentsRequired(this.id + ' watchOrderBookForSymbols() requires a non-empty array of symbols');
517
+ }
518
+ symbols = this.marketSymbols(symbols);
519
+ const url = this.getUrlByMarketType(symbols[0], false, params);
520
+ params = this.cleanParams(params);
521
+ const market = this.market(symbols[0]);
522
+ if (limit === undefined) {
523
+ limit = (market['spot']) ? 50 : 500;
524
+ }
525
+ else {
526
+ if (!market['spot']) {
527
+ // bybit only support limit 1, 50, 200, 500 for contract
528
+ if ((limit !== 1) && (limit !== 50) && (limit !== 200) && (limit !== 500)) {
529
+ throw new BadRequest(this.id + ' watchOrderBookForSymbols() can only use limit 1, 50, 200 and 500.');
530
+ }
531
+ }
532
+ }
533
+ const topics = [];
534
+ for (let i = 0; i < symbols.length; i++) {
535
+ const symbol = symbols[i];
536
+ const market = this.market(symbol);
537
+ const topic = 'orderbook.' + limit.toString() + '.' + market['id'];
538
+ topics.push(topic);
539
+ }
540
+ const messageHash = 'multipleOrderbook::' + symbols.join(',');
541
+ const orderbook = await this.watchTopics(url, messageHash, topics, params);
542
+ return orderbook.limit();
543
+ }
457
544
  handleOrderBook(client, message) {
458
545
  //
459
546
  // {
@@ -516,6 +603,8 @@ export default class bybit extends bybitRest {
516
603
  const messageHash = 'orderbook' + ':' + symbol;
517
604
  this.orderbooks[symbol] = orderbook;
518
605
  client.resolve(orderbook, messageHash);
606
+ // handle watchOrderBookForSymbols
607
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbook::', symbol, orderbook);
519
608
  }
520
609
  handleDelta(bookside, delta) {
521
610
  const bidAsk = this.parseBidAsk(delta, 0, 1);
@@ -551,6 +640,42 @@ export default class bybit extends bybitRest {
551
640
  }
552
641
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
553
642
  }
643
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
644
+ /**
645
+ * @method
646
+ * @name bybit#watchTradesForSymbols
647
+ * @description get the list of most recent trades for a list of symbols
648
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/trade
649
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
650
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
651
+ * @param {int} [limit] the maximum amount of trades to fetch
652
+ * @param {object} [params] extra parameters specific to the bybit api endpoint
653
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
654
+ */
655
+ await this.loadMarkets();
656
+ symbols = this.marketSymbols(symbols);
657
+ const symbolsLength = symbols.length;
658
+ if (symbolsLength === 0) {
659
+ throw new ArgumentsRequired(this.id + ' watchTradesForSymbols() requires a non-empty array of symbols');
660
+ }
661
+ const url = this.getUrlByMarketType(symbols[0], false, params);
662
+ const topics = [];
663
+ params = this.cleanParams(params);
664
+ for (let i = 0; i < symbols.length; i++) {
665
+ const symbol = symbols[i];
666
+ const market = this.market(symbol);
667
+ const topic = 'publicTrade.' + market['id'];
668
+ topics.push(topic);
669
+ }
670
+ const messageHash = 'multipleTrades::' + symbols.join(',');
671
+ const trades = await this.watchTopics(url, messageHash, topics, params);
672
+ if (this.newUpdates) {
673
+ const first = this.safeValue(trades, 0);
674
+ const tradeSymbol = this.safeString(first, 'symbol');
675
+ limit = trades.getLimit(tradeSymbol, limit);
676
+ }
677
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
678
+ }
554
679
  handleTrades(client, message) {
555
680
  //
556
681
  // {
@@ -592,6 +717,8 @@ export default class bybit extends bybitRest {
592
717
  }
593
718
  const messageHash = 'trade' + ':' + symbol;
594
719
  client.resolve(stored, messageHash);
720
+ // handle watchTradesForSymbols part
721
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, stored);
595
722
  }
596
723
  parseWsTrade(trade, market = undefined) {
597
724
  //
@@ -707,7 +834,7 @@ export default class bybit extends bybitRest {
707
834
  if (this.newUpdates) {
708
835
  limit = trades.getLimit(symbol, limit);
709
836
  }
710
- return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
837
+ return this.filterBySymbolSinceLimit(trades, symbol, since, limit, true);
711
838
  }
712
839
  handleMyTrades(client, message) {
713
840
  //
@@ -14,9 +14,11 @@ export default class coinbasepro extends coinbaseproRest {
14
14
  watchTicker(symbol: string, params?: {}): Promise<any>;
15
15
  watchTickers(symbols?: string[], params?: {}): Promise<any>;
16
16
  watchTrades(symbol: string, since?: Int, limit?: Int, params?: {}): Promise<any>;
17
+ watchTradesForSymbols(symbols: string[], since?: Int, limit?: Int, params?: {}): Promise<any>;
17
18
  watchMyTrades(symbol?: string, since?: Int, limit?: Int, params?: {}): Promise<any>;
18
19
  watchOrders(symbol?: string, since?: Int, limit?: Int, params?: {}): Promise<any>;
19
20
  watchOrderBook(symbol: string, limit?: Int, params?: {}): Promise<any>;
21
+ watchOrderBookForSymbols(symbols: string[], limit?: Int, params?: {}): Promise<any>;
20
22
  handleTrade(client: Client, message: any): any;
21
23
  handleMyTrade(client: Client, message: any): any;
22
24
  parseWsTrade(trade: any, market?: any): import("../base/types.js").Trade;
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import coinbaseproRest from '../coinbasepro.js';
9
- import { AuthenticationError, ExchangeError, BadSymbol } from '../base/errors.js';
9
+ import { AuthenticationError, ExchangeError, BadSymbol, BadRequest } from '../base/errors.js';
10
10
  import { ArrayCache, ArrayCacheBySymbolById } from '../base/ws/Cache.js';
11
11
  import { sha256 } from '../static_dependencies/noble-hashes/sha256.js';
12
12
  // ---------------------------------------------------------------------------
@@ -17,9 +17,11 @@ export default class coinbasepro extends coinbaseproRest {
17
17
  'ws': true,
18
18
  'watchOHLCV': false,
19
19
  'watchOrderBook': true,
20
+ 'watchOrderBookForSymbols': true,
20
21
  'watchTicker': true,
21
22
  'watchTickers': true,
22
23
  'watchTrades': true,
24
+ 'watchTradesForSymbols': true,
23
25
  'watchBalance': false,
24
26
  'watchStatus': false,
25
27
  'watchOrders': true,
@@ -160,6 +162,33 @@ export default class coinbasepro extends coinbaseproRest {
160
162
  }
161
163
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
162
164
  }
165
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
166
+ /**
167
+ * @method
168
+ * @name coinbase#watchTradesForSymbols
169
+ * @description get the list of most recent trades for a particular symbol
170
+ * @param {string} symbol unified symbol of the market to fetch trades for
171
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
172
+ * @param {int} [limit] the maximum amount of trades to fetch
173
+ * @param {object} [params] extra parameters specific to the coinbase api endpoint
174
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
175
+ */
176
+ const symbolsLength = symbols.length;
177
+ if (symbolsLength === 0) {
178
+ throw new BadRequest(this.id + ' watchTradesForSymbols() requires a non-empty array of symbols');
179
+ }
180
+ await this.loadMarkets();
181
+ symbols = this.marketSymbols(symbols);
182
+ const name = 'matches';
183
+ const messageHash = 'multipleTrades::';
184
+ const trades = await this.subscribeMultiple(name, symbols, messageHash, params);
185
+ if (this.newUpdates) {
186
+ const first = this.safeValue(trades, 0);
187
+ const tradeSymbol = this.safeString(first, 'symbol');
188
+ limit = trades.getLimit(tradeSymbol, limit);
189
+ }
190
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
191
+ }
163
192
  async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
164
193
  /**
165
194
  * @method
@@ -244,6 +273,44 @@ export default class coinbasepro extends coinbaseproRest {
244
273
  const orderbook = await this.watch(url, messageHash, this.extend(request, authentication), messageHash, subscription);
245
274
  return orderbook.limit();
246
275
  }
276
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
277
+ /**
278
+ * @method
279
+ * @name coinbasepro#watchOrderBookForSymbols
280
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
281
+ * @param {string[]} symbols unified array of symbols
282
+ * @param {int} [limit] the maximum amount of order book entries to return
283
+ * @param {object} [params] extra parameters specific to the coinbasepro api endpoint
284
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
285
+ */
286
+ const symbolsLength = symbols.length;
287
+ if (symbolsLength === 0) {
288
+ throw new BadRequest(this.id + ' watchOrderBookForSymbols() requires a non-empty array of symbols');
289
+ }
290
+ const name = 'level2';
291
+ await this.loadMarkets();
292
+ symbols = this.marketSymbols(symbols);
293
+ const marketIds = this.marketIds(symbols);
294
+ const messageHash = 'multipleOrderbooks' + '::' + symbols.join(',');
295
+ const url = this.urls['api']['ws'];
296
+ const subscribe = {
297
+ 'type': 'subscribe',
298
+ 'product_ids': marketIds,
299
+ 'channels': [
300
+ name,
301
+ ],
302
+ };
303
+ const request = this.extend(subscribe, params);
304
+ const subscription = {
305
+ 'messageHash': messageHash,
306
+ 'symbols': symbols,
307
+ 'marketIds': marketIds,
308
+ 'limit': limit,
309
+ };
310
+ const authentication = this.authenticate();
311
+ const orderbook = await this.watch(url, messageHash, this.extend(request, authentication), messageHash, subscription);
312
+ return orderbook.limit();
313
+ }
247
314
  handleTrade(client, message) {
248
315
  //
249
316
  // {
@@ -276,6 +343,7 @@ export default class coinbasepro extends coinbaseproRest {
276
343
  }
277
344
  tradesArray.append(trade);
278
345
  client.resolve(tradesArray, messageHash);
346
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, tradesArray);
279
347
  }
280
348
  return message;
281
349
  }
@@ -746,6 +814,7 @@ export default class coinbasepro extends coinbaseproRest {
746
814
  orderbook['datetime'] = undefined;
747
815
  orderbook['symbol'] = symbol;
748
816
  client.resolve(orderbook, messageHash);
817
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbooks::', symbol, orderbook);
749
818
  }
750
819
  else if (type === 'l2update') {
751
820
  const orderbook = this.orderbooks[symbol];
@@ -767,6 +836,7 @@ export default class coinbasepro extends coinbaseproRest {
767
836
  orderbook['timestamp'] = timestamp;
768
837
  orderbook['datetime'] = this.iso8601(timestamp);
769
838
  client.resolve(orderbook, messageHash);
839
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbooks::', symbol, orderbook);
770
840
  }
771
841
  }
772
842
  handleSubscriptionStatus(client, message) {
@@ -5,8 +5,10 @@ export default class cryptocom extends cryptocomRest {
5
5
  describe(): any;
6
6
  pong(client: any, message: any): Promise<void>;
7
7
  watchOrderBook(symbol: string, limit?: Int, params?: {}): Promise<any>;
8
+ watchOrderBookForSymbols(symbols: string[], limit?: Int, params?: {}): Promise<any>;
8
9
  handleOrderBookSnapshot(client: Client, message: any): void;
9
10
  watchTrades(symbol: string, since?: Int, limit?: Int, params?: {}): Promise<any>;
11
+ watchTradesForSymbols(symbols: string[], since?: Int, limit?: Int, params?: {}): Promise<any>;
10
12
  handleTrades(client: Client, message: any): void;
11
13
  watchMyTrades(symbol?: string, since?: Int, limit?: Int, params?: {}): Promise<any>;
12
14
  watchTicker(symbol: string, params?: {}): Promise<any>;
@@ -23,6 +25,7 @@ export default class cryptocom extends cryptocomRest {
23
25
  cancelAllOrdersWs(symbol?: string, params?: {}): Promise<any>;
24
26
  handleCancelAllOrders(client: Client, message: any): void;
25
27
  watchPublic(messageHash: any, params?: {}): Promise<any>;
28
+ watchPublicMultiple(messageHash: any, topics: any, params?: {}): Promise<any>;
26
29
  watchPrivateRequest(nonce: any, params?: {}): Promise<any>;
27
30
  watchPrivateSubscribe(messageHash: any, params?: {}): Promise<any>;
28
31
  handleErrorMessage(client: Client, message: any): boolean;
@@ -20,7 +20,9 @@ export default class cryptocom extends cryptocomRest {
20
20
  'watchTickers': false,
21
21
  'watchMyTrades': true,
22
22
  'watchTrades': true,
23
+ 'watchTradesForSymbols': true,
23
24
  'watchOrderBook': true,
25
+ 'watchOrderBookForSymbols': true,
24
26
  'watchOrders': true,
25
27
  'watchOHLCV': true,
26
28
  'createOrderWs': true,
@@ -74,6 +76,30 @@ export default class cryptocom extends cryptocomRest {
74
76
  const orderbook = await this.watchPublic(messageHash, params);
75
77
  return orderbook.limit();
76
78
  }
79
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
80
+ /**
81
+ * @method
82
+ * @name cryptocom#watchOrderBook
83
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
84
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#book-instrument_name
85
+ * @param {string[]} symbols unified array of symbols
86
+ * @param {int} [limit] the maximum amount of order book entries to return
87
+ * @param {object} [params] extra parameters specific to the cryptocom api endpoint
88
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
89
+ */
90
+ await this.loadMarkets();
91
+ symbols = this.marketSymbols(symbols);
92
+ const topics = [];
93
+ for (let i = 0; i < symbols.length; i++) {
94
+ const symbol = symbols[i];
95
+ const market = this.market(symbol);
96
+ const messageHash = 'book' + '.' + market['id'];
97
+ topics.push(messageHash);
98
+ }
99
+ const messageHash = 'multipleOrderbooks::' + symbols.join(',');
100
+ const orderbook = await this.watchPublicMultiple(messageHash, topics, params);
101
+ return orderbook.limit();
102
+ }
77
103
  handleOrderBookSnapshot(client, message) {
78
104
  // full snapshot
79
105
  //
@@ -113,6 +139,7 @@ export default class cryptocom extends cryptocomRest {
113
139
  orderbook.reset(snapshot);
114
140
  this.orderbooks[symbol] = orderbook;
115
141
  client.resolve(orderbook, messageHash);
142
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbooks::', symbol, orderbook);
116
143
  }
117
144
  async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
118
145
  /**
@@ -136,6 +163,36 @@ export default class cryptocom extends cryptocomRest {
136
163
  }
137
164
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
138
165
  }
166
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
167
+ /**
168
+ * @method
169
+ * @name cryptocom#watchTradesForSymbols
170
+ * @description get the list of most recent trades for a particular symbol
171
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#trade-instrument_name
172
+ * @param {string} symbol unified symbol of the market to fetch trades for
173
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
174
+ * @param {int} [limit] the maximum amount of trades to fetch
175
+ * @param {object} [params] extra parameters specific to the cryptocom api endpoint
176
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
177
+ */
178
+ await this.loadMarkets();
179
+ symbols = this.marketSymbols(symbols);
180
+ const topics = [];
181
+ for (let i = 0; i < symbols.length; i++) {
182
+ const symbol = symbols[i];
183
+ const market = this.market(symbol);
184
+ const messageHash = 'trade' + '.' + market['id'];
185
+ topics.push(messageHash);
186
+ }
187
+ const messageHash = 'multipleTrades::' + symbols.join(',');
188
+ const trades = await this.watchPublicMultiple(messageHash, topics, params);
189
+ if (this.newUpdates) {
190
+ const first = this.safeValue(trades, 0);
191
+ const tradeSymbol = this.safeString(first, 'symbol');
192
+ limit = trades.getLimit(tradeSymbol, limit);
193
+ }
194
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
195
+ }
139
196
  handleTrades(client, message) {
140
197
  //
141
198
  // {
@@ -182,6 +239,7 @@ export default class cryptocom extends cryptocomRest {
182
239
  const channelReplaced = channel.replace('.' + marketId, '');
183
240
  client.resolve(stored, symbolSpecificMessageHash);
184
241
  client.resolve(stored, channelReplaced);
242
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, stored);
185
243
  }
186
244
  async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
187
245
  /**
@@ -577,6 +635,19 @@ export default class cryptocom extends cryptocomRest {
577
635
  const message = this.extend(request, params);
578
636
  return await this.watch(url, messageHash, message, messageHash);
579
637
  }
638
+ async watchPublicMultiple(messageHash, topics, params = {}) {
639
+ const url = this.urls['api']['ws']['public'];
640
+ const id = this.nonce();
641
+ const request = {
642
+ 'method': 'subscribe',
643
+ 'params': {
644
+ 'channels': topics,
645
+ },
646
+ 'nonce': id,
647
+ };
648
+ const message = this.extend(request, params);
649
+ return await this.watch(url, messageHash, message, messageHash);
650
+ }
580
651
  async watchPrivateRequest(nonce, params = {}) {
581
652
  await this.authenticate();
582
653
  const url = this.urls['api']['ws']['private'];
@@ -13,6 +13,7 @@ export default class gate extends gateRest {
13
13
  watchTickers(symbols?: string[], params?: {}): Promise<any>;
14
14
  handleTicker(client: Client, message: any): void;
15
15
  watchTrades(symbol: string, since?: Int, limit?: Int, params?: {}): Promise<any>;
16
+ watchTradesForSymbols(symbols: string[], since?: Int, limit?: Int, params?: {}): Promise<any>;
16
17
  handleTrades(client: Client, message: any): void;
17
18
  watchOHLCV(symbol: string, timeframe?: string, since?: Int, limit?: Int, params?: {}): Promise<any>;
18
19
  handleOHLCV(client: Client, message: any): void;
@@ -19,6 +19,7 @@ export default class gate extends gateRest {
19
19
  'watchTicker': true,
20
20
  'watchTickers': true,
21
21
  'watchTrades': true,
22
+ 'watchTradesForSymbols': true,
22
23
  'watchMyTrades': true,
23
24
  'watchOHLCV': true,
24
25
  'watchBalance': true,
@@ -397,6 +398,33 @@ export default class gate extends gateRest {
397
398
  }
398
399
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
399
400
  }
401
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
402
+ /**
403
+ * @method
404
+ * @name gate#watchTradesForSymbols
405
+ * @description get the list of most recent trades for a particular symbol
406
+ * @param {string} symbol unified symbol of the market to fetch trades for
407
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
408
+ * @param {int} [limit] the maximum amount of trades to fetch
409
+ * @param {object} [params] extra parameters specific to the gate api endpoint
410
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
411
+ */
412
+ await this.loadMarkets();
413
+ symbols = this.marketSymbols(symbols);
414
+ const marketIds = this.marketIds(symbols);
415
+ const market = this.market(symbols[0]);
416
+ const messageType = this.getTypeByMarket(market);
417
+ const channel = messageType + '.trades';
418
+ const messageHash = 'multipleTrades::' + symbols.join(',');
419
+ const url = this.getUrlByMarket(market);
420
+ const trades = await this.subscribePublic(url, messageHash, marketIds, channel, params);
421
+ if (this.newUpdates) {
422
+ const first = this.safeValue(trades, 0);
423
+ const tradeSymbol = this.safeString(first, 'symbol');
424
+ limit = trades.getLimit(tradeSymbol, limit);
425
+ }
426
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
427
+ }
400
428
  handleTrades(client, message) {
401
429
  //
402
430
  // {
@@ -431,6 +459,7 @@ export default class gate extends gateRest {
431
459
  cachedTrades.append(trade);
432
460
  const hash = 'trades:' + symbol;
433
461
  client.resolve(cachedTrades, hash);
462
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, cachedTrades);
434
463
  }
435
464
  }
436
465
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
@@ -12,8 +12,10 @@ export default class kucoin extends kucoinRest {
12
12
  watchOHLCV(symbol: string, timeframe?: string, since?: Int, limit?: Int, params?: {}): Promise<any>;
13
13
  handleOHLCV(client: Client, message: any): void;
14
14
  watchTrades(symbol: string, since?: Int, limit?: Int, params?: {}): Promise<any>;
15
+ watchTradesForSymbols(symbols: string[], since?: Int, limit?: Int, params?: {}): Promise<any>;
15
16
  handleTrade(client: Client, message: any): void;
16
17
  watchOrderBook(symbol: string, limit?: Int, params?: {}): Promise<any>;
18
+ watchOrderBookForSymbols(symbols: string[], limit?: Int, params?: {}): Promise<any>;
17
19
  handleOrderBook(client: Client, message: any): void;
18
20
  getCacheIndex(orderbook: any, cache: any): any;
19
21
  handleDelta(orderbook: any, delta: any): void;