ccxt 4.4.1 → 4.4.3

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 (67) hide show
  1. package/README.md +4 -4
  2. package/dist/ccxt.browser.min.js +3 -3
  3. package/dist/cjs/ccxt.js +1 -1
  4. package/dist/cjs/src/base/Exchange.js +69 -0
  5. package/dist/cjs/src/binance.js +88 -18
  6. package/dist/cjs/src/bitmart.js +3 -1
  7. package/dist/cjs/src/bitstamp.js +24 -36
  8. package/dist/cjs/src/bybit.js +1 -0
  9. package/dist/cjs/src/cryptocom.js +3 -2
  10. package/dist/cjs/src/currencycom.js +1 -2
  11. package/dist/cjs/src/htx.js +1 -1
  12. package/dist/cjs/src/mexc.js +88 -1
  13. package/dist/cjs/src/pro/binance.js +3 -63
  14. package/dist/cjs/src/pro/bitget.js +1 -9
  15. package/dist/cjs/src/pro/bitmex.js +11 -1
  16. package/dist/cjs/src/pro/bybit.js +2 -54
  17. package/dist/cjs/src/pro/cryptocom.js +193 -61
  18. package/dist/cjs/src/pro/gate.js +1 -9
  19. package/dist/cjs/src/pro/hyperliquid.js +4 -36
  20. package/dist/cjs/src/pro/kucoin.js +2 -59
  21. package/dist/cjs/src/pro/kucoinfutures.js +139 -1
  22. package/dist/cjs/src/pro/mexc.js +82 -3
  23. package/dist/cjs/src/pro/okx.js +14 -39
  24. package/dist/cjs/src/pro/oxfun.js +75 -0
  25. package/dist/cjs/src/pro/phemex.js +45 -1
  26. package/dist/cjs/src/pro/woofipro.js +67 -0
  27. package/dist/cjs/src/xt.js +7 -2
  28. package/examples/js/cli.js +8 -4
  29. package/js/ccxt.d.ts +3 -3
  30. package/js/ccxt.js +1 -1
  31. package/js/src/abstract/bitmart.d.ts +1 -0
  32. package/js/src/base/Exchange.d.ts +2 -0
  33. package/js/src/base/Exchange.js +70 -1
  34. package/js/src/base/types.d.ts +5 -4
  35. package/js/src/binance.js +88 -18
  36. package/js/src/bitmart.js +3 -1
  37. package/js/src/bitstamp.js +24 -36
  38. package/js/src/bybit.js +2 -1
  39. package/js/src/cryptocom.js +3 -2
  40. package/js/src/currencycom.js +1 -2
  41. package/js/src/htx.js +1 -1
  42. package/js/src/mexc.js +88 -1
  43. package/js/src/pro/binance.d.ts +0 -1
  44. package/js/src/pro/binance.js +4 -64
  45. package/js/src/pro/bitget.js +1 -9
  46. package/js/src/pro/bitmex.js +11 -1
  47. package/js/src/pro/bybit.d.ts +1 -2
  48. package/js/src/pro/bybit.js +3 -55
  49. package/js/src/pro/cryptocom.d.ts +7 -2
  50. package/js/src/pro/cryptocom.js +194 -62
  51. package/js/src/pro/gate.js +2 -10
  52. package/js/src/pro/hyperliquid.js +5 -37
  53. package/js/src/pro/kucoin.d.ts +0 -1
  54. package/js/src/pro/kucoin.js +3 -60
  55. package/js/src/pro/kucoinfutures.d.ts +7 -1
  56. package/js/src/pro/kucoinfutures.js +139 -1
  57. package/js/src/pro/mexc.d.ts +3 -1
  58. package/js/src/pro/mexc.js +82 -3
  59. package/js/src/pro/okx.js +15 -40
  60. package/js/src/pro/oxfun.d.ts +3 -0
  61. package/js/src/pro/oxfun.js +75 -0
  62. package/js/src/pro/phemex.d.ts +2 -1
  63. package/js/src/pro/phemex.js +45 -1
  64. package/js/src/pro/woofipro.d.ts +3 -0
  65. package/js/src/pro/woofipro.js +67 -0
  66. package/js/src/xt.js +7 -2
  67. package/package.json +1 -1
@@ -14,7 +14,8 @@ class cryptocom extends cryptocom$1 {
14
14
  'ws': true,
15
15
  'watchBalance': true,
16
16
  'watchTicker': true,
17
- 'watchTickers': false,
17
+ 'watchTickers': true,
18
+ 'watchBidsAsks': true,
18
19
  'watchMyTrades': true,
19
20
  'watchTrades': true,
20
21
  'watchTradesForSymbols': true,
@@ -371,7 +372,7 @@ class cryptocom extends cryptocom$1 {
371
372
  messageHashes.push('unsubscribe:trades:' + market['symbol']);
372
373
  topics.push(currentTopic);
373
374
  }
374
- return await this.unWatchPublicMultiple('trade', symbols, messageHashes, topics, topics, params);
375
+ return await this.unWatchPublicMultiple('trades', symbols, messageHashes, topics, topics, params);
375
376
  }
376
377
  handleTrades(client, message) {
377
378
  //
@@ -477,41 +478,210 @@ class cryptocom extends cryptocom$1 {
477
478
  const messageHash = 'unsubscribe:ticker:' + market['symbol'];
478
479
  return await this.unWatchPublicMultiple('ticker', [market['symbol']], [messageHash], [subMessageHash], [subMessageHash], params);
479
480
  }
481
+ async watchTickers(symbols = undefined, params = {}) {
482
+ /**
483
+ * @method
484
+ * @name cryptocom#watchTickers
485
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
486
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#ticker-instrument_name
487
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
488
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
489
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
490
+ */
491
+ await this.loadMarkets();
492
+ symbols = this.marketSymbols(symbols, undefined, false);
493
+ const messageHashes = [];
494
+ const marketIds = this.marketIds(symbols);
495
+ for (let i = 0; i < marketIds.length; i++) {
496
+ const marketId = marketIds[i];
497
+ messageHashes.push('ticker.' + marketId);
498
+ }
499
+ const url = this.urls['api']['ws']['public'];
500
+ const id = this.nonce();
501
+ const request = {
502
+ 'method': 'subscribe',
503
+ 'params': {
504
+ 'channels': messageHashes,
505
+ },
506
+ 'nonce': id,
507
+ };
508
+ const ticker = await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes);
509
+ if (this.newUpdates) {
510
+ const result = {};
511
+ result[ticker['symbol']] = ticker;
512
+ return result;
513
+ }
514
+ return this.filterByArray(this.tickers, 'symbol', symbols);
515
+ }
516
+ async unWatchTickers(symbols = undefined, params = {}) {
517
+ /**
518
+ * @method
519
+ * @name cryptocom#unWatchTickers
520
+ * @description unWatches a price ticker
521
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#ticker-instrument_name
522
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
523
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
524
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
525
+ */
526
+ await this.loadMarkets();
527
+ symbols = this.marketSymbols(symbols, undefined, false);
528
+ const messageHashes = [];
529
+ const subMessageHashes = [];
530
+ const marketIds = this.marketIds(symbols);
531
+ for (let i = 0; i < marketIds.length; i++) {
532
+ const marketId = marketIds[i];
533
+ const symbol = symbols[i];
534
+ subMessageHashes.push('ticker.' + marketId);
535
+ messageHashes.push('unsubscribe:ticker:' + symbol);
536
+ }
537
+ return await this.unWatchPublicMultiple('ticker', symbols, messageHashes, subMessageHashes, subMessageHashes, params);
538
+ }
480
539
  handleTicker(client, message) {
481
540
  //
482
- // {
483
- // "info":{
484
- // "instrument_name":"BTC_USDT",
485
- // "subscription":"ticker.BTC_USDT",
486
- // "channel":"ticker",
487
- // "data":[
488
- // {
489
- // "i":"BTC_USDT",
490
- // "b":43063.19,
491
- // "k":43063.2,
492
- // "a":43063.19,
493
- // "t":1648121165658,
494
- // "v":43573.912409,
495
- // "h":43498.51,
496
- // "l":41876.58,
497
- // "c":1087.43
498
- // }
499
- // ]
541
+ // {
542
+ // "instrument_name": "ETHUSD-PERP",
543
+ // "subscription": "ticker.ETHUSD-PERP",
544
+ // "channel": "ticker",
545
+ // "data": [
546
+ // {
547
+ // "h": "2400.20",
548
+ // "l": "2277.10",
549
+ // "a": "2335.25",
550
+ // "c": "-0.0022",
551
+ // "b": "2335.10",
552
+ // "bs": "5.4000",
553
+ // "k": "2335.16",
554
+ // "ks": "1.9970",
555
+ // "i": "ETHUSD-PERP",
556
+ // "v": "1305697.6462",
557
+ // "vv": "3058704939.17",
558
+ // "oi": "161646.3614",
559
+ // "t": 1726069647560
560
+ // }
561
+ // ]
500
562
  // }
501
- // }
502
563
  //
564
+ this.handleBidAsk(client, message);
503
565
  const messageHash = this.safeString(message, 'subscription');
504
566
  const marketId = this.safeString(message, 'instrument_name');
505
567
  const market = this.safeMarket(marketId);
506
568
  const data = this.safeValue(message, 'data', []);
507
569
  for (let i = 0; i < data.length; i++) {
508
570
  const ticker = data[i];
509
- const parsed = this.parseTicker(ticker, market);
571
+ const parsed = this.parseWsTicker(ticker, market);
510
572
  const symbol = parsed['symbol'];
511
573
  this.tickers[symbol] = parsed;
512
574
  client.resolve(parsed, messageHash);
513
575
  }
514
576
  }
577
+ parseWsTicker(ticker, market = undefined) {
578
+ //
579
+ // {
580
+ // "h": "2400.20",
581
+ // "l": "2277.10",
582
+ // "a": "2335.25",
583
+ // "c": "-0.0022",
584
+ // "b": "2335.10",
585
+ // "bs": "5.4000",
586
+ // "k": "2335.16",
587
+ // "ks": "1.9970",
588
+ // "i": "ETHUSD-PERP",
589
+ // "v": "1305697.6462",
590
+ // "vv": "3058704939.17",
591
+ // "oi": "161646.3614",
592
+ // "t": 1726069647560
593
+ // }
594
+ //
595
+ const timestamp = this.safeInteger(ticker, 't');
596
+ const marketId = this.safeString(ticker, 'i');
597
+ market = this.safeMarket(marketId, market, '_');
598
+ const quote = this.safeString(market, 'quote');
599
+ const last = this.safeString(ticker, 'a');
600
+ return this.safeTicker({
601
+ 'symbol': market['symbol'],
602
+ 'timestamp': timestamp,
603
+ 'datetime': this.iso8601(timestamp),
604
+ 'high': this.safeNumber(ticker, 'h'),
605
+ 'low': this.safeNumber(ticker, 'l'),
606
+ 'bid': this.safeNumber(ticker, 'b'),
607
+ 'bidVolume': this.safeNumber(ticker, 'bs'),
608
+ 'ask': this.safeNumber(ticker, 'k'),
609
+ 'askVolume': this.safeNumber(ticker, 'ks'),
610
+ 'vwap': undefined,
611
+ 'open': undefined,
612
+ 'close': last,
613
+ 'last': last,
614
+ 'previousClose': undefined,
615
+ 'change': undefined,
616
+ 'percentage': this.safeString(ticker, 'c'),
617
+ 'average': undefined,
618
+ 'baseVolume': this.safeString(ticker, 'v'),
619
+ 'quoteVolume': (quote === 'USD') ? this.safeString(ticker, 'vv') : undefined,
620
+ 'info': ticker,
621
+ }, market);
622
+ }
623
+ async watchBidsAsks(symbols = undefined, params = {}) {
624
+ /**
625
+ * @method
626
+ * @name cryptocom#watchBidsAsks
627
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#ticker-instrument_name
628
+ * @description watches best bid & ask for symbols
629
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
630
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
631
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
632
+ */
633
+ await this.loadMarkets();
634
+ symbols = this.marketSymbols(symbols, undefined, false);
635
+ const messageHashes = [];
636
+ const topics = [];
637
+ const marketIds = this.marketIds(symbols);
638
+ for (let i = 0; i < marketIds.length; i++) {
639
+ const marketId = marketIds[i];
640
+ messageHashes.push('bidask.' + symbols[i]);
641
+ topics.push('ticker.' + marketId);
642
+ }
643
+ const url = this.urls['api']['ws']['public'];
644
+ const id = this.nonce();
645
+ const request = {
646
+ 'method': 'subscribe',
647
+ 'params': {
648
+ 'channels': topics,
649
+ },
650
+ 'nonce': id,
651
+ };
652
+ const newTickers = await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes);
653
+ if (this.newUpdates) {
654
+ const tickers = {};
655
+ tickers[newTickers['symbol']] = newTickers;
656
+ return tickers;
657
+ }
658
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
659
+ }
660
+ handleBidAsk(client, message) {
661
+ const data = this.safeList(message, 'data', []);
662
+ const ticker = this.safeDict(data, 0, {});
663
+ const parsedTicker = this.parseWsBidAsk(ticker);
664
+ const symbol = parsedTicker['symbol'];
665
+ this.bidsasks[symbol] = parsedTicker;
666
+ const messageHash = 'bidask.' + symbol;
667
+ client.resolve(parsedTicker, messageHash);
668
+ }
669
+ parseWsBidAsk(ticker, market = undefined) {
670
+ const marketId = this.safeString(ticker, 'i');
671
+ market = this.safeMarket(marketId, market);
672
+ const symbol = this.safeString(market, 'symbol');
673
+ const timestamp = this.safeInteger(ticker, 't');
674
+ return this.safeTicker({
675
+ 'symbol': symbol,
676
+ 'timestamp': timestamp,
677
+ 'datetime': this.iso8601(timestamp),
678
+ 'ask': this.safeString(ticker, 'k'),
679
+ 'askVolume': this.safeString(ticker, 'ks'),
680
+ 'bid': this.safeString(ticker, 'b'),
681
+ 'bidVolume': this.safeString(ticker, 'bs'),
682
+ 'info': ticker,
683
+ }, market);
684
+ }
515
685
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
516
686
  /**
517
687
  * @method
@@ -1205,50 +1375,12 @@ class cryptocom extends cryptocom$1 {
1205
1375
  for (let j = 0; j < messageHashes.length; j++) {
1206
1376
  const unsubHash = messageHashes[j];
1207
1377
  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);
1378
+ this.cleanUnsubscription(client, subHash, unsubHash);
1217
1379
  }
1218
1380
  this.cleanCache(subscription);
1219
1381
  }
1220
1382
  }
1221
1383
  }
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
- }
1252
1384
  }
1253
1385
 
1254
1386
  module.exports = cryptocom;
@@ -1660,15 +1660,7 @@ class gate extends gate$1 {
1660
1660
  for (let j = 0; j < messageHashes.length; j++) {
1661
1661
  const unsubHash = messageHashes[j];
1662
1662
  const subHash = subMessageHashes[j];
1663
- if (unsubHash in client.subscriptions) {
1664
- delete client.subscriptions[unsubHash];
1665
- }
1666
- if (subHash in client.subscriptions) {
1667
- delete client.subscriptions[subHash];
1668
- }
1669
- const error = new errors.UnsubscribeError(this.id + ' ' + messageHash);
1670
- client.reject(error, subHash);
1671
- client.resolve(true, unsubHash);
1663
+ this.cleanUnsubscription(client, subHash, unsubHash);
1672
1664
  }
1673
1665
  this.cleanCache(subscription);
1674
1666
  }
@@ -841,15 +841,7 @@ class hyperliquid extends hyperliquid$1 {
841
841
  const symbol = this.safeSymbol(marketId);
842
842
  const subMessageHash = 'orderbook:' + symbol;
843
843
  const messageHash = 'unsubscribe:' + subMessageHash;
844
- if (messageHash in client.subscriptions) {
845
- delete client.subscriptions[messageHash];
846
- }
847
- if (subMessageHash in client.subscriptions) {
848
- delete client.subscriptions[subMessageHash];
849
- }
850
- const error = new errors.UnsubscribeError(this.id + ' ' + subMessageHash);
851
- client.reject(error, subMessageHash);
852
- client.resolve(true, messageHash);
844
+ this.cleanUnsubscription(client, subMessageHash, messageHash);
853
845
  if (symbol in this.orderbooks) {
854
846
  delete this.orderbooks[symbol];
855
847
  }
@@ -861,15 +853,7 @@ class hyperliquid extends hyperliquid$1 {
861
853
  const symbol = this.safeSymbol(marketId);
862
854
  const subMessageHash = 'trade:' + symbol;
863
855
  const messageHash = 'unsubscribe:' + subMessageHash;
864
- if (messageHash in client.subscriptions) {
865
- delete client.subscriptions[messageHash];
866
- }
867
- if (subMessageHash in client.subscriptions) {
868
- delete client.subscriptions[subMessageHash];
869
- }
870
- const error = new errors.UnsubscribeError(this.id + ' ' + subMessageHash);
871
- client.reject(error, subMessageHash);
872
- client.resolve(true, messageHash);
856
+ this.cleanUnsubscription(client, subMessageHash, messageHash);
873
857
  if (symbol in this.trades) {
874
858
  delete this.trades[symbol];
875
859
  }
@@ -878,15 +862,7 @@ class hyperliquid extends hyperliquid$1 {
878
862
  //
879
863
  const subMessageHash = 'tickers';
880
864
  const messageHash = 'unsubscribe:' + subMessageHash;
881
- if (messageHash in client.subscriptions) {
882
- delete client.subscriptions[messageHash];
883
- }
884
- if (subMessageHash in client.subscriptions) {
885
- delete client.subscriptions[subMessageHash];
886
- }
887
- const error = new errors.UnsubscribeError(this.id + ' ' + subMessageHash);
888
- client.reject(error, subMessageHash);
889
- client.resolve(true, messageHash);
865
+ this.cleanUnsubscription(client, subMessageHash, messageHash);
890
866
  const symbols = Object.keys(this.tickers);
891
867
  for (let i = 0; i < symbols.length; i++) {
892
868
  delete this.tickers[symbols[i]];
@@ -900,15 +876,7 @@ class hyperliquid extends hyperliquid$1 {
900
876
  const timeframe = this.findTimeframe(interval);
901
877
  const subMessageHash = 'candles:' + timeframe + ':' + symbol;
902
878
  const messageHash = 'unsubscribe:' + subMessageHash;
903
- if (messageHash in client.subscriptions) {
904
- delete client.subscriptions[messageHash];
905
- }
906
- if (subMessageHash in client.subscriptions) {
907
- delete client.subscriptions[subMessageHash];
908
- }
909
- const error = new errors.UnsubscribeError(this.id + ' ' + subMessageHash);
910
- client.reject(error, subMessageHash);
911
- client.resolve(true, messageHash);
879
+ this.cleanUnsubscription(client, subMessageHash, messageHash);
912
880
  if (symbol in this.ohlcvs) {
913
881
  if (timeframe in this.ohlcvs[symbol]) {
914
882
  delete this.ohlcvs[symbol][timeframe];
@@ -535,8 +535,6 @@ class kucoin extends kucoin$1 {
535
535
  * @description unWatches trades stream
536
536
  * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/match-execution-data
537
537
  * @param {string} symbol unified symbol of the market to fetch trades for
538
- * @param {int} [since] timestamp in ms of the earliest trade to fetch
539
- * @param {int} [limit] the maximum amount of trades to fetch
540
538
  * @param {object} [params] extra parameters specific to the exchange API endpoint
541
539
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
542
540
  */
@@ -923,64 +921,9 @@ class kucoin extends kucoin$1 {
923
921
  for (let i = 0; i < messageHashes.length; i++) {
924
922
  const messageHash = messageHashes[i];
925
923
  const subHash = subMessageHashes[i];
926
- if (messageHash in client.subscriptions) {
927
- delete client.subscriptions[messageHash];
928
- }
929
- if (subHash in client.subscriptions) {
930
- delete client.subscriptions[subHash];
931
- }
932
- const error = new errors.UnsubscribeError(this.id + ' ' + subHash);
933
- client.reject(error, subHash);
934
- client.resolve(true, messageHash);
935
- this.cleanCache(subscription);
936
- }
937
- }
938
- }
939
- cleanCache(subscription) {
940
- const topic = this.safeString(subscription, 'topic');
941
- const symbols = this.safeList(subscription, 'symbols', []);
942
- const symbolsLength = symbols.length;
943
- if (symbolsLength > 0) {
944
- for (let i = 0; i < symbols.length; i++) {
945
- const symbol = symbols[i];
946
- if (topic === 'trades') {
947
- if (symbol in this.trades) {
948
- delete this.trades[symbol];
949
- }
950
- }
951
- else if (topic === 'orderbook') {
952
- if (symbol in this.orderbooks) {
953
- delete this.orderbooks[symbol];
954
- }
955
- }
956
- else if (topic === 'ticker') {
957
- if (symbol in this.tickers) {
958
- delete this.tickers[symbol];
959
- }
960
- }
961
- }
962
- }
963
- else {
964
- if (topic === 'myTrades') {
965
- // don't reset this.myTrades directly here
966
- // because in c# we need to use a different object
967
- const keys = Object.keys(this.myTrades);
968
- for (let i = 0; i < keys.length; i++) {
969
- delete this.myTrades[keys[i]];
970
- }
971
- }
972
- else if (topic === 'orders') {
973
- const orderSymbols = Object.keys(this.orders);
974
- for (let i = 0; i < orderSymbols.length; i++) {
975
- delete this.orders[orderSymbols[i]];
976
- }
977
- }
978
- else if (topic === 'ticker') {
979
- const tickerSymbols = Object.keys(this.tickers);
980
- for (let i = 0; i < tickerSymbols.length; i++) {
981
- delete this.tickers[tickerSymbols[i]];
982
- }
924
+ this.cleanUnsubscription(client, subHash, messageHash);
983
925
  }
926
+ this.cleanCache(subscription);
984
927
  }
985
928
  }
986
929
  handleSystemStatus(client, message) {
@@ -175,6 +175,27 @@ class kucoinfutures extends kucoinfutures$1 {
175
175
  };
176
176
  return await this.watchMultiple(url, messageHashes, this.extend(request, params), subscriptionHashes, subscriptionArgs);
177
177
  }
178
+ async unSubscribeMultiple(url, messageHashes, topic, subscriptionHashes, params = {}, subscription = undefined) {
179
+ const requestId = this.requestId().toString();
180
+ const request = {
181
+ 'id': requestId,
182
+ 'type': 'unsubscribe',
183
+ 'topic': topic,
184
+ 'response': true,
185
+ };
186
+ const message = this.extend(request, params);
187
+ if (subscription !== undefined) {
188
+ subscription[requestId] = requestId;
189
+ }
190
+ const client = this.client(url);
191
+ for (let i = 0; i < subscriptionHashes.length; i++) {
192
+ const subscriptionHash = subscriptionHashes[i];
193
+ if (!(subscriptionHash in client.subscriptions)) {
194
+ client.subscriptions[requestId] = subscriptionHash;
195
+ }
196
+ }
197
+ return await this.watchMultiple(url, messageHashes, message, subscriptionHashes, subscription);
198
+ }
178
199
  async watchTicker(symbol, params = {}) {
179
200
  /**
180
201
  * @method
@@ -518,7 +539,7 @@ class kucoinfutures extends kucoinfutures$1 {
518
539
  async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
519
540
  /**
520
541
  * @method
521
- * @name kucoinfutures#watchTrades
542
+ * @name kucoinfutures#watchTradesForSymbols
522
543
  * @description get the list of most recent trades for a particular symbol
523
544
  * @param {string} symbol unified symbol of the market to fetch trades for
524
545
  * @param {int} [since] timestamp in ms of the earliest trade to fetch
@@ -552,6 +573,49 @@ class kucoinfutures extends kucoinfutures$1 {
552
573
  }
553
574
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
554
575
  }
576
+ async unWatchTrades(symbol, params = {}) {
577
+ /**
578
+ * @method
579
+ * @name kucoinfutures#unWatchTrades
580
+ * @description unWatches trades stream
581
+ * @see https://docs.kucoin.com/futures/#execution-data
582
+ * @param {string} symbol unified symbol of the market to fetch trades for
583
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
584
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
585
+ */
586
+ return await this.unWatchTradesForSymbols([symbol], params);
587
+ }
588
+ async unWatchTradesForSymbols(symbols, params = {}) {
589
+ /**
590
+ * @method
591
+ * @name kucoinfutures#unWatchTradesForSymbols
592
+ * @description get the list of most recent trades for a particular symbol
593
+ * @param {string} symbol unified symbol of the market to fetch trades for
594
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
595
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
596
+ */
597
+ await this.loadMarkets();
598
+ symbols = this.marketSymbols(symbols, undefined, false);
599
+ const url = await this.negotiate(false);
600
+ symbols = this.marketSymbols(symbols);
601
+ const marketIds = this.marketIds(symbols);
602
+ const topic = '/contractMarket/execution:' + marketIds.join(',');
603
+ const subscriptionHashes = [];
604
+ const messageHashes = [];
605
+ for (let i = 0; i < symbols.length; i++) {
606
+ const symbol = symbols[i];
607
+ messageHashes.push('unsubscribe:trades:' + symbol);
608
+ subscriptionHashes.push('trades:' + symbol);
609
+ }
610
+ const subscription = {
611
+ 'messageHashes': messageHashes,
612
+ 'subMessageHashes': subscriptionHashes,
613
+ 'topic': 'trades',
614
+ 'unsubscribe': true,
615
+ 'symbols': symbols,
616
+ };
617
+ return await this.unSubscribeMultiple(url, messageHashes, topic, messageHashes, params, subscription);
618
+ }
555
619
  handleTrade(client, message) {
556
620
  //
557
621
  // {
@@ -686,6 +750,7 @@ class kucoinfutures extends kucoinfutures$1 {
686
750
  * @method
687
751
  * @name kucoinfutures#watchOrderBookForSymbols
688
752
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
753
+ * @see https://docs.kucoin.com/futures/#level-2-market-data
689
754
  * @param {string[]} symbols unified array of symbols
690
755
  * @param {int} [limit] the maximum amount of order book entries to return
691
756
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -719,6 +784,48 @@ class kucoinfutures extends kucoinfutures$1 {
719
784
  const orderbook = await this.subscribeMultiple(url, messageHashes, topic, subscriptionHashes, subscriptionArgs, params);
720
785
  return orderbook.limit();
721
786
  }
787
+ async unWatchOrderBook(symbol, params = {}) {
788
+ /**
789
+ * @method
790
+ * @name kucoinfutures#unWatchOrderBook
791
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
792
+ * @see https://docs.kucoin.com/futures/#level-2-market-data
793
+ * @param {string} symbol unified symbol of the market to fetch the order book for
794
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
795
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
796
+ */
797
+ return await this.unWatchOrderBookForSymbols([symbol], params);
798
+ }
799
+ async unWatchOrderBookForSymbols(symbols, params = {}) {
800
+ /**
801
+ * @method
802
+ * @name kucoinfutures#unWatchOrderBookForSymbols
803
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
804
+ * @param {string[]} symbols unified array of symbols
805
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
806
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
807
+ */
808
+ await this.loadMarkets();
809
+ symbols = this.marketSymbols(symbols);
810
+ const marketIds = this.marketIds(symbols);
811
+ const url = await this.negotiate(false);
812
+ const topic = '/contractMarket/level2:' + marketIds.join(',');
813
+ const subscriptionHashes = [];
814
+ const messageHashes = [];
815
+ for (let i = 0; i < symbols.length; i++) {
816
+ const symbol = symbols[i];
817
+ messageHashes.push('unsubscribe:orderbook:' + symbol);
818
+ subscriptionHashes.push('orderbook:' + symbol);
819
+ }
820
+ const subscription = {
821
+ 'messageHashes': messageHashes,
822
+ 'symbols': symbols,
823
+ 'unsubscribe': true,
824
+ 'topic': 'orderbook',
825
+ 'subMessageHashes': subscriptionHashes,
826
+ };
827
+ return await this.unSubscribeMultiple(url, messageHashes, topic, messageHashes, params, subscription);
828
+ }
722
829
  handleDelta(orderbook, delta) {
723
830
  orderbook['nonce'] = this.safeInteger(delta, 'sequence');
724
831
  const timestamp = this.safeInteger(delta, 'timestamp');
@@ -1136,6 +1243,36 @@ class kucoinfutures extends kucoinfutures$1 {
1136
1243
  }
1137
1244
  this.handleErrors(undefined, undefined, client.url, undefined, undefined, data, message, undefined, undefined);
1138
1245
  }
1246
+ handleSubscriptionStatus(client, message) {
1247
+ //
1248
+ // {
1249
+ // "id": "1578090438322",
1250
+ // "type": "ack"
1251
+ // }
1252
+ //
1253
+ const id = this.safeString(message, 'id');
1254
+ if (!(id in client.subscriptions)) {
1255
+ return;
1256
+ }
1257
+ const subscriptionHash = this.safeString(client.subscriptions, id);
1258
+ const subscription = this.safeValue(client.subscriptions, subscriptionHash);
1259
+ delete client.subscriptions[id];
1260
+ const method = this.safeValue(subscription, 'method');
1261
+ if (method !== undefined) {
1262
+ method.call(this, client, message, subscription);
1263
+ }
1264
+ const isUnSub = this.safeBool(subscription, 'unsubscribe', false);
1265
+ if (isUnSub) {
1266
+ const messageHashes = this.safeList(subscription, 'messageHashes', []);
1267
+ const subMessageHashes = this.safeList(subscription, 'subMessageHashes', []);
1268
+ for (let i = 0; i < messageHashes.length; i++) {
1269
+ const messageHash = messageHashes[i];
1270
+ const subHash = subMessageHashes[i];
1271
+ this.cleanUnsubscription(client, subHash, messageHash);
1272
+ }
1273
+ this.cleanCache(subscription);
1274
+ }
1275
+ }
1139
1276
  handleMessage(client, message) {
1140
1277
  const type = this.safeString(message, 'type');
1141
1278
  const methods = {
@@ -1144,6 +1281,7 @@ class kucoinfutures extends kucoinfutures$1 {
1144
1281
  'message': this.handleSubject,
1145
1282
  'pong': this.handlePong,
1146
1283
  'error': this.handleErrorMessage,
1284
+ 'ack': this.handleSubscriptionStatus,
1147
1285
  };
1148
1286
  const method = this.safeValue(methods, type);
1149
1287
  if (method !== undefined) {