ccxt 4.5.20 → 4.5.21

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 (71) 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/ascendex.js +7 -0
  5. package/dist/cjs/src/base/Exchange.js +6 -0
  6. package/dist/cjs/src/binance.js +1 -0
  7. package/dist/cjs/src/bingx.js +10 -0
  8. package/dist/cjs/src/bitfinex.js +5 -0
  9. package/dist/cjs/src/bitflyer.js +20 -0
  10. package/dist/cjs/src/bitget.js +19 -0
  11. package/dist/cjs/src/bybit.js +12 -6
  12. package/dist/cjs/src/defx.js +1 -0
  13. package/dist/cjs/src/deribit.js +102 -0
  14. package/dist/cjs/src/hyperliquid.js +30 -6
  15. package/dist/cjs/src/pro/bittrade.js +2 -0
  16. package/dist/cjs/src/pro/bybit.js +2 -0
  17. package/dist/cjs/src/pro/cex.js +2 -0
  18. package/dist/cjs/src/pro/coinex.js +2 -0
  19. package/dist/cjs/src/pro/deepcoin.js +2 -0
  20. package/dist/cjs/src/pro/exmo.js +2 -0
  21. package/dist/cjs/src/pro/gate.js +5 -3
  22. package/dist/cjs/src/pro/htx.js +2 -0
  23. package/dist/cjs/src/pro/kraken.js +2 -0
  24. package/dist/cjs/src/pro/kucoin.js +2 -0
  25. package/dist/cjs/src/pro/kucoinfutures.js +2 -0
  26. package/dist/cjs/src/pro/lbank.js +2 -0
  27. package/dist/cjs/src/pro/phemex.js +2 -0
  28. package/dist/cjs/src/pro/upbit.js +24 -13
  29. package/dist/cjs/src/pro/xt.js +10 -9
  30. package/dist/cjs/src/upbit.js +4 -3
  31. package/js/ccxt.d.ts +1 -1
  32. package/js/ccxt.js +1 -1
  33. package/js/src/abstract/binance.d.ts +1 -0
  34. package/js/src/abstract/binancecoinm.d.ts +1 -0
  35. package/js/src/abstract/binanceus.d.ts +1 -0
  36. package/js/src/abstract/binanceusdm.d.ts +1 -0
  37. package/js/src/abstract/bingx.d.ts +10 -0
  38. package/js/src/abstract/bitget.d.ts +19 -0
  39. package/js/src/abstract/upbit.d.ts +2 -1
  40. package/js/src/ascendex.js +7 -0
  41. package/js/src/base/Exchange.d.ts +2 -0
  42. package/js/src/base/Exchange.js +6 -0
  43. package/js/src/binance.js +1 -0
  44. package/js/src/bingx.js +10 -0
  45. package/js/src/bitfinex.js +5 -0
  46. package/js/src/bitflyer.js +20 -0
  47. package/js/src/bitget.js +19 -0
  48. package/js/src/bybit.d.ts +1 -0
  49. package/js/src/bybit.js +12 -6
  50. package/js/src/defx.js +1 -0
  51. package/js/src/deribit.d.ts +11 -0
  52. package/js/src/deribit.js +102 -0
  53. package/js/src/hyperliquid.d.ts +3 -0
  54. package/js/src/hyperliquid.js +30 -6
  55. package/js/src/pro/bittrade.js +2 -0
  56. package/js/src/pro/bybit.js +2 -0
  57. package/js/src/pro/cex.js +2 -0
  58. package/js/src/pro/coinex.js +2 -0
  59. package/js/src/pro/deepcoin.js +2 -0
  60. package/js/src/pro/exmo.js +2 -0
  61. package/js/src/pro/gate.js +5 -3
  62. package/js/src/pro/htx.js +2 -0
  63. package/js/src/pro/kraken.js +2 -0
  64. package/js/src/pro/kucoin.js +2 -0
  65. package/js/src/pro/kucoinfutures.js +2 -0
  66. package/js/src/pro/lbank.js +2 -0
  67. package/js/src/pro/phemex.js +2 -0
  68. package/js/src/pro/upbit.js +24 -13
  69. package/js/src/pro/xt.js +10 -9
  70. package/js/src/upbit.js +4 -3
  71. package/package.json +1 -1
