ccxt 4.3.98 → 4.4.2

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 (53) 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 +78 -8
  6. package/dist/cjs/src/bitget.js +3 -2
  7. package/dist/cjs/src/cryptocom.js +1 -1
  8. package/dist/cjs/src/currencycom.js +1 -2
  9. package/dist/cjs/src/gate.js +1 -0
  10. package/dist/cjs/src/htx.js +1 -1
  11. package/dist/cjs/src/mexc.js +69 -1
  12. package/dist/cjs/src/pro/binance.js +3 -63
  13. package/dist/cjs/src/pro/bitget.js +1 -9
  14. package/dist/cjs/src/pro/bitmex.js +11 -1
  15. package/dist/cjs/src/pro/bybit.js +2 -54
  16. package/dist/cjs/src/pro/cryptocom.js +2 -40
  17. package/dist/cjs/src/pro/gate.js +1 -9
  18. package/dist/cjs/src/pro/hyperliquid.js +232 -11
  19. package/dist/cjs/src/pro/kucoin.js +2 -59
  20. package/dist/cjs/src/pro/kucoinfutures.js +139 -1
  21. package/dist/cjs/src/pro/okx.js +8 -36
  22. package/dist/cjs/src/xt.js +1 -1
  23. package/examples/js/cli.js +9 -5
  24. package/js/ccxt.d.ts +3 -3
  25. package/js/ccxt.js +1 -1
  26. package/js/src/base/Exchange.d.ts +2 -0
  27. package/js/src/base/Exchange.js +70 -1
  28. package/js/src/base/types.d.ts +5 -4
  29. package/js/src/binance.js +78 -8
  30. package/js/src/bitget.js +3 -2
  31. package/js/src/cryptocom.js +1 -1
  32. package/js/src/currencycom.js +1 -2
  33. package/js/src/gate.js +1 -0
  34. package/js/src/htx.js +1 -1
  35. package/js/src/mexc.js +69 -1
  36. package/js/src/pro/binance.d.ts +0 -1
  37. package/js/src/pro/binance.js +4 -64
  38. package/js/src/pro/bitget.js +1 -9
  39. package/js/src/pro/bitmex.js +11 -1
  40. package/js/src/pro/bybit.d.ts +1 -2
  41. package/js/src/pro/bybit.js +3 -55
  42. package/js/src/pro/cryptocom.d.ts +1 -2
  43. package/js/src/pro/cryptocom.js +3 -41
  44. package/js/src/pro/gate.js +2 -10
  45. package/js/src/pro/hyperliquid.d.ts +10 -1
  46. package/js/src/pro/hyperliquid.js +232 -11
  47. package/js/src/pro/kucoin.d.ts +0 -1
  48. package/js/src/pro/kucoin.js +3 -60
  49. package/js/src/pro/kucoinfutures.d.ts +7 -1
  50. package/js/src/pro/kucoinfutures.js +139 -1
  51. package/js/src/pro/okx.js +9 -37
  52. package/js/src/xt.js +1 -1
  53. package/package.json +1 -1
@@ -163,6 +163,34 @@ export default class hyperliquid extends hyperliquidRest {
163
163
  const orderbook = await this.watch(url, messageHash, message, messageHash);
164
164
  return orderbook.limit();
165
165
  }
166
+ async unWatchOrderBook(symbol, params = {}) {
167
+ /**
168
+ * @method
169
+ * @name hyperliquid#unWatchOrderBook
170
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
171
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions
172
+ * @param {string} symbol unified symbol of the market to fetch the order book for
173
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
174
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
175
+ */
176
+ await this.loadMarkets();
177
+ const market = this.market(symbol);
178
+ symbol = market['symbol'];
179
+ const subMessageHash = 'orderbook:' + symbol;
180
+ const messageHash = 'unsubscribe:' + subMessageHash;
181
+ const url = this.urls['api']['ws']['public'];
182
+ const id = this.nonce().toString();
183
+ const request = {
184
+ 'id': id,
185
+ 'method': 'unsubscribe',
186
+ 'subscription': {
187
+ 'type': 'l2Book',
188
+ 'coin': market['swap'] ? market['base'] : market['id'],
189
+ },
190
+ };
191
+ const message = this.extend(request, params);
192
+ return await this.watch(url, messageHash, message, messageHash);
193
+ }
166
194
  handleOrderBook(client, message) {
167
195
  //
168
196
  // {
@@ -237,6 +265,30 @@ export default class hyperliquid extends hyperliquidRest {
237
265
  }
238
266
  return this.tickers;
239
267
  }
268
+ async unWatchTickers(symbols = undefined, params = {}) {
269
+ /**
270
+ * @method
271
+ * @name hyperliquid#unWatchTickers
272
+ * @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
273
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions
274
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
275
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
276
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
277
+ */
278
+ await this.loadMarkets();
279
+ symbols = this.marketSymbols(symbols, undefined, true);
280
+ const subMessageHash = 'tickers';
281
+ const messageHash = 'unsubscribe:' + subMessageHash;
282
+ const url = this.urls['api']['ws']['public'];
283
+ const request = {
284
+ 'method': 'unsubscribe',
285
+ 'subscription': {
286
+ 'type': 'webData2',
287
+ 'user': '0x0000000000000000000000000000000000000000',
288
+ },
289
+ };
290
+ return await this.watch(url, messageHash, this.extend(request, params), messageHash);
291
+ }
240
292
  async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
241
293
  /**
242
294
  * @method
@@ -406,17 +458,17 @@ export default class hyperliquid extends hyperliquidRest {
406
458
  client.resolve(trades, messageHash);
407
459
  }
408
460
  async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
409
- /**
410
- * @method
411
- * @name hyperliquid#watchTrades
412
- * @description watches information on multiple trades made in a market
413
- * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions
414
- * @param {string} symbol unified market symbol of the market trades were made in
415
- * @param {int} [since] the earliest time in ms to fetch trades for
416
- * @param {int} [limit] the maximum number of trade structures to retrieve
417
- * @param {object} [params] extra parameters specific to the exchange API endpoint
418
- * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
419
- */
461
+ // s
462
+ // @method
463
+ // @name hyperliquid#watchTrades
464
+ // @description watches information on multiple trades made in a market
465
+ // @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions
466
+ // @param {string} symbol unified market symbol of the market trades were made in
467
+ // @param {int} [since] the earliest time in ms to fetch trades for
468
+ // @param {int} [limit] the maximum number of trade structures to retrieve
469
+ // @param {object} [params] extra parameters specific to the exchange API endpoint
470
+ // @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
471
+ //
420
472
  await this.loadMarkets();
421
473
  const market = this.market(symbol);
422
474
  symbol = market['symbol'];
@@ -436,6 +488,32 @@ export default class hyperliquid extends hyperliquidRest {
436
488
  }
437
489
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
438
490
  }
491
+ async unWatchTrades(symbol, params = {}) {
492
+ /**
493
+ * @method
494
+ * @name hyperliquid#unWatchTrades
495
+ * @description unWatches information on multiple trades made in a market
496
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions
497
+ * @param {string} symbol unified market symbol of the market trades were made in
498
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
499
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
500
+ */
501
+ await this.loadMarkets();
502
+ const market = this.market(symbol);
503
+ symbol = market['symbol'];
504
+ const subMessageHash = 'trade:' + symbol;
505
+ const messageHash = 'unsubscribe:' + subMessageHash;
506
+ const url = this.urls['api']['ws']['public'];
507
+ const request = {
508
+ 'method': 'unsubscribe',
509
+ 'subscription': {
510
+ 'type': 'trades',
511
+ 'coin': market['swap'] ? market['base'] : market['id'],
512
+ },
513
+ };
514
+ const message = this.extend(request, params);
515
+ return await this.watch(url, messageHash, message, messageHash);
516
+ }
439
517
  handleTrades(client, message) {
440
518
  //
441
519
  // {
@@ -569,6 +647,34 @@ export default class hyperliquid extends hyperliquidRest {
569
647
  }
570
648
  return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
571
649
  }
650
+ async unWatchOHLCV(symbol, timeframe = '1m', params = {}) {
651
+ /**
652
+ * @method
653
+ * @name hyperliquid#unWatchOHLCV
654
+ * @description watches historical candlestick data containing the open, high, low, close price, and the volume of a market
655
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions
656
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
657
+ * @param {string} timeframe the length of time each candle represents
658
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
659
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
660
+ */
661
+ await this.loadMarkets();
662
+ const market = this.market(symbol);
663
+ symbol = market['symbol'];
664
+ const url = this.urls['api']['ws']['public'];
665
+ const request = {
666
+ 'method': 'unsubscribe',
667
+ 'subscription': {
668
+ 'type': 'candle',
669
+ 'coin': market['swap'] ? market['base'] : market['id'],
670
+ 'interval': timeframe,
671
+ },
672
+ };
673
+ const subMessageHash = 'candles:' + timeframe + ':' + symbol;
674
+ const messagehash = 'unsubscribe:' + subMessageHash;
675
+ const message = this.extend(request, params);
676
+ return await this.watch(url, messagehash, message, messagehash);
677
+ }
572
678
  handleOHLCV(client, message) {
573
679
  //
574
680
  // {
@@ -724,7 +830,121 @@ export default class hyperliquid extends hyperliquidRest {
724
830
  return false;
725
831
  }
726
832
  }
833
+ handleOrderBookUnsubscription(client, subscription) {
834
+ //
835
+ // "subscription":{
836
+ // "type":"l2Book",
837
+ // "coin":"BTC",
838
+ // "nSigFigs":5,
839
+ // "mantissa":null
840
+ // }
841
+ //
842
+ const coin = this.safeString(subscription, 'coin');
843
+ const marketId = this.coinToMarketId(coin);
844
+ const symbol = this.safeSymbol(marketId);
845
+ const subMessageHash = 'orderbook:' + symbol;
846
+ const messageHash = 'unsubscribe:' + subMessageHash;
847
+ this.cleanUnsubscription(client, subMessageHash, messageHash);
848
+ if (symbol in this.orderbooks) {
849
+ delete this.orderbooks[symbol];
850
+ }
851
+ }
852
+ handleTradesUnsubscription(client, subscription) {
853
+ //
854
+ const coin = this.safeString(subscription, 'coin');
855
+ const marketId = this.coinToMarketId(coin);
856
+ const symbol = this.safeSymbol(marketId);
857
+ const subMessageHash = 'trade:' + symbol;
858
+ const messageHash = 'unsubscribe:' + subMessageHash;
859
+ this.cleanUnsubscription(client, subMessageHash, messageHash);
860
+ if (symbol in this.trades) {
861
+ delete this.trades[symbol];
862
+ }
863
+ }
864
+ handleTickersUnsubscription(client, subscription) {
865
+ //
866
+ const subMessageHash = 'tickers';
867
+ const messageHash = 'unsubscribe:' + subMessageHash;
868
+ this.cleanUnsubscription(client, subMessageHash, messageHash);
869
+ const symbols = Object.keys(this.tickers);
870
+ for (let i = 0; i < symbols.length; i++) {
871
+ delete this.tickers[symbols[i]];
872
+ }
873
+ }
874
+ handleOHLCVUnsubscription(client, subscription) {
875
+ const coin = this.safeString(subscription, 'coin');
876
+ const marketId = this.coinToMarketId(coin);
877
+ const symbol = this.safeSymbol(marketId);
878
+ const interval = this.safeString(subscription, 'interval');
879
+ const timeframe = this.findTimeframe(interval);
880
+ const subMessageHash = 'candles:' + timeframe + ':' + symbol;
881
+ const messageHash = 'unsubscribe:' + subMessageHash;
882
+ this.cleanUnsubscription(client, subMessageHash, messageHash);
883
+ if (symbol in this.ohlcvs) {
884
+ if (timeframe in this.ohlcvs[symbol]) {
885
+ delete this.ohlcvs[symbol][timeframe];
886
+ }
887
+ }
888
+ }
889
+ handleSubscriptionResponse(client, message) {
890
+ // {
891
+ // "channel":"subscriptionResponse",
892
+ // "data":{
893
+ // "method":"unsubscribe",
894
+ // "subscription":{
895
+ // "type":"l2Book",
896
+ // "coin":"BTC",
897
+ // "nSigFigs":5,
898
+ // "mantissa":null
899
+ // }
900
+ // }
901
+ // }
902
+ //
903
+ // {
904
+ // "channel":"subscriptionResponse",
905
+ // "data":{
906
+ // "method":"unsubscribe",
907
+ // "subscription":{
908
+ // "type":"trades",
909
+ // "coin":"PURR/USDC"
910
+ // }
911
+ // }
912
+ // }
913
+ //
914
+ const data = this.safeDict(message, 'data', {});
915
+ const method = this.safeString(data, 'method');
916
+ if (method === 'unsubscribe') {
917
+ const subscription = this.safeDict(data, 'subscription', {});
918
+ const type = this.safeString(subscription, 'type');
919
+ if (type === 'l2Book') {
920
+ this.handleOrderBookUnsubscription(client, subscription);
921
+ }
922
+ else if (type === 'trades') {
923
+ this.handleTradesUnsubscription(client, subscription);
924
+ }
925
+ else if (type === 'webData2') {
926
+ this.handleTickersUnsubscription(client, subscription);
927
+ }
928
+ else if (type === 'candle') {
929
+ this.handleOHLCVUnsubscription(client, subscription);
930
+ }
931
+ }
932
+ }
727
933
  handleMessage(client, message) {
934
+ //
935
+ // {
936
+ // "channel":"subscriptionResponse",
937
+ // "data":{
938
+ // "method":"unsubscribe",
939
+ // "subscription":{
940
+ // "type":"l2Book",
941
+ // "coin":"BTC",
942
+ // "nSigFigs":5,
943
+ // "mantissa":null
944
+ // }
945
+ // }
946
+ // }
947
+ //
728
948
  if (this.handleErrorMessage(client, message)) {
729
949
  return;
730
950
  }
@@ -738,6 +958,7 @@ export default class hyperliquid extends hyperliquidRest {
738
958
  'userFills': this.handleMyTrades,
739
959
  'webData2': this.handleWsTickers,
740
960
  'post': this.handleWsPost,
961
+ 'subscriptionResponse': this.handleSubscriptionResponse,
741
962
  };
742
963
  const exacMethod = this.safeValue(methods, topic);
743
964
  if (exacMethod !== undefined) {
@@ -33,7 +33,6 @@ export default class kucoin extends kucoinRest {
33
33
  handleBidAsks(bookSide: any, bidAsks: any): void;
34
34
  handleOrderBookSubscription(client: Client, message: any, subscription: any): void;
35
35
  handleSubscriptionStatus(client: Client, message: any): void;
36
- cleanCache(subscription: Dict): void;
37
36
  handleSystemStatus(client: Client, message: any): any;
38
37
  watchOrders(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
39
38
  parseWsOrderStatus(status: any): string;
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import kucoinRest from '../kucoin.js';
9
- import { ExchangeError, ArgumentsRequired, UnsubscribeError } from '../base/errors.js';
9
+ import { ExchangeError, ArgumentsRequired } from '../base/errors.js';
10
10
  import { ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById } from '../base/ws/Cache.js';
11
11
  // ---------------------------------------------------------------------------
12
12
  export default class kucoin extends kucoinRest {
@@ -538,8 +538,6 @@ export default class kucoin extends kucoinRest {
538
538
  * @description unWatches trades stream
539
539
  * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/match-execution-data
540
540
  * @param {string} symbol unified symbol of the market to fetch trades for
541
- * @param {int} [since] timestamp in ms of the earliest trade to fetch
542
- * @param {int} [limit] the maximum amount of trades to fetch
543
541
  * @param {object} [params] extra parameters specific to the exchange API endpoint
544
542
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
545
543
  */
@@ -926,64 +924,9 @@ export default class kucoin extends kucoinRest {
926
924
  for (let i = 0; i < messageHashes.length; i++) {
927
925
  const messageHash = messageHashes[i];
928
926
  const subHash = subMessageHashes[i];
929
- if (messageHash in client.subscriptions) {
930
- delete client.subscriptions[messageHash];
931
- }
932
- if (subHash in client.subscriptions) {
933
- delete client.subscriptions[subHash];
934
- }
935
- const error = new UnsubscribeError(this.id + ' ' + subHash);
936
- client.reject(error, subHash);
937
- client.resolve(true, messageHash);
938
- this.cleanCache(subscription);
939
- }
940
- }
941
- }
942
- cleanCache(subscription) {
943
- const topic = this.safeString(subscription, 'topic');
944
- const symbols = this.safeList(subscription, 'symbols', []);
945
- const symbolsLength = symbols.length;
946
- if (symbolsLength > 0) {
947
- for (let i = 0; i < symbols.length; i++) {
948
- const symbol = symbols[i];
949
- if (topic === 'trades') {
950
- if (symbol in this.trades) {
951
- delete this.trades[symbol];
952
- }
953
- }
954
- else if (topic === 'orderbook') {
955
- if (symbol in this.orderbooks) {
956
- delete this.orderbooks[symbol];
957
- }
958
- }
959
- else if (topic === 'ticker') {
960
- if (symbol in this.tickers) {
961
- delete this.tickers[symbol];
962
- }
963
- }
964
- }
965
- }
966
- else {
967
- if (topic === 'myTrades') {
968
- // don't reset this.myTrades directly here
969
- // because in c# we need to use a different object
970
- const keys = Object.keys(this.myTrades);
971
- for (let i = 0; i < keys.length; i++) {
972
- delete this.myTrades[keys[i]];
973
- }
974
- }
975
- else if (topic === 'orders') {
976
- const orderSymbols = Object.keys(this.orders);
977
- for (let i = 0; i < orderSymbols.length; i++) {
978
- delete this.orders[orderSymbols[i]];
979
- }
980
- }
981
- else if (topic === 'ticker') {
982
- const tickerSymbols = Object.keys(this.tickers);
983
- for (let i = 0; i < tickerSymbols.length; i++) {
984
- delete this.tickers[tickerSymbols[i]];
985
- }
927
+ this.cleanUnsubscription(client, subHash, messageHash);
986
928
  }
929
+ this.cleanCache(subscription);
987
930
  }
988
931
  }
989
932
  handleSystemStatus(client, message) {
@@ -1,5 +1,5 @@
1
1
  import kucoinfuturesRest from '../kucoinfutures.js';
2
- import type { Int, Str, OrderBook, Order, Trade, Ticker, Balances, Position, Strings, Tickers, OHLCV } from '../base/types.js';
2
+ import type { Int, Str, OrderBook, Order, Trade, Ticker, Balances, Position, Strings, Tickers, OHLCV, Dict } from '../base/types.js';
3
3
  import Client from '../base/ws/Client.js';
4
4
  export default class kucoinfutures extends kucoinfuturesRest {
5
5
  describe(): any;
@@ -8,6 +8,7 @@ export default class kucoinfutures extends kucoinfuturesRest {
8
8
  requestId(): any;
9
9
  subscribe(url: any, messageHash: any, subscriptionHash: any, subscription: any, params?: {}): Promise<any>;
10
10
  subscribeMultiple(url: any, messageHashes: any, topic: any, subscriptionHashes: any, subscriptionArgs: any, params?: {}): Promise<any>;
11
+ unSubscribeMultiple(url: any, messageHashes: any, topic: any, subscriptionHashes: any, params?: {}, subscription?: Dict): Promise<any>;
11
12
  watchTicker(symbol: string, params?: {}): Promise<Ticker>;
12
13
  watchTickers(symbols?: Strings, params?: {}): Promise<Tickers>;
13
14
  handleTicker(client: Client, message: any): void;
@@ -22,11 +23,15 @@ export default class kucoinfutures extends kucoinfuturesRest {
22
23
  handlePosition(client: Client, message: any): void;
23
24
  watchTrades(symbol: string, since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
24
25
  watchTradesForSymbols(symbols: string[], since?: Int, limit?: Int, params?: {}): Promise<Trade[]>;
26
+ unWatchTrades(symbol: string, params?: {}): Promise<any>;
27
+ unWatchTradesForSymbols(symbols: string[], params?: {}): Promise<any>;
25
28
  handleTrade(client: Client, message: any): any;
26
29
  watchOHLCV(symbol: string, timeframe?: string, since?: Int, limit?: Int, params?: {}): Promise<OHLCV[]>;
27
30
  handleOHLCV(client: Client, message: any): void;
28
31
  watchOrderBook(symbol: string, limit?: Int, params?: {}): Promise<OrderBook>;
29
32
  watchOrderBookForSymbols(symbols: string[], limit?: Int, params?: {}): Promise<OrderBook>;
33
+ unWatchOrderBook(symbol: string, params?: {}): Promise<any>;
34
+ unWatchOrderBookForSymbols(symbols: string[], params?: {}): Promise<any>;
30
35
  handleDelta(orderbook: any, delta: any): void;
31
36
  handleDeltas(bookside: any, deltas: any): void;
32
37
  handleOrderBook(client: Client, message: any): void;
@@ -48,5 +53,6 @@ export default class kucoinfutures extends kucoinfuturesRest {
48
53
  };
49
54
  handlePong(client: Client, message: any): any;
50
55
  handleErrorMessage(client: Client, message: any): void;
56
+ handleSubscriptionStatus(client: Client, message: any): void;
51
57
  handleMessage(client: Client, message: any): void;
52
58
  }
@@ -178,6 +178,27 @@ export default class kucoinfutures extends kucoinfuturesRest {
178
178
  };
179
179
  return await this.watchMultiple(url, messageHashes, this.extend(request, params), subscriptionHashes, subscriptionArgs);
180
180
  }
181
+ async unSubscribeMultiple(url, messageHashes, topic, subscriptionHashes, params = {}, subscription = undefined) {
182
+ const requestId = this.requestId().toString();
183
+ const request = {
184
+ 'id': requestId,
185
+ 'type': 'unsubscribe',
186
+ 'topic': topic,
187
+ 'response': true,
188
+ };
189
+ const message = this.extend(request, params);
190
+ if (subscription !== undefined) {
191
+ subscription[requestId] = requestId;
192
+ }
193
+ const client = this.client(url);
194
+ for (let i = 0; i < subscriptionHashes.length; i++) {
195
+ const subscriptionHash = subscriptionHashes[i];
196
+ if (!(subscriptionHash in client.subscriptions)) {
197
+ client.subscriptions[requestId] = subscriptionHash;
198
+ }
199
+ }
200
+ return await this.watchMultiple(url, messageHashes, message, subscriptionHashes, subscription);
201
+ }
181
202
  async watchTicker(symbol, params = {}) {
182
203
  /**
183
204
  * @method
@@ -521,7 +542,7 @@ export default class kucoinfutures extends kucoinfuturesRest {
521
542
  async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
522
543
  /**
523
544
  * @method
524
- * @name kucoinfutures#watchTrades
545
+ * @name kucoinfutures#watchTradesForSymbols
525
546
  * @description get the list of most recent trades for a particular symbol
526
547
  * @param {string} symbol unified symbol of the market to fetch trades for
527
548
  * @param {int} [since] timestamp in ms of the earliest trade to fetch
@@ -555,6 +576,49 @@ export default class kucoinfutures extends kucoinfuturesRest {
555
576
  }
556
577
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
557
578
  }
579
+ async unWatchTrades(symbol, params = {}) {
580
+ /**
581
+ * @method
582
+ * @name kucoinfutures#unWatchTrades
583
+ * @description unWatches trades stream
584
+ * @see https://docs.kucoin.com/futures/#execution-data
585
+ * @param {string} symbol unified symbol of the market to fetch trades for
586
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
587
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
588
+ */
589
+ return await this.unWatchTradesForSymbols([symbol], params);
590
+ }
591
+ async unWatchTradesForSymbols(symbols, params = {}) {
592
+ /**
593
+ * @method
594
+ * @name kucoinfutures#unWatchTradesForSymbols
595
+ * @description get the list of most recent trades for a particular symbol
596
+ * @param {string} symbol unified symbol of the market to fetch trades for
597
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
598
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
599
+ */
600
+ await this.loadMarkets();
601
+ symbols = this.marketSymbols(symbols, undefined, false);
602
+ const url = await this.negotiate(false);
603
+ symbols = this.marketSymbols(symbols);
604
+ const marketIds = this.marketIds(symbols);
605
+ const topic = '/contractMarket/execution:' + marketIds.join(',');
606
+ const subscriptionHashes = [];
607
+ const messageHashes = [];
608
+ for (let i = 0; i < symbols.length; i++) {
609
+ const symbol = symbols[i];
610
+ messageHashes.push('unsubscribe:trades:' + symbol);
611
+ subscriptionHashes.push('trades:' + symbol);
612
+ }
613
+ const subscription = {
614
+ 'messageHashes': messageHashes,
615
+ 'subMessageHashes': subscriptionHashes,
616
+ 'topic': 'trades',
617
+ 'unsubscribe': true,
618
+ 'symbols': symbols,
619
+ };
620
+ return await this.unSubscribeMultiple(url, messageHashes, topic, messageHashes, params, subscription);
621
+ }
558
622
  handleTrade(client, message) {
559
623
  //
560
624
  // {
@@ -689,6 +753,7 @@ export default class kucoinfutures extends kucoinfuturesRest {
689
753
  * @method
690
754
  * @name kucoinfutures#watchOrderBookForSymbols
691
755
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
756
+ * @see https://docs.kucoin.com/futures/#level-2-market-data
692
757
  * @param {string[]} symbols unified array of symbols
693
758
  * @param {int} [limit] the maximum amount of order book entries to return
694
759
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -722,6 +787,48 @@ export default class kucoinfutures extends kucoinfuturesRest {
722
787
  const orderbook = await this.subscribeMultiple(url, messageHashes, topic, subscriptionHashes, subscriptionArgs, params);
723
788
  return orderbook.limit();
724
789
  }
790
+ async unWatchOrderBook(symbol, params = {}) {
791
+ /**
792
+ * @method
793
+ * @name kucoinfutures#unWatchOrderBook
794
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
795
+ * @see https://docs.kucoin.com/futures/#level-2-market-data
796
+ * @param {string} symbol unified symbol of the market to fetch the order book for
797
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
798
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
799
+ */
800
+ return await this.unWatchOrderBookForSymbols([symbol], params);
801
+ }
802
+ async unWatchOrderBookForSymbols(symbols, params = {}) {
803
+ /**
804
+ * @method
805
+ * @name kucoinfutures#unWatchOrderBookForSymbols
806
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
807
+ * @param {string[]} symbols unified array of symbols
808
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
809
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
810
+ */
811
+ await this.loadMarkets();
812
+ symbols = this.marketSymbols(symbols);
813
+ const marketIds = this.marketIds(symbols);
814
+ const url = await this.negotiate(false);
815
+ const topic = '/contractMarket/level2:' + marketIds.join(',');
816
+ const subscriptionHashes = [];
817
+ const messageHashes = [];
818
+ for (let i = 0; i < symbols.length; i++) {
819
+ const symbol = symbols[i];
820
+ messageHashes.push('unsubscribe:orderbook:' + symbol);
821
+ subscriptionHashes.push('orderbook:' + symbol);
822
+ }
823
+ const subscription = {
824
+ 'messageHashes': messageHashes,
825
+ 'symbols': symbols,
826
+ 'unsubscribe': true,
827
+ 'topic': 'orderbook',
828
+ 'subMessageHashes': subscriptionHashes,
829
+ };
830
+ return await this.unSubscribeMultiple(url, messageHashes, topic, messageHashes, params, subscription);
831
+ }
725
832
  handleDelta(orderbook, delta) {
726
833
  orderbook['nonce'] = this.safeInteger(delta, 'sequence');
727
834
  const timestamp = this.safeInteger(delta, 'timestamp');
@@ -1139,6 +1246,36 @@ export default class kucoinfutures extends kucoinfuturesRest {
1139
1246
  }
1140
1247
  this.handleErrors(undefined, undefined, client.url, undefined, undefined, data, message, undefined, undefined);
1141
1248
  }
1249
+ handleSubscriptionStatus(client, message) {
1250
+ //
1251
+ // {
1252
+ // "id": "1578090438322",
1253
+ // "type": "ack"
1254
+ // }
1255
+ //
1256
+ const id = this.safeString(message, 'id');
1257
+ if (!(id in client.subscriptions)) {
1258
+ return;
1259
+ }
1260
+ const subscriptionHash = this.safeString(client.subscriptions, id);
1261
+ const subscription = this.safeValue(client.subscriptions, subscriptionHash);
1262
+ delete client.subscriptions[id];
1263
+ const method = this.safeValue(subscription, 'method');
1264
+ if (method !== undefined) {
1265
+ method.call(this, client, message, subscription);
1266
+ }
1267
+ const isUnSub = this.safeBool(subscription, 'unsubscribe', false);
1268
+ if (isUnSub) {
1269
+ const messageHashes = this.safeList(subscription, 'messageHashes', []);
1270
+ const subMessageHashes = this.safeList(subscription, 'subMessageHashes', []);
1271
+ for (let i = 0; i < messageHashes.length; i++) {
1272
+ const messageHash = messageHashes[i];
1273
+ const subHash = subMessageHashes[i];
1274
+ this.cleanUnsubscription(client, subHash, messageHash);
1275
+ }
1276
+ this.cleanCache(subscription);
1277
+ }
1278
+ }
1142
1279
  handleMessage(client, message) {
1143
1280
  const type = this.safeString(message, 'type');
1144
1281
  const methods = {
@@ -1147,6 +1284,7 @@ export default class kucoinfutures extends kucoinfuturesRest {
1147
1284
  'message': this.handleSubject,
1148
1285
  'pong': this.handlePong,
1149
1286
  'error': this.handleErrorMessage,
1287
+ 'ack': this.handleSubscriptionStatus,
1150
1288
  };
1151
1289
  const method = this.safeValue(methods, type);
1152
1290
  if (method !== undefined) {