ccxt 4.0.89 → 4.0.91

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 (56) hide show
  1. package/README.md +3 -3
  2. package/dist/ccxt.browser.js +1038 -60
  3. package/dist/ccxt.browser.min.js +10 -10
  4. package/dist/cjs/ccxt.js +1 -1
  5. package/dist/cjs/src/base/Exchange.js +62 -0
  6. package/dist/cjs/src/binance.js +7 -2
  7. package/dist/cjs/src/bitmex.js +1 -0
  8. package/dist/cjs/src/mexc.js +3 -1
  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 +129 -2
  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/krakenfutures.js +4 -2
  17. package/dist/cjs/src/pro/kucoin.js +92 -3
  18. package/dist/cjs/src/pro/kucoinfutures.js +91 -5
  19. package/dist/cjs/src/pro/okx.js +88 -5
  20. package/dist/cjs/src/pro/poloniexfutures.js +2 -1
  21. package/dist/cjs/src/pro/probit.js +4 -2
  22. package/js/ccxt.d.ts +3 -3
  23. package/js/ccxt.js +1 -1
  24. package/js/src/abstract/binance.d.ts +6 -1
  25. package/js/src/abstract/binancecoinm.d.ts +6 -1
  26. package/js/src/abstract/binanceus.d.ts +6 -1
  27. package/js/src/abstract/binanceusdm.d.ts +6 -1
  28. package/js/src/base/Exchange.d.ts +18 -1
  29. package/js/src/base/Exchange.js +62 -0
  30. package/js/src/binance.js +7 -2
  31. package/js/src/bitmex.js +1 -0
  32. package/js/src/mexc.js +3 -1
  33. package/js/src/pro/binance.d.ts +3 -0
  34. package/js/src/pro/binance.js +190 -15
  35. package/js/src/pro/bitget.d.ts +4 -0
  36. package/js/src/pro/bitget.js +127 -0
  37. package/js/src/pro/bitmex.d.ts +1 -0
  38. package/js/src/pro/bitmex.js +46 -0
  39. package/js/src/pro/bybit.d.ts +3 -0
  40. package/js/src/pro/bybit.js +130 -3
  41. package/js/src/pro/coinbasepro.d.ts +2 -0
  42. package/js/src/pro/coinbasepro.js +71 -1
  43. package/js/src/pro/cryptocom.d.ts +3 -0
  44. package/js/src/pro/cryptocom.js +71 -0
  45. package/js/src/pro/gate.d.ts +1 -0
  46. package/js/src/pro/gate.js +29 -0
  47. package/js/src/pro/krakenfutures.js +4 -2
  48. package/js/src/pro/kucoin.d.ts +2 -0
  49. package/js/src/pro/kucoin.js +93 -4
  50. package/js/src/pro/kucoinfutures.d.ts +2 -0
  51. package/js/src/pro/kucoinfutures.js +92 -6
  52. package/js/src/pro/okx.d.ts +2 -0
  53. package/js/src/pro/okx.js +89 -6
  54. package/js/src/pro/poloniexfutures.js +2 -1
  55. package/js/src/pro/probit.js +4 -2
  56. package/package.json +1 -1
@@ -6965,6 +6965,17 @@ class Exchange {
6965
6965
  'signIn': undefined,
6966
6966
  'transfer': undefined,
6967
6967
  'withdraw': undefined,
6968
+ 'watchOrderBook': undefined,
6969
+ 'watchOrders': undefined,
6970
+ 'watchMyTrades': undefined,
6971
+ 'watchTickers': undefined,
6972
+ 'watchTicker': undefined,
6973
+ 'watchTrades': undefined,
6974
+ 'watchTradesForSymbols': undefined,
6975
+ 'watchOrderBookForSymbols': undefined,
6976
+ 'watchOHLCVForSymbols': undefined,
6977
+ 'watchBalance': undefined,
6978
+ 'watchOHLCV': undefined,
6968
6979
  },
6969
6980
  'urls': {
6970
6981
  'logo': undefined,
@@ -7835,6 +7846,15 @@ class Exchange {
7835
7846
  async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
7836
7847
  throw new _errors_js__WEBPACK_IMPORTED_MODULE_1__.NotSupported(this.id + ' watchTrades() is not supported yet');
7837
7848
  }
7849
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
7850
+ throw new _errors_js__WEBPACK_IMPORTED_MODULE_1__.NotSupported(this.id + ' watchTradesForSymbols() is not supported yet');
7851
+ }
7852
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
7853
+ throw new _errors_js__WEBPACK_IMPORTED_MODULE_1__.NotSupported(this.id + ' watchOHLCVForSymbols() is not supported yet');
7854
+ }
7855
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
7856
+ throw new _errors_js__WEBPACK_IMPORTED_MODULE_1__.NotSupported(this.id + ' watchOrderBookForSymbols() is not supported yet');
7857
+ }
7838
7858
  async fetchDepositAddresses(codes = undefined, params = {}) {
7839
7859
  throw new _errors_js__WEBPACK_IMPORTED_MODULE_1__.NotSupported(this.id + ' fetchDepositAddresses() is not supported yet');
7840
7860
  }
@@ -9090,6 +9110,17 @@ class Exchange {
9090
9110
  const percentageString = _Precise_js__WEBPACK_IMPORTED_MODULE_5__/* .Precise.stringMul */ .O.stringMul(_Precise_js__WEBPACK_IMPORTED_MODULE_5__/* .Precise.stringDiv */ .O.stringDiv(unrealizedPnlString, initialMarginString, 4), '100');
9091
9111
  position['percentage'] = this.parseNumber(percentageString);
9092
9112
  }
9113
+ // if contractSize is undefined get from market
9114
+ let contractSize = this.safeNumber(position, 'contractSize');
9115
+ const symbol = this.safeString(position, 'symbol');
9116
+ let market = undefined;
9117
+ if (symbol !== undefined) {
9118
+ market = this.market(symbol);
9119
+ }
9120
+ if (contractSize === undefined && market !== undefined) {
9121
+ contractSize = this.safeNumber(market, 'contractSize');
9122
+ position['contractSize'] = contractSize;
9123
+ }
9093
9124
  return position;
9094
9125
  }
9095
9126
  parsePositions(positions, symbols = undefined, params = {}) {
@@ -10553,6 +10584,37 @@ class Exchange {
10553
10584
  */
10554
10585
  return this.filterByArray(objects, key, values, indexed);
10555
10586
  }
10587
+ resolvePromiseIfMessagehashMatches(client, prefix, symbol, data) {
10588
+ const messageHashes = this.findMessageHashes(client, prefix);
10589
+ for (let i = 0; i < messageHashes.length; i++) {
10590
+ const messageHash = messageHashes[i];
10591
+ const parts = messageHash.split('::');
10592
+ const symbolsString = parts[1];
10593
+ const symbols = symbolsString.split(',');
10594
+ if (this.inArray(symbol, symbols)) {
10595
+ client.resolve(data, messageHash);
10596
+ }
10597
+ }
10598
+ }
10599
+ resolveMultipleOHLCV(client, prefix, symbol, timeframe, data) {
10600
+ const messageHashes = this.findMessageHashes(client, 'multipleOHLCV::');
10601
+ for (let i = 0; i < messageHashes.length; i++) {
10602
+ const messageHash = messageHashes[i];
10603
+ const parts = messageHash.split('::');
10604
+ const symbolsAndTimeframes = parts[1];
10605
+ const splitted = symbolsAndTimeframes.split(',');
10606
+ const id = symbol + '#' + timeframe;
10607
+ if (this.inArray(id, splitted)) {
10608
+ client.resolve([symbol, timeframe, data], messageHash);
10609
+ }
10610
+ }
10611
+ }
10612
+ createOHLCVObject(symbol, timeframe, data) {
10613
+ const res = {};
10614
+ res[symbol] = {};
10615
+ res[symbol][timeframe] = data;
10616
+ return res;
10617
+ }
10556
10618
  }
10557
10619
 
10558
10620
 
@@ -16167,6 +16229,7 @@ class binance extends _abstract_binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
16167
16229
  'continuousKlines': { 'cost': 1, 'byLimit': [[99, 1], [499, 2], [1000, 5], [10000, 10]] },
16168
16230
  'indexPriceKlines': { 'cost': 1, 'byLimit': [[99, 1], [499, 2], [1000, 5], [10000, 10]] },
16169
16231
  'markPriceKlines': { 'cost': 1, 'byLimit': [[99, 1], [499, 2], [1000, 5], [10000, 10]] },
16232
+ 'premiumIndexKlines': { 'cost': 1, 'byLimit': [[99, 1], [499, 2], [1000, 5], [10000, 10]] },
16170
16233
  'ticker/24hr': { 'cost': 1, 'noSymbol': 40 },
16171
16234
  'ticker/price': { 'cost': 1, 'noSymbol': 2 },
16172
16235
  'ticker/bookTicker': { 'cost': 1, 'noSymbol': 2 },