package/js/src/bybit.js CHANGED
@@ -4386,7 +4386,7 @@ export default class bybit extends Exchange {
4386
4386
  const market = this.market(symbol);
4387
4387
  const request = {
4388
4388
  'symbol': market['id'],
4389
- 'orderId': id,
4389
+ // 'orderId': id,
4390
4390
  // 'orderLinkId': 'string', // unique client order id, max 36 characters
4391
4391
  // 'takeProfit': 123.45, // take profit price, only take effect upon opening the position
4392
4392
  // 'stopLoss': 123.45, // stop loss price, only take effect upon opening the position
@@ -4397,6 +4397,13 @@ export default class bybit extends Exchange {
4397
4397
  // Valid for option only.
4398
4398
  // 'orderIv': '0', // Implied volatility; parameters are passed according to the real value; for example, for 10%, 0.1 is passed
4399
4399
  };
4400
+ const clientOrderId = this.safeString2(params, 'orderLinkId', 'clientOrderId');
4401
+ if (clientOrderId === undefined) {
4402
+ request['orderId'] = id;
4403
+ }
4404
+ else {
4405
+ request['orderLinkId'] = clientOrderId;
4406
+ }
4400
4407
  let category = undefined;
4401
4408
  [category, params] = this.getBybitType('editOrderRequest', market, params);
4402
4409
  request['category'] = category;
@@ -4440,10 +4447,6 @@ export default class bybit extends Exchange {
4440
4447
  request['tpTriggerBy'] = tpTriggerBy;
4441
4448
  }
4442
4449
  }
4443
- const clientOrderId = this.safeString(params, 'clientOrderId');
4444
- if (clientOrderId !== undefined) {
4445
- request['orderLinkId'] = clientOrderId;
4446
- }
4447
4450
  params = this.omit(params, ['stopPrice', 'stopLossPrice', 'takeProfitPrice', 'triggerPrice', 'clientOrderId', 'stopLoss', 'takeProfit']);
4448
4451
  return request;
4449
4452
  }
@@ -4461,6 +4464,7 @@ export default class bybit extends Exchange {
4461
4464
  * @param {float} amount how much of currency you want to trade in units of base currency
4462
4465
  * @param {float} price the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
4463
4466
  * @param {object} [params] extra parameters specific to the exchange API endpoint
4467
+ * @param {string} [params.clientOrderId] unique client order id
4464
4468
  * @param {float} [params.triggerPrice] The price that a trigger order is triggered at
4465
4469
  * @param {float} [params.stopLossPrice] The price that a stop loss order is triggered at
4466
4470
  * @param {float} [params.takeProfitPrice] The price that a take profit order is triggered at
@@ -4478,6 +4482,7 @@ export default class bybit extends Exchange {
4478
4482
  if (symbol === undefined) {
4479
4483
  throw new ArgumentsRequired(this.id + ' editOrder() requires a symbol argument');
4480
4484
  }
4485
+ const market = this.market(symbol);
4481
4486
  const request = this.editOrderRequest(id, symbol, type, side, amount, price, params);
4482
4487
  const response = await this.privatePostV5OrderAmend(this.extend(request, params));
4483
4488
  //
@@ -4496,7 +4501,8 @@ export default class bybit extends Exchange {
4496
4501
  return this.safeOrder({
4497
4502
  'info': response,
4498
4503
  'id': this.safeString(result, 'orderId'),
4499
- });
4504
+ 'clientOrderId': this.safeString(result, 'orderLinkId'),
4505
+ }, market);
4500
4506
  }
4501
4507
  /**
4502
4508
  * @method
package/js/src/defx.js CHANGED
@@ -344,6 +344,7 @@ export default class defx extends Exchange {
344
344
  'exact': {
345
345
  '404': BadRequest,
346
346
  'missing_auth_signature': AuthenticationError,
347
+ 'leverage_higher_than_capped_leverage': BadRequest,
347
348
  'order_rejected': InvalidOrder,
348
349
  'invalid_order_id': InvalidOrder,
349
350
  'filter_lotsize_maxqty': InvalidOrder,
@@ -505,6 +505,17 @@ export default class deribit extends Exchange {
505
505
  */
506
506
  fetchOptionChain(code: string, params?: {}): Promise<OptionChain>;
507
507
  parseOption(chain: Dict, currency?: Currency, market?: Market): Option;
508
+ /**
509
+ * @method
510
+ * @name deribit#fetchOpenInterest
511
+ * @description Retrieves the open interest of a symbol
512
+ * @see https://docs.deribit.com/?shell#public-get_book_summary_by_instrument
513
+ * @param {string} symbol unified CCXT market symbol
514
+ * @param {object} [params] exchange specific parameters
515
+ * @returns {object} an open interest structure{@link https://docs.ccxt.com/#/?id=open-interest-structure}
516
+ */
517
+ fetchOpenInterest(symbol: string, params?: {}): Promise<import("./base/types.js").OpenInterest>;
518
+ parseOpenInterest(interest: any, market?: Market): import("./base/types.js").OpenInterest;
508
519
  nonce(): number;
509
520
  sign(path: any, api?: string, method?: string, params?: {}, headers?: any, body?: any): {
510
521
  url: string;
package/js/src/deribit.js CHANGED
@@ -76,6 +76,8 @@ export default class deribit extends Exchange {
76
76
  'fetchMyTrades': true,
77
77
  'fetchOHLCV': true,
78
78
  'fetchOpenOrders': true,
79
+ 'fetchOpenInterest': true,
80
+ 'fetchOpenInterests': false,
79
81
  'fetchOption': true,
80
82
  'fetchOptionChain': true,
81
83
  'fetchOrder': true,
@@ -3741,6 +3743,106 @@ export default class deribit extends Exchange {
3741
3743
  'quoteVolume': this.safeNumber(chain, 'volume_usd'),
3742
3744
  };
3743
3745
  }
3746
+ /**
3747
+ * @method
3748
+ * @name deribit#fetchOpenInterest
3749
+ * @description Retrieves the open interest of a symbol
3750
+ * @see https://docs.deribit.com/?shell#public-get_book_summary_by_instrument
3751
+ * @param {string} symbol unified CCXT market symbol
3752
+ * @param {object} [params] exchange specific parameters
3753
+ * @returns {object} an open interest structure{@link https://docs.ccxt.com/#/?id=open-interest-structure}
3754
+ */
3755
+ async fetchOpenInterest(symbol, params = {}) {
3756
+ await this.loadMarkets();
3757
+ const market = this.market(symbol);
3758
+ if (!market['contract']) {
3759
+ throw new BadRequest(this.id + ' fetchOpenInterest() supports contract markets only');
3760
+ }
3761
+ const request = {
3762
+ 'instrument_name': market['id'],
3763
+ };
3764
+ const response = await this.publicGetGetBookSummaryByInstrument(this.extend(request, params));
3765
+ //
3766
+ // {
3767
+ // "jsonrpc": "2.0",
3768
+ // "result": [
3769
+ // {
3770
+ // "high": 93099.5,
3771
+ // "low": 81773.0,
3772
+ // "last": 87197.0,
3773
+ // "instrument_name": "BTC-PERPETUAL",
3774
+ // "bid_price": 87083.0,
3775
+ // "ask_price": 87149.5,
3776
+ // "open_interest": 9978911260,
3777
+ // "mark_price": 87102.01,
3778
+ // "creation_timestamp": 1763674177068,
3779
+ // "price_change": -3.2032,
3780
+ // "volume": 7377.18657991,
3781
+ // "estimated_delivery_price": 87047.2,
3782
+ // "base_currency": "BTC",
3783
+ // "quote_currency": "USD",
3784
+ // "volume_usd": 661040250.0,
3785
+ // "volume_notional": 661040250.0,
3786
+ // "current_funding": 1.2966e-4,
3787
+ // "funding_8h": -8.1069e-4,
3788
+ // "mid_price": 87116.25
3789
+ // }
3790
+ // ],
3791
+ // "usIn": 1763674177068845,
3792
+ // "usOut": 1763674177068996,
3793
+ // "usDiff": 151,
3794
+ // "testnet": true
3795
+ // }
3796
+ //
3797
+ const result = this.safeList(response, 'result', []);
3798
+ const data = this.safeDict(result, 0, {});
3799
+ return this.parseOpenInterest(data, market);
3800
+ }
3801
+ parseOpenInterest(interest, market = undefined) {
3802
+ //
3803
+ // {
3804
+ // "high": 93099.5,
3805
+ // "low": 81773.0,
3806
+ // "last": 87197.0,
3807
+ // "instrument_name": "BTC-PERPETUAL",
3808
+ // "bid_price": 87083.0,
3809
+ // "ask_price": 87149.5,
3810
+ // "open_interest": 9978911260,
3811
+ // "mark_price": 87102.01,
3812
+ // "creation_timestamp": 1763674177068,
3813
+ // "price_change": -3.2032,
3814
+ // "volume": 7377.18657991,
3815
+ // "estimated_delivery_price": 87047.2,
3816
+ // "base_currency": "BTC",
3817
+ // "quote_currency": "USD",
3818
+ // "volume_usd": 661040250.0,
3819
+ // "volume_notional": 661040250.0,
3820
+ // "current_funding": 1.2966e-4,
3821
+ // "funding_8h": -8.1069e-4,
3822
+ // "mid_price": 87116.25
3823
+ // }
3824
+ //
3825
+ const timestamp = this.safeInteger(interest, 'creation_timestamp');
3826
+ const marketId = this.safeString(interest, 'instrument_name');
3827
+ market = this.safeMarket(marketId, market);
3828
+ const openInterest = this.safeNumber(interest, 'open_interest');
3829
+ let openInterestAmount = undefined;
3830
+ let openInterestValue = undefined;
3831
+ if (market['option'] || (market['future'] && market['linear'])) {
3832
+ openInterestAmount = openInterest;
3833
+ }
3834
+ else {
3835
+ openInterestValue = openInterest;
3836
+ }
3837
+ return this.safeOpenInterest({
3838
+ 'symbol': this.safeSymbol(marketId, market),
3839
+ 'openInterestAmount': openInterestAmount,
3840
+ 'openInterestValue': openInterestValue,
3841
+ 'timestamp': timestamp,
3842
+ 'datetime': this.iso8601(timestamp),
3843
+ 'info': interest,
3844
+ }, market);
3845
+ }
3744
3846
  nonce() {
3745
3847
  return this.milliseconds();
3746
3848
  }
@@ -348,6 +348,7 @@ export default class hyperliquid extends Exchange {
348
348
  * @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure}
349
349
  */
350
350
  fetchFundingRateHistory(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<FundingRateHistory[]>;
351
+ getDexFromHip3Symbol(market: any): string;
351
352
  /**
352
353
  * @method
353
354
  * @name hyperliquid#fetchOpenOrders
@@ -410,6 +411,7 @@ export default class hyperliquid extends Exchange {
410
411
  * @param {object} [params] extra parameters specific to the exchange API endpoint
411
412
  * @param {string} [params.user] user address, will default to this.walletAddress if not provided
412
413
  * @param {string} [params.subAccountAddress] sub account user address
414
+ * @param {string} [params.dex] perp dex name. default is null
413
415
  * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
414
416
  */
415
417
  fetchOrders(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
@@ -466,6 +468,7 @@ export default class hyperliquid extends Exchange {
466
468
  * @param {object} [params] extra parameters specific to the exchange API endpoint
467
469
  * @param {string} [params.user] user address, will default to this.walletAddress if not provided
468
470
  * @param {string} [params.subAccountAddress] sub account user address
471
+ * @param {string} [params.dex] perp dex name, eg: XYZ
469
472
  * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
470
473
  */
471
474
  fetchPositions(symbols?: Strings, params?: {}): Promise<Position[]>;
@@ -2552,6 +2552,15 @@ export default class hyperliquid extends Exchange {
2552
2552
  const sorted = this.sortBy(result, 'timestamp');
2553
2553
  return this.filterBySymbolSinceLimit(sorted, symbol, since, limit);
2554
2554
  }
2555
+ getDexFromHip3Symbol(market) {
2556
+ const baseName = this.safeString(market, 'baseName', '');
2557
+ const part = baseName.split(':');
2558
+ const partsLength = part.length;
2559
+ if (partsLength > 1) {
2560
+ return this.safeString(part, 0);
2561
+ }
2562
+ return undefined;
2563
+ }
2555
2564
  /**
2556
2565
  * @method
2557
2566
  * @name hyperliquid#fetchOpenOrders
@@ -2581,11 +2590,9 @@ export default class hyperliquid extends Exchange {
2581
2590
  if (symbol !== undefined) {
2582
2591
  market = this.market(symbol);
2583
2592
  // check if is hip3 symbol
2584
- const baseName = this.safeString(market, 'baseName', '');
2585
- const part = baseName.split(':');
2586
- const partsLength = part.length;
2587
- if (partsLength > 1) {
2588
- request['dex'] = this.safeString(part, 0);
2593
+ const dexName = this.getDexFromHip3Symbol(market);
2594
+ if (dexName !== undefined) {
2595
+ request['dex'] = dexName;
2589
2596
  }
2590
2597
  }
2591
2598
  const response = await this.publicPostInfo(this.extend(request, params));
@@ -2674,17 +2681,26 @@ export default class hyperliquid extends Exchange {
2674
2681
  * @param {object} [params] extra parameters specific to the exchange API endpoint
2675
2682
  * @param {string} [params.user] user address, will default to this.walletAddress if not provided
2676
2683
  * @param {string} [params.subAccountAddress] sub account user address
2684
+ * @param {string} [params.dex] perp dex name. default is null
2677
2685
  * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
2678
2686
  */
2679
2687
  async fetchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2680
2688
  let userAddress = undefined;
2681
2689
  [userAddress, params] = this.handlePublicAddress('fetchOrders', params);
2682
2690
  await this.loadMarkets();
2683
- const market = this.safeMarket(symbol);
2691
+ let market = undefined;
2684
2692
  const request = {
2685
2693
  'type': 'historicalOrders',
2686
2694
  'user': userAddress,
2687
2695
  };
2696
+ if (symbol !== undefined) {
2697
+ market = this.market(symbol);
2698
+ // check if is hip3 symbol
2699
+ const dexName = this.getDexFromHip3Symbol(market);
2700
+ if (dexName !== undefined) {
2701
+ request['dex'] = dexName;
2702
+ }
2703
+ }
2688
2704
  const response = await this.publicPostInfo(this.extend(request, params));
2689
2705
  //
2690
2706
  // [
@@ -3088,6 +3104,7 @@ export default class hyperliquid extends Exchange {
3088
3104
  * @param {object} [params] extra parameters specific to the exchange API endpoint
3089
3105
  * @param {string} [params.user] user address, will default to this.walletAddress if not provided
3090
3106
  * @param {string} [params.subAccountAddress] sub account user address
3107
+ * @param {string} [params.dex] perp dex name, eg: XYZ
3091
3108
  * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
3092
3109
  */
3093
3110
  async fetchPositions(symbols = undefined, params = {}) {
@@ -3099,6 +3116,13 @@ export default class hyperliquid extends Exchange {
3099
3116
  'type': 'clearinghouseState',
3100
3117
  'user': userAddress,
3101
3118
  };
3119
+ if (symbols !== undefined) {
3120
+ const market = this.market(symbols[0]);
3121
+ const dexName = this.getDexFromHip3Symbol(market);
3122
+ if (dexName !== undefined) {
3123
+ request['dex'] = dexName;
3124
+ }
3125
+ }
3102
3126
  const response = await this.publicPostInfo(this.extend(request, params));
3103
3127
  //
3104
3128
  // {
@@ -43,8 +43,10 @@ export default class bittrade extends bittradeRest {
43
43
  });
44
44
  }
45
45
  requestId() {
46
+ this.lockId();
46
47
  const requestId = this.sum(this.safeInteger(this.options, 'requestId', 0), 1);
47
48
  this.options['requestId'] = requestId;
49
+ this.unlockId();
48
50
  return requestId.toString();
49
51
  }
50
52
  /**
@@ -168,8 +168,10 @@ export default class bybit extends bybitRest {
168
168
  });
169
169
  }
170
170
  requestId() {
171
+ this.lockId();
171
172
  const requestId = this.sum(this.safeInteger(this.options, 'requestId', 0), 1);
172
173
  this.options['requestId'] = requestId;
174
+ this.unlockId();
173
175
  return requestId;
174
176
  }
175
177
  async getUrlByMarketType(symbol = undefined, isPrivate = false, method = undefined, params = {}) {
package/js/src/pro/cex.js CHANGED
@@ -48,8 +48,10 @@ export default class cex extends cexRest {
48
48
  });
49
49
  }
50
50
  requestId() {
51
+ this.lockId();
51
52
  const requestId = this.sum(this.safeInteger(this.options, 'requestId', 0), 1);
52
53
  this.options['requestId'] = requestId;
54
+ this.unlockId();
53
55
  return requestId.toString();
54
56
  }
55
57
  /**
@@ -88,8 +88,10 @@ export default class coinex extends coinexRest {
88
88
  });
89
89
  }
90
90
  requestId() {
91
+ this.lockId();
91
92
  const requestId = this.sum(this.safeInteger(this.options, 'requestId', 0), 1);
92
93
  this.options['requestId'] = requestId;
94
+ this.unlockId();
93
95
  return requestId;
94
96
  }
95
97
  handleTicker(client, message) {
@@ -95,9 +95,11 @@ export default class deepcoin extends deepcoinRest {
95
95
  return message;
96
96
  }
97
97
  requestId() {
98
+ this.lockId();
98
99
  const previousValue = this.safeInteger(this.options, 'lastRequestId', 0);
99
100
  const newValue = this.sum(previousValue, 1);
100
101
  this.options['lastRequestId'] = newValue;
102
+ this.unlockId();
101
103
  return newValue;
102
104
  }
103
105
  createPublicRequest(market, requestId, topicID, suffix = '', unWatch = false) {
@@ -39,8 +39,10 @@ export default class exmo extends exmoRest {
39
39
  });
40
40
  }
41
41
  requestId() {
42
+ this.lockId();
42
43
  const requestId = this.sum(this.safeInteger(this.options, 'requestId', 0), 1);
43
44
  this.options['requestId'] = requestId;
45
+ this.unlockId();
44
46
  return requestId;
45
47
  }
46
48
  /**
@@ -886,8 +886,8 @@ export default class gate extends gateRest {
886
886
  const ohlcv = result[i];
887
887
  const subscription = this.safeString(ohlcv, 'n', '');
888
888
  const parts = subscription.split('_');
889
- const timeframe = this.safeString(parts, 0);
890
- const timeframeId = this.findTimeframe(timeframe);
889
+ const timeframeId = this.safeString(parts, 0);
890
+ const timeframe = this.findTimeframe(timeframeId);
891
891
  const prefix = timeframe + '_';
892
892
  const marketId = subscription.replace(prefix, '');
893
893
  const symbol = this.safeSymbol(marketId, undefined, '_', marketType);
@@ -897,7 +897,7 @@ export default class gate extends gateRest {
897
897
  if (stored === undefined) {
898
898
  const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
899
899
  stored = new ArrayCacheByTimestamp(limit);
900
- this.ohlcvs[symbol][timeframeId] = stored;
900
+ this.ohlcvs[symbol][timeframe] = stored;
901
901
  }
902
902
  stored.append(parsed);
903
903
  marketIds[symbol] = timeframe;
@@ -1964,8 +1964,10 @@ export default class gate extends gateRest {
1964
1964
  }
1965
1965
  requestId() {
1966
1966
  // their support said that reqid must be an int32, not documented
1967
+ this.lockId();
1967
1968
  const reqid = this.sum(this.safeInteger(this.options, 'reqid', 0), 1);
1968
1969
  this.options['reqid'] = reqid;
1970
+ this.unlockId();
1969
1971
  return reqid;
1970
1972
  }
1971
1973
  async subscribePublic(url, messageHash, payload, channel, params = {}, subscription = undefined) {
package/js/src/pro/htx.js CHANGED
@@ -131,8 +131,10 @@ export default class htx extends htxRest {
131
131
  });
132
132
  }
133
133
  requestId() {
134
+ this.lockId();
134
135
  const requestId = this.sum(this.safeInteger(this.options, 'requestId', 0), 1);
135
136
  this.options['requestId'] = requestId;
137
+ this.unlockId();
136
138
  return requestId.toString();
137
139
  }
138
140
  /**
@@ -648,8 +648,10 @@ export default class kraken extends krakenRest {
648
648
  }
649
649
  requestId() {
650
650
  // their support said that reqid must be an int32, not documented
651
+ this.lockId();
651
652
  const reqid = this.sum(this.safeInteger(this.options, 'reqid', 0), 1);
652
653
  this.options['reqid'] = reqid;
654
+ this.unlockId();
653
655
  return reqid;
654
656
  }
655
657
  /**
@@ -125,8 +125,10 @@ export default class kucoin extends kucoinRest {
125
125
  return undefined;
126
126
  }
127
127
  requestId() {
128
+ this.lockId();
128
129
  const requestId = this.sum(this.safeInteger(this.options, 'requestId', 0), 1);
129
130
  this.options['requestId'] = requestId;
131
+ this.unlockId();
130
132
  return requestId;
131
133
  }
132
134
  async subscribe(url, messageHash, subscriptionHash, params = {}, subscription = undefined) {
@@ -144,8 +144,10 @@ export default class kucoinfutures extends kucoinfuturesRest {
144
144
  return undefined;
145
145
  }
146
146
  requestId() {
147
+ this.lockId();
147
148
  const requestId = this.sum(this.safeInteger(this.options, 'requestId', 0), 1);
148
149
  this.options['requestId'] = requestId;
150
+ this.unlockId();
149
151
  return requestId;
150
152
  }
151
153
  async subscribe(url, messageHash, subscriptionHash, subscription, params = {}) {
@@ -53,9 +53,11 @@ export default class lbank extends lbankRest {
53
53
  });
54
54
  }
55
55
  requestId() {
56
+ this.lockId();
56
57
  const previousValue = this.safeInteger(this.options, 'requestId', 0);
57
58
  const newValue = this.sum(previousValue, 1);
58
59
  this.options['requestId'] = newValue;
60
+ this.unlockId();
59
61
  return newValue;
60
62
  }
61
63
  /**
@@ -75,8 +75,10 @@ export default class phemex extends phemexRest {
75
75
  return this.fromEn(er, this.safeInteger(market, 'ratioScale'));
76
76
  }
77
77
  requestId() {
78
+ this.lockId();
78
79
  const requestId = this.sum(this.safeInteger(this.options, 'requestId', 0), 1);
79
80
  this.options['requestId'] = requestId;
81
+ this.unlockId();
80
82
  return requestId;
81
83
  }
82
84
  parseSwapTicker(ticker, market = undefined) {
@@ -44,23 +44,34 @@ export default class upbit extends upbitRest {
44
44
  const url = this.implodeParams(this.urls['api']['ws'], {
45
45
  'hostname': this.hostname,
46
46
  });
47
- this.options[channel] = this.safeValue(this.options, channel, {});
48
- this.options[channel][symbol] = true;
49
- const symbols = Object.keys(this.options[channel]);
50
- const marketIds = this.marketIds(symbols);
51
- const request = [
47
+ const client = this.client(url);
48
+ const subscriptionsKey = 'upbitPublicSubscriptions';
49
+ if (!(subscriptionsKey in client.subscriptions)) {
50
+ client.subscriptions[subscriptionsKey] = {};
51
+ }
52
+ const subscriptions = client.subscriptions[subscriptionsKey];
53
+ let messageHash = channel;
54
+ const request = {
55
+ 'type': channel,
56
+ };
57
+ if (symbol !== undefined) {
58
+ messageHash = channel + ':' + symbol;
59
+ request['codes'] = [marketId];
60
+ }
61
+ if (!(messageHash in subscriptions)) {
62
+ subscriptions[messageHash] = request;
63
+ }
64
+ const finalMessage = [
52
65
  {
53
66
  'ticket': this.uuid(),
54
67
  },
55
- {
56
- 'type': channel,
57
- 'codes': marketIds,
58
- // 'isOnlySnapshot': false,
59
- // 'isOnlyRealtime': false,
60
- },
61
68
  ];
62
- const messageHash = channel + ':' + marketId;
63
- return await this.watch(url, messageHash, request, messageHash);
69
+ const channelKeys = Object.keys(subscriptions);
70
+ for (let i = 0; i < channelKeys.length; i++) {
71
+ const key = channelKeys[i];
72
+ finalMessage.push(subscriptions[key]);
73
+ }
74
+ return await this.watch(url, messageHash, finalMessage, messageHash);
64
75
  }
65
76
  async watchPublicMultiple(symbols, channel, params = {}) {
66
77
  await this.loadMarkets();
package/js/src/pro/xt.js CHANGED
@@ -245,10 +245,7 @@ export default class xt extends xtRest {
245
245
  unsubscribe['params'] = [name];
246
246
  }
247
247
  const tradeType = isContract ? 'contract' : 'spot';
248
- let subMessageHash = name + '::' + tradeType;
249
- if (symbols !== undefined) {
250
- subMessageHash = subMessageHash + '::' + symbols.join(',');
251
- }
248
+ const subMessageHash = name + '::' + tradeType;
252
249
  const request = this.extend(unsubscribe, params);
253
250
  let tail = access;
254
251
  if (isContract) {
@@ -263,6 +260,11 @@ export default class xt extends xtRest {
263
260
  'symbols': symbols,
264
261
  'topic': topic,
265
262
  };
263
+ const symbolsAndTimeframes = this.safeList(subscriptionParams, 'symbolsAndTimeframes');
264
+ if (symbolsAndTimeframes !== undefined) {
265
+ subscription['symbolsAndTimeframes'] = symbolsAndTimeframes;
266
+ subscriptionParams = this.omit(subscriptionParams, 'symbolsAndTimeframes');
267
+ }
266
268
  return await this.watch(url, messageHash, this.extend(request, params), messageHash, this.extend(subscription, subscriptionParams));
267
269
  }
268
270
  /**
@@ -325,7 +327,6 @@ export default class xt extends xtRest {
325
327
  const options = this.safeDict(this.options, 'watchTickers');
326
328
  const defaultMethod = this.safeString(options, 'method', 'tickers');
327
329
  const name = this.safeString(params, 'method', defaultMethod);
328
- symbols = this.marketSymbols(symbols);
329
330
  let market = undefined;
330
331
  if (symbols !== undefined) {
331
332
  market = this.market(symbols[0]);
@@ -402,8 +403,8 @@ export default class xt extends xtRest {
402
403
  const market = this.market(symbol);
403
404
  const name = 'kline@' + market['id'] + ',' + timeframe;
404
405
  const messageHash = 'unsubscribe::' + name;
405
- params['symbolsAndTimeframes'] = [[market['symbol'], timeframe]];
406
- return await this.unSubscribe(messageHash, name, 'public', 'unWatchOHLCV', 'kline', market, undefined, params);
406
+ const symbolsAndTimeframes = [[market['symbol'], timeframe]];
407
+ return await this.unSubscribe(messageHash, name, 'public', 'unWatchOHLCV', 'ohlcv', market, [symbol], params, { 'symbolsAndTimeframes': symbolsAndTimeframes });
407
408
  }
408
409
  /**
409
410
  * @method
@@ -442,7 +443,7 @@ export default class xt extends xtRest {
442
443
  const market = this.market(symbol);
443
444
  const name = 'trade@' + market['id'];
444
445
  const messageHash = 'unsubscribe::' + name;
445
- return await this.unSubscribe(messageHash, name, 'public', 'unWatchTrades', 'trade', market, undefined, params);
446
+ return await this.unSubscribe(messageHash, name, 'public', 'unWatchTrades', 'trades', market, [symbol], params);
446
447
  }
447
448
  /**
448
449
  * @method
@@ -493,7 +494,7 @@ export default class xt extends xtRest {
493
494
  name = 'depth@' + market['id'] + ',' + levels;
494
495
  }
495
496
  const messageHash = 'unsubscribe::' + name;
496
- return await this.unSubscribe(messageHash, name, 'public', 'unWatchOrderBook', 'depth', market, undefined, params);
497
+ return await this.unSubscribe(messageHash, name, 'public', 'unWatchOrderBook', 'orderbook', market, [symbol], params);
497
498
  }
498
499
  /**
499
500
  * @method
package/js/src/upbit.js CHANGED
@@ -22,7 +22,7 @@ export default class upbit extends Exchange {
22
22
  return this.deepExtend(super.describe(), {
23
23
  'id': 'upbit',
24
24
  'name': 'Upbit',
25
- 'countries': ['KR'],
25
+ 'countries': ['KR', 'ID', 'SG', 'TH'],
26
26
  'version': 'v1',
27
27
  'rateLimit': 50,
28
28
  'pro': true,
@@ -103,7 +103,7 @@ export default class upbit extends Exchange {
103
103
  'private': 'https://{hostname}',
104
104
  },
105
105
  'www': 'https://upbit.com',
106
- 'doc': 'https://docs.upbit.com/docs/%EC%9A%94%EC%B2%AD-%EC%88%98-%EC%A0%9C%ED%95%9C',
106
+ 'doc': ['https://docs.upbit.com/kr', 'https://global-docs.upbit.com'],
107
107
  'fees': 'https://upbit.com/service_center/guide',
108
108
  },
109
109
  'api': {
@@ -133,7 +133,6 @@ export default class upbit extends Exchange {
133
133
  'ticker/all': 2,
134
134
  'orderbook': 2,
135
135
  'orderbook/instruments': 2,
136
- 'orderbook/supported_levels': 2, // Upbit KR only, deprecatd
137
136
  },
138
137
  },
139
138
  'private': {
@@ -159,6 +158,7 @@ export default class upbit extends Exchange {
159
158
  },
160
159
  'post': {
161
160
  'orders': 2.5,
161
+ 'orders/test': 2.5,
162
162
  'orders/cancel_and_new': 2.5,
163
163
  'withdraws/coin': 0.67,
164
164
  'withdraws/krw': 0.67,
@@ -171,6 +171,7 @@ export default class upbit extends Exchange {
171
171
  'order': 0.67,
172
172
  'orders/open': 40,
173
173
  'orders/uuids': 0.67,
174
+ 'withdraws/coin': 0.67,
174
175
  },
175
176
  },
176
177
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccxt",
3
- "version": "4.5.20",
3
+ "version": "4.5.21",
4
4
  "description": "A cryptocurrency trading API with more than 100 exchanges in JavaScript / TypeScript / Python / C# / PHP / Go",
5
5
  "unpkg": "dist/ccxt.browser.min.js",
6
6
  "type": "module",