ccxt 4.3.95 → 4.3.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/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/bingx.js +2 -1
  6. package/dist/cjs/src/blofin.js +0 -1
  7. package/dist/cjs/src/bybit.js +8 -2
  8. package/dist/cjs/src/hyperliquid.js +262 -32
  9. package/dist/cjs/src/kucoin.js +12 -12
  10. package/dist/cjs/src/mexc.js +6 -0
  11. package/dist/cjs/src/okx.js +0 -1
  12. package/dist/cjs/src/p2b.js +0 -1
  13. package/dist/cjs/src/pro/binance.js +100 -2
  14. package/dist/cjs/src/pro/bybit.js +65 -4
  15. package/dist/cjs/src/pro/cryptocom.js +224 -0
  16. package/dist/cjs/src/pro/okx.js +264 -35
  17. package/dist/cjs/src/tradeogre.js +0 -1
  18. package/js/ccxt.d.ts +2 -8
  19. package/js/ccxt.js +2 -6
  20. package/js/src/base/Exchange.d.ts +0 -2
  21. package/js/src/base/Exchange.js +0 -4
  22. package/js/src/bingx.js +2 -1
  23. package/js/src/blofin.js +0 -1
  24. package/js/src/bybit.js +8 -2
  25. package/js/src/hyperliquid.d.ts +22 -0
  26. package/js/src/hyperliquid.js +262 -32
  27. package/js/src/kucoin.d.ts +1 -1
  28. package/js/src/kucoin.js +12 -12
  29. package/js/src/mexc.js +6 -0
  30. package/js/src/okx.js +0 -1
  31. package/js/src/p2b.js +0 -1
  32. package/js/src/pro/binance.d.ts +2 -0
  33. package/js/src/pro/binance.js +100 -2
  34. package/js/src/pro/bybit.d.ts +3 -1
  35. package/js/src/pro/bybit.js +65 -4
  36. package/js/src/pro/cryptocom.d.ts +10 -1
  37. package/js/src/pro/cryptocom.js +225 -1
  38. package/js/src/pro/okx.d.ts +10 -1
  39. package/js/src/pro/okx.js +264 -35
  40. package/js/src/tradeogre.js +0 -1
  41. package/package.json +1 -1
  42. package/js/src/abstract/bitbay.d.ts +0 -56
  43. package/js/src/abstract/bitbay.js +0 -11
  44. package/js/src/abstract/hitbtc3.d.ts +0 -118
  45. package/js/src/abstract/hitbtc3.js +0 -11
@@ -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;