@@ -16186,6 +16249,7 @@ class binance extends _abstract_binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
16186
16249
  'dapiPrivate': {
16187
16250
  'get': {
16188
16251
  'positionSide/dual': 30,
16252
+ 'orderAmendment': 1,
16189
16253
  'order': 1,
16190
16254
  'openOrder': 1,
16191
16255
  'openOrders': { 'cost': 1, 'noSymbol': 5 },
@@ -16199,8 +16263,11 @@ class binance extends _abstract_binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
16199
16263
  'leverageBracket': 1,
16200
16264
  'forceOrders': { 'cost': 20, 'noSymbol': 50 },
16201
16265
  'adlQuantile': 5,
16202
- 'orderAmendment': 1,
16203
- 'pmAccountInfo': 5,
16266
+ 'commissionRate': 20,
16267
+ 'income/asyn': 5,
16268
+ 'income/asyn/id': 5,
16269
+ 'pmExchangeInfo': 0.5,
16270
+ 'pmAccountInfo': 0.5, // Weight(IP): 5 => cost = 0.1 * 5 = 0.5
16204
16271
  },
16205
16272
  'post': {
16206
16273
  'positionSide/dual': 1,
@@ -48892,6 +48959,7 @@ class bitmex extends _abstract_bitmex_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
48892
48959
  if (until !== undefined) {
48893
48960
  request['endTime'] = this.iso8601(until);
48894
48961
  }
48962
+ request['reverse'] = true;
48895
48963
  const response = await this.publicGetFunding(this.extend(request, params));
48896
48964
  //
48897
48965
  // [
@@ -164041,7 +164109,9 @@ class mexc extends _abstract_mexc_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
164041
164109
  //
164042
164110
  // {}
164043
164111
  //
164044
- status = Object.keys(response).length ? this.json(response) : 'ok';
164112
+ const keys = Object.keys(response);
164113
+ const length = keys.length;
164114
+ status = length ? this.json(response) : 'ok';
164045
164115
  }
164046
164116
  else if (marketType === 'swap') {
164047
164117
  response = await this.contractPublicGetPing(query);
@@ -195075,11 +195145,14 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
195075
195145
  'watchBalance': true,
195076
195146
  'watchMyTrades': true,
195077
195147
  'watchOHLCV': true,
195148
+ 'watchOHLCVForSymbols': true,
195078
195149
  'watchOrderBook': true,
195150
+ 'watchOrderBookForSymbols': true,
195079
195151
  'watchOrders': true,
195080
195152
  'watchTicker': true,
195081
195153
  'watchTickers': true,
195082
195154
  'watchTrades': true,
195155
+ 'watchTradesForSymbols': true,
195083
195156
  'createOrderWs': true,
195084
195157
  'editOrderWs': true,
195085
195158
  'cancelOrderWs': true,
@@ -195266,6 +195339,60 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
195266
195339
  const orderbook = await this.watch(url, messageHash, message, messageHash, subscription);
195267
195340
  return orderbook.limit();
195268
195341
  }
195342
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
195343
+ /**
195344
+ * @method
195345
+ * @name binance#watchOrderBookForSymbols
195346
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
195347
+ * @param {string[]} symbols unified array of symbols
195348
+ * @param {int} [limit] the maximum amount of order book entries to return
195349
+ * @param {object} [params] extra parameters specific to the binance api endpoint
195350
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
195351
+ */
195352
+ if (limit !== undefined) {
195353
+ if ((limit !== 5) && (limit !== 10) && (limit !== 20) && (limit !== 50) && (limit !== 100) && (limit !== 500) && (limit !== 1000)) {
195354
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ExchangeError(this.id + ' watchOrderBook limit argument must be undefined, 5, 10, 20, 50, 100, 500 or 1000');
195355
+ }
195356
+ }
195357
+ //
195358
+ await this.loadMarkets();
195359
+ symbols = this.marketSymbols(symbols);
195360
+ const firstMarket = this.market(symbols[0]);
195361
+ let type = firstMarket['type'];
195362
+ if (firstMarket['contract']) {
195363
+ type = firstMarket['linear'] ? 'future' : 'delivery';
195364
+ }
195365
+ const name = 'depth';
195366
+ const messageHash = 'multipleOrderbook::' + symbols.join(',');
195367
+ const url = this.urls['api']['ws'][type] + '/' + this.stream(type, 'multipleOrderbook');
195368
+ const requestId = this.requestId(url);
195369
+ const watchOrderBookRate = this.safeString(this.options, 'watchOrderBookRate', '100');
195370
+ const subParams = [];
195371
+ for (let i = 0; i < symbols.length; i++) {
195372
+ const symbol = symbols[i];
195373
+ const market = this.market(symbol);
195374
+ const messageHash = market['lowercaseId'] + '@' + name + '@' + watchOrderBookRate + 'ms';
195375
+ subParams.push(messageHash);
195376
+ }
195377
+ const request = {
195378
+ 'method': 'SUBSCRIBE',
195379
+ 'params': subParams,
195380
+ 'id': requestId,
195381
+ };
195382
+ const subscription = {
195383
+ 'id': requestId.toString(),
195384
+ 'messageHash': messageHash,
195385
+ 'name': name,
195386
+ 'symbols': symbols,
195387
+ 'method': this.handleOrderBookSubscription,
195388
+ 'limit': limit,
195389
+ 'type': type,
195390
+ 'params': params,
195391
+ };
195392
+ const message = this.extend(request, params);
195393
+ const orderbook = await this.watch(url, messageHash, message, messageHash, subscription);
195394
+ return orderbook.limit();
195395
+ }
195269
195396
  async fetchOrderBookSnapshot(client, message, subscription) {
195270
195397
  const messageHash = this.safeString(subscription, 'messageHash');
195271
195398
  const symbol = this.safeString(subscription, 'symbol');
@@ -195408,6 +195535,8 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
195408
195535
  this.handleOrderBookMessage(client, message, orderbook);
195409
195536
  if (nonce < orderbook['nonce']) {
195410
195537
  client.resolve(orderbook, messageHash);
195538
+ // watchOrderBookForSymbols part (dry logic)
195539
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbook::', symbol, orderbook);
195411
195540
  }
195412
195541
  }
195413
195542
  else {
@@ -195426,6 +195555,8 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
195426
195555
  this.handleOrderBookMessage(client, message, orderbook);
195427
195556
  if (nonce <= orderbook['nonce']) {
195428
195557
  client.resolve(orderbook, messageHash);
195558
+ // watchOrderBookForSymbols part (dry logic)
195559
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbook::', symbol, orderbook);
195429
195560
  }
195430
195561
  }
195431
195562
  else {
@@ -195444,14 +195575,21 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
195444
195575
  }
195445
195576
  handleOrderBookSubscription(client, message, subscription) {
195446
195577
  const defaultLimit = this.safeInteger(this.options, 'watchOrderBookLimit', 1000);
195447
- const symbol = this.safeString(subscription, 'symbol');
195578
+ // const messageHash = this.safeString (subscription, 'messageHash');
195579
+ const symbol = this.safeString(subscription, 'symbol'); // watchOrderBook
195580
+ const symbols = this.safeValue(subscription, 'symbols', [symbol]); // watchOrderBookForSymbols
195448
195581
  const limit = this.safeInteger(subscription, 'limit', defaultLimit);
195449
- if (symbol in this.orderbooks) {
195450
- delete this.orderbooks[symbol];
195582
+ // handle list of symbols
195583
+ for (let i = 0; i < symbols.length; i++) {
195584
+ const symbol = symbols[i];
195585
+ if (symbol in this.orderbooks) {
195586
+ delete this.orderbooks[symbol];
195587
+ }
195588
+ this.orderbooks[symbol] = this.orderBook({}, limit);
195589
+ subscription['symbol'] = symbol;
195590
+ // fetch the snapshot in a separate async call
195591
+ this.spawn(this.fetchOrderBookSnapshot, client, message, subscription);
195451
195592
  }
195452
- this.orderbooks[symbol] = this.orderBook({}, limit);
195453
- // fetch the snapshot in a separate async call
195454
- this.spawn(this.fetchOrderBookSnapshot, client, message, subscription);
195455
195593
  }
195456
195594
  handleSubscriptionStatus(client, message) {
195457
195595
  //
@@ -195469,6 +195607,53 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
195469
195607
  }
195470
195608
  return message;
195471
195609
  }
195610
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
195611
+ /**
195612
+ * @method
195613
+ * @name binance#watchTradesForSymbols
195614
+ * @description get the list of most recent trades for a list of symbols
195615
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
195616
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
195617
+ * @param {int} [limit] the maximum amount of trades to fetch
195618
+ * @param {object} [params] extra parameters specific to the binance api endpoint
195619
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
195620
+ */
195621
+ await this.loadMarkets();
195622
+ symbols = this.marketSymbols(symbols);
195623
+ const options = this.safeValue(this.options, 'watchTradesForSymbols', {});
195624
+ const name = this.safeString(options, 'name', 'trade');
195625
+ const firstMarket = this.market(symbols[0]);
195626
+ let type = firstMarket['type'];
195627
+ if (firstMarket['contract']) {
195628
+ type = firstMarket['linear'] ? 'future' : 'delivery';
195629
+ }
195630
+ const subParams = [];
195631
+ for (let i = 0; i < symbols.length; i++) {
195632
+ const symbol = symbols[i];
195633
+ const market = this.market(symbol);
195634
+ const messageHash = market['lowercaseId'] + '@' + name;
195635
+ subParams.push(messageHash);
195636
+ }
195637
+ const messageHash = 'multipleTrades::' + symbols.join(',');
195638
+ const query = this.omit(params, 'type');
195639
+ const url = this.urls['api']['ws'][type] + '/' + this.stream(type, messageHash);
195640
+ const requestId = this.requestId(url);
195641
+ const request = {
195642
+ 'method': 'SUBSCRIBE',
195643
+ 'params': subParams,
195644
+ 'id': requestId,
195645
+ };
195646
+ const subscribe = {
195647
+ 'id': requestId,
195648
+ };
195649
+ const trades = await this.watch(url, messageHash, this.extend(request, query), messageHash, subscribe);
195650
+ if (this.newUpdates) {
195651
+ const first = this.safeValue(trades, 0);
195652
+ const tradeSymbol = this.safeString(first, 'symbol');
195653
+ limit = trades.getLimit(tradeSymbol, limit);
195654
+ }
195655
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
195656
+ }
195472
195657
  async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
195473
195658
  /**
195474
195659
  * @method
@@ -195673,8 +195858,8 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
195673
195858
  handleTrade(client, message) {
195674
195859
  // the trade streams push raw trade information in real-time
195675
195860
  // each trade has a unique buyer and seller
195676
- const index = client.url.indexOf('/stream');
195677
- const marketType = (index >= 0) ? 'spot' : 'contract';
195861
+ const isSpot = ((client.url.indexOf('/stream') > -1) || (client.url.indexOf('/testnet.binance') > -1));
195862
+ const marketType = (isSpot) ? 'spot' : 'contract';
195678
195863
  const marketId = this.safeString(message, 's');
195679
195864
  const market = this.safeMarket(marketId, undefined, undefined, marketType);
195680
195865
  const symbol = market['symbol'];
@@ -195690,6 +195875,8 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
195690
195875
  tradesArray.append(trade);
195691
195876
  this.trades[symbol] = tradesArray;
195692
195877
  client.resolve(tradesArray, messageHash);
195878
+ // watchTradesForSymbols part
195879
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, tradesArray);
195693
195880
  }
195694
195881
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
195695
195882
  /**
@@ -195711,8 +195898,8 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
195711
195898
  const nameOption = this.safeString(options, 'name', 'kline');
195712
195899
  const name = this.safeString(params, 'name', nameOption);
195713
195900
  if (name === 'indexPriceKline') {
195714
- // weird behavior for index price kline we can't use the perp suffix
195715
195901
  marketId = marketId.replace('_perp', '');
195902
+ // weird behavior for index price kline we can't use the perp suffix
195716
195903
  }
195717
195904
  params = this.omit(params, 'name');
195718
195905
  const messageHash = marketId + '@' + name + '_' + interval;
@@ -195738,6 +195925,62 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
195738
195925
  }
195739
195926
  return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
195740
195927
  }
195928
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
195929
+ /**
195930
+ * @method
195931
+ * @name binance#watchOHLCVForSymbols
195932
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
195933
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
195934
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
195935
+ * @param {int} [limit] the maximum amount of candles to fetch
195936
+ * @param {object} [params] extra parameters specific to the binance api endpoint
195937
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
195938
+ */
195939
+ await this.loadMarkets();
195940
+ const options = this.safeValue(this.options, 'watchOHLCV', {});
195941
+ const nameOption = this.safeString(options, 'name', 'kline');
195942
+ const name = this.safeString(params, 'name', nameOption);
195943
+ params = this.omit(params, 'name');
195944
+ const firstMarket = this.market(symbolsAndTimeframes[0][0]);
195945
+ let type = firstMarket['type'];
195946
+ if (firstMarket['contract']) {
195947
+ type = firstMarket['linear'] ? 'future' : 'delivery';
195948
+ }
195949
+ const subParams = [];
195950
+ const hashes = [];
195951
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
195952
+ const data = symbolsAndTimeframes[i];
195953
+ const symbol = data[0];
195954
+ const timeframe = data[1];
195955
+ const interval = this.safeString(this.timeframes, timeframe, timeframe);
195956
+ const market = this.market(symbol);
195957
+ let marketId = market['lowercaseId'];
195958
+ if (name === 'indexPriceKline') {
195959
+ // weird behavior for index price kline we can't use the perp suffix
195960
+ marketId = marketId.replace('_perp', '');
195961
+ }
195962
+ const topic = marketId + '@' + name + '_' + interval;
195963
+ subParams.push(topic);
195964
+ hashes.push(symbol + '#' + timeframe);
195965
+ }
195966
+ const messageHash = 'multipleOHLCV::' + hashes.join(',');
195967
+ const url = this.urls['api']['ws'][type] + '/' + this.stream(type, messageHash);
195968
+ const requestId = this.requestId(url);
195969
+ const request = {
195970
+ 'method': 'SUBSCRIBE',
195971
+ 'params': subParams,
195972
+ 'id': requestId,
195973
+ };
195974
+ const subscribe = {
195975
+ 'id': requestId,
195976
+ };
195977
+ const [symbol, timeframe, stored] = await this.watch(url, messageHash, this.extend(request, params), messageHash, subscribe);
195978
+ if (this.newUpdates) {
195979
+ limit = stored.getLimit(symbol, limit);
195980
+ }
195981
+ const filtered = this.filterBySinceLimit(stored, since, limit, 0, true);
195982
+ return this.createOHLCVObject(symbol, timeframe, filtered);
195983
+ }
195741
195984
  handleOHLCV(client, message) {
195742
195985
  //
195743
195986
  // {
@@ -195790,8 +196033,8 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
195790
196033
  this.safeFloat(kline, 'c'),
195791
196034
  this.safeFloat(kline, 'v'),
195792
196035
  ];
195793
- const index = client.url.indexOf('/stream');
195794
- const marketType = (index >= 0) ? 'spot' : 'contract';
196036
+ const isSpot = ((client.url.indexOf('/stream') > -1) || (client.url.indexOf('/testnet.binance') > -1));
196037
+ const marketType = (isSpot) ? 'spot' : 'contract';
195795
196038
  const symbol = this.safeSymbol(marketId, undefined, undefined, marketType);
195796
196039
  this.ohlcvs[symbol] = this.safeValue(this.ohlcvs, symbol, {});
195797
196040
  let stored = this.safeValue(this.ohlcvs[symbol], timeframe);
@@ -195802,6 +196045,8 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
195802
196045
  }
195803
196046
  stored.append(parsed);
195804
196047
  client.resolve(stored, messageHash);
196048
+ // watchOHLCVForSymbols part
196049
+ this.resolveMultipleOHLCV(client, 'multipleOHLCV::', symbol, timeframe, stored);
195805
196050
  }
195806
196051
  async watchTicker(symbol, params = {}) {
195807
196052
  /**
@@ -196028,8 +196273,8 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
196028
196273
  }
196029
196274
  const wsMarketId = this.safeStringLower(message, 's');
196030
196275
  const messageHash = wsMarketId + '@' + event;
196031
- const index = client.url.indexOf('/stream');
196032
- const marketType = (index >= 0) ? 'spot' : 'contract';
196276
+ const isSpot = ((client.url.indexOf('/stream') > -1) || (client.url.indexOf('/testnet.binance') > -1));
196277
+ const marketType = (isSpot) ? 'spot' : 'contract';
196033
196278
  const result = this.parseWsTicker(message, marketType);
196034
196279
  const symbol = result['symbol'];
196035
196280
  this.tickers[symbol] = result;
@@ -196050,8 +196295,8 @@ class binance extends _binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
196050
196295
  }
196051
196296
  }
196052
196297
  handleTickers(client, message) {
196053
- const index = client.url.indexOf('/stream');
196054
- const marketType = (index >= 0) ? 'spot' : 'contract';
196298
+ const isSpot = ((client.url.indexOf('/stream') > -1) || (client.url.indexOf('/testnet.binance') > -1));
196299
+ const marketType = (isSpot) ? 'spot' : 'contract';
196055
196300
  let rawTickers = [];
196056
196301
  const newTickers = [];
196057
196302
  if (Array.isArray(message)) {
@@ -199536,11 +199781,14 @@ class bitget extends _bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
199536
199781
  'watchBalance': true,
199537
199782
  'watchMyTrades': true,
199538
199783
  'watchOHLCV': true,
199784
+ 'watchOHLCVForSymbols': true,
199539
199785
  'watchOrderBook': true,
199786
+ 'watchOrderBookForSymbols': true,
199540
199787
  'watchOrders': true,
199541
199788
  'watchTicker': true,
199542
199789
  'watchTickers': false,
199543
199790
  'watchTrades': true,
199791
+ 'watchTradesForSymbols': true,
199544
199792
  },
199545
199793
  'urls': {
199546
199794
  'api': {
@@ -199794,6 +200042,43 @@ class bitget extends _bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
199794
200042
  }
199795
200043
  return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
199796
200044
  }
200045
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
200046
+ /**
200047
+ * @method
200048
+ * @name bitget#watchOHLCVForSymbols
200049
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
200050
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
200051
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
200052
+ * @param {int} [limit] the maximum amount of candles to fetch
200053
+ * @param {object} [params] extra parameters specific to the bitget api endpoint
200054
+ * @returns {object} A list of candles ordered as timestamp, open, high, low, close, volume
200055
+ */
200056
+ await this.loadMarkets();
200057
+ const topics = [];
200058
+ const hashes = [];
200059
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
200060
+ const data = symbolsAndTimeframes[i];
200061
+ const symbol = this.safeString(data, 0);
200062
+ const timeframe = this.safeString(data, 1);
200063
+ const market = this.market(symbol);
200064
+ const interval = this.safeString(this.options['timeframes'], timeframe);
200065
+ const instType = market['spot'] ? 'sp' : 'mc';
200066
+ const args = {
200067
+ 'instType': instType,
200068
+ 'channel': 'candle' + interval,
200069
+ 'instId': this.getWsMarketId(market),
200070
+ };
200071
+ topics.push(args);
200072
+ hashes.push(symbol + '#' + timeframe);
200073
+ }
200074
+ const messageHash = 'multipleOHLCV::' + hashes.join(',');
200075
+ const [symbol, timeframe, stored] = await this.watchPublicMultiple(messageHash, topics, params);
200076
+ if (this.newUpdates) {
200077
+ limit = stored.getLimit(symbol, limit);
200078
+ }
200079
+ const filtered = this.filterBySinceLimit(stored, since, limit, 0, true);
200080
+ return this.createOHLCVObject(symbol, timeframe, filtered);
200081
+ }
199797
200082
  handleOHLCV(client, message) {
199798
200083
  //
199799
200084
  // {
@@ -199845,6 +200130,7 @@ class bitget extends _bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
199845
200130
  }
199846
200131
  const messageHash = 'candles:' + timeframe + ':' + symbol;
199847
200132
  client.resolve(stored, messageHash);
200133
+ this.resolveMultipleOHLCV(client, 'multipleOHLCV::', symbol, timeframe, stored);
199848
200134
  }
199849
200135
  parseWsOHLCV(ohlcv, market = undefined) {
199850
200136
  //
@@ -199900,6 +200186,44 @@ class bitget extends _bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
199900
200186
  return orderbook;
199901
200187
  }
199902
200188
  }
200189
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
200190
+ /**
200191
+ * @method
200192
+ * @name bitget#watchOrderBookForSymbols
200193
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
200194
+ * @param {string[]} symbols unified array of symbols
200195
+ * @param {int} [limit] the maximum amount of order book entries to return
200196
+ * @param {object} [params] extra parameters specific to the bitget api endpoint
200197
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
200198
+ */
200199
+ await this.loadMarkets();
200200
+ symbols = this.marketSymbols(symbols);
200201
+ let channel = 'books';
200202
+ let incrementalFeed = true;
200203
+ if ((limit === 5) || (limit === 15)) {
200204
+ channel += limit.toString();
200205
+ incrementalFeed = false;
200206
+ }
200207
+ const topics = [];
200208
+ for (let i = 0; i < symbols.length; i++) {
200209
+ const market = this.market(symbols[i]);
200210
+ const instType = market['spot'] ? 'sp' : 'mc';
200211
+ const args = {
200212
+ 'instType': instType,
200213
+ 'channel': channel,
200214
+ 'instId': this.getWsMarketId(market),
200215
+ };
200216
+ topics.push(args);
200217
+ }
200218
+ const messageHash = 'multipleOrderbooks::' + symbols.join(',');
200219
+ const orderbook = await this.watchPublicMultiple(messageHash, topics, params);
200220
+ if (incrementalFeed) {
200221
+ return orderbook.limit();
200222
+ }
200223
+ else {
200224
+ return orderbook;
200225
+ }
200226
+ }
199903
200227
  handleOrderBook(client, message) {
199904
200228
  //
199905
200229
  // {
@@ -199985,6 +200309,7 @@ class bitget extends _bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
199985
200309
  }
199986
200310
  this.orderbooks[symbol] = storedOrderBook;
199987
200311
  client.resolve(storedOrderBook, messageHash);
200312
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbooks::', symbol, storedOrderBook);
199988
200313
  }
199989
200314
  handleDelta(bookside, delta) {
199990
200315
  const bidAsk = this.parseBidAsk(delta, 0, 1);
@@ -200025,6 +200350,43 @@ class bitget extends _bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
200025
200350
  }
200026
200351
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
200027
200352
  }
200353
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
200354
+ /**
200355
+ * @method
200356
+ * @name bitget#watchTradesForSymbols
200357
+ * @description get the list of most recent trades for a particular symbol
200358
+ * @param {string} symbol unified symbol of the market to fetch trades for
200359
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
200360
+ * @param {int} [limit] the maximum amount of trades to fetch
200361
+ * @param {object} [params] extra parameters specific to the bitget api endpoint
200362
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
200363
+ */
200364
+ const symbolsLength = symbols.length;
200365
+ if (symbolsLength === 0) {
200366
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ArgumentsRequired(this.id + ' watchTradesForSymbols() requires a non-empty array of symbols');
200367
+ }
200368
+ await this.loadMarkets();
200369
+ symbols = this.marketSymbols(symbols);
200370
+ const topics = [];
200371
+ for (let i = 0; i < symbols.length; i++) {
200372
+ const market = this.market(symbols[i]);
200373
+ const instType = market['spot'] ? 'sp' : 'mc';
200374
+ const args = {
200375
+ 'instType': instType,
200376
+ 'channel': 'trade',
200377
+ 'instId': this.getWsMarketId(market),
200378
+ };
200379
+ topics.push(args);
200380
+ }
200381
+ const messageHash = 'multipleTrades::' + symbols.join(',');
200382
+ const trades = await this.watchPublicMultiple(messageHash, topics, params);
200383
+ if (this.newUpdates) {
200384
+ const first = this.safeValue(trades, 0);
200385
+ const tradeSymbol = this.safeString(first, 'symbol');
200386
+ limit = trades.getLimit(tradeSymbol, limit);
200387
+ }
200388
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
200389
+ }
200028
200390
  handleTrades(client, message) {
200029
200391
  //
200030
200392
  // {
@@ -200060,6 +200422,7 @@ class bitget extends _bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
200060
200422
  }
200061
200423
  const messageHash = 'trade:' + symbol;
200062
200424
  client.resolve(stored, messageHash);
200425
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, stored);
200063
200426
  }
200064
200427
  parseWsTrade(trade, market = undefined) {
200065
200428
  //
@@ -200616,6 +200979,15 @@ class bitget extends _bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
200616
200979
  const message = this.extend(request, params);
200617
200980
  return await this.watch(url, messageHash, message, messageHash);
200618
200981
  }
200982
+ async watchPublicMultiple(messageHash, argsArray, params = {}) {
200983
+ const url = this.urls['api']['ws'];
200984
+ const request = {
200985
+ 'op': 'subscribe',
200986
+ 'args': argsArray,
200987
+ };
200988
+ const message = this.extend(request, params);
200989
+ return await this.watch(url, messageHash, message, messageHash);
200990
+ }
200619
200991
  async authenticate(params = {}) {
200620
200992
  this.checkRequiredCredentials();
200621
200993
  const url = this.urls['api']['ws'];
@@ -201456,10 +201828,12 @@ class bitmex extends _bitmex_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
201456
201828
  'watchMyTrades': true,
201457
201829
  'watchOHLCV': true,
201458
201830
  'watchOrderBook': true,
201831
+ 'watchOrderBookForSymbols': true,
201459
201832
  'watchOrders': true,
201460
201833
  'watchTicker': true,
201461
201834
  'watchTickers': false,
201462
201835
  'watchTrades': true,
201836
+ 'watchTradesForSymbols': true,
201463
201837
  },
201464
201838
  'urls': {
201465
201839
  'test': {
@@ -201957,6 +202331,7 @@ class bitmex extends _bitmex_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
201957
202331
  stored.append(trades[j]);
201958
202332
  }
201959
202333
  client.resolve(stored, messageHash);
202334
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, stored);
201960
202335
  }
201961
202336
  }
201962
202337
  async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
@@ -202396,6 +202771,47 @@ class bitmex extends _bitmex_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
202396
202771
  const orderbook = await this.watch(url, messageHash, this.deepExtend(request, params), messageHash);
202397
202772
  return orderbook.limit();
202398
202773
  }
202774
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
202775
+ /**
202776
+ * @method
202777
+ * @name bitmex#watchOrderBookForSymbols
202778
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
202779
+ * @param {string[]} symbols unified array of symbols
202780
+ * @param {int} [limit] the maximum amount of order book entries to return
202781
+ * @param {object} [params] extra parameters specific to the bitmex api endpoint
202782
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
202783
+ */
202784
+ let table = undefined;
202785
+ if (limit === undefined) {
202786
+ table = this.safeString(this.options, 'watchOrderBookLevel', 'orderBookL2');
202787
+ }
202788
+ else if (limit === 25) {
202789
+ table = 'orderBookL2_25';
202790
+ }
202791
+ else if (limit === 10) {
202792
+ table = 'orderBookL10';
202793
+ }
202794
+ else {
202795
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ExchangeError(this.id + ' watchOrderBookForSymbols limit argument must be undefined (L2), 25 (L2) or 10 (L3)');
202796
+ }
202797
+ await this.loadMarkets();
202798
+ symbols = this.marketSymbols(symbols);
202799
+ const topics = [];
202800
+ for (let i = 0; i < symbols.length; i++) {
202801
+ const symbol = symbols[i];
202802
+ const market = this.market(symbol);
202803
+ const messageHash = table + ':' + market['id'];
202804
+ topics.push(messageHash);
202805
+ }
202806
+ const messageHash = 'multipleOrderbook::' + symbols.join(',');
202807
+ const url = this.urls['api']['ws'];
202808
+ const request = {
202809
+ 'op': 'subscribe',
202810
+ 'args': topics,
202811
+ };
202812
+ const orderbook = await this.watch(url, messageHash, this.deepExtend(request, params), messageHash);
202813
+ return orderbook.limit();
202814
+ }
202399
202815
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
202400
202816
  /**
202401
202817
  * @method
@@ -202618,6 +203034,7 @@ class bitmex extends _bitmex_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
202618
203034
  }
202619
203035
  const messageHash = table + ':' + marketId;
202620
203036
  client.resolve(orderbook, messageHash);
203037
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbook::', symbol, orderbook);
202621
203038
  }
202622
203039
  else {
202623
203040
  const numUpdatesByMarketId = {};
@@ -202649,6 +203066,7 @@ class bitmex extends _bitmex_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
202649
203066
  const symbol = market['symbol'];
202650
203067
  const orderbook = this.orderbooks[symbol];
202651
203068
  client.resolve(orderbook, messageHash);
203069
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbook::', symbol, orderbook);
202652
203070
  }
202653
203071
  }
202654
203072
  }
@@ -207953,11 +208371,14 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
207953
208371
  'watchBalance': true,
207954
208372
  'watchMyTrades': true,
207955
208373
  'watchOHLCV': true,
208374
+ 'watchOHLCVForSymbols': true,
207956
208375
  'watchOrderBook': true,
208376
+ 'watchOrderBookForSymbols': true,
207957
208377
  'watchOrders': true,
207958
208378
  'watchTicker': true,
207959
208379
  'watchTickers': false,
207960
208380
  'watchTrades': true,
208381
+ 'watchTradesForSymbols': true,
207961
208382
  'watchPosition': undefined,
207962
208383
  },
207963
208384
  'urls': {
@@ -208277,6 +208698,46 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
208277
208698
  }
208278
208699
  return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
208279
208700
  }
208701
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
208702
+ /**
208703
+ * @method
208704
+ * @name bybit#watchOHLCVForSymbols
208705
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
208706
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/kline
208707
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/etp-kline
208708
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
208709
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
208710
+ * @param {int} [limit] the maximum amount of candles to fetch
208711
+ * @param {object} [params] extra parameters specific to the bybit api endpoint
208712
+ * @returns {object} A list of candles ordered as timestamp, open, high, low, close, volume
208713
+ */
208714
+ await this.loadMarkets();
208715
+ const topics = [];
208716
+ const hashes = [];
208717
+ let firstSymbol = undefined;
208718
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
208719
+ const data = symbolsAndTimeframes[i];
208720
+ let symbol = this.safeString(data, 0);
208721
+ const timeframe = this.safeString(data, 1);
208722
+ const market = this.market(symbol);
208723
+ symbol = market['symbol'];
208724
+ if (i === 0) {
208725
+ firstSymbol = market['symbol'];
208726
+ }
208727
+ const timeframeId = this.safeString(this.timeframes, timeframe, timeframe);
208728
+ const topic = 'kline.' + timeframeId + '.' + market['id'];
208729
+ topics.push(topic);
208730
+ hashes.push(symbol + '#' + timeframe);
208731
+ }
208732
+ const messageHash = 'multipleOHLCV::' + hashes.join(',');
208733
+ const url = this.getUrlByMarketType(firstSymbol, false, params);
208734
+ const [symbol, timeframe, stored] = await this.watchTopics(url, messageHash, topics, params);
208735
+ if (this.newUpdates) {
208736
+ limit = stored.getLimit(symbol, limit);
208737
+ }
208738
+ const filtered = this.filterBySinceLimit(stored, since, limit, 0, true);
208739
+ return this.createOHLCVObject(symbol, timeframe, filtered);
208740
+ }
208280
208741
  handleOHLCV(client, message) {
208281
208742
  //
208282
208743
  // {
@@ -208305,6 +208766,7 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
208305
208766
  const topicParts = topic.split('.');
208306
208767
  const topicLength = topicParts.length;
208307
208768
  const timeframeId = this.safeString(topicParts, 1);
208769
+ const timeframe = this.findTimeframe(timeframeId);
208308
208770
  const marketId = this.safeString(topicParts, topicLength - 1);
208309
208771
  const isSpot = client.url.indexOf('spot') > -1;
208310
208772
  const marketType = isSpot ? 'spot' : 'contract';
@@ -208314,11 +208776,11 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
208314
208776
  if (ohlcvsByTimeframe === undefined) {
208315
208777
  this.ohlcvs[symbol] = {};
208316
208778
  }
208317
- let stored = this.safeValue(ohlcvsByTimeframe, timeframeId);
208779
+ let stored = this.safeValue(ohlcvsByTimeframe, timeframe);
208318
208780
  if (stored === undefined) {
208319
208781
  const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
208320
208782
  stored = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheByTimestamp */ .Py(limit);
208321
- this.ohlcvs[symbol][timeframeId] = stored;
208783
+ this.ohlcvs[symbol][timeframe] = stored;
208322
208784
  }
208323
208785
  for (let i = 0; i < data.length; i++) {
208324
208786
  const parsed = this.parseWsOHLCV(data[i]);
@@ -208326,6 +208788,7 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
208326
208788
  }
208327
208789
  const messageHash = 'kline' + ':' + timeframeId + ':' + symbol;
208328
208790
  client.resolve(stored, messageHash);
208791
+ this.resolveMultipleOHLCV(client, 'multipleOHLCV::', symbol, timeframe, stored);
208329
208792
  }
208330
208793
  parseWsOHLCV(ohlcv, market = undefined) {
208331
208794
  //
@@ -208389,6 +208852,48 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
208389
208852
  const orderbook = await this.watchTopics(url, messageHash, topics, params);
208390
208853
  return orderbook.limit();
208391
208854
  }
208855
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
208856
+ /**
208857
+ * @method
208858
+ * @name bybit#watchOrderBook
208859
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
208860
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/orderbook
208861
+ * @param {string[]} symbols unified array of symbols
208862
+ * @param {int} [limit] the maximum amount of order book entries to return.
208863
+ * @param {object} [params] extra parameters specific to the bybit api endpoint
208864
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
208865
+ */
208866
+ await this.loadMarkets();
208867
+ const symbolsLength = symbols.length;
208868
+ if (symbolsLength === 0) {
208869
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ArgumentsRequired(this.id + ' watchOrderBookForSymbols() requires a non-empty array of symbols');
208870
+ }
208871
+ symbols = this.marketSymbols(symbols);
208872
+ const url = this.getUrlByMarketType(symbols[0], false, params);
208873
+ params = this.cleanParams(params);
208874
+ const market = this.market(symbols[0]);
208875
+ if (limit === undefined) {
208876
+ limit = (market['spot']) ? 50 : 500;
208877
+ }
208878
+ else {
208879
+ if (!market['spot']) {
208880
+ // bybit only support limit 1, 50, 200, 500 for contract
208881
+ if ((limit !== 1) && (limit !== 50) && (limit !== 200) && (limit !== 500)) {
208882
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.BadRequest(this.id + ' watchOrderBookForSymbols() can only use limit 1, 50, 200 and 500.');
208883
+ }
208884
+ }
208885
+ }
208886
+ const topics = [];
208887
+ for (let i = 0; i < symbols.length; i++) {
208888
+ const symbol = symbols[i];
208889
+ const market = this.market(symbol);
208890
+ const topic = 'orderbook.' + limit.toString() + '.' + market['id'];
208891
+ topics.push(topic);
208892
+ }
208893
+ const messageHash = 'multipleOrderbook::' + symbols.join(',');
208894
+ const orderbook = await this.watchTopics(url, messageHash, topics, params);
208895
+ return orderbook.limit();
208896
+ }
208392
208897
  handleOrderBook(client, message) {
208393
208898
  //
208394
208899
  // {
@@ -208451,6 +208956,8 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
208451
208956
  const messageHash = 'orderbook' + ':' + symbol;
208452
208957
  this.orderbooks[symbol] = orderbook;
208453
208958
  client.resolve(orderbook, messageHash);
208959
+ // handle watchOrderBookForSymbols
208960
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbook::', symbol, orderbook);
208454
208961
  }
208455
208962
  handleDelta(bookside, delta) {
208456
208963
  const bidAsk = this.parseBidAsk(delta, 0, 1);
@@ -208486,6 +208993,42 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
208486
208993
  }
208487
208994
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
208488
208995
  }
208996
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
208997
+ /**
208998
+ * @method
208999
+ * @name bybit#watchTradesForSymbols
209000
+ * @description get the list of most recent trades for a list of symbols
209001
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/trade
209002
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
209003
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
209004
+ * @param {int} [limit] the maximum amount of trades to fetch
209005
+ * @param {object} [params] extra parameters specific to the bybit api endpoint
209006
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
209007
+ */
209008
+ await this.loadMarkets();
209009
+ symbols = this.marketSymbols(symbols);
209010
+ const symbolsLength = symbols.length;
209011
+ if (symbolsLength === 0) {
209012
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ArgumentsRequired(this.id + ' watchTradesForSymbols() requires a non-empty array of symbols');
209013
+ }
209014
+ const url = this.getUrlByMarketType(symbols[0], false, params);
209015
+ const topics = [];
209016
+ params = this.cleanParams(params);
209017
+ for (let i = 0; i < symbols.length; i++) {
209018
+ const symbol = symbols[i];
209019
+ const market = this.market(symbol);
209020
+ const topic = 'publicTrade.' + market['id'];
209021
+ topics.push(topic);
209022
+ }
209023
+ const messageHash = 'multipleTrades::' + symbols.join(',');
209024
+ const trades = await this.watchTopics(url, messageHash, topics, params);
209025
+ if (this.newUpdates) {
209026
+ const first = this.safeValue(trades, 0);
209027
+ const tradeSymbol = this.safeString(first, 'symbol');
209028
+ limit = trades.getLimit(tradeSymbol, limit);
209029
+ }
209030
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
209031
+ }
208489
209032
  handleTrades(client, message) {
208490
209033
  //
208491
209034
  // {
@@ -208527,6 +209070,8 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
208527
209070
  }
208528
209071
  const messageHash = 'trade' + ':' + symbol;
208529
209072
  client.resolve(stored, messageHash);
209073
+ // handle watchTradesForSymbols part
209074
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, stored);
208530
209075
  }
208531
209076
  parseWsTrade(trade, market = undefined) {
208532
209077
  //
@@ -211371,9 +211916,11 @@ class coinbasepro extends _coinbasepro_js__WEBPACK_IMPORTED_MODULE_0__/* ["defau
211371
211916
  'ws': true,
211372
211917
  'watchOHLCV': false,
211373
211918
  'watchOrderBook': true,
211919
+ 'watchOrderBookForSymbols': true,
211374
211920
  'watchTicker': true,
211375
211921
  'watchTickers': true,
211376
211922
  'watchTrades': true,
211923
+ 'watchTradesForSymbols': true,
211377
211924
  'watchBalance': false,
211378
211925
  'watchStatus': false,
211379
211926
  'watchOrders': true,
@@ -211514,6 +212061,33 @@ class coinbasepro extends _coinbasepro_js__WEBPACK_IMPORTED_MODULE_0__/* ["defau
211514
212061
  }
211515
212062
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
211516
212063
  }
212064
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
212065
+ /**
212066
+ * @method
212067
+ * @name coinbase#watchTradesForSymbols
212068
+ * @description get the list of most recent trades for a particular symbol
212069
+ * @param {string} symbol unified symbol of the market to fetch trades for
212070
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
212071
+ * @param {int} [limit] the maximum amount of trades to fetch
212072
+ * @param {object} [params] extra parameters specific to the coinbase api endpoint
212073
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
212074
+ */
212075
+ const symbolsLength = symbols.length;
212076
+ if (symbolsLength === 0) {
212077
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.BadRequest(this.id + ' watchTradesForSymbols() requires a non-empty array of symbols');
212078
+ }
212079
+ await this.loadMarkets();
212080
+ symbols = this.marketSymbols(symbols);
212081
+ const name = 'matches';
212082
+ const messageHash = 'multipleTrades::';
212083
+ const trades = await this.subscribeMultiple(name, symbols, messageHash, params);
212084
+ if (this.newUpdates) {
212085
+ const first = this.safeValue(trades, 0);
212086
+ const tradeSymbol = this.safeString(first, 'symbol');
212087
+ limit = trades.getLimit(tradeSymbol, limit);
212088
+ }
212089
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
212090
+ }
211517
212091
  async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
211518
212092
  /**
211519
212093
  * @method
@@ -211598,6 +212172,44 @@ class coinbasepro extends _coinbasepro_js__WEBPACK_IMPORTED_MODULE_0__/* ["defau
211598
212172
  const orderbook = await this.watch(url, messageHash, this.extend(request, authentication), messageHash, subscription);
211599
212173
  return orderbook.limit();
211600
212174
  }
212175
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
212176
+ /**
212177
+ * @method
212178
+ * @name coinbasepro#watchOrderBookForSymbols
212179
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
212180
+ * @param {string[]} symbols unified array of symbols
212181
+ * @param {int} [limit] the maximum amount of order book entries to return
212182
+ * @param {object} [params] extra parameters specific to the coinbasepro api endpoint
212183
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
212184
+ */
212185
+ const symbolsLength = symbols.length;
212186
+ if (symbolsLength === 0) {
212187
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.BadRequest(this.id + ' watchOrderBookForSymbols() requires a non-empty array of symbols');
212188
+ }
212189
+ const name = 'level2';
212190
+ await this.loadMarkets();
212191
+ symbols = this.marketSymbols(symbols);
212192
+ const marketIds = this.marketIds(symbols);
212193
+ const messageHash = 'multipleOrderbooks' + '::' + symbols.join(',');
212194
+ const url = this.urls['api']['ws'];
212195
+ const subscribe = {
212196
+ 'type': 'subscribe',
212197
+ 'product_ids': marketIds,
212198
+ 'channels': [
212199
+ name,
212200
+ ],
212201
+ };
212202
+ const request = this.extend(subscribe, params);
212203
+ const subscription = {
212204
+ 'messageHash': messageHash,
212205
+ 'symbols': symbols,
212206
+ 'marketIds': marketIds,
212207
+ 'limit': limit,
212208
+ };
212209
+ const authentication = this.authenticate();
212210
+ const orderbook = await this.watch(url, messageHash, this.extend(request, authentication), messageHash, subscription);
212211
+ return orderbook.limit();
212212
+ }
211601
212213
  handleTrade(client, message) {
211602
212214
  //
211603
212215
  // {
@@ -211630,6 +212242,7 @@ class coinbasepro extends _coinbasepro_js__WEBPACK_IMPORTED_MODULE_0__/* ["defau
211630
212242
  }
211631
212243
  tradesArray.append(trade);
211632
212244
  client.resolve(tradesArray, messageHash);
212245
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, tradesArray);
211633
212246
  }
211634
212247
  return message;
211635
212248
  }
@@ -212100,6 +212713,7 @@ class coinbasepro extends _coinbasepro_js__WEBPACK_IMPORTED_MODULE_0__/* ["defau
212100
212713
  orderbook['datetime'] = undefined;
212101
212714
  orderbook['symbol'] = symbol;
212102
212715
  client.resolve(orderbook, messageHash);
212716
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbooks::', symbol, orderbook);
212103
212717
  }
212104
212718
  else if (type === 'l2update') {
212105
212719
  const orderbook = this.orderbooks[symbol];
@@ -212121,6 +212735,7 @@ class coinbasepro extends _coinbasepro_js__WEBPACK_IMPORTED_MODULE_0__/* ["defau
212121
212735
  orderbook['timestamp'] = timestamp;
212122
212736
  orderbook['datetime'] = this.iso8601(timestamp);
212123
212737
  client.resolve(orderbook, messageHash);
212738
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbooks::', symbol, orderbook);
212124
212739
  }
212125
212740
  }
212126
212741
  handleSubscriptionStatus(client, message) {
@@ -213337,7 +213952,9 @@ class cryptocom extends _cryptocom_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
213337
213952
  'watchTickers': false,
213338
213953
  'watchMyTrades': true,
213339
213954
  'watchTrades': true,
213955
+ 'watchTradesForSymbols': true,
213340
213956
  'watchOrderBook': true,
213957
+ 'watchOrderBookForSymbols': true,
213341
213958
  'watchOrders': true,
213342
213959
  'watchOHLCV': true,
213343
213960
  'createOrderWs': true,
@@ -213391,6 +214008,30 @@ class cryptocom extends _cryptocom_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
213391
214008
  const orderbook = await this.watchPublic(messageHash, params);
213392
214009
  return orderbook.limit();
213393
214010
  }
214011
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
214012
+ /**
214013
+ * @method
214014
+ * @name cryptocom#watchOrderBook
214015
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
214016
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#book-instrument_name
214017
+ * @param {string[]} symbols unified array of symbols
214018
+ * @param {int} [limit] the maximum amount of order book entries to return
214019
+ * @param {object} [params] extra parameters specific to the cryptocom api endpoint
214020
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
214021
+ */
214022
+ await this.loadMarkets();
214023
+ symbols = this.marketSymbols(symbols);
214024
+ const topics = [];
214025
+ for (let i = 0; i < symbols.length; i++) {
214026
+ const symbol = symbols[i];
214027
+ const market = this.market(symbol);
214028
+ const messageHash = 'book' + '.' + market['id'];
214029
+ topics.push(messageHash);
214030
+ }
214031
+ const messageHash = 'multipleOrderbooks::' + symbols.join(',');
214032
+ const orderbook = await this.watchPublicMultiple(messageHash, topics, params);
214033
+ return orderbook.limit();
214034
+ }
213394
214035
  handleOrderBookSnapshot(client, message) {
213395
214036
  // full snapshot
213396
214037
  //
@@ -213430,6 +214071,7 @@ class cryptocom extends _cryptocom_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
213430
214071
  orderbook.reset(snapshot);
213431
214072
  this.orderbooks[symbol] = orderbook;
213432
214073
  client.resolve(orderbook, messageHash);
214074
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbooks::', symbol, orderbook);
213433
214075
  }
213434
214076
  async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
213435
214077
  /**
@@ -213453,6 +214095,36 @@ class cryptocom extends _cryptocom_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
213453
214095
  }
213454
214096
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
213455
214097
  }
214098
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
214099
+ /**
214100
+ * @method
214101
+ * @name cryptocom#watchTradesForSymbols
214102
+ * @description get the list of most recent trades for a particular symbol
214103
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#trade-instrument_name
214104
+ * @param {string} symbol unified symbol of the market to fetch trades for
214105
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
214106
+ * @param {int} [limit] the maximum amount of trades to fetch
214107
+ * @param {object} [params] extra parameters specific to the cryptocom api endpoint
214108
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
214109
+ */
214110
+ await this.loadMarkets();
214111
+ symbols = this.marketSymbols(symbols);
214112
+ const topics = [];
214113
+ for (let i = 0; i < symbols.length; i++) {
214114
+ const symbol = symbols[i];
214115
+ const market = this.market(symbol);
214116
+ const messageHash = 'trade' + '.' + market['id'];
214117
+ topics.push(messageHash);
214118
+ }
214119
+ const messageHash = 'multipleTrades::' + symbols.join(',');
214120
+ const trades = await this.watchPublicMultiple(messageHash, topics, params);
214121
+ if (this.newUpdates) {
214122
+ const first = this.safeValue(trades, 0);
214123
+ const tradeSymbol = this.safeString(first, 'symbol');
214124
+ limit = trades.getLimit(tradeSymbol, limit);
214125
+ }
214126
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
214127
+ }
213456
214128
  handleTrades(client, message) {
213457
214129
  //
213458
214130
  // {
@@ -213499,6 +214171,7 @@ class cryptocom extends _cryptocom_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
213499
214171
  const channelReplaced = channel.replace('.' + marketId, '');
213500
214172
  client.resolve(stored, symbolSpecificMessageHash);
213501
214173
  client.resolve(stored, channelReplaced);
214174
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, stored);
213502
214175
  }
213503
214176
  async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
213504
214177
  /**
@@ -213894,6 +214567,19 @@ class cryptocom extends _cryptocom_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
213894
214567
  const message = this.extend(request, params);
213895
214568
  return await this.watch(url, messageHash, message, messageHash);
213896
214569
  }
214570
+ async watchPublicMultiple(messageHash, topics, params = {}) {
214571
+ const url = this.urls['api']['ws']['public'];
214572
+ const id = this.nonce();
214573
+ const request = {
214574
+ 'method': 'subscribe',
214575
+ 'params': {
214576
+ 'channels': topics,
214577
+ },
214578
+ 'nonce': id,
214579
+ };
214580
+ const message = this.extend(request, params);
214581
+ return await this.watch(url, messageHash, message, messageHash);
214582
+ }
213897
214583
  async watchPrivateRequest(nonce, params = {}) {
213898
214584
  await this.authenticate();
213899
214585
  const url = this.urls['api']['ws']['private'];
@@ -216169,6 +216855,7 @@ class gate extends _gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
216169
216855
  'watchTicker': true,
216170
216856
  'watchTickers': true,
216171
216857
  'watchTrades': true,
216858
+ 'watchTradesForSymbols': true,
216172
216859
  'watchMyTrades': true,
216173
216860
  'watchOHLCV': true,
216174
216861
  'watchBalance': true,
@@ -216547,6 +217234,33 @@ class gate extends _gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
216547
217234
  }
216548
217235
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
216549
217236
  }
217237
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
217238
+ /**
217239
+ * @method
217240
+ * @name gate#watchTradesForSymbols
217241
+ * @description get the list of most recent trades for a particular symbol
217242
+ * @param {string} symbol unified symbol of the market to fetch trades for
217243
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
217244
+ * @param {int} [limit] the maximum amount of trades to fetch
217245
+ * @param {object} [params] extra parameters specific to the gate api endpoint
217246
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
217247
+ */
217248
+ await this.loadMarkets();
217249
+ symbols = this.marketSymbols(symbols);
217250
+ const marketIds = this.marketIds(symbols);
217251
+ const market = this.market(symbols[0]);
217252
+ const messageType = this.getTypeByMarket(market);
217253
+ const channel = messageType + '.trades';
217254
+ const messageHash = 'multipleTrades::' + symbols.join(',');
217255
+ const url = this.getUrlByMarket(market);
217256
+ const trades = await this.subscribePublic(url, messageHash, marketIds, channel, params);
217257
+ if (this.newUpdates) {
217258
+ const first = this.safeValue(trades, 0);
217259
+ const tradeSymbol = this.safeString(first, 'symbol');
217260
+ limit = trades.getLimit(tradeSymbol, limit);
217261
+ }
217262
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
217263
+ }
216550
217264
  handleTrades(client, message) {
216551
217265
  //
216552
217266
  // {
@@ -216581,6 +217295,7 @@ class gate extends _gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
216581
217295
  cachedTrades.append(trade);
216582
217296
  const hash = 'trades:' + symbol;
216583
217297
  client.resolve(cachedTrades, hash);
217298
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, cachedTrades);
216584
217299
  }
216585
217300
  }
216586
217301
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
@@ -224275,7 +224990,8 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
224275
224990
  const symbol = symbols[i];
224276
224991
  marketIds.push(this.marketId(symbol));
224277
224992
  }
224278
- if (symbols.length === 1) {
224993
+ const length = symbols.length;
224994
+ if (length === 1) {
224279
224995
  const market = this.market(marketIds[0]);
224280
224996
  messageHash = messageHash + ':' + market['symbol'];
224281
224997
  }
@@ -224793,7 +225509,8 @@ class krakenfutures extends _krakenfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
224793
225509
  symbols[symbol] = true;
224794
225510
  cachedOrders.append(parsed);
224795
225511
  }
224796
- if (this.orders.length) {
225512
+ const length = this.orders.length;
225513
+ if (length > 0) {
224797
225514
  client.resolve(this.orders, 'orders');
224798
225515
  const keys = Object.keys(symbols);
224799
225516
  for (let i = 0; i < keys.length; i++) {
@@ -225514,6 +226231,8 @@ class kucoin extends _kucoin_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
225514
226231
  'watchTickers': false,
225515
226232
  'watchTicker': true,
225516
226233
  'watchTrades': true,
226234
+ 'watchTradesForSymbols': true,
226235
+ 'watchOrderBookForSymbols': true,
225517
226236
  'watchBalance': true,
225518
226237
  'watchOHLCV': true,
225519
226238
  },
@@ -225788,6 +226507,36 @@ class kucoin extends _kucoin_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
225788
226507
  }
225789
226508
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
225790
226509
  }
226510
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
226511
+ /**
226512
+ * @method
226513
+ * @name kucoin#watchTrades
226514
+ * @description get the list of most recent trades for a particular symbol
226515
+ * @param {string} symbol unified symbol of the market to fetch trades for
226516
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
226517
+ * @param {int} [limit] the maximum amount of trades to fetch
226518
+ * @param {object} [params] extra parameters specific to the kucoin api endpoint
226519
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
226520
+ */
226521
+ const symbolsLength = symbols.length;
226522
+ if (symbolsLength === 0) {
226523
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.ArgumentsRequired(this.id + ' watchTradesForSymbols() requires a non-empty array of symbols');
226524
+ }
226525
+ await this.loadMarkets();
226526
+ symbols = this.marketSymbols(symbols);
226527
+ const url = await this.negotiate(false);
226528
+ symbols = this.marketSymbols(symbols);
226529
+ const marketIds = this.marketIds(symbols);
226530
+ const topic = '/market/match:' + marketIds.join(',');
226531
+ const messageHash = 'multipleTrades::' + symbols.join(',');
226532
+ const trades = await this.subscribe(url, messageHash, topic, params);
226533
+ if (this.newUpdates) {
226534
+ const first = this.safeValue(trades, 0);
226535
+ const tradeSymbol = this.safeString(first, 'symbol');
226536
+ limit = trades.getLimit(tradeSymbol, limit);
226537
+ }
226538
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
226539
+ }
225791
226540
  handleTrade(client, message) {
225792
226541
  //
225793
226542
  // {
@@ -225820,6 +226569,8 @@ class kucoin extends _kucoin_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
225820
226569
  }
225821
226570
  trades.append(trade);
225822
226571
  client.resolve(trades, messageHash);
226572
+ // watchMultipleTrades
226573
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, trades);
225823
226574
  }
225824
226575
  async watchOrderBook(symbol, limit = undefined, params = {}) {
225825
226576
  /**
@@ -225865,6 +226616,39 @@ class kucoin extends _kucoin_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
225865
226616
  const orderbook = await this.subscribe(url, messageHash, topic, params, subscription);
225866
226617
  return orderbook.limit();
225867
226618
  }
226619
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
226620
+ /**
226621
+ * @method
226622
+ * @name kucoin#watchOrderBookForSymbols
226623
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
226624
+ * @param {string[]} symbols unified array of symbols
226625
+ * @param {int} [limit] the maximum amount of order book entries to return
226626
+ * @param {object} [params] extra parameters specific to the kucoin api endpoint
226627
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
226628
+ */
226629
+ const symbolsLength = symbols.length;
226630
+ if (symbolsLength === 0) {
226631
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.ArgumentsRequired(this.id + ' watchOrderBookForSymbols() requires a non-empty array of symbols');
226632
+ }
226633
+ if (limit !== undefined) {
226634
+ if ((limit !== 20) && (limit !== 100)) {
226635
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.ExchangeError(this.id + " watchOrderBook 'limit' argument must be undefined, 20 or 100");
226636
+ }
226637
+ }
226638
+ await this.loadMarkets();
226639
+ symbols = this.marketSymbols(symbols);
226640
+ const marketIds = this.marketIds(symbols);
226641
+ const url = await this.negotiate(false);
226642
+ const topic = '/market/level2:' + marketIds.join(',');
226643
+ const messageHash = 'multipleOrderbook::' + symbols.join(',');
226644
+ const subscription = {
226645
+ 'method': this.handleOrderBookSubscription,
226646
+ 'symbols': symbols,
226647
+ 'limit': limit,
226648
+ };
226649
+ const orderbook = await this.subscribe(url, messageHash, topic, params, subscription);
226650
+ return orderbook.limit();
226651
+ }
225868
226652
  handleOrderBook(client, message) {
225869
226653
  //
225870
226654
  // initial snapshot is fetched with ccxt's fetchOrderBook
@@ -225895,7 +226679,18 @@ class kucoin extends _kucoin_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
225895
226679
  if (nonce === undefined) {
225896
226680
  const cacheLength = storedOrderBook.cache.length;
225897
226681
  const topic = this.safeString(message, 'topic');
225898
- const subscription = client.subscriptions[topic];
226682
+ const topicParts = topic.split(':');
226683
+ const topicSymbol = this.safeString(topicParts, 1);
226684
+ const topicChannel = this.safeString(topicParts, 0);
226685
+ const subscriptions = Object.keys(client.subscriptions);
226686
+ let subscription = undefined;
226687
+ for (let i = 0; i < subscriptions.length; i++) {
226688
+ const key = subscriptions[i];
226689
+ if ((key.indexOf(topicSymbol) >= 0) && (key.indexOf(topicChannel) >= 0)) {
226690
+ subscription = client.subscriptions[key];
226691
+ break;
226692
+ }
226693
+ }
225899
226694
  const limit = this.safeInteger(subscription, 'limit');
225900
226695
  const snapshotDelay = this.handleOption('watchOrderBook', 'snapshotDelay', 5);
225901
226696
  if (cacheLength === snapshotDelay) {
@@ -225909,6 +226704,8 @@ class kucoin extends _kucoin_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
225909
226704
  }
225910
226705
  this.handleDelta(storedOrderBook, data);
225911
226706
  client.resolve(storedOrderBook, messageHash);
226707
+ // watchMultipleOrderBook
226708
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbook::', symbol, storedOrderBook);
225912
226709
  }
225913
226710
  getCacheIndex(orderbook, cache) {
225914
226711
  const firstDelta = this.safeValue(cache, 0);
@@ -225947,9 +226744,18 @@ class kucoin extends _kucoin_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
225947
226744
  }
225948
226745
  }
225949
226746
  handleOrderBookSubscription(client, message, subscription) {
225950
- const symbol = this.safeString(subscription, 'symbol');
225951
226747
  const limit = this.safeInteger(subscription, 'limit');
225952
- this.orderbooks[symbol] = this.orderBook({}, limit);
226748
+ const symbols = this.safeValue(subscription, 'symbols');
226749
+ if (symbols === undefined) {
226750
+ const symbol = this.safeString(subscription, 'symbol');
226751
+ this.orderbooks[symbol] = this.orderBook({}, limit);
226752
+ }
226753
+ else {
226754
+ for (let i = 0; i < symbols.length; i++) {
226755
+ const symbol = symbols[i];
226756
+ this.orderbooks[symbol] = this.orderBook({}, limit);
226757
+ }
226758
+ }
225953
226759
  // moved snapshot initialization to handleOrderBook to fix
225954
226760
  // https://github.com/ccxt/ccxt/issues/6820
225955
226761
  // the general idea is to fetch the snapshot after the first delta
@@ -226360,8 +227166,8 @@ class kucoin extends _kucoin_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
226360
227166
  /* harmony export */ "Z": () => (/* binding */ kucoinfutures)
226361
227167
  /* harmony export */ });
226362
227168
  /* harmony import */ var _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1924);
226363
- /* harmony import */ var _base_errors_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6689);
226364
- /* harmony import */ var _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3020);
227169
+ /* harmony import */ var _base_errors_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6689);
227170
+ /* harmony import */ var _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3020);
226365
227171
  // ---------------------------------------------------------------------------
226366
227172
 
226367
227173
 
@@ -226377,6 +227183,8 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
226377
227183
  'watchOrderBook': true,
226378
227184
  'watchOrders': true,
226379
227185
  'watchBalance': true,
227186
+ 'watchTradesForSymbols': true,
227187
+ 'watchOrderBookForSymbols': true,
226380
227188
  },
226381
227189
  'options': {
226382
227190
  'accountsByType': {
@@ -226560,6 +227368,36 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
226560
227368
  }
226561
227369
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
226562
227370
  }
227371
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
227372
+ /**
227373
+ * @method
227374
+ * @name kucoinfutures#watchTrades
227375
+ * @description get the list of most recent trades for a particular symbol
227376
+ * @param {string} symbol unified symbol of the market to fetch trades for
227377
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
227378
+ * @param {int} [limit] the maximum amount of trades to fetch
227379
+ * @param {object} [params] extra parameters specific to the kucoinfutures api endpoint
227380
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
227381
+ */
227382
+ const symbolsLength = symbols.length;
227383
+ if (symbolsLength === 0) {
227384
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ArgumentsRequired(this.id + ' watchTradesForSymbols() requires a non-empty array of symbols');
227385
+ }
227386
+ await this.loadMarkets();
227387
+ symbols = this.marketSymbols(symbols);
227388
+ const url = await this.negotiate(false);
227389
+ symbols = this.marketSymbols(symbols);
227390
+ const marketIds = this.marketIds(symbols);
227391
+ const topic = '/contractMarket/execution:' + marketIds.join(',');
227392
+ const messageHash = 'multipleTrades::' + symbols.join(',');
227393
+ const trades = await this.subscribe(url, messageHash, topic, params);
227394
+ if (this.newUpdates) {
227395
+ const first = this.safeValue(trades, 0);
227396
+ const tradeSymbol = this.safeString(first, 'symbol');
227397
+ limit = trades.getLimit(tradeSymbol, limit);
227398
+ }
227399
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
227400
+ }
226563
227401
  handleTrade(client, message) {
226564
227402
  //
226565
227403
  // {
@@ -226587,12 +227425,13 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
226587
227425
  let trades = this.safeValue(this.trades, symbol);
226588
227426
  if (trades === undefined) {
226589
227427
  const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
226590
- trades = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__/* .ArrayCache */ .ZL(limit);
227428
+ trades = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCache */ .ZL(limit);
226591
227429
  this.trades[symbol] = trades;
226592
227430
  }
226593
227431
  trades.append(trade);
226594
227432
  const messageHash = 'trades:' + symbol;
226595
227433
  client.resolve(trades, messageHash);
227434
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, trades);
226596
227435
  return message;
226597
227436
  }
226598
227437
  async watchOrderBook(symbol, limit = undefined, params = {}) {
@@ -226614,7 +227453,7 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
226614
227453
  */
226615
227454
  if (limit !== undefined) {
226616
227455
  if ((limit !== 20) && (limit !== 100)) {
226617
- throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.ExchangeError(this.id + " watchOrderBook 'limit' argument must be undefined, 20 or 100");
227456
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ExchangeError(this.id + " watchOrderBook 'limit' argument must be undefined, 20 or 100");
226618
227457
  }
226619
227458
  }
226620
227459
  await this.loadMarkets();
@@ -226631,6 +227470,39 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
226631
227470
  const orderbook = await this.subscribe(url, messageHash, topic, subscription, params);
226632
227471
  return orderbook.limit();
226633
227472
  }
227473
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
227474
+ /**
227475
+ * @method
227476
+ * @name kucoinfutures#watchOrderBookForSymbols
227477
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
227478
+ * @param {string[]} symbols unified array of symbols
227479
+ * @param {int} [limit] the maximum amount of order book entries to return
227480
+ * @param {object} [params] extra parameters specific to the kucoinfutures api endpoint
227481
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
227482
+ */
227483
+ const symbolsLength = symbols.length;
227484
+ if (symbolsLength === 0) {
227485
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ArgumentsRequired(this.id + ' watchOrderBookForSymbols() requires a non-empty array of symbols');
227486
+ }
227487
+ if (limit !== undefined) {
227488
+ if ((limit !== 20) && (limit !== 100)) {
227489
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ExchangeError(this.id + " watchOrderBook 'limit' argument must be undefined, 20 or 100");
227490
+ }
227491
+ }
227492
+ await this.loadMarkets();
227493
+ symbols = this.marketSymbols(symbols);
227494
+ const marketIds = this.marketIds(symbols);
227495
+ const url = await this.negotiate(false);
227496
+ const topic = '/contractMarket/level2:' + marketIds.join(',');
227497
+ const messageHash = 'multipleOrderbook::' + symbols.join(',');
227498
+ const subscription = {
227499
+ 'method': this.handleOrderBookSubscription,
227500
+ 'symbols': symbols,
227501
+ 'limit': limit,
227502
+ };
227503
+ const orderbook = await this.subscribe(url, messageHash, topic, subscription, params);
227504
+ return orderbook.limit();
227505
+ }
226634
227506
  handleDelta(orderbook, delta) {
226635
227507
  orderbook['nonce'] = this.safeInteger(delta, 'sequence');
226636
227508
  const timestamp = this.safeInteger(delta, 'timestamp');
@@ -226679,13 +227551,23 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
226679
227551
  const marketId = this.safeString(topicParts, 1);
226680
227552
  const symbol = this.safeSymbol(marketId, undefined, '-');
226681
227553
  const messageHash = 'orderbook:' + symbol;
226682
- const storedOrderBook = this.orderbooks[symbol];
227554
+ const storedOrderBook = this.safeValue(this.orderbooks, symbol);
226683
227555
  const nonce = this.safeInteger(storedOrderBook, 'nonce');
226684
227556
  const deltaEnd = this.safeInteger(data, 'sequence');
226685
227557
  if (nonce === undefined) {
226686
227558
  const cacheLength = storedOrderBook.cache.length;
226687
- const topic = this.safeString(message, 'topic');
226688
- const subscription = client.subscriptions[topic];
227559
+ const topicParts = topic.split(':');
227560
+ const topicSymbol = this.safeString(topicParts, 1);
227561
+ const topicChannel = this.safeString(topicParts, 0);
227562
+ const subscriptions = Object.keys(client.subscriptions);
227563
+ let subscription = undefined;
227564
+ for (let i = 0; i < subscriptions.length; i++) {
227565
+ const key = subscriptions[i];
227566
+ if ((key.indexOf(topicSymbol) >= 0) && (key.indexOf(topicChannel) >= 0)) {
227567
+ subscription = client.subscriptions[key];
227568
+ break;
227569
+ }
227570
+ }
226689
227571
  const limit = this.safeInteger(subscription, 'limit');
226690
227572
  const snapshotDelay = this.handleOption('watchOrderBook', 'snapshotDelay', 5);
226691
227573
  if (cacheLength === snapshotDelay) {
@@ -226699,6 +227581,7 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
226699
227581
  }
226700
227582
  this.handleDelta(storedOrderBook, data);
226701
227583
  client.resolve(storedOrderBook, messageHash);
227584
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbook::', symbol, storedOrderBook);
226702
227585
  }
226703
227586
  getCacheIndex(orderbook, cache) {
226704
227587
  const firstDelta = this.safeValue(cache, 0);
@@ -226717,9 +227600,18 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
226717
227600
  return cache.length;
226718
227601
  }
226719
227602
  handleOrderBookSubscription(client, message, subscription) {
226720
- const symbol = this.safeString(subscription, 'symbol');
226721
227603
  const limit = this.safeInteger(subscription, 'limit');
226722
- this.orderbooks[symbol] = this.orderBook({}, limit);
227604
+ const symbols = this.safeValue(subscription, 'symbols');
227605
+ if (symbols === undefined) {
227606
+ const symbol = this.safeString(subscription, 'symbol');
227607
+ this.orderbooks[symbol] = this.orderBook({}, limit);
227608
+ }
227609
+ else {
227610
+ for (let i = 0; i < symbols.length; i++) {
227611
+ const symbol = symbols[i];
227612
+ this.orderbooks[symbol] = this.orderBook({}, limit);
227613
+ }
227614
+ }
226723
227615
  // moved snapshot initialization to handleOrderBook to fix
226724
227616
  // https://github.com/ccxt/ccxt/issues/6820
226725
227617
  // the general idea is to fetch the snapshot after the first delta
@@ -226858,7 +227750,7 @@ class kucoinfutures extends _kucoinfutures_js__WEBPACK_IMPORTED_MODULE_0__/* ["d
226858
227750
  if (symbol !== undefined) {
226859
227751
  if (this.orders === undefined) {
226860
227752
  const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
226861
- this.orders = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__/* .ArrayCacheBySymbolById */ .hl(limit);
227753
+ this.orders = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolById */ .hl(limit);
226862
227754
  }
226863
227755
  const cachedOrders = this.orders;
226864
227756
  const orders = this.safeValue(cachedOrders.hashmap, symbol, {});
@@ -229931,8 +230823,8 @@ class okex extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
229931
230823
  /* harmony export */ "Z": () => (/* binding */ okx)
229932
230824
  /* harmony export */ });
229933
230825
  /* harmony import */ var _okx_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4042);
229934
- /* harmony import */ var _base_errors_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6689);
229935
- /* harmony import */ var _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3020);
230826
+ /* harmony import */ var _base_errors_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6689);
230827
+ /* harmony import */ var _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3020);
229936
230828
  /* harmony import */ var _static_dependencies_noble_hashes_sha256_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1372);
229937
230829
  // ---------------------------------------------------------------------------
229938
230830
 
@@ -229949,6 +230841,8 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
229949
230841
  'watchTickers': true,
229950
230842
  'watchOrderBook': true,
229951
230843
  'watchTrades': true,
230844
+ 'watchTradesForSymbols': true,
230845
+ 'watchOrderBookForSymbols': true,
229952
230846
  'watchBalance': true,
229953
230847
  'watchOHLCV': true,
229954
230848
  'watchOrders': true,
@@ -230030,9 +230924,10 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
230030
230924
  // for context: https://www.okx.com/help-center/changes-to-v5-api-websocket-subscription-parameter-and-url
230031
230925
  const isSandbox = this.options['sandboxMode'];
230032
230926
  const sandboxSuffix = isSandbox ? '?brokerId=9999' : '';
230927
+ const isBusiness = (access === 'business');
230033
230928
  const isPublic = (access === 'public');
230034
230929
  const url = this.urls['api']['ws'];
230035
- if ((channel.indexOf('candle') > -1) || (channel === 'orders-algo')) {
230930
+ if (isBusiness || (channel.indexOf('candle') > -1) || (channel === 'orders-algo')) {
230036
230931
  return url + '/business' + sandboxSuffix;
230037
230932
  }
230038
230933
  else if (isPublic) {
@@ -230102,6 +230997,47 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
230102
230997
  }
230103
230998
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
230104
230999
  }
231000
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
231001
+ /**
231002
+ * @method
231003
+ * @name okx#watchTradesForSymbols
231004
+ * @description get the list of most recent trades for a particular symbol
231005
+ * @param {string} symbol unified symbol of the market to fetch trades for
231006
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
231007
+ * @param {int} [limit] the maximum amount of trades to fetch
231008
+ * @param {object} [params] extra parameters specific to the okx api endpoint
231009
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
231010
+ */
231011
+ const symbolsLength = symbols.length;
231012
+ if (symbolsLength === 0) {
231013
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ArgumentsRequired(this.id + ' watchTradesForSymbols() requires a non-empty array of symbols');
231014
+ }
231015
+ await this.loadMarkets();
231016
+ symbols = this.marketSymbols(symbols);
231017
+ const channel = 'trades';
231018
+ const topics = [];
231019
+ for (let i = 0; i < symbols.length; i++) {
231020
+ const marketId = this.marketId(symbols[i]);
231021
+ const topic = {
231022
+ 'channel': channel,
231023
+ 'instId': marketId,
231024
+ };
231025
+ topics.push(topic);
231026
+ }
231027
+ const request = {
231028
+ 'op': 'subscribe',
231029
+ 'args': topics,
231030
+ };
231031
+ const messageHash = 'multipleTrades::' + symbols.join(',');
231032
+ const url = this.getUrl(channel, 'public');
231033
+ const trades = await this.watch(url, messageHash, request, messageHash);
231034
+ if (this.newUpdates) {
231035
+ const first = this.safeValue(trades, 0);
231036
+ const tradeSymbol = this.safeString(first, 'symbol');
231037
+ limit = trades.getLimit(tradeSymbol, limit);
231038
+ }
231039
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
231040
+ }
230105
231041
  handleTrades(client, message) {
230106
231042
  //
230107
231043
  // {
@@ -230129,11 +231065,12 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
230129
231065
  const messageHash = channel + ':' + marketId;
230130
231066
  let stored = this.safeValue(this.trades, symbol);
230131
231067
  if (stored === undefined) {
230132
- stored = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__/* .ArrayCache */ .ZL(tradesLimit);
231068
+ stored = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCache */ .ZL(tradesLimit);
230133
231069
  this.trades[symbol] = stored;
230134
231070
  }
230135
231071
  stored.append(trade);
230136
231072
  client.resolve(stored, messageHash);
231073
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleTrades::', symbol, stored);
230137
231074
  }
230138
231075
  return message;
230139
231076
  }
@@ -230166,7 +231103,7 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
230166
231103
  * @returns {object} a [ticker structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#ticker-structure}
230167
231104
  */
230168
231105
  if (this.isEmpty(symbols)) {
230169
- throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.ArgumentsRequired(this.id + ' watchTickers requires a list of symbols');
231106
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ArgumentsRequired(this.id + ' watchTickers requires a list of symbols');
230170
231107
  }
230171
231108
  let channel = undefined;
230172
231109
  [channel, params] = this.handleOptionAndParams(params, 'watchTickers', 'channel', 'tickers');
@@ -230281,7 +231218,7 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
230281
231218
  let stored = this.safeValue(this.ohlcvs[symbol], timeframe);
230282
231219
  if (stored === undefined) {
230283
231220
  const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
230284
- stored = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__/* .ArrayCacheByTimestamp */ .Py(limit);
231221
+ stored = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheByTimestamp */ .Py(limit);
230285
231222
  this.ohlcvs[symbol][timeframe] = stored;
230286
231223
  }
230287
231224
  stored.append(parsed);
@@ -230330,6 +231267,41 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
230330
231267
  const orderbook = await this.subscribe('public', depth, depth, symbol, params);
230331
231268
  return orderbook.limit();
230332
231269
  }
231270
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
231271
+ /**
231272
+ * @method
231273
+ * @name okx#watchOrderBookForSymbols
231274
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
231275
+ * @param {string[]} symbols unified array of symbols
231276
+ * @param {int} [limit] the maximum amount of order book entries to return
231277
+ * @param {object} [params] extra parameters specific to the okx api endpoint
231278
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
231279
+ */
231280
+ await this.loadMarkets();
231281
+ symbols = this.marketSymbols(symbols);
231282
+ const options = this.safeValue(this.options, 'watchOrderBook', {});
231283
+ const depth = this.safeString(options, 'depth', 'books');
231284
+ if ((depth === 'books-l2-tbt') || (depth === 'books50-l2-tbt')) {
231285
+ await this.authenticate({ 'access': 'public' });
231286
+ }
231287
+ const topics = [];
231288
+ for (let i = 0; i < symbols.length; i++) {
231289
+ const marketId = this.marketId(symbols[i]);
231290
+ const topic = {
231291
+ 'channel': depth,
231292
+ 'instId': marketId,
231293
+ };
231294
+ topics.push(topic);
231295
+ }
231296
+ const request = {
231297
+ 'op': 'subscribe',
231298
+ 'args': topics,
231299
+ };
231300
+ const url = this.getUrl(depth, 'public');
231301
+ const messageHash = 'multipleOrderbooks::' + symbols.join(',');
231302
+ const orderbook = await this.watch(url, messageHash, request, messageHash);
231303
+ return orderbook.limit();
231304
+ }
230333
231305
  handleDelta(bookside, delta) {
230334
231306
  //
230335
231307
  // [
@@ -230390,7 +231362,7 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
230390
231362
  const responseChecksum = this.safeInteger(message, 'checksum');
230391
231363
  const localChecksum = this.crc32(payload, true);
230392
231364
  if (responseChecksum !== localChecksum) {
230393
- const error = new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.InvalidNonce(this.id + ' invalid checksum');
231365
+ const error = new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.InvalidNonce(this.id + ' invalid checksum');
230394
231366
  client.reject(error, messageHash);
230395
231367
  }
230396
231368
  }
@@ -230509,6 +231481,7 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
230509
231481
  orderbook['symbol'] = symbol;
230510
231482
  this.handleOrderBookMessage(client, update, orderbook, messageHash);
230511
231483
  client.resolve(orderbook, messageHash);
231484
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbooks::', symbol, orderbook);
230512
231485
  }
230513
231486
  }
230514
231487
  else if (action === 'update') {
@@ -230518,6 +231491,7 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
230518
231491
  const update = data[i];
230519
231492
  this.handleOrderBookMessage(client, update, orderbook, messageHash);
230520
231493
  client.resolve(orderbook, messageHash);
231494
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbooks::', symbol, orderbook);
230521
231495
  }
230522
231496
  }
230523
231497
  }
@@ -230533,6 +231507,7 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
230533
231507
  const snapshot = this.parseOrderBook(update, symbol, timestamp, 'bids', 'asks', 0, 1);
230534
231508
  orderbook.reset(snapshot);
230535
231509
  client.resolve(orderbook, messageHash);
231510
+ this.resolvePromiseIfMessagehashMatches(client, 'multipleOrderbooks::', symbol, orderbook);
230536
231511
  }
230537
231512
  }
230538
231513
  return message;
@@ -230671,13 +231646,13 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
230671
231646
  * @param {bool} [params.stop] true if fetching trigger or conditional trades
230672
231647
  * @returns {object[]} a list of [trade structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#trade-structure
230673
231648
  */
230674
- await this.loadMarkets();
230675
- await this.authenticate();
230676
231649
  // By default, receive order updates from any instrument type
230677
231650
  let type = undefined;
230678
231651
  [type, params] = this.handleOptionAndParams(params, 'watchMyTrades', 'type', 'ANY');
230679
231652
  const isStop = this.safeValue(params, 'stop', false);
230680
231653
  params = this.omit(params, ['stop']);
231654
+ await this.loadMarkets();
231655
+ await this.authenticate({ 'access': isStop ? 'business' : 'private' });
230681
231656
  const channel = isStop ? 'orders-algo' : 'orders';
230682
231657
  let messageHash = channel + '::myTrades';
230683
231658
  let market = undefined;
@@ -230713,13 +231688,13 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
230713
231688
  * @param {bool} [params.stop] true if fetching trigger or conditional orders
230714
231689
  * @returns {object[]} a list of [order structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
230715
231690
  */
230716
- await this.loadMarkets();
230717
- await this.authenticate();
230718
231691
  let type = undefined;
230719
231692
  // By default, receive order updates from any instrument type
230720
231693
  [type, params] = this.handleOptionAndParams(params, 'watchOrders', 'type', 'ANY');
230721
231694
  const isStop = this.safeValue(params, 'stop', false);
230722
231695
  params = this.omit(params, ['stop']);
231696
+ await this.loadMarkets();
231697
+ await this.authenticate({ 'access': isStop ? 'business' : 'private' });
230723
231698
  let market = undefined;
230724
231699
  if (symbol !== undefined) {
230725
231700
  market = this.market(symbol);
@@ -230803,7 +231778,7 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
230803
231778
  if (ordersLength > 0) {
230804
231779
  const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
230805
231780
  if (this.orders === undefined) {
230806
- this.orders = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__/* .ArrayCacheBySymbolById */ .hl(limit);
231781
+ this.orders = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolById */ .hl(limit);
230807
231782
  }
230808
231783
  const stored = this.orders;
230809
231784
  const marketIds = [];
@@ -230896,7 +231871,7 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
230896
231871
  }
230897
231872
  if (this.myTrades === undefined) {
230898
231873
  const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
230899
- this.myTrades = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_1__/* .ArrayCacheBySymbolById */ .hl(limit);
231874
+ this.myTrades = new _base_ws_Cache_js__WEBPACK_IMPORTED_MODULE_2__/* .ArrayCacheBySymbolById */ .hl(limit);
230900
231875
  }
230901
231876
  const myTrades = this.myTrades;
230902
231877
  const symbols = {};
@@ -230939,10 +231914,10 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
230939
231914
  const args = this.createOrderRequest(symbol, type, side, amount, price, params);
230940
231915
  const ordType = this.safeString(args, 'ordType');
230941
231916
  if ((ordType === 'trigger') || (ordType === 'conditional') || (type === 'oco') || (type === 'move_order_stop') || (type === 'iceberg') || (type === 'twap')) {
230942
- throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.BadRequest(this.id + ' createOrderWs() does not support algo trading. this.options["createOrderWs"]["op"] must be either order or batch-order');
231917
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.BadRequest(this.id + ' createOrderWs() does not support algo trading. this.options["createOrderWs"]["op"] must be either order or batch-order');
230943
231918
  }
230944
231919
  if ((op !== 'order') && (op !== 'batch-orders')) {
230945
- throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.BadRequest(this.id + ' createOrderWs() does not support algo trading. this.options["createOrderWs"]["op"] must be either order or privatePostTradeOrder or privatePostTradeOrderAlgo');
231920
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.BadRequest(this.id + ' createOrderWs() does not support algo trading. this.options["createOrderWs"]["op"] must be either order or privatePostTradeOrder or privatePostTradeOrderAlgo');
230946
231921
  }
230947
231922
  const request = {
230948
231923
  'id': messageHash,
@@ -231026,7 +232001,7 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
231026
232001
  * @returns {object} an list of [order structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
231027
232002
  */
231028
232003
  if (symbol === undefined) {
231029
- throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.BadRequest(this.id + ' cancelOrderWs() requires a symbol argument');
232004
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.BadRequest(this.id + ' cancelOrderWs() requires a symbol argument');
231030
232005
  }
231031
232006
  await this.loadMarkets();
231032
232007
  await this.authenticate();
@@ -231063,10 +232038,10 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
231063
232038
  */
231064
232039
  const idsLength = ids.length;
231065
232040
  if (idsLength > 20) {
231066
- throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.BadRequest(this.id + ' cancelOrdersWs() accepts up to 20 ids at a time');
232041
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.BadRequest(this.id + ' cancelOrdersWs() accepts up to 20 ids at a time');
231067
232042
  }
231068
232043
  if (symbol === undefined) {
231069
- throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.BadRequest(this.id + ' cancelOrdersWs() requires a symbol argument');
232044
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.BadRequest(this.id + ' cancelOrdersWs() requires a symbol argument');
231070
232045
  }
231071
232046
  await this.loadMarkets();
231072
232047
  await this.authenticate();
@@ -231098,13 +232073,13 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
231098
232073
  * @returns {object[]} a list of [order structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
231099
232074
  */
231100
232075
  if (symbol === undefined) {
231101
- throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.BadRequest(this.id + ' cancelAllOrdersWs() requires a symbol argument');
232076
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.BadRequest(this.id + ' cancelAllOrdersWs() requires a symbol argument');
231102
232077
  }
231103
232078
  await this.loadMarkets();
231104
232079
  await this.authenticate();
231105
232080
  const market = this.market(symbol);
231106
232081
  if (market['type'] !== 'option') {
231107
- throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.BadRequest(this.id + 'cancelAllOrdersWs is only applicable to Option in Portfolio Margin mode, and MMP privilege is required.');
232082
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.BadRequest(this.id + 'cancelAllOrdersWs is only applicable to Option in Portfolio Margin mode, and MMP privilege is required.');
231108
232083
  }
231109
232084
  const url = this.getUrl('private', 'private');
231110
232085
  const messageHash = this.nonce().toString();
@@ -231177,7 +232152,7 @@ class okx extends _okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
231177
232152
  }
231178
232153
  }
231179
232154
  catch (e) {
231180
- if (e instanceof _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.AuthenticationError) {
232155
+ if (e instanceof _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.AuthenticationError) {
231181
232156
  const messageHash = 'authenticated';
231182
232157
  client.reject(e, messageHash);
231183
232158
  if (messageHash in client.subscriptions) {
@@ -234185,7 +235160,8 @@ class poloniexfutures extends _poloniexfutures_js__WEBPACK_IMPORTED_MODULE_0__/*
234185
235160
  limit = orders.getLimit(symbol, limit);
234186
235161
  }
234187
235162
  orders = this.filterBySymbolSinceLimit(orders, symbol, since, limit);
234188
- if (orders.length === 0) {
235163
+ const length = orders.length;
235164
+ if (length === 0) {
234189
235165
  return await this.watchOrders(symbol, since, limit, params);
234190
235166
  }
234191
235167
  return orders;
@@ -235168,7 +236144,8 @@ class probit extends _probit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
235168
236144
  // }
235169
236145
  //
235170
236146
  const rawTrades = this.safeValue(message, 'data', []);
235171
- if (rawTrades.length === 0) {
236147
+ const length = rawTrades.length;
236148
+ if (length === 0) {
235172
236149
  return;
235173
236150
  }
235174
236151
  const reset = this.safeValue(message, 'reset', false);
@@ -235254,7 +236231,8 @@ class probit extends _probit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
235254
236231
  // }
235255
236232
  //
235256
236233
  const rawOrders = this.safeValue(message, 'data', []);
235257
- if (rawOrders.length === 0) {
236234
+ const length = rawOrders.length;
236235
+ if (length === 0) {
235258
236236
  return;
235259
236237
  }
235260
236238
  const messageHash = 'orders';
@@ -273892,7 +274870,7 @@ SOFTWARE.
273892
274870
 
273893
274871
  //-----------------------------------------------------------------------------
273894
274872
  // this is updated by vss.js when building
273895
- const version = '4.0.89';
274873
+ const version = '4.0.91';
273896
274874
  _src_base_Exchange_js__WEBPACK_IMPORTED_MODULE_0__/* .Exchange.ccxtVersion */ .e.ccxtVersion = version;
273897
274875
  //-----------------------------------------------------------------------------
273898
274876