ccxt 4.3.96 → 4.3.98

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.
package/dist/cjs/ccxt.js CHANGED
@@ -194,7 +194,7 @@ var xt$1 = require('./src/pro/xt.js');
194
194
 
195
195
  //-----------------------------------------------------------------------------
196
196
  // this is updated by vss.js when building
197
- const version = '4.3.96';
197
+ const version = '4.3.98';
198
198
  Exchange["default"].ccxtVersion = version;
199
199
  const exchanges = {
200
200
  'ace': ace,
@@ -4249,6 +4249,9 @@ class binance extends binance$1 {
4249
4249
  const price = this.safeString(params, 'price');
4250
4250
  const until = this.safeInteger(params, 'until');
4251
4251
  params = this.omit(params, ['price', 'until']);
4252
+ if (since !== undefined && until !== undefined && limit === undefined) {
4253
+ limit = maxLimit;
4254
+ }
4252
4255
  limit = (limit === undefined) ? defaultLimit : Math.min(limit, maxLimit);
4253
4256
  const request = {
4254
4257
  'interval': this.safeString(this.timeframes, timeframe, timeframe),
@@ -1230,6 +1230,8 @@ class bitget extends bitget$1 {
1230
1230
  '40714': errors.ExchangeError,
1231
1231
  '40762': errors.InsufficientFunds,
1232
1232
  '40768': errors.OrderNotFound,
1233
+ '40808': errors.InvalidOrder,
1234
+ '41103': errors.InvalidOrder,
1233
1235
  '41114': errors.OnMaintenance,
1234
1236
  '43011': errors.InvalidOrder,
1235
1237
  '43012': errors.InsufficientFunds,
@@ -1210,7 +1210,10 @@ class coinex extends coinex$1 {
1210
1210
  // "side": "buy",
1211
1211
  // "order_id": 136915589622,
1212
1212
  // "price": "64376",
1213
- // "amount": "0.0001"
1213
+ // "amount": "0.0001",
1214
+ // "role": "taker",
1215
+ // "fee": "0.0299",
1216
+ // "fee_ccy": "USDT"
1214
1217
  // }
1215
1218
  //
1216
1219
  const timestamp = this.safeInteger(trade, 'created_at');
@@ -1220,6 +1223,16 @@ class coinex extends coinex$1 {
1220
1223
  }
1221
1224
  const marketId = this.safeString(trade, 'market');
1222
1225
  market = this.safeMarket(marketId, market, undefined, defaultType);
1226
+ const feeCostString = this.safeString(trade, 'fee');
1227
+ let fee = undefined;
1228
+ if (feeCostString !== undefined) {
1229
+ const feeCurrencyId = this.safeString(trade, 'fee_ccy');
1230
+ const feeCurrencyCode = this.safeCurrencyCode(feeCurrencyId);
1231
+ fee = {
1232
+ 'cost': feeCostString,
1233
+ 'currency': feeCurrencyCode,
1234
+ };
1235
+ }
1223
1236
  return this.safeTrade({
1224
1237
  'info': trade,
1225
1238
  'timestamp': timestamp,
@@ -1229,11 +1242,11 @@ class coinex extends coinex$1 {
1229
1242
  'order': this.safeString(trade, 'order_id'),
1230
1243
  'type': undefined,
1231
1244
  'side': this.safeString(trade, 'side'),
1232
- 'takerOrMaker': undefined,
1245
+ 'takerOrMaker': this.safeString(trade, 'role'),
1233
1246
  'price': this.safeString(trade, 'price'),
1234
1247
  'amount': this.safeString(trade, 'amount'),
1235
1248
  'cost': this.safeString(trade, 'deal_money'),
1236
- 'fee': undefined,
1249
+ 'fee': fee,
1237
1250
  }, market);
1238
1251
  }
1239
1252
  async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
@@ -4017,7 +4017,7 @@ class gate extends gate$1 {
4017
4017
  request['settle'] = market['settleId']; // filled in prepareRequest above
4018
4018
  }
4019
4019
  if (isMarketOrder) {
4020
- request['price'] = price; // set to 0 for market orders
4020
+ request['price'] = '0'; // set to 0 for market orders
4021
4021
  }
4022
4022
  else {
4023
4023
  request['price'] = (price === 0) ? '0' : this.priceToPrecision(symbol, price);
@@ -3828,7 +3828,7 @@ class kucoin extends kucoin$1 {
3828
3828
  params = this.omit(params, 'type');
3829
3829
  let hf = undefined;
3830
3830
  [hf, params] = this.handleHfAndParams(params);
3831
- if (hf) {
3831
+ if (hf && (type !== 'main')) {
3832
3832
  type = 'trade_hf';
3833
3833
  }
3834
3834
  const [marginMode, query] = this.handleMarginModeAndParams('fetchBalance', params);
@@ -385,6 +385,34 @@ class gate extends gate$1 {
385
385
  const orderbook = await this.subscribePublic(url, messageHash, payload, channel, query, subscription);
386
386
  return orderbook.limit();
387
387
  }
388
+ async unWatchOrderBook(symbol, params = {}) {
389
+ /**
390
+ * @method
391
+ * @name gate#unWatchOrderBook
392
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
393
+ * @param {string} symbol unified symbol of the market to fetch the order book for
394
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
395
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
396
+ */
397
+ await this.loadMarkets();
398
+ const market = this.market(symbol);
399
+ symbol = market['symbol'];
400
+ const marketId = market['id'];
401
+ let interval = '100ms';
402
+ [interval, params] = this.handleOptionAndParams(params, 'watchOrderBook', 'interval', interval);
403
+ const messageType = this.getTypeByMarket(market);
404
+ const channel = messageType + '.order_book_update';
405
+ const subMessageHash = 'orderbook' + ':' + symbol;
406
+ const messageHash = 'unsubscribe:orderbook' + ':' + symbol;
407
+ const url = this.getUrlByMarket(market);
408
+ const payload = [marketId, interval];
409
+ const limit = this.safeInteger(params, 'limit', 100);
410
+ if (market['contract']) {
411
+ const stringLimit = limit.toString();
412
+ payload.push(stringLimit);
413
+ }
414
+ return await this.unSubscribePublicMultiple(url, 'orderbook', [symbol], [messageHash], [subMessageHash], payload, channel, params);
415
+ }
388
416
  handleOrderBookSubscription(client, message, subscription) {
389
417
  const symbol = this.safeString(subscription, 'symbol');
390
418
  const limit = this.safeInteger(subscription, 'limit');
@@ -717,6 +745,42 @@ class gate extends gate$1 {
717
745
  }
718
746
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
719
747
  }
748
+ async unWatchTradesForSymbols(symbols, params = {}) {
749
+ /**
750
+ * @method
751
+ * @name gate#unWatchTradesForSymbols
752
+ * @description get the list of most recent trades for a particular symbol
753
+ * @param {string} symbol unified symbol of the market to fetch trades for
754
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
755
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
756
+ */
757
+ await this.loadMarkets();
758
+ symbols = this.marketSymbols(symbols);
759
+ const marketIds = this.marketIds(symbols);
760
+ const market = this.market(symbols[0]);
761
+ const messageType = this.getTypeByMarket(market);
762
+ const channel = messageType + '.trades';
763
+ const subMessageHashes = [];
764
+ const messageHashes = [];
765
+ for (let i = 0; i < symbols.length; i++) {
766
+ const symbol = symbols[i];
767
+ subMessageHashes.push('trades:' + symbol);
768
+ messageHashes.push('unsubscribe:trades:' + symbol);
769
+ }
770
+ const url = this.getUrlByMarket(market);
771
+ return await this.unSubscribePublicMultiple(url, 'trades', symbols, messageHashes, subMessageHashes, marketIds, channel, params);
772
+ }
773
+ async unWatchTrades(symbol, params = {}) {
774
+ /**
775
+ * @method
776
+ * @name gate#unWatchTrades
777
+ * @description get the list of most recent trades for a particular symbol
778
+ * @param {string} symbol unified symbol of the market to fetch trades for
779
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
780
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
781
+ */
782
+ return await this.unWatchTradesForSymbols([symbol], params);
783
+ }
720
784
  handleTrades(client, message) {
721
785
  //
722
786
  // {
@@ -1558,6 +1622,96 @@ class gate extends gate$1 {
1558
1622
  delete client.subscriptions[id];
1559
1623
  }
1560
1624
  }
1625
+ handleUnSubscribe(client, message) {
1626
+ //
1627
+ // {
1628
+ // "time":1725534679,
1629
+ // "time_ms":1725534679786,
1630
+ // "id":2,
1631
+ // "conn_id":"fac539b443fd7002",
1632
+ // "trace_id":"efe1d282b630b4aa266b84bee177791a",
1633
+ // "channel":"spot.trades",
1634
+ // "event":"unsubscribe",
1635
+ // "payload":[
1636
+ // "LTC_USDT"
1637
+ // ],
1638
+ // "result":{
1639
+ // "status":"success"
1640
+ // },
1641
+ // "requestId":"efe1d282b630b4aa266b84bee177791a"
1642
+ // }
1643
+ //
1644
+ const id = this.safeString(message, 'id');
1645
+ const keys = Object.keys(client.subscriptions);
1646
+ for (let i = 0; i < keys.length; i++) {
1647
+ const messageHash = keys[i];
1648
+ if (!(messageHash in client.subscriptions)) {
1649
+ continue;
1650
+ // the previous iteration can have deleted the messageHash from the subscriptions
1651
+ }
1652
+ if (messageHash.startsWith('unsubscribe')) {
1653
+ const subscription = client.subscriptions[messageHash];
1654
+ const subId = this.safeString(subscription, 'id');
1655
+ if (id !== subId) {
1656
+ continue;
1657
+ }
1658
+ const messageHashes = this.safeList(subscription, 'messageHashes', []);
1659
+ const subMessageHashes = this.safeList(subscription, 'subMessageHashes', []);
1660
+ for (let j = 0; j < messageHashes.length; j++) {
1661
+ const unsubHash = messageHashes[j];
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);
1672
+ }
1673
+ this.cleanCache(subscription);
1674
+ }
1675
+ }
1676
+ }
1677
+ cleanCache(subscription) {
1678
+ const topic = this.safeString(subscription, 'topic', '');
1679
+ const symbols = this.safeList(subscription, 'symbols', []);
1680
+ const symbolsLength = symbols.length;
1681
+ if (topic === 'ohlcv') {
1682
+ const symbolsAndTimeFrames = this.safeList(subscription, 'symbolsAndTimeframes', []);
1683
+ for (let i = 0; i < symbolsAndTimeFrames.length; i++) {
1684
+ const symbolAndTimeFrame = symbolsAndTimeFrames[i];
1685
+ const symbol = this.safeString(symbolAndTimeFrame, 0);
1686
+ const timeframe = this.safeString(symbolAndTimeFrame, 1);
1687
+ delete this.ohlcvs[symbol][timeframe];
1688
+ }
1689
+ }
1690
+ else if (symbolsLength > 0) {
1691
+ for (let i = 0; i < symbols.length; i++) {
1692
+ const symbol = symbols[i];
1693
+ if (topic.endsWith('trades')) {
1694
+ delete this.trades[symbol];
1695
+ }
1696
+ else if (topic === 'orderbook') {
1697
+ delete this.orderbooks[symbol];
1698
+ }
1699
+ else if (topic === 'ticker') {
1700
+ delete this.tickers[symbol];
1701
+ }
1702
+ }
1703
+ }
1704
+ else {
1705
+ if (topic.endsWith('trades')) {
1706
+ // don't reset this.myTrades directly here
1707
+ // because in c# we need to use a different object
1708
+ const keys = Object.keys(this.trades);
1709
+ for (let i = 0; i < keys.length; i++) {
1710
+ delete this.trades[keys[i]];
1711
+ }
1712
+ }
1713
+ }
1714
+ }
1561
1715
  handleMessage(client, message) {
1562
1716
  //
1563
1717
  // subscribe
@@ -1656,6 +1810,10 @@ class gate extends gate$1 {
1656
1810
  this.handleSubscriptionStatus(client, message);
1657
1811
  return;
1658
1812
  }
1813
+ if (event === 'unsubscribe') {
1814
+ this.handleUnSubscribe(client, message);
1815
+ return;
1816
+ }
1659
1817
  const channel = this.safeString(message, 'channel', '');
1660
1818
  const channelParts = channel.split('.');
1661
1819
  const channelType = this.safeValue(channelParts, 1);
@@ -1775,6 +1933,27 @@ class gate extends gate$1 {
1775
1933
  const message = this.extend(request, params);
1776
1934
  return await this.watchMultiple(url, messageHashes, message, messageHashes);
1777
1935
  }
1936
+ async unSubscribePublicMultiple(url, topic, symbols, messageHashes, subMessageHashes, payload, channel, params = {}) {
1937
+ const requestId = this.requestId();
1938
+ const time = this.seconds();
1939
+ const request = {
1940
+ 'id': requestId,
1941
+ 'time': time,
1942
+ 'channel': channel,
1943
+ 'event': 'unsubscribe',
1944
+ 'payload': payload,
1945
+ };
1946
+ const sub = {
1947
+ 'id': requestId.toString(),
1948
+ 'topic': topic,
1949
+ 'unsubscribe': true,
1950
+ 'messageHashes': messageHashes,
1951
+ 'subMessageHashes': subMessageHashes,
1952
+ 'symbols': symbols,
1953
+ };
1954
+ const message = this.extend(request, params);
1955
+ return await this.watchMultiple(url, messageHashes, message, messageHashes, sub);
1956
+ }
1778
1957
  async authenticate(url, messageType) {
1779
1958
  const channel = messageType + '.login';
1780
1959
  const client = this.client(url);
@@ -112,7 +112,7 @@ class kraken extends kraken$1 {
112
112
  /**
113
113
  * @method
114
114
  * @name kraken#createOrderWs
115
- * @see https://docs.kraken.com/websockets/#message-addOrder
115
+ * @see https://docs.kraken.com/api/docs/websocket-v1/addorder
116
116
  * @description create a trade order
117
117
  * @param {string} symbol unified symbol of the market to create an order in
118
118
  * @param {string} type 'market' or 'limit'
@@ -169,7 +169,7 @@ class kraken extends kraken$1 {
169
169
  * @method
170
170
  * @name kraken#editOrderWs
171
171
  * @description edit a trade order
172
- * @see https://docs.kraken.com/websockets/#message-editOrder
172
+ * @see https://docs.kraken.com/api/docs/websocket-v1/editorder
173
173
  * @param {string} id order id
174
174
  * @param {string} symbol unified symbol of the market to create an order in
175
175
  * @param {string} type 'market' or 'limit'
@@ -202,7 +202,7 @@ class kraken extends kraken$1 {
202
202
  /**
203
203
  * @method
204
204
  * @name kraken#cancelOrdersWs
205
- * @see https://docs.kraken.com/websockets/#message-cancelOrder
205
+ * @see https://docs.kraken.com/api/docs/websocket-v1/cancelorder
206
206
  * @description cancel multiple orders
207
207
  * @param {string[]} ids order ids
208
208
  * @param {string} symbol unified market symbol, default is undefined
@@ -226,7 +226,7 @@ class kraken extends kraken$1 {
226
226
  /**
227
227
  * @method
228
228
  * @name kraken#cancelOrderWs
229
- * @see https://docs.kraken.com/websockets/#message-cancelOrder
229
+ * @see https://docs.kraken.com/api/docs/websocket-v1/cancelorder
230
230
  * @description cancels an open order
231
231
  * @param {string} id order id
232
232
  * @param {string} symbol unified symbol of the market the order was made in
@@ -264,7 +264,7 @@ class kraken extends kraken$1 {
264
264
  /**
265
265
  * @method
266
266
  * @name kraken#cancelAllOrdersWs
267
- * @see https://docs.kraken.com/websockets/#message-cancelAll
267
+ * @see https://docs.kraken.com/api/docs/websocket-v1/cancelall
268
268
  * @description cancel all open orders
269
269
  * @param {string} symbol unified market symbol, only orders in the market of this symbol are cancelled when symbol is not undefined
270
270
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -466,6 +466,7 @@ class kraken extends kraken$1 {
466
466
  * @method
467
467
  * @name kraken#watchTicker
468
468
  * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
469
+ * @see https://docs.kraken.com/api/docs/websocket-v1/ticker
469
470
  * @param {string} symbol unified symbol of the market to fetch the ticker for
470
471
  * @param {object} [params] extra parameters specific to the exchange API endpoint
471
472
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
@@ -480,6 +481,7 @@ class kraken extends kraken$1 {
480
481
  * @method
481
482
  * @name kraken#watchTickers
482
483
  * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
484
+ * @see https://docs.kraken.com/api/docs/websocket-v1/ticker
483
485
  * @param {string} symbol unified symbol of the market to fetch the ticker for
484
486
  * @param {object} [params] extra parameters specific to the exchange API endpoint
485
487
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
@@ -499,7 +501,7 @@ class kraken extends kraken$1 {
499
501
  * @method
500
502
  * @name kraken#watchTrades
501
503
  * @description get the list of most recent trades for a particular symbol
502
- * @see https://docs.kraken.com/websockets/#message-trade
504
+ * @see https://docs.kraken.com/api/docs/websocket-v1/trade
503
505
  * @param {string} symbol unified symbol of the market to fetch trades for
504
506
  * @param {int} [since] timestamp in ms of the earliest trade to fetch
505
507
  * @param {int} [limit] the maximum amount of trades to fetch
@@ -512,7 +514,7 @@ class kraken extends kraken$1 {
512
514
  /**
513
515
  * @method
514
516
  * @name kraken#watchTradesForSymbols
515
- * @see https://docs.kraken.com/websockets/#message-trade
517
+ * @see https://docs.kraken.com/api/docs/websocket-v1/trade
516
518
  * @description get the list of most recent trades for a list of symbols
517
519
  * @param {string[]} symbols unified symbol of the market to fetch trades for
518
520
  * @param {int} [since] timestamp in ms of the earliest trade to fetch
@@ -533,7 +535,7 @@ class kraken extends kraken$1 {
533
535
  * @method
534
536
  * @name kraken#watchOrderBook
535
537
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
536
- * @see https://docs.kraken.com/websockets/#message-book
538
+ * @see https://docs.kraken.com/api/docs/websocket-v1/book
537
539
  * @param {string} symbol unified symbol of the market to fetch the order book for
538
540
  * @param {int} [limit] the maximum amount of order book entries to return
539
541
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -546,7 +548,7 @@ class kraken extends kraken$1 {
546
548
  * @method
547
549
  * @name kraken#watchOrderBookForSymbols
548
550
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
549
- * @see https://docs.kraken.com/websockets/#message-book
551
+ * @see https://docs.kraken.com/api/docs/websocket-v1/book
550
552
  * @param {string[]} symbols unified array of symbols
551
553
  * @param {int} [limit] the maximum amount of order book entries to return
552
554
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -571,6 +573,7 @@ class kraken extends kraken$1 {
571
573
  * @method
572
574
  * @name kraken#watchOHLCV
573
575
  * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
576
+ * @see https://docs.kraken.com/api/docs/websocket-v1/ohlc
574
577
  * @param {string} symbol unified symbol of the market to fetch OHLCV data for
575
578
  * @param {string} timeframe the length of time each candle represents
576
579
  * @param {int} [since] timestamp in ms of the earliest candle to fetch
@@ -880,6 +883,7 @@ class kraken extends kraken$1 {
880
883
  * @method
881
884
  * @name kraken#watchMyTrades
882
885
  * @description watches information on multiple trades made by the user
886
+ * @see https://docs.kraken.com/api/docs/websocket-v1/owntrades
883
887
  * @param {string} symbol unified market symbol of the market trades were made in
884
888
  * @param {int} [since] the earliest time in ms to fetch trades for
885
889
  * @param {int} [limit] the maximum number of trade structures to retrieve
@@ -1040,7 +1044,7 @@ class kraken extends kraken$1 {
1040
1044
  /**
1041
1045
  * @method
1042
1046
  * @name kraken#watchOrders
1043
- * @see https://docs.kraken.com/websockets/#message-openOrders
1047
+ * @see https://docs.kraken.com/api/docs/websocket-v1/openorders
1044
1048
  * @description watches information on multiple orders made by the user
1045
1049
  * @param {string} symbol unified market symbol of the market orders were made in
1046
1050
  * @param {int} [since] the earliest time in ms to fetch orders for
@@ -154,6 +154,27 @@ class kucoin extends kucoin$1 {
154
154
  }
155
155
  return await this.watchMultiple(url, messageHashes, message, subscriptionHashes, subscription);
156
156
  }
157
+ async unSubscribeMultiple(url, messageHashes, topic, subscriptionHashes, params = {}, subscription = undefined) {
158
+ const requestId = this.requestId().toString();
159
+ const request = {
160
+ 'id': requestId,
161
+ 'type': 'unsubscribe',
162
+ 'topic': topic,
163
+ 'response': true,
164
+ };
165
+ const message = this.extend(request, params);
166
+ if (subscription !== undefined) {
167
+ subscription[requestId] = requestId;
168
+ }
169
+ const client = this.client(url);
170
+ for (let i = 0; i < subscriptionHashes.length; i++) {
171
+ const subscriptionHash = subscriptionHashes[i];
172
+ if (!(subscriptionHash in client.subscriptions)) {
173
+ client.subscriptions[requestId] = subscriptionHash;
174
+ }
175
+ }
176
+ return await this.watchMultiple(url, messageHashes, message, subscriptionHashes, subscription);
177
+ }
157
178
  async watchTicker(symbol, params = {}) {
158
179
  /**
159
180
  * @method
@@ -507,6 +528,51 @@ class kucoin extends kucoin$1 {
507
528
  }
508
529
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
509
530
  }
531
+ async unWatchTradesForSymbols(symbols, params = {}) {
532
+ /**
533
+ * @method
534
+ * @name kucoin#unWatchTradesForSymbols
535
+ * @description unWatches trades stream
536
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/match-execution-data
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
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
541
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
542
+ */
543
+ await this.loadMarkets();
544
+ symbols = this.marketSymbols(symbols, undefined, false);
545
+ const marketIds = this.marketIds(symbols);
546
+ const url = await this.negotiate(false);
547
+ const messageHashes = [];
548
+ const subscriptionHashes = [];
549
+ const topic = '/market/match:' + marketIds.join(',');
550
+ for (let i = 0; i < symbols.length; i++) {
551
+ const symbol = symbols[i];
552
+ messageHashes.push('unsubscribe:trades:' + symbol);
553
+ subscriptionHashes.push('trades:' + symbol);
554
+ }
555
+ const subscription = {
556
+ 'messageHashes': messageHashes,
557
+ 'subMessageHashes': subscriptionHashes,
558
+ 'topic': 'trades',
559
+ 'unsubscribe': true,
560
+ 'symbols': symbols,
561
+ };
562
+ return await this.unSubscribeMultiple(url, messageHashes, topic, messageHashes, params, subscription);
563
+ }
564
+ async unWatchTrades(symbol, params = {}) {
565
+ /**
566
+ * @method
567
+ * @name kucoin#unWatchTrades
568
+ * @description unWatches trades stream
569
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/match-execution-data
570
+ * @param {string} symbol unified symbol of the market to fetch trades for
571
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
572
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
573
+ */
574
+ return await this.unWatchTradesForSymbols([symbol], params);
575
+ }
510
576
  handleTrade(client, message) {
511
577
  //
512
578
  // {
@@ -572,6 +638,22 @@ class kucoin extends kucoin$1 {
572
638
  //
573
639
  return await this.watchOrderBookForSymbols([symbol], limit, params);
574
640
  }
641
+ async unWatchOrderBook(symbol, params = {}) {
642
+ /**
643
+ * @method
644
+ * @name kucoin#unWatchOrderBook
645
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level1-bbo-market-data
646
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-market-data
647
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-5-best-ask-bid-orders
648
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-50-best-ask-bid-orders
649
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
650
+ * @param {string} symbol unified symbol of the market to fetch the order book for
651
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
652
+ * @param {string} [params.method] either '/market/level2' or '/spotMarket/level2Depth5' or '/spotMarket/level2Depth50' default is '/market/level2'
653
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
654
+ */
655
+ return await this.unWatchOrderBookForSymbols([symbol], params);
656
+ }
575
657
  async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
576
658
  /**
577
659
  * @method
@@ -625,6 +707,49 @@ class kucoin extends kucoin$1 {
625
707
  const orderbook = await this.subscribeMultiple(url, messageHashes, topic, subscriptionHashes, params, subscription);
626
708
  return orderbook.limit();
627
709
  }
710
+ async unWatchOrderBookForSymbols(symbols, params = {}) {
711
+ /**
712
+ * @method
713
+ * @name kucoin#unWatchOrderBookForSymbols
714
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level1-bbo-market-data
715
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-market-data
716
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-5-best-ask-bid-orders
717
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level2-50-best-ask-bid-orders
718
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
719
+ * @param {string[]} symbols unified array of symbols
720
+ * @param {int} [limit] the maximum amount of order book entries to return
721
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
722
+ * @param {string} [params.method] either '/market/level2' or '/spotMarket/level2Depth5' or '/spotMarket/level2Depth50' default is '/market/level2'
723
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
724
+ */
725
+ const limit = this.safeInteger(params, 'limit');
726
+ params = this.omit(params, 'limit');
727
+ await this.loadMarkets();
728
+ symbols = this.marketSymbols(symbols, undefined, false);
729
+ const marketIds = this.marketIds(symbols);
730
+ const url = await this.negotiate(false);
731
+ let method = undefined;
732
+ [method, params] = this.handleOptionAndParams(params, 'watchOrderBook', 'method', '/market/level2');
733
+ if ((limit === 5) || (limit === 50)) {
734
+ method = '/spotMarket/level2Depth' + limit.toString();
735
+ }
736
+ const topic = method + ':' + marketIds.join(',');
737
+ const messageHashes = [];
738
+ const subscriptionHashes = [];
739
+ for (let i = 0; i < symbols.length; i++) {
740
+ const symbol = symbols[i];
741
+ messageHashes.push('unsubscribe:orderbook:' + symbol);
742
+ subscriptionHashes.push('orderbook:' + symbol);
743
+ }
744
+ const subscription = {
745
+ 'messageHashes': messageHashes,
746
+ 'symbols': symbols,
747
+ 'unsubscribe': true,
748
+ 'topic': 'orderbook',
749
+ 'subMessageHashes': subscriptionHashes,
750
+ };
751
+ return await this.unSubscribeMultiple(url, messageHashes, topic, messageHashes, params, subscription);
752
+ }
628
753
  handleOrderBook(client, message) {
629
754
  //
630
755
  // initial snapshot is fetched with ccxt's fetchOrderBook
@@ -791,6 +916,72 @@ class kucoin extends kucoin$1 {
791
916
  if (method !== undefined) {
792
917
  method.call(this, client, message, subscription);
793
918
  }
919
+ const isUnSub = this.safeBool(subscription, 'unsubscribe', false);
920
+ if (isUnSub) {
921
+ const messageHashes = this.safeList(subscription, 'messageHashes', []);
922
+ const subMessageHashes = this.safeList(subscription, 'subMessageHashes', []);
923
+ for (let i = 0; i < messageHashes.length; i++) {
924
+ const messageHash = messageHashes[i];
925
+ 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
+ }
983
+ }
984
+ }
794
985
  }
795
986
  handleSystemStatus(client, message) {
796
987
  //