ccxt 4.3.86 → 4.3.87

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 (41) hide show
  1. package/README.md +6 -5
  2. package/dist/ccxt.browser.min.js +3 -3
  3. package/dist/cjs/ccxt.js +2 -1
  4. package/dist/cjs/src/base/errors.js +8 -1
  5. package/dist/cjs/src/bingx.js +7 -1
  6. package/dist/cjs/src/hashkey.js +3 -4
  7. package/dist/cjs/src/kraken.js +37 -6
  8. package/dist/cjs/src/pro/bitget.js +164 -19
  9. package/dist/cjs/src/pro/p2b.js +34 -7
  10. package/dist/cjs/src/pro/poloniex.js +36 -3
  11. package/dist/cjs/src/pro/poloniexfutures.js +1 -0
  12. package/dist/cjs/src/pro/probit.js +2 -0
  13. package/dist/cjs/src/pro/upbit.js +48 -3
  14. package/dist/cjs/src/pro/vertex.js +1 -0
  15. package/dist/cjs/src/pro/wazirx.js +3 -0
  16. package/dist/cjs/src/pro/whitebit.js +9 -0
  17. package/dist/cjs/src/upbit.js +1 -1
  18. package/js/ccxt.d.ts +3 -3
  19. package/js/ccxt.js +3 -3
  20. package/js/src/base/errorHierarchy.d.ts +1 -0
  21. package/js/src/base/errorHierarchy.js +1 -0
  22. package/js/src/base/errors.d.ts +5 -1
  23. package/js/src/base/errors.js +8 -2
  24. package/js/src/bingx.js +7 -1
  25. package/js/src/hashkey.js +3 -4
  26. package/js/src/kraken.js +37 -6
  27. package/js/src/pro/bitget.d.ts +8 -0
  28. package/js/src/pro/bitget.js +165 -20
  29. package/js/src/pro/p2b.d.ts +1 -0
  30. package/js/src/pro/p2b.js +34 -7
  31. package/js/src/pro/poloniex.d.ts +1 -0
  32. package/js/src/pro/poloniex.js +36 -3
  33. package/js/src/pro/poloniexfutures.js +1 -0
  34. package/js/src/pro/probit.js +2 -0
  35. package/js/src/pro/upbit.d.ts +1 -0
  36. package/js/src/pro/upbit.js +48 -3
  37. package/js/src/pro/vertex.js +1 -0
  38. package/js/src/pro/wazirx.js +3 -0
  39. package/js/src/pro/whitebit.js +9 -0
  40. package/js/src/upbit.js +1 -1
  41. package/package.json +1 -1
package/dist/cjs/ccxt.js CHANGED
@@ -196,7 +196,7 @@ var xt$1 = require('./src/pro/xt.js');
196
196
 
197
197
  //-----------------------------------------------------------------------------
198
198
  // this is updated by vss.js when building
199
- const version = '4.3.86';
199
+ const version = '4.3.87';
200
200
  Exchange["default"].ccxtVersion = version;
201
201
  const exchanges = {
202
202
  'ace': ace,
@@ -431,6 +431,7 @@ exports.OrderNotFound = errors.OrderNotFound;
431
431
  exports.PermissionDenied = errors.PermissionDenied;
432
432
  exports.RateLimitExceeded = errors.RateLimitExceeded;
433
433
  exports.RequestTimeout = errors.RequestTimeout;
434
+ exports.UnsubscribeError = errors.UnsubscribeError;
434
435
  exports.errors = errors;
435
436
  exports.ace = ace;
436
437
  exports.alpaca = alpaca;
@@ -237,7 +237,13 @@ class CancelPending extends OperationFailed {
237
237
  this.name = 'CancelPending';
238
238
  }
239
239
  }
240
- var errors = { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, MarketClosed, ManualInteractionNeeded, InsufficientFunds, InvalidAddress, AddressPending, InvalidOrder, OrderNotFound, OrderNotCached, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, ContractUnavailable, NotSupported, InvalidProxySettings, ExchangeClosedByUser, OperationFailed, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, ChecksumError, RequestTimeout, BadResponse, NullResponse, CancelPending };
240
+ class UnsubscribeError extends BaseError {
241
+ constructor(message) {
242
+ super(message);
243
+ this.name = 'UnsubscribeError';
244
+ }
245
+ }
246
+ var errors = { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, MarketClosed, ManualInteractionNeeded, InsufficientFunds, InvalidAddress, AddressPending, InvalidOrder, OrderNotFound, OrderNotCached, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, ContractUnavailable, NotSupported, InvalidProxySettings, ExchangeClosedByUser, OperationFailed, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, ChecksumError, RequestTimeout, BadResponse, NullResponse, CancelPending, UnsubscribeError };
241
247
 
242
248
  exports.AccountNotEnabled = AccountNotEnabled;
243
249
  exports.AccountSuspended = AccountSuspended;
@@ -278,4 +284,5 @@ exports.OrderNotFound = OrderNotFound;
278
284
  exports.PermissionDenied = PermissionDenied;
279
285
  exports.RateLimitExceeded = RateLimitExceeded;
280
286
  exports.RequestTimeout = RequestTimeout;
287
+ exports.UnsubscribeError = UnsubscribeError;
281
288
  exports["default"] = errors;
@@ -747,7 +747,13 @@ class bingx extends bingx$1 {
747
747
  }
748
748
  const fees = this.safeDict(this.fees, type, {});
749
749
  const contractSize = (swap) ? this.parseNumber('1') : undefined;
750
- const isActive = this.safeString(market, 'status') === '1';
750
+ let isActive = false;
751
+ if ((this.safeString(market, 'apiStateOpen') === 'true') && (this.safeString(market, 'apiStateClose') === 'true')) {
752
+ isActive = true; // swap active
753
+ }
754
+ else if (this.safeBool(market, 'apiStateSell') && this.safeBool(market, 'apiStateBuy')) {
755
+ isActive = true; // spot active
756
+ }
751
757
  const isInverse = (spot) ? undefined : checkIsInverse;
752
758
  const isLinear = (spot) ? undefined : checkIsLinear;
753
759
  let timeOnline = this.safeInteger(market, 'timeOnline');
@@ -22,7 +22,6 @@ class hashkey extends hashkey$1 {
22
22
  'version': 'v1',
23
23
  'certified': true,
24
24
  'pro': true,
25
- 'hostname': '/api-glb',
26
25
  'has': {
27
26
  'CORS': undefined,
28
27
  'spot': true,
@@ -143,7 +142,7 @@ class hashkey extends hashkey$1 {
143
142
  'www': 'https://global.hashkey.com/',
144
143
  'doc': 'https://hashkeyglobal-apidoc.readme.io/',
145
144
  'fees': 'https://support.global.hashkey.com/hc/en-us/articles/13199900083612-HashKey-Global-Fee-Structure',
146
- 'referral': '',
145
+ 'referral': 'https://global.hashkey.com/en-US/register/invite?invite_code=82FQUN',
147
146
  },
148
147
  'api': {
149
148
  'public': {
@@ -2383,7 +2382,7 @@ class hashkey extends hashkey$1 {
2383
2382
  async createMarketBuyOrderWithCost(symbol, cost, params = {}) {
2384
2383
  /**
2385
2384
  * @method
2386
- * @name createMarketBuyOrderWithCost
2385
+ * @name hashkey#createMarketBuyOrderWithCost
2387
2386
  * @description create a market buy order by providing the symbol and cost
2388
2387
  * @param {string} symbol unified symbol of the market to create an order in
2389
2388
  * @param {float} cost how much you want to trade in units of the quote currency
@@ -4172,7 +4171,7 @@ class hashkey extends hashkey$1 {
4172
4171
  async fetchTradingFees(params = {}) {
4173
4172
  /**
4174
4173
  * @method
4175
- * @name binance#fetchTradingFees
4174
+ * @name hashkey#fetchTradingFees
4176
4175
  * @description *for spot markets only* fetch the trading fees for multiple markets
4177
4176
  * @see https://developers.binance.com/docs/wallet/asset/trade-fee
4178
4177
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -1109,11 +1109,12 @@ class kraken extends kraken$1 {
1109
1109
  * @param {int} [limit] max number of ledger entrys to return, default is undefined
1110
1110
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1111
1111
  * @param {int} [params.until] timestamp in ms of the latest ledger entry
1112
+ * @param {int} [params.end] timestamp in seconds of the latest ledger entry
1112
1113
  * @returns {object} a [ledger structure]{@link https://docs.ccxt.com/#/?id=ledger-structure}
1113
1114
  */
1114
1115
  // https://www.kraken.com/features/api#get-ledgers-info
1115
1116
  await this.loadMarkets();
1116
- let request = {};
1117
+ const request = {};
1117
1118
  let currency = undefined;
1118
1119
  if (code !== undefined) {
1119
1120
  currency = this.currency(code);
@@ -1122,7 +1123,12 @@ class kraken extends kraken$1 {
1122
1123
  if (since !== undefined) {
1123
1124
  request['start'] = this.parseToInt(since / 1000);
1124
1125
  }
1125
- [request, params] = this.handleUntilOption('end', request, params);
1126
+ const until = this.safeStringN(params, ['until', 'till']);
1127
+ if (until !== undefined) {
1128
+ params = this.omit(params, ['until', 'till']);
1129
+ const untilDivided = Precise["default"].stringDiv(until, '1000');
1130
+ request['end'] = this.parseToInt(Precise["default"].stringAdd(untilDivided, '1'));
1131
+ }
1126
1132
  const response = await this.privatePostLedgers(this.extend(request, params));
1127
1133
  // { error: [],
1128
1134
  // "result": { ledger: { 'LPUAIB-TS774-UKHP7X': { refid: "A2B4HBV-L4MDIE-JU4N3N",
@@ -2122,6 +2128,8 @@ class kraken extends kraken$1 {
2122
2128
  * @param {int} [since] the earliest time in ms to fetch trades for
2123
2129
  * @param {int} [limit] the maximum number of trades structures to retrieve
2124
2130
  * @param {object} [params] extra parameters specific to the exchange API endpoint
2131
+ * @param {int} [params.until] timestamp in ms of the latest trade entry
2132
+ * @param {int} [params.end] timestamp in seconds of the latest trade entry
2125
2133
  * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
2126
2134
  */
2127
2135
  await this.loadMarkets();
@@ -2135,6 +2143,12 @@ class kraken extends kraken$1 {
2135
2143
  if (since !== undefined) {
2136
2144
  request['start'] = this.parseToInt(since / 1000);
2137
2145
  }
2146
+ const until = this.safeStringN(params, ['until', 'till']);
2147
+ if (until !== undefined) {
2148
+ params = this.omit(params, ['until', 'till']);
2149
+ const untilDivided = Precise["default"].stringDiv(until, '1000');
2150
+ request['end'] = this.parseToInt(Precise["default"].stringAdd(untilDivided, '1'));
2151
+ }
2138
2152
  const response = await this.privatePostTradesHistory(this.extend(request, params));
2139
2153
  //
2140
2154
  // {
@@ -2550,6 +2564,8 @@ class kraken extends kraken$1 {
2550
2564
  * @param {int} [since] the earliest time in ms to fetch deposits for
2551
2565
  * @param {int} [limit] the maximum number of deposits structures to retrieve
2552
2566
  * @param {object} [params] extra parameters specific to the exchange API endpoint
2567
+ * @param {int} [params.until] timestamp in ms of the latest transaction entry
2568
+ * @param {int} [params.end] timestamp in seconds of the latest transaction entry
2553
2569
  * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2554
2570
  */
2555
2571
  // https://www.kraken.com/en-us/help/api#deposit-status
@@ -2560,7 +2576,14 @@ class kraken extends kraken$1 {
2560
2576
  request['asset'] = currency['id'];
2561
2577
  }
2562
2578
  if (since !== undefined) {
2563
- request['start'] = since;
2579
+ const sinceString = this.numberToString(since);
2580
+ request['start'] = Precise["default"].stringDiv(sinceString, '1000');
2581
+ }
2582
+ const until = this.safeStringN(params, ['until', 'till']);
2583
+ if (until !== undefined) {
2584
+ params = this.omit(params, ['until', 'till']);
2585
+ const untilDivided = Precise["default"].stringDiv(until, '1000');
2586
+ request['end'] = Precise["default"].stringAdd(untilDivided, '1');
2564
2587
  }
2565
2588
  const response = await this.privatePostDepositStatus(this.extend(request, params));
2566
2589
  //
@@ -2611,8 +2634,9 @@ class kraken extends kraken$1 {
2611
2634
  * @param {int} [since] the earliest time in ms to fetch withdrawals for
2612
2635
  * @param {int} [limit] the maximum number of withdrawals structures to retrieve
2613
2636
  * @param {object} [params] extra parameters specific to the exchange API endpoint
2614
- * @param {object} [params.end] End timestamp, withdrawals created strictly after will be not be included in the response
2615
- * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times
2637
+ * @param {int} [params.until] timestamp in ms of the latest transaction entry
2638
+ * @param {int} [params.end] timestamp in seconds of the latest transaction entry
2639
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times
2616
2640
  * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2617
2641
  */
2618
2642
  await this.loadMarkets();
@@ -2628,7 +2652,14 @@ class kraken extends kraken$1 {
2628
2652
  request['asset'] = currency['id'];
2629
2653
  }
2630
2654
  if (since !== undefined) {
2631
- request['since'] = since.toString();
2655
+ const sinceString = this.numberToString(since);
2656
+ request['start'] = Precise["default"].stringDiv(sinceString, '1000');
2657
+ }
2658
+ const until = this.safeStringN(params, ['until', 'till']);
2659
+ if (until !== undefined) {
2660
+ params = this.omit(params, ['until', 'till']);
2661
+ const untilDivided = Precise["default"].stringDiv(until, '1000');
2662
+ request['end'] = Precise["default"].stringAdd(untilDivided, '1');
2632
2663
  }
2633
2664
  const response = await this.privatePostWithdrawStatus(this.extend(request, params));
2634
2665
  //
@@ -131,6 +131,19 @@ class bitget extends bitget$1 {
131
131
  };
132
132
  return await this.watchPublic(messageHash, args, params);
133
133
  }
134
+ async unWatchTicker(symbol, params = {}) {
135
+ /**
136
+ * @method
137
+ * @name bitget#unWatchTicker
138
+ * @description unsubscribe from the ticker channel
139
+ * @see https://www.bitget.com/api-doc/spot/websocket/public/Tickers-Channel
140
+ * @see https://www.bitget.com/api-doc/contract/websocket/public/Tickers-Channel
141
+ * @param {string} symbol unified symbol of the market to unwatch the ticker for
142
+ * @returns {any} status of the unwatch request
143
+ */
144
+ await this.loadMarkets();
145
+ return await this.unWatchChannel(symbol, 'ticker', 'ticker', params);
146
+ }
134
147
  async watchTickers(symbols = undefined, params = {}) {
135
148
  /**
136
149
  * @method
@@ -343,6 +356,22 @@ class bitget extends bitget$1 {
343
356
  }
344
357
  return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
345
358
  }
359
+ async unWatchOHLCV(symbol, timeframe = '1m', params = {}) {
360
+ /**
361
+ * @method
362
+ * @name bitget#unWatchOHLCV
363
+ * @description unsubscribe from the ohlcv channel
364
+ * @see https://www.bitget.com/api-doc/spot/websocket/public/Candlesticks-Channel
365
+ * @see https://www.bitget.com/api-doc/contract/websocket/public/Candlesticks-Channel
366
+ * @param {string} symbol unified symbol of the market to unwatch the ohlcv for
367
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
368
+ */
369
+ await this.loadMarkets();
370
+ const timeframes = this.safeDict(this.options, 'timeframes');
371
+ const interval = this.safeString(timeframes, timeframe);
372
+ const channel = 'candle' + interval;
373
+ return await this.unWatchChannel(symbol, channel, 'candles:' + timeframe, params);
374
+ }
346
375
  handleOHLCV(client, message) {
347
376
  //
348
377
  // {
@@ -451,14 +480,18 @@ class bitget extends bitget$1 {
451
480
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
452
481
  */
453
482
  await this.loadMarkets();
454
- const market = this.market(symbol);
455
- const messageHash = 'unsubscribe:orderbook:' + market['symbol'];
456
483
  let channel = 'books';
457
484
  const limit = this.safeInteger(params, 'limit');
458
485
  if ((limit === 1) || (limit === 5) || (limit === 15)) {
459
486
  params = this.omit(params, 'limit');
460
487
  channel += limit.toString();
461
488
  }
489
+ return await this.unWatchChannel(symbol, channel, 'orderbook', params);
490
+ }
491
+ async unWatchChannel(symbol, channel, messageHashTopic, params = {}) {
492
+ await this.loadMarkets();
493
+ const market = this.market(symbol);
494
+ const messageHash = 'unsubscribe:' + messageHashTopic + ':' + market['symbol'];
462
495
  let instType = undefined;
463
496
  [instType, params] = this.getInstType(market, params);
464
497
  const args = {
@@ -682,6 +715,19 @@ class bitget extends bitget$1 {
682
715
  }
683
716
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
684
717
  }
718
+ async unWatchTrades(symbol, params = {}) {
719
+ /**
720
+ * @method
721
+ * @name bitget#unWatchTrades
722
+ * @description unsubscribe from the trades channel
723
+ * @see https://www.bitget.com/api-doc/spot/websocket/public/Trades-Channel
724
+ * @see https://www.bitget.com/api-doc/contract/websocket/public/New-Trades-Channel
725
+ * @param {string} symbol unified symbol of the market to unwatch the trades for
726
+ * @returns {any} status of the unwatch request
727
+ */
728
+ await this.loadMarkets();
729
+ return await this.unWatchChannel(symbol, 'trade', 'trade', params);
730
+ }
685
731
  handleTrades(client, message) {
686
732
  //
687
733
  // {
@@ -1868,6 +1914,112 @@ class bitget extends bitget$1 {
1868
1914
  //
1869
1915
  return message;
1870
1916
  }
1917
+ handleOrderBookUnSubscription(client, message) {
1918
+ //
1919
+ // {"event":"unsubscribe","arg":{"instType":"SPOT","channel":"books","instId":"BTCUSDT"}}
1920
+ //
1921
+ const arg = this.safeDict(message, 'arg', {});
1922
+ const instType = this.safeStringLower(arg, 'instType');
1923
+ const type = (instType === 'spot') ? 'spot' : 'contract';
1924
+ const instId = this.safeString(arg, 'instId');
1925
+ const market = this.safeMarket(instId, undefined, undefined, type);
1926
+ const symbol = market['symbol'];
1927
+ const messageHash = 'unsubscribe:orderbook:' + market['symbol'];
1928
+ const subMessageHash = 'orderbook:' + symbol;
1929
+ if (symbol in this.orderbooks) {
1930
+ delete this.orderbooks[symbol];
1931
+ }
1932
+ if (subMessageHash in client.subscriptions) {
1933
+ delete client.subscriptions[subMessageHash];
1934
+ }
1935
+ if (messageHash in client.subscriptions) {
1936
+ delete client.subscriptions[messageHash];
1937
+ }
1938
+ const error = new errors.UnsubscribeError(this.id + 'orderbook ' + symbol);
1939
+ client.reject(error, subMessageHash);
1940
+ client.resolve(true, messageHash);
1941
+ }
1942
+ handleTradesUnSubscription(client, message) {
1943
+ //
1944
+ // {"event":"unsubscribe","arg":{"instType":"SPOT","channel":"trade","instId":"BTCUSDT"}}
1945
+ //
1946
+ const arg = this.safeDict(message, 'arg', {});
1947
+ const instType = this.safeStringLower(arg, 'instType');
1948
+ const type = (instType === 'spot') ? 'spot' : 'contract';
1949
+ const instId = this.safeString(arg, 'instId');
1950
+ const market = this.safeMarket(instId, undefined, undefined, type);
1951
+ const symbol = market['symbol'];
1952
+ const messageHash = 'unsubscribe:trade:' + market['symbol'];
1953
+ const subMessageHash = 'trade:' + symbol;
1954
+ if (symbol in this.trades) {
1955
+ delete this.trades[symbol];
1956
+ }
1957
+ if (subMessageHash in client.subscriptions) {
1958
+ delete client.subscriptions[subMessageHash];
1959
+ }
1960
+ if (messageHash in client.subscriptions) {
1961
+ delete client.subscriptions[messageHash];
1962
+ }
1963
+ const error = new errors.UnsubscribeError(this.id + 'trades ' + symbol);
1964
+ client.reject(error, subMessageHash);
1965
+ client.resolve(true, messageHash);
1966
+ }
1967
+ handleTickerUnSubscription(client, message) {
1968
+ //
1969
+ // {"event":"unsubscribe","arg":{"instType":"SPOT","channel":"trade","instId":"BTCUSDT"}}
1970
+ //
1971
+ const arg = this.safeDict(message, 'arg', {});
1972
+ const instType = this.safeStringLower(arg, 'instType');
1973
+ const type = (instType === 'spot') ? 'spot' : 'contract';
1974
+ const instId = this.safeString(arg, 'instId');
1975
+ const market = this.safeMarket(instId, undefined, undefined, type);
1976
+ const symbol = market['symbol'];
1977
+ const messageHash = 'unsubscribe:ticker:' + market['symbol'];
1978
+ const subMessageHash = 'ticker:' + symbol;
1979
+ if (symbol in this.tickers) {
1980
+ delete this.tickers[symbol];
1981
+ }
1982
+ if (subMessageHash in client.subscriptions) {
1983
+ delete client.subscriptions[subMessageHash];
1984
+ }
1985
+ if (messageHash in client.subscriptions) {
1986
+ delete client.subscriptions[messageHash];
1987
+ }
1988
+ const error = new errors.UnsubscribeError(this.id + 'ticker ' + symbol);
1989
+ client.reject(error, subMessageHash);
1990
+ client.resolve(true, messageHash);
1991
+ }
1992
+ handleOHLCVUnSubscription(client, message) {
1993
+ //
1994
+ // {"event":"unsubscribe","arg":{"instType":"SPOT","channel":"candle1m","instId":"BTCUSDT"}}
1995
+ //
1996
+ const arg = this.safeDict(message, 'arg', {});
1997
+ const instType = this.safeStringLower(arg, 'instType');
1998
+ const type = (instType === 'spot') ? 'spot' : 'contract';
1999
+ const instId = this.safeString(arg, 'instId');
2000
+ const channel = this.safeString(arg, 'channel');
2001
+ const interval = channel.replace('candle', '');
2002
+ const timeframes = this.safeValue(this.options, 'timeframes');
2003
+ const timeframe = this.findTimeframe(interval, timeframes);
2004
+ const market = this.safeMarket(instId, undefined, undefined, type);
2005
+ const symbol = market['symbol'];
2006
+ const messageHash = 'unsubscribe:candles:' + timeframe + ':' + market['symbol'];
2007
+ const subMessageHash = 'candles:' + timeframe + ':' + symbol;
2008
+ if (symbol in this.ohlcvs) {
2009
+ if (timeframe in this.ohlcvs[symbol]) {
2010
+ delete this.ohlcvs[symbol][timeframe];
2011
+ }
2012
+ }
2013
+ if (subMessageHash in client.subscriptions) {
2014
+ delete client.subscriptions[subMessageHash];
2015
+ }
2016
+ if (messageHash in client.subscriptions) {
2017
+ delete client.subscriptions[messageHash];
2018
+ }
2019
+ const error = new errors.UnsubscribeError(this.id + ' ohlcv ' + timeframe + ' ' + symbol);
2020
+ client.reject(error, subMessageHash);
2021
+ client.resolve(true, messageHash);
2022
+ }
1871
2023
  handleUnSubscriptionStatus(client, message) {
1872
2024
  //
1873
2025
  // {
@@ -1897,23 +2049,16 @@ class bitget extends bitget$1 {
1897
2049
  const channel = this.safeString(arg, 'channel');
1898
2050
  if (channel === 'books') {
1899
2051
  // for now only unWatchOrderBook is supporteod
1900
- const instType = this.safeStringLower(arg, 'instType');
1901
- const type = (instType === 'spot') ? 'spot' : 'contract';
1902
- const instId = this.safeString(arg, 'instId');
1903
- const market = this.safeMarket(instId, undefined, undefined, type);
1904
- const symbol = market['symbol'];
1905
- const messageHash = 'unsubscribe:orderbook:' + market['symbol'];
1906
- const subMessageHash = 'orderbook:' + symbol;
1907
- if (symbol in this.orderbooks) {
1908
- delete this.orderbooks[symbol];
1909
- }
1910
- if (subMessageHash in client.subscriptions) {
1911
- delete client.subscriptions[subMessageHash];
1912
- }
1913
- if (messageHash in client.subscriptions) {
1914
- delete client.subscriptions[messageHash];
1915
- }
1916
- client.resolve(true, messageHash);
2052
+ this.handleOrderBookUnSubscription(client, message);
2053
+ }
2054
+ else if (channel === 'trade') {
2055
+ this.handleTradesUnSubscription(client, message);
2056
+ }
2057
+ else if (channel === 'ticker') {
2058
+ this.handleTickerUnSubscription(client, message);
2059
+ }
2060
+ else if (channel.startsWith('candle')) {
2061
+ this.handleOHLCVUnSubscription(client, message);
1917
2062
  }
1918
2063
  }
1919
2064
  return message;
@@ -29,6 +29,7 @@ class p2b extends p2b$1 {
29
29
  'watchTicker': true,
30
30
  'watchTickers': false,
31
31
  'watchTrades': true,
32
+ 'watchTradesForSymbols': true,
32
33
  },
33
34
  'urls': {
34
35
  'api': {
@@ -144,15 +145,41 @@ class p2b extends p2b$1 {
144
145
  * @param {object} [params] extra parameters specific to the exchange API endpoint
145
146
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
146
147
  */
148
+ return await this.watchTradesForSymbols([symbol], since, limit, params);
149
+ }
150
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
151
+ /**
152
+ * @method
153
+ * @name p2b#watchTradesForSymbols
154
+ * @description get the list of most recent trades for a list of symbols
155
+ * @see https://github.com/P2B-team/P2B-WSS-Public/blob/main/wss_documentation.md#deals
156
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
157
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
158
+ * @param {int} [limit] the maximum amount of trades to fetch
159
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
160
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
161
+ */
147
162
  await this.loadMarkets();
148
- const market = this.market(symbol);
149
- const request = [
150
- market['id'],
151
- ];
152
- const messageHash = 'deals::' + market['symbol'];
153
- const trades = await this.subscribe('deals.subscribe', messageHash, request, params);
163
+ symbols = this.marketSymbols(symbols, undefined, false, true, true);
164
+ const messageHashes = [];
165
+ if (symbols !== undefined) {
166
+ for (let i = 0; i < symbols.length; i++) {
167
+ messageHashes.push('deals::' + symbols[i]);
168
+ }
169
+ }
170
+ const marketIds = this.marketIds(symbols);
171
+ const url = this.urls['api']['ws'];
172
+ const subscribe = {
173
+ 'method': 'deals.subscribe',
174
+ 'params': marketIds,
175
+ 'id': this.milliseconds(),
176
+ };
177
+ const query = this.extend(subscribe, params);
178
+ const trades = await this.watchMultiple(url, messageHashes, query, messageHashes);
154
179
  if (this.newUpdates) {
155
- limit = trades.getLimit(symbol, limit);
180
+ const first = this.safeValue(trades, 0);
181
+ const tradeSymbol = this.safeString(first, 'symbol');
182
+ limit = trades.getLimit(tradeSymbol, limit);
156
183
  }
157
184
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
158
185
  }
@@ -18,6 +18,7 @@ class poloniex extends poloniex$1 {
18
18
  'watchTicker': true,
19
19
  'watchTickers': true,
20
20
  'watchTrades': true,
21
+ 'watchTradesForSymbols': true,
21
22
  'watchBalance': true,
22
23
  'watchStatus': false,
23
24
  'watchOrders': true,
@@ -395,12 +396,44 @@ class poloniex extends poloniex$1 {
395
396
  * @param {object} [params] extra parameters specific to the exchange API endpoint
396
397
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
397
398
  */
399
+ return await this.watchTradesForSymbols([symbol], since, limit, params);
400
+ }
401
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
402
+ /**
403
+ * @method
404
+ * @name poloniex#watchTradesForSymbols
405
+ * @description get the list of most recent trades for a list of symbols
406
+ * @see https://api-docs.poloniex.com/spot/websocket/market-data#trades
407
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
408
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
409
+ * @param {int} [limit] the maximum amount of trades to fetch
410
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
411
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
412
+ */
398
413
  await this.loadMarkets();
399
- symbol = this.symbol(symbol);
414
+ symbols = this.marketSymbols(symbols, undefined, false, true, true);
400
415
  const name = 'trades';
401
- const trades = await this.subscribe(name, name, false, [symbol], params);
416
+ const url = this.urls['api']['ws']['public'];
417
+ const marketIds = this.marketIds(symbols);
418
+ const subscribe = {
419
+ 'event': 'subscribe',
420
+ 'channel': [
421
+ name,
422
+ ],
423
+ 'symbols': marketIds,
424
+ };
425
+ const request = this.extend(subscribe, params);
426
+ const messageHashes = [];
427
+ if (symbols !== undefined) {
428
+ for (let i = 0; i < symbols.length; i++) {
429
+ messageHashes.push(name + '::' + symbols[i]);
430
+ }
431
+ }
432
+ const trades = await this.watchMultiple(url, messageHashes, request, messageHashes);
402
433
  if (this.newUpdates) {
403
- limit = trades.getLimit(symbol, limit);
434
+ const first = this.safeValue(trades, 0);
435
+ const tradeSymbol = this.safeString(first, 'symbol');
436
+ limit = trades.getLimit(tradeSymbol, limit);
404
437
  }
405
438
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
406
439
  }
@@ -25,6 +25,7 @@ class poloniexfutures extends poloniexfutures$1 {
25
25
  'watchTicker': true,
26
26
  'watchTickers': false,
27
27
  'watchTrades': true,
28
+ 'watchTradesForSymbols': false,
28
29
  'watchBalance': true,
29
30
  'watchOrders': true,
30
31
  'watchMyTrades': false,
@@ -15,6 +15,7 @@ class probit extends probit$1 {
15
15
  'watchTicker': true,
16
16
  'watchTickers': false,
17
17
  'watchTrades': true,
18
+ 'watchTradesForSymbols': false,
18
19
  'watchMyTrades': true,
19
20
  'watchOrders': true,
20
21
  'watchOrderBook': true,
@@ -222,6 +223,7 @@ class probit extends probit$1 {
222
223
  * @method
223
224
  * @name probit#watchMyTrades
224
225
  * @description get the list of trades associated with the user
226
+ * @see https://docs-en.probit.com/reference/trade_history
225
227
  * @param {string} symbol unified symbol of the market to fetch trades for
226
228
  * @param {int} [since] timestamp in ms of the earliest trade to fetch
227
229
  * @param {int} [limit] the maximum amount of trades to fetch
@@ -15,6 +15,7 @@ class upbit extends upbit$1 {
15
15
  'watchOrderBook': true,
16
16
  'watchTicker': true,
17
17
  'watchTrades': true,
18
+ 'watchTradesForSymbols': true,
18
19
  'watchOrders': true,
19
20
  'watchMyTrades': true,
20
21
  'watchBalance': true,
@@ -79,11 +80,55 @@ class upbit extends upbit$1 {
79
80
  * @param {object} [params] extra parameters specific to the exchange API endpoint
80
81
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
81
82
  */
83
+ return await this.watchTradesForSymbols([symbol], since, limit, params);
84
+ }
85
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
86
+ /**
87
+ * @method
88
+ * @name upbit#watchTradesForSymbols
89
+ * @description get the list of most recent trades for a list of symbols
90
+ * @see https://global-docs.upbit.com/reference/websocket-trade
91
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
92
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
93
+ * @param {int} [limit] the maximum amount of trades to fetch
94
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
95
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
96
+ */
82
97
  await this.loadMarkets();
83
- symbol = this.symbol(symbol);
84
- const trades = await this.watchPublic(symbol, 'trade');
98
+ symbols = this.marketSymbols(symbols, undefined, false, true, true);
99
+ const channel = 'trade';
100
+ const messageHashes = [];
101
+ const url = this.implodeParams(this.urls['api']['ws'], {
102
+ 'hostname': this.hostname,
103
+ });
104
+ if (symbols !== undefined) {
105
+ for (let i = 0; i < symbols.length; i++) {
106
+ const market = this.market(symbols[i]);
107
+ const marketId = market['id'];
108
+ const symbol = market['symbol'];
109
+ this.options[channel] = this.safeValue(this.options, channel, {});
110
+ this.options[channel][symbol] = true;
111
+ messageHashes.push(channel + ':' + marketId);
112
+ }
113
+ }
114
+ const optionSymbols = Object.keys(this.options[channel]);
115
+ const marketIds = this.marketIds(optionSymbols);
116
+ const request = [
117
+ {
118
+ 'ticket': this.uuid(),
119
+ },
120
+ {
121
+ 'type': channel,
122
+ 'codes': marketIds,
123
+ // 'isOnlySnapshot': false,
124
+ // 'isOnlyRealtime': false,
125
+ },
126
+ ];
127
+ const trades = await this.watchMultiple(url, messageHashes, request, messageHashes);
85
128
  if (this.newUpdates) {
86
- limit = trades.getLimit(symbol, limit);
129
+ const first = this.safeValue(trades, 0);
130
+ const tradeSymbol = this.safeString(first, 'symbol');
131
+ limit = trades.getLimit(tradeSymbol, limit);
87
132
  }
88
133
  return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
89
134
  }
@@ -20,6 +20,7 @@ class vertex extends vertex$1 {
20
20
  'watchTicker': true,
21
21
  'watchTickers': false,
22
22
  'watchTrades': true,
23
+ 'watchTradesForSymbols': false,
23
24
  'watchPositions': true,
24
25
  },
25
26
  'urls': {