ccxt 4.3.95 → 4.3.97

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 (55) hide show
  1. package/README.md +4 -4
  2. package/dist/ccxt.browser.min.js +3 -3
  3. package/dist/cjs/ccxt.js +1 -7
  4. package/dist/cjs/src/base/Exchange.js +0 -4
  5. package/dist/cjs/src/binance.js +3 -0
  6. package/dist/cjs/src/bingx.js +2 -1
  7. package/dist/cjs/src/blofin.js +0 -1
  8. package/dist/cjs/src/bybit.js +8 -2
  9. package/dist/cjs/src/coinex.js +16 -3
  10. package/dist/cjs/src/hyperliquid.js +262 -32
  11. package/dist/cjs/src/kucoin.js +12 -12
  12. package/dist/cjs/src/mexc.js +6 -0
  13. package/dist/cjs/src/okx.js +0 -1
  14. package/dist/cjs/src/p2b.js +0 -1
  15. package/dist/cjs/src/pro/binance.js +100 -2
  16. package/dist/cjs/src/pro/bybit.js +65 -4
  17. package/dist/cjs/src/pro/cryptocom.js +224 -0
  18. package/dist/cjs/src/pro/gate.js +179 -0
  19. package/dist/cjs/src/pro/kucoin.js +132 -0
  20. package/dist/cjs/src/pro/okx.js +264 -35
  21. package/dist/cjs/src/tradeogre.js +0 -1
  22. package/js/ccxt.d.ts +2 -8
  23. package/js/ccxt.js +2 -6
  24. package/js/src/base/Exchange.d.ts +0 -2
  25. package/js/src/base/Exchange.js +0 -4
  26. package/js/src/binance.js +3 -0
  27. package/js/src/bingx.js +2 -1
  28. package/js/src/blofin.js +0 -1
  29. package/js/src/bybit.js +8 -2
  30. package/js/src/coinex.js +16 -3
  31. package/js/src/hyperliquid.d.ts +22 -0
  32. package/js/src/hyperliquid.js +262 -32
  33. package/js/src/kucoin.d.ts +1 -1
  34. package/js/src/kucoin.js +12 -12
  35. package/js/src/mexc.js +6 -0
  36. package/js/src/okx.js +0 -1
  37. package/js/src/p2b.js +0 -1
  38. package/js/src/pro/binance.d.ts +2 -0
  39. package/js/src/pro/binance.js +100 -2
  40. package/js/src/pro/bybit.d.ts +3 -1
  41. package/js/src/pro/bybit.js +65 -4
  42. package/js/src/pro/cryptocom.d.ts +10 -1
  43. package/js/src/pro/cryptocom.js +225 -1
  44. package/js/src/pro/gate.d.ts +7 -1
  45. package/js/src/pro/gate.js +180 -1
  46. package/js/src/pro/kucoin.d.ts +5 -1
  47. package/js/src/pro/kucoin.js +133 -1
  48. package/js/src/pro/okx.d.ts +10 -1
  49. package/js/src/pro/okx.js +264 -35
  50. package/js/src/tradeogre.js +0 -1
  51. package/package.json +1 -1
  52. package/js/src/abstract/bitbay.d.ts +0 -56
  53. package/js/src/abstract/bitbay.js +0 -11
  54. package/js/src/abstract/hitbtc3.d.ts +0 -118
  55. package/js/src/abstract/hitbtc3.js +0 -11
@@ -625,6 +625,7 @@ class kucoin extends kucoin$1 {
625
625
  'KALT': 'ALT', // ALTLAYER
626
626
  },
627
627
  'options': {
628
+ 'hf': false,
628
629
  'version': 'v1',
629
630
  'symbolSeparator': '-',
630
631
  'fetchMyTradesMethod': 'private_get_fills',
@@ -1218,9 +1219,8 @@ class kucoin extends kucoin$1 {
1218
1219
  this.options['hfMigrated'] = (status === 2);
1219
1220
  }
1220
1221
  }
1221
- async handleHfAndParams(params = {}) {
1222
- await this.loadMigrationStatus();
1223
- const migrated = this.safeBool(this.options, 'hfMigrated');
1222
+ handleHfAndParams(params = {}) {
1223
+ const migrated = this.safeBool2(this.options, 'hfMigrated', 'hf', false);
1224
1224
  let loadedHf = undefined;
1225
1225
  if (migrated !== undefined) {
1226
1226
  if (migrated) {
@@ -2119,7 +2119,7 @@ class kucoin extends kucoin$1 {
2119
2119
  const testOrder = this.safeBool(params, 'test', false);
2120
2120
  params = this.omit(params, 'test');
2121
2121
  let hf = undefined;
2122
- [hf, params] = await this.handleHfAndParams(params);
2122
+ [hf, params] = this.handleHfAndParams(params);
2123
2123
  let useSync = false;
2124
2124
  [useSync, params] = this.handleOptionAndParams(params, 'createOrder', 'sync', false);
2125
2125
  const [triggerPrice, stopLossPrice, takeProfitPrice] = this.handleTriggerPrices(params);
@@ -2257,7 +2257,7 @@ class kucoin extends kucoin$1 {
2257
2257
  'orderList': ordersRequests,
2258
2258
  };
2259
2259
  let hf = undefined;
2260
- [hf, params] = await this.handleHfAndParams(params);
2260
+ [hf, params] = this.handleHfAndParams(params);
2261
2261
  let useSync = false;
2262
2262
  [useSync, params] = this.handleOptionAndParams(params, 'createOrders', 'sync', false);
2263
2263
  let response = undefined;
@@ -2455,7 +2455,7 @@ class kucoin extends kucoin$1 {
2455
2455
  const clientOrderId = this.safeString2(params, 'clientOid', 'clientOrderId');
2456
2456
  const stop = this.safeBool2(params, 'stop', 'trigger', false);
2457
2457
  let hf = undefined;
2458
- [hf, params] = await this.handleHfAndParams(params);
2458
+ [hf, params] = this.handleHfAndParams(params);
2459
2459
  let useSync = false;
2460
2460
  [useSync, params] = this.handleOptionAndParams(params, 'cancelOrder', 'sync', false);
2461
2461
  if (hf || useSync) {
@@ -2577,7 +2577,7 @@ class kucoin extends kucoin$1 {
2577
2577
  const request = {};
2578
2578
  const stop = this.safeBool(params, 'stop', false);
2579
2579
  let hf = undefined;
2580
- [hf, params] = await this.handleHfAndParams(params);
2580
+ [hf, params] = this.handleHfAndParams(params);
2581
2581
  params = this.omit(params, 'stop');
2582
2582
  const [marginMode, query] = this.handleMarginModeAndParams('cancelAllOrders', params);
2583
2583
  if (symbol !== undefined) {
@@ -2636,7 +2636,7 @@ class kucoin extends kucoin$1 {
2636
2636
  const until = this.safeInteger(params, 'until');
2637
2637
  const stop = this.safeBool2(params, 'stop', 'trigger', false);
2638
2638
  let hf = undefined;
2639
- [hf, params] = await this.handleHfAndParams(params);
2639
+ [hf, params] = this.handleHfAndParams(params);
2640
2640
  if (hf && (symbol === undefined)) {
2641
2641
  throw new errors.ArgumentsRequired(this.id + ' fetchOrdersByStatus() requires a symbol parameter for hf orders');
2642
2642
  }
@@ -2819,7 +2819,7 @@ class kucoin extends kucoin$1 {
2819
2819
  const clientOrderId = this.safeString2(params, 'clientOid', 'clientOrderId');
2820
2820
  const stop = this.safeBool2(params, 'stop', 'trigger', false);
2821
2821
  let hf = undefined;
2822
- [hf, params] = await this.handleHfAndParams(params);
2822
+ [hf, params] = this.handleHfAndParams(params);
2823
2823
  let market = undefined;
2824
2824
  if (symbol !== undefined) {
2825
2825
  market = this.market(symbol);
@@ -3097,7 +3097,7 @@ class kucoin extends kucoin$1 {
3097
3097
  }
3098
3098
  let request = {};
3099
3099
  let hf = undefined;
3100
- [hf, params] = await this.handleHfAndParams(params);
3100
+ [hf, params] = this.handleHfAndParams(params);
3101
3101
  if (hf && symbol === undefined) {
3102
3102
  throw new errors.ArgumentsRequired(this.id + ' fetchMyTrades() requires a symbol parameter for hf orders');
3103
3103
  }
@@ -3827,7 +3827,7 @@ class kucoin extends kucoin$1 {
3827
3827
  let type = this.safeString(accountsByType, requestedType, requestedType);
3828
3828
  params = this.omit(params, 'type');
3829
3829
  let hf = undefined;
3830
- [hf, params] = await this.handleHfAndParams(params);
3830
+ [hf, params] = this.handleHfAndParams(params);
3831
3831
  if (hf) {
3832
3832
  type = 'trade_hf';
3833
3833
  }
@@ -4287,7 +4287,7 @@ class kucoin extends kucoin$1 {
4287
4287
  let paginate = false;
4288
4288
  [paginate, params] = this.handleOptionAndParams(params, 'fetchLedger', 'paginate');
4289
4289
  let hf = undefined;
4290
- [hf, params] = await this.handleHfAndParams(params);
4290
+ [hf, params] = this.handleHfAndParams(params);
4291
4291
  if (paginate) {
4292
4292
  return await this.fetchPaginatedCallDynamic('fetchLedger', code, since, limit, params);
4293
4293
  }
@@ -797,6 +797,8 @@ class mexc extends mexc$1 {
797
797
  * @method
798
798
  * @name mexc#fetchStatus
799
799
  * @description the latest known information on the availability of the exchange API
800
+ * @see https://mexcdevelop.github.io/apidocs/spot_v3_en/#test-connectivity
801
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-the-server-time
800
802
  * @param {object} [params] extra parameters specific to the exchange API endpoint
801
803
  * @returns {object} a [status structure]{@link https://docs.ccxt.com/#/?id=exchange-status-structure}
802
804
  */
@@ -834,6 +836,8 @@ class mexc extends mexc$1 {
834
836
  * @method
835
837
  * @name mexc#fetchTime
836
838
  * @description fetches the current integer timestamp in milliseconds from the exchange server
839
+ * @see https://mexcdevelop.github.io/apidocs/spot_v3_en/#check-server-time
840
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-the-server-time
837
841
  * @param {object} [params] extra parameters specific to the exchange API endpoint
838
842
  * @returns {int} the current integer timestamp in milliseconds from the exchange server
839
843
  */
@@ -1005,6 +1009,8 @@ class mexc extends mexc$1 {
1005
1009
  * @method
1006
1010
  * @name mexc#fetchMarkets
1007
1011
  * @description retrieves data on all markets for mexc
1012
+ * @see https://mexcdevelop.github.io/apidocs/spot_v3_en/#exchange-information
1013
+ * @see https://mexcdevelop.github.io/apidocs/contract_v1_en/#get-the-contract-information
1008
1014
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1009
1015
  * @returns {object[]} an array of objects representing market data
1010
1016
  */
@@ -109,7 +109,6 @@ class okx extends okx$1 {
109
109
  'fetchOrderBooks': false,
110
110
  'fetchOrders': false,
111
111
  'fetchOrderTrades': true,
112
- 'fetchPermissions': undefined,
113
112
  'fetchPosition': true,
114
113
  'fetchPositionHistory': 'emulated',
115
114
  'fetchPositions': true,
@@ -77,7 +77,6 @@ class p2b extends p2b$1 {
77
77
  'fetchOrderBooks': false,
78
78
  'fetchOrders': true,
79
79
  'fetchOrderTrades': true,
80
- 'fetchPermissions': false,
81
80
  'fetchPosition': false,
82
81
  'fetchPositionHistory': false,
83
82
  'fetchPositionMode': false,
@@ -1032,14 +1032,25 @@ class binance extends binance$1 {
1032
1032
  const error = new errors.UnsubscribeError(this.id + ' ' + subHash);
1033
1033
  client.reject(error, subHash);
1034
1034
  client.resolve(true, unsubHash);
1035
- this.cleanCache(subscription);
1036
1035
  }
1036
+ this.cleanCache(subscription);
1037
1037
  }
1038
1038
  cleanCache(subscription) {
1039
1039
  const topic = this.safeString(subscription, 'topic');
1040
1040
  const symbols = this.safeList(subscription, 'symbols', []);
1041
1041
  const symbolsLength = symbols.length;
1042
- if (symbolsLength > 0) {
1042
+ if (topic === 'ohlcv') {
1043
+ const symbolsAndTimeFrames = this.safeList(subscription, 'symbolsAndTimeframes', []);
1044
+ for (let i = 0; i < symbolsAndTimeFrames.length; i++) {
1045
+ const symbolAndTimeFrame = symbolsAndTimeFrames[i];
1046
+ const symbol = this.safeString(symbolAndTimeFrame, 0);
1047
+ const timeframe = this.safeString(symbolAndTimeFrame, 1);
1048
+ if (timeframe in this.ohlcvs[symbol]) {
1049
+ delete this.ohlcvs[symbol][timeframe];
1050
+ }
1051
+ }
1052
+ }
1053
+ else if (symbolsLength > 0) {
1043
1054
  for (let i = 0; i < symbols.length; i++) {
1044
1055
  const symbol = symbols[i];
1045
1056
  if (topic === 'trade') {
@@ -1507,6 +1518,93 @@ class binance extends binance$1 {
1507
1518
  const filtered = this.filterBySinceLimit(candles, since, limit, 0, true);
1508
1519
  return this.createOHLCVObject(symbol, timeframe, filtered);
1509
1520
  }
1521
+ async unWatchOHLCVForSymbols(symbolsAndTimeframes, params = {}) {
1522
+ /**
1523
+ * @method
1524
+ * @name binance#unWatchOHLCVForSymbols
1525
+ * @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1526
+ * @see https://binance-docs.github.io/apidocs/spot/en/#kline-candlestick-data
1527
+ * @see https://binance-docs.github.io/apidocs/futures/en/#kline-candlestick-data
1528
+ * @see https://binance-docs.github.io/apidocs/delivery/en/#kline-candlestick-data
1529
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
1530
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1531
+ * @param {object} [params.timezone] if provided, kline intervals are interpreted in that timezone instead of UTC, example '+08:00'
1532
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1533
+ */
1534
+ await this.loadMarkets();
1535
+ let klineType = undefined;
1536
+ [klineType, params] = this.handleParamString2(params, 'channel', 'name', 'kline');
1537
+ const symbols = this.getListFromObjectValues(symbolsAndTimeframes, 0);
1538
+ const marketSymbols = this.marketSymbols(symbols, undefined, false, false, true);
1539
+ const firstMarket = this.market(marketSymbols[0]);
1540
+ let type = firstMarket['type'];
1541
+ if (firstMarket['contract']) {
1542
+ type = firstMarket['linear'] ? 'future' : 'delivery';
1543
+ }
1544
+ const isSpot = (type === 'spot');
1545
+ let timezone = undefined;
1546
+ [timezone, params] = this.handleParamString(params, 'timezone', undefined);
1547
+ const isUtc8 = (timezone !== undefined) && ((timezone === '+08:00') || Precise["default"].stringEq(timezone, '8'));
1548
+ const rawHashes = [];
1549
+ const subMessageHashes = [];
1550
+ const messageHashes = [];
1551
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
1552
+ const symAndTf = symbolsAndTimeframes[i];
1553
+ const symbolString = symAndTf[0];
1554
+ const timeframeString = symAndTf[1];
1555
+ const interval = this.safeString(this.timeframes, timeframeString, timeframeString);
1556
+ const market = this.market(symbolString);
1557
+ let marketId = market['lowercaseId'];
1558
+ if (klineType === 'indexPriceKline') {
1559
+ // weird behavior for index price kline we can't use the perp suffix
1560
+ marketId = marketId.replace('_perp', '');
1561
+ }
1562
+ const shouldUseUTC8 = (isUtc8 && isSpot);
1563
+ const suffix = '@+08:00';
1564
+ const utcSuffix = shouldUseUTC8 ? suffix : '';
1565
+ rawHashes.push(marketId + '@' + klineType + '_' + interval + utcSuffix);
1566
+ subMessageHashes.push('ohlcv::' + market['symbol'] + '::' + timeframeString);
1567
+ messageHashes.push('unsubscribe::ohlcv::' + market['symbol'] + '::' + timeframeString);
1568
+ }
1569
+ const url = this.urls['api']['ws'][type] + '/' + this.stream(type, 'multipleOHLCV');
1570
+ const requestId = this.requestId(url);
1571
+ const request = {
1572
+ 'method': 'UNSUBSCRIBE',
1573
+ 'params': rawHashes,
1574
+ 'id': requestId,
1575
+ };
1576
+ const subscribe = {
1577
+ 'unsubscribe': true,
1578
+ 'id': requestId.toString(),
1579
+ 'symbols': symbols,
1580
+ 'symbolsAndTimeframes': symbolsAndTimeframes,
1581
+ 'subMessageHashes': subMessageHashes,
1582
+ 'messageHashes': messageHashes,
1583
+ 'topic': 'ohlcv',
1584
+ };
1585
+ params = this.omit(params, 'callerMethodName');
1586
+ return await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes, subscribe);
1587
+ }
1588
+ async unWatchOHLCV(symbol, timeframe = '1m', params = {}) {
1589
+ /**
1590
+ * @method
1591
+ * @name binance#unWatchOHLCV
1592
+ * @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1593
+ * @see https://binance-docs.github.io/apidocs/spot/en/#kline-candlestick-data
1594
+ * @see https://binance-docs.github.io/apidocs/futures/en/#kline-candlestick-data
1595
+ * @see https://binance-docs.github.io/apidocs/delivery/en/#kline-candlestick-data
1596
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
1597
+ * @param {string} timeframe the length of time each candle represents
1598
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1599
+ * @param {object} [params.timezone] if provided, kline intervals are interpreted in that timezone instead of UTC, example '+08:00'
1600
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1601
+ */
1602
+ await this.loadMarkets();
1603
+ const market = this.market(symbol);
1604
+ symbol = market['symbol'];
1605
+ params['callerMethodName'] = 'watchOHLCV';
1606
+ return await this.unWatchOHLCVForSymbols([[symbol, timeframe]], params);
1607
+ }
1510
1608
  handleOHLCV(client, message) {
1511
1609
  //
1512
1610
  // {
@@ -633,6 +633,58 @@ class bybit extends bybit$1 {
633
633
  const filtered = this.filterBySinceLimit(stored, since, limit, 0, true);
634
634
  return this.createOHLCVObject(symbol, timeframe, filtered);
635
635
  }
636
+ async unWatchOHLCVForSymbols(symbolsAndTimeframes, params = {}) {
637
+ /**
638
+ * @method
639
+ * @name bybit#unWatchOHLCVForSymbols
640
+ * @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
641
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/kline
642
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/etp-kline
643
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
644
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
645
+ * @returns {object} A list of candles ordered as timestamp, open, high, low, close, volume
646
+ */
647
+ await this.loadMarkets();
648
+ const symbols = this.getListFromObjectValues(symbolsAndTimeframes, 0);
649
+ const marketSymbols = this.marketSymbols(symbols, undefined, false, true, true);
650
+ const firstSymbol = marketSymbols[0];
651
+ const url = await this.getUrlByMarketType(firstSymbol, false, 'watchOHLCVForSymbols', params);
652
+ const rawHashes = [];
653
+ const subMessageHashes = [];
654
+ const messageHashes = [];
655
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
656
+ const data = symbolsAndTimeframes[i];
657
+ let symbolString = this.safeString(data, 0);
658
+ const market = this.market(symbolString);
659
+ symbolString = market['symbol'];
660
+ const unfiedTimeframe = this.safeString(data, 1);
661
+ const timeframeId = this.safeString(this.timeframes, unfiedTimeframe, unfiedTimeframe);
662
+ rawHashes.push('kline.' + timeframeId + '.' + market['id']);
663
+ subMessageHashes.push('ohlcv::' + symbolString + '::' + unfiedTimeframe);
664
+ messageHashes.push('unsubscribe::ohlcv::' + symbolString + '::' + unfiedTimeframe);
665
+ }
666
+ const subExtension = {
667
+ 'symbolsAndTimeframes': symbolsAndTimeframes,
668
+ };
669
+ return await this.unWatchTopics(url, 'ohlcv', symbols, messageHashes, subMessageHashes, rawHashes, params, subExtension);
670
+ }
671
+ async unWatchOHLCV(symbol, timeframe = '1m', params = {}) {
672
+ /**
673
+ * @method
674
+ * @name bybit#unWatchOHLCV
675
+ * @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
676
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/kline
677
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/etp-kline
678
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
679
+ * @param {string} timeframe the length of time each candle represents
680
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
681
+ * @param {int} [limit] the maximum amount of candles to fetch
682
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
683
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
684
+ */
685
+ params['callerMethodName'] = 'watchOHLCV';
686
+ return await this.unWatchOHLCVForSymbols([[symbol, timeframe]], params);
687
+ }
636
688
  handleOHLCV(client, message) {
637
689
  //
638
690
  // {
@@ -2142,7 +2194,7 @@ class bybit extends bybit$1 {
2142
2194
  const message = this.extend(request, params);
2143
2195
  return await this.watchMultiple(url, messageHashes, message, messageHashes);
2144
2196
  }
2145
- async unWatchTopics(url, topic, symbols, messageHashes, subMessageHashes, topics, params = {}) {
2197
+ async unWatchTopics(url, topic, symbols, messageHashes, subMessageHashes, topics, params = {}, subExtension = {}) {
2146
2198
  const reqId = this.requestId();
2147
2199
  const request = {
2148
2200
  'op': 'unsubscribe',
@@ -2157,7 +2209,7 @@ class bybit extends bybit$1 {
2157
2209
  'symbols': symbols,
2158
2210
  };
2159
2211
  const message = this.extend(request, params);
2160
- return await this.watchMultiple(url, messageHashes, message, messageHashes, subscription);
2212
+ return await this.watchMultiple(url, messageHashes, message, messageHashes, this.extend(subscription, subExtension));
2161
2213
  }
2162
2214
  async authenticate(url, params = {}) {
2163
2215
  this.checkRequiredCredentials();
@@ -2440,8 +2492,8 @@ class bybit extends bybit$1 {
2440
2492
  const error = new errors.UnsubscribeError(this.id + ' ' + messageHash);
2441
2493
  client.reject(error, subHash);
2442
2494
  client.resolve(true, unsubHash);
2443
- this.cleanCache(subscription);
2444
2495
  }
2496
+ this.cleanCache(subscription);
2445
2497
  }
2446
2498
  }
2447
2499
  return message;
@@ -2450,7 +2502,16 @@ class bybit extends bybit$1 {
2450
2502
  const topic = this.safeString(subscription, 'topic');
2451
2503
  const symbols = this.safeList(subscription, 'symbols', []);
2452
2504
  const symbolsLength = symbols.length;
2453
- if (symbolsLength > 0) {
2505
+ if (topic === 'ohlcv') {
2506
+ const symbolsAndTimeFrames = this.safeList(subscription, 'symbolsAndTimeframes', []);
2507
+ for (let i = 0; i < symbolsAndTimeFrames.length; i++) {
2508
+ const symbolAndTimeFrame = symbolsAndTimeFrames[i];
2509
+ const symbol = this.safeString(symbolAndTimeFrame, 0);
2510
+ const timeframe = this.safeString(symbolAndTimeFrame, 1);
2511
+ delete this.ohlcvs[symbol][timeframe];
2512
+ }
2513
+ }
2514
+ else if (symbolsLength > 0) {
2454
2515
  for (let i = 0; i < symbols.length; i++) {
2455
2516
  const symbol = symbols[i];
2456
2517
  if (topic === 'trade') {
@@ -80,6 +80,20 @@ class cryptocom extends cryptocom$1 {
80
80
  */
81
81
  return await this.watchOrderBookForSymbols([symbol], limit, params);
82
82
  }
83
+ async unWatchOrderBook(symbol, params = {}) {
84
+ /**
85
+ * @method
86
+ * @name cryptocom#unWatchOrderBook
87
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
88
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#book-instrument_name
89
+ * @param {string} symbol unified symbol of the market to fetch the order book for
90
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
91
+ * @param {string} [params.bookSubscriptionType] The subscription type. Allowed values: SNAPSHOT full snapshot. This is the default if not specified. SNAPSHOT_AND_UPDATE delta updates
92
+ * @param {int} [params.bookUpdateFrequency] Book update interval in ms. Allowed values: 100 for snapshot subscription 10 for delta subscription
93
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
94
+ */
95
+ return await this.unWatchOrderBookForSymbols([symbol], params);
96
+ }
83
97
  async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
84
98
  /**
85
99
  * @method
@@ -127,6 +141,52 @@ class cryptocom extends cryptocom$1 {
127
141
  const orderbook = await this.watchPublicMultiple(messageHashes, topics, params);
128
142
  return orderbook.limit();
129
143
  }
144
+ async unWatchOrderBookForSymbols(symbols, params = {}) {
145
+ /**
146
+ * @method
147
+ * @name cryptocom#unWatchOrderBookForSymbols
148
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
149
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#book-instrument_name
150
+ * @param {string[]} symbols unified array of symbols
151
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
152
+ * @param {int} [params.limit] orderbook limit, default is 50
153
+ * @param {string} [params.bookSubscriptionType] The subscription type. Allowed values: SNAPSHOT full snapshot. This is the default if not specified. SNAPSHOT_AND_UPDATE delta updates
154
+ * @param {int} [params.bookUpdateFrequency] Book update interval in ms. Allowed values: 100 for snapshot subscription 10 for delta subscription
155
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
156
+ */
157
+ await this.loadMarkets();
158
+ symbols = this.marketSymbols(symbols);
159
+ const topics = [];
160
+ const subMessageHashes = [];
161
+ const messageHashes = [];
162
+ const limit = this.safeInteger(params, 'limit', 50);
163
+ const topicParams = this.safeValue(params, 'params');
164
+ if (topicParams === undefined) {
165
+ params['params'] = {};
166
+ }
167
+ let bookSubscriptionType = undefined;
168
+ let bookSubscriptionType2 = undefined;
169
+ [bookSubscriptionType, params] = this.handleOptionAndParams(params, 'watchOrderBook', 'bookSubscriptionType', 'SNAPSHOT_AND_UPDATE');
170
+ [bookSubscriptionType2, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'bookSubscriptionType', bookSubscriptionType);
171
+ params['params']['bookSubscriptionType'] = bookSubscriptionType2;
172
+ let bookUpdateFrequency = undefined;
173
+ let bookUpdateFrequency2 = undefined;
174
+ [bookUpdateFrequency, params] = this.handleOptionAndParams(params, 'watchOrderBook', 'bookUpdateFrequency');
175
+ [bookUpdateFrequency2, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'bookUpdateFrequency', bookUpdateFrequency);
176
+ if (bookUpdateFrequency2 !== undefined) {
177
+ params['params']['bookSubscriptionType'] = bookUpdateFrequency2;
178
+ }
179
+ for (let i = 0; i < symbols.length; i++) {
180
+ const symbol = symbols[i];
181
+ const market = this.market(symbol);
182
+ const currentTopic = 'book' + '.' + market['id'] + '.' + limit.toString();
183
+ const messageHash = 'orderbook:' + market['symbol'];
184
+ subMessageHashes.push(messageHash);
185
+ messageHashes.push('unsubscribe:' + messageHash);
186
+ topics.push(currentTopic);
187
+ }
188
+ return await this.unWatchPublicMultiple('orderbook', symbols, messageHashes, subMessageHashes, topics, params);
189
+ }
130
190
  handleDelta(bookside, delta) {
131
191
  const price = this.safeFloat(delta, 0);
132
192
  const amount = this.safeFloat(delta, 1);
@@ -247,6 +307,20 @@ class cryptocom extends cryptocom$1 {
247
307
  */
248
308
  return await this.watchTradesForSymbols([symbol], since, limit, params);
249
309
  }
310
+ async unWatchTrades(symbol, params = {}) {
311
+ /**
312
+ * @method
313
+ * @name cryptocom#unWatchTrades
314
+ * @description get the list of most recent trades for a particular symbol
315
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#trade-instrument_name
316
+ * @param {string} symbol unified symbol of the market to fetch trades for
317
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
318
+ * @param {int} [limit] the maximum amount of trades to fetch
319
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
320
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
321
+ */
322
+ return await this.unWatchTradesForSymbols([symbol], params);
323
+ }
250
324
  async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
251
325
  /**
252
326
  * @method
@@ -276,6 +350,29 @@ class cryptocom extends cryptocom$1 {
276
350
  }
277
351
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
278
352
  }
353
+ async unWatchTradesForSymbols(symbols, params = {}) {
354
+ /**
355
+ * @method
356
+ * @name cryptocom#unWatchTradesForSymbols
357
+ * @description get the list of most recent trades for a particular symbol
358
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#trade-instrument_name
359
+ * @param {string} symbol unified symbol of the market to fetch trades for
360
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
361
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
362
+ */
363
+ await this.loadMarkets();
364
+ symbols = this.marketSymbols(symbols);
365
+ const topics = [];
366
+ const messageHashes = [];
367
+ for (let i = 0; i < symbols.length; i++) {
368
+ const symbol = symbols[i];
369
+ const market = this.market(symbol);
370
+ const currentTopic = 'trade' + '.' + market['id'];
371
+ messageHashes.push('unsubscribe:trades:' + market['symbol']);
372
+ topics.push(currentTopic);
373
+ }
374
+ return await this.unWatchPublicMultiple('trade', symbols, messageHashes, topics, topics, params);
375
+ }
279
376
  handleTrades(client, message) {
280
377
  //
281
378
  // {
@@ -364,6 +461,22 @@ class cryptocom extends cryptocom$1 {
364
461
  const messageHash = 'ticker' + '.' + market['id'];
365
462
  return await this.watchPublic(messageHash, params);
366
463
  }
464
+ async unWatchTicker(symbol, params = {}) {
465
+ /**
466
+ * @method
467
+ * @name cryptocom#unWatchTicker
468
+ * @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
469
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#ticker-instrument_name
470
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
471
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
472
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
473
+ */
474
+ await this.loadMarkets();
475
+ const market = this.market(symbol);
476
+ const subMessageHash = 'ticker' + '.' + market['id'];
477
+ const messageHash = 'unsubscribe:ticker:' + market['symbol'];
478
+ return await this.unWatchPublicMultiple('ticker', [market['symbol']], [messageHash], [subMessageHash], [subMessageHash], params);
479
+ }
367
480
  handleTicker(client, message) {
368
481
  //
369
482
  // {
@@ -423,6 +536,28 @@ class cryptocom extends cryptocom$1 {
423
536
  }
424
537
  return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
425
538
  }
539
+ async unWatchOHLCV(symbol, timeframe = '1m', params = {}) {
540
+ /**
541
+ * @method
542
+ * @name cryptocom#unWatchOHLCV
543
+ * @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
544
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#candlestick-time_frame-instrument_name
545
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
546
+ * @param {string} timeframe the length of time each candle represents
547
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
548
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
549
+ */
550
+ await this.loadMarkets();
551
+ const market = this.market(symbol);
552
+ symbol = market['symbol'];
553
+ const interval = this.safeString(this.timeframes, timeframe, timeframe);
554
+ const subMessageHash = 'candlestick' + '.' + interval + '.' + market['id'];
555
+ const messageHash = 'unsubscribe:ohlcv:' + market['symbol'] + ':' + timeframe;
556
+ const subExtend = {
557
+ 'symbolsAndTimeframes': [[market['symbol'], timeframe]],
558
+ };
559
+ return await this.unWatchPublicMultiple('ohlcv', [market['symbol']], [messageHash], [subMessageHash], [subMessageHash], params, subExtend);
560
+ }
426
561
  handleOHLCV(client, message) {
427
562
  //
428
563
  // {
@@ -853,6 +988,27 @@ class cryptocom extends cryptocom$1 {
853
988
  const message = this.deepExtend(request, params);
854
989
  return await this.watchMultiple(url, messageHashes, message, messageHashes);
855
990
  }
991
+ async unWatchPublicMultiple(topic, symbols, messageHashes, subMessageHashes, topics, params = {}, subExtend = {}) {
992
+ const url = this.urls['api']['ws']['public'];
993
+ const id = this.nonce();
994
+ const request = {
995
+ 'method': 'unsubscribe',
996
+ 'params': {
997
+ 'channels': topics,
998
+ },
999
+ 'nonce': id,
1000
+ 'id': id.toString(),
1001
+ };
1002
+ const subscription = {
1003
+ 'id': id.toString(),
1004
+ 'topic': topic,
1005
+ 'symbols': symbols,
1006
+ 'subMessageHashes': subMessageHashes,
1007
+ 'messageHashes': messageHashes,
1008
+ };
1009
+ const message = this.deepExtend(request, params);
1010
+ return await this.watchMultiple(url, messageHashes, message, messageHashes, this.extend(subscription, subExtend));
1011
+ }
856
1012
  async watchPrivateRequest(nonce, params = {}) {
857
1013
  await this.authenticate();
858
1014
  const url = this.urls['api']['ws']['private'];
@@ -972,6 +1128,9 @@ class cryptocom extends cryptocom$1 {
972
1128
  // "channel":"ticker",
973
1129
  // "data":[ { } ]
974
1130
  //
1131
+ // handle unsubscribe
1132
+ // {"id":1725448572836,"method":"unsubscribe","code":0}
1133
+ //
975
1134
  if (this.handleErrorMessage(client, message)) {
976
1135
  return;
977
1136
  }
@@ -985,6 +1144,7 @@ class cryptocom extends cryptocom$1 {
985
1144
  'private/cancel-all-orders': this.handleCancelAllOrders,
986
1145
  'private/close-position': this.handleOrder,
987
1146
  'subscribe': this.handleSubscribe,
1147
+ 'unsubscribe': this.handleUnsubscribe,
988
1148
  };
989
1149
  const callMethod = this.safeValue(methods, method);
990
1150
  if (callMethod !== undefined) {
@@ -1025,6 +1185,70 @@ class cryptocom extends cryptocom$1 {
1025
1185
  const future = this.safeValue(client.futures, 'authenticated');
1026
1186
  future.resolve(true);
1027
1187
  }
1188
+ handleUnsubscribe(client, message) {
1189
+ const id = this.safeString(message, 'id');
1190
+ const keys = Object.keys(client.subscriptions);
1191
+ for (let i = 0; i < keys.length; i++) {
1192
+ const messageHash = keys[i];
1193
+ if (!(messageHash in client.subscriptions)) {
1194
+ continue;
1195
+ // the previous iteration can have deleted the messageHash from the subscriptions
1196
+ }
1197
+ if (messageHash.startsWith('unsubscribe')) {
1198
+ const subscription = client.subscriptions[messageHash];
1199
+ const subId = this.safeString(subscription, 'id');
1200
+ if (id !== subId) {
1201
+ continue;
1202
+ }
1203
+ const messageHashes = this.safeList(subscription, 'messageHashes', []);
1204
+ const subMessageHashes = this.safeList(subscription, 'subMessageHashes', []);
1205
+ for (let j = 0; j < messageHashes.length; j++) {
1206
+ const unsubHash = messageHashes[j];
1207
+ const subHash = subMessageHashes[j];
1208
+ if (unsubHash in client.subscriptions) {
1209
+ delete client.subscriptions[unsubHash];
1210
+ }
1211
+ if (subHash in client.subscriptions) {
1212
+ delete client.subscriptions[subHash];
1213
+ }
1214
+ const error = new errors.UnsubscribeError(this.id + ' ' + subHash);
1215
+ client.reject(error, subHash);
1216
+ client.resolve(true, unsubHash);
1217
+ }
1218
+ this.cleanCache(subscription);
1219
+ }
1220
+ }
1221
+ }
1222
+ cleanCache(subscription) {
1223
+ const topic = this.safeString(subscription, 'topic');
1224
+ const symbols = this.safeList(subscription, 'symbols', []);
1225
+ const symbolsLength = symbols.length;
1226
+ if (topic === 'ohlcv') {
1227
+ const symbolsAndTimeFrames = this.safeList(subscription, 'symbolsAndTimeframes', []);
1228
+ for (let i = 0; i < symbolsAndTimeFrames.length; i++) {
1229
+ const symbolAndTimeFrame = symbolsAndTimeFrames[i];
1230
+ const symbol = this.safeString(symbolAndTimeFrame, 0);
1231
+ const timeframe = this.safeString(symbolAndTimeFrame, 1);
1232
+ if (timeframe in this.ohlcvs[symbol]) {
1233
+ delete this.ohlcvs[symbol][timeframe];
1234
+ }
1235
+ }
1236
+ }
1237
+ else if (symbolsLength > 0) {
1238
+ for (let i = 0; i < symbols.length; i++) {
1239
+ const symbol = symbols[i];
1240
+ if (topic === 'trade') {
1241
+ delete this.trades[symbol];
1242
+ }
1243
+ else if (topic === 'orderbook') {
1244
+ delete this.orderbooks[symbol];
1245
+ }
1246
+ else if (topic === 'ticker') {
1247
+ delete this.tickers[symbol];
1248
+ }
1249
+ }
1250
+ }
1251
+ }
1028
1252
  }
1029
1253
 
1030
1254
  module.exports = cryptocom;