ccxt 4.5.22 → 4.5.23

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 (68) hide show
  1. package/README.md +6 -5
  2. package/dist/ccxt.browser.min.js +2 -2
  3. package/dist/cjs/ccxt.js +6 -1
  4. package/dist/cjs/src/abstract/bullish.js +11 -0
  5. package/dist/cjs/src/base/Exchange.js +3 -2
  6. package/dist/cjs/src/base/ws/WsClient.js +15 -0
  7. package/dist/cjs/src/binance.js +159 -36
  8. package/dist/cjs/src/bingx.js +2 -1
  9. package/dist/cjs/src/bitmart.js +1 -0
  10. package/dist/cjs/src/bullish.js +2919 -0
  11. package/dist/cjs/src/bybit.js +34 -37
  12. package/dist/cjs/src/gate.js +2 -2
  13. package/dist/cjs/src/htx.js +4 -1
  14. package/dist/cjs/src/hyperliquid.js +115 -12
  15. package/dist/cjs/src/kucoin.js +22 -3
  16. package/dist/cjs/src/mexc.js +7 -0
  17. package/dist/cjs/src/okx.js +117 -63
  18. package/dist/cjs/src/paradex.js +78 -3
  19. package/dist/cjs/src/pro/binance.js +131 -29
  20. package/dist/cjs/src/pro/bullish.js +781 -0
  21. package/dist/cjs/src/pro/coinbase.js +2 -2
  22. package/dist/cjs/src/pro/hyperliquid.js +75 -15
  23. package/dist/cjs/src/pro/upbit.js +28 -82
  24. package/js/ccxt.d.ts +8 -2
  25. package/js/ccxt.js +6 -2
  26. package/js/src/abstract/binance.d.ts +1 -0
  27. package/js/src/abstract/binancecoinm.d.ts +1 -0
  28. package/js/src/abstract/binanceus.d.ts +1 -0
  29. package/js/src/abstract/binanceusdm.d.ts +1 -0
  30. package/js/src/abstract/bingx.d.ts +1 -0
  31. package/js/src/abstract/bullish.d.ts +65 -0
  32. package/js/src/abstract/bullish.js +5 -0
  33. package/js/src/abstract/kucoin.d.ts +15 -0
  34. package/js/src/abstract/kucoinfutures.d.ts +15 -0
  35. package/js/src/abstract/mexc.d.ts +7 -0
  36. package/js/src/abstract/myokx.d.ts +90 -39
  37. package/js/src/abstract/okx.d.ts +90 -39
  38. package/js/src/abstract/okxus.d.ts +90 -39
  39. package/js/src/base/Exchange.d.ts +1 -1
  40. package/js/src/base/Exchange.js +3 -2
  41. package/js/src/base/ws/Client.d.ts +1 -0
  42. package/js/src/base/ws/WsClient.js +15 -0
  43. package/js/src/binance.d.ts +14 -5
  44. package/js/src/binance.js +159 -36
  45. package/js/src/bingx.js +2 -1
  46. package/js/src/bitmart.js +1 -0
  47. package/js/src/bullish.d.ts +446 -0
  48. package/js/src/bullish.js +2912 -0
  49. package/js/src/bybit.js +34 -37
  50. package/js/src/gate.js +2 -2
  51. package/js/src/htx.js +4 -1
  52. package/js/src/hyperliquid.d.ts +24 -0
  53. package/js/src/hyperliquid.js +115 -12
  54. package/js/src/kucoin.js +22 -3
  55. package/js/src/mexc.js +7 -0
  56. package/js/src/okx.js +117 -63
  57. package/js/src/paradex.d.ts +15 -1
  58. package/js/src/paradex.js +78 -3
  59. package/js/src/pro/binance.d.ts +7 -0
  60. package/js/src/pro/binance.js +131 -29
  61. package/js/src/pro/bullish.d.ts +108 -0
  62. package/js/src/pro/bullish.js +774 -0
  63. package/js/src/pro/coinbase.js +2 -2
  64. package/js/src/pro/hyperliquid.d.ts +13 -1
  65. package/js/src/pro/hyperliquid.js +75 -15
  66. package/js/src/pro/upbit.d.ts +0 -1
  67. package/js/src/pro/upbit.js +28 -82
  68. package/package.json +2 -2
package/js/src/bybit.js CHANGED
@@ -3966,15 +3966,12 @@ export default class bybit extends Exchange {
3966
3966
  const market = this.market(symbol);
3967
3967
  const parts = await this.isUnifiedEnabled();
3968
3968
  const enableUnifiedAccount = parts[1];
3969
- const trailingAmount = this.safeString2(params, 'trailingAmount', 'trailingStop');
3970
- const stopLossPrice = this.safeString(params, 'stopLossPrice');
3971
- const takeProfitPrice = this.safeString(params, 'takeProfitPrice');
3972
- const isTrailingAmountOrder = trailingAmount !== undefined;
3973
- const isStopLoss = stopLossPrice !== undefined;
3974
- const isTakeProfit = takeProfitPrice !== undefined;
3969
+ const isTrailingOrder = this.safeString2(params, 'trailingAmount', 'trailingStop') !== undefined;
3970
+ const isStopLossOrder = this.safeString(params, 'stopLossPrice') !== undefined;
3971
+ const isTakeProfitOrder = this.safeString(params, 'takeProfitPrice') !== undefined;
3975
3972
  const orderRequest = this.createOrderRequest(symbol, type, side, amount, price, params, enableUnifiedAccount);
3976
3973
  let defaultMethod = undefined;
3977
- if ((isTrailingAmountOrder || isStopLoss || isTakeProfit) && !market['spot']) {
3974
+ if ((isTrailingOrder || isStopLossOrder || isTakeProfitOrder) && !market['spot']) {
3978
3975
  defaultMethod = 'privatePostV5PositionTradingStop';
3979
3976
  }
3980
3977
  else {
@@ -4045,17 +4042,17 @@ export default class bybit extends Exchange {
4045
4042
  const takeProfit = this.safeValue(params, 'takeProfit');
4046
4043
  const trailingTriggerPrice = this.safeString2(params, 'trailingTriggerPrice', 'activePrice', this.numberToString(price));
4047
4044
  const trailingAmount = this.safeString2(params, 'trailingAmount', 'trailingStop');
4048
- const isTrailingAmountOrder = trailingAmount !== undefined;
4045
+ const isTrailingOrder = trailingAmount !== undefined;
4049
4046
  const isTriggerOrder = triggerPrice !== undefined;
4050
- const isStopLossTriggerOrder = stopLossTriggerPrice !== undefined;
4051
- const isTakeProfitTriggerOrder = takeProfitTriggerPrice !== undefined;
4052
- const isStopLoss = stopLoss !== undefined;
4047
+ const isStopLossOrder = stopLossTriggerPrice !== undefined;
4048
+ const isTakeProfitOrder = takeProfitTriggerPrice !== undefined;
4049
+ const hasStopLoss = stopLoss !== undefined;
4053
4050
  const isTakeProfit = takeProfit !== undefined;
4054
4051
  const isMarket = lowerCaseType === 'market';
4055
4052
  const isLimit = lowerCaseType === 'limit';
4056
4053
  const isBuy = side === 'buy';
4057
4054
  let defaultMethod = undefined;
4058
- if ((isTrailingAmountOrder || isStopLossTriggerOrder || isTakeProfitTriggerOrder) && !market['spot']) {
4055
+ if ((isTrailingOrder || isStopLossOrder || isTakeProfitOrder) && !market['spot']) {
4059
4056
  defaultMethod = 'privatePostV5PositionTradingStop';
4060
4057
  }
4061
4058
  else {
@@ -4063,14 +4060,14 @@ export default class bybit extends Exchange {
4063
4060
  }
4064
4061
  let method = undefined;
4065
4062
  [method, params] = this.handleOptionAndParams(params, 'createOrder', 'method', defaultMethod);
4066
- const isAlternativeEndpoint = method === 'privatePostV5PositionTradingStop';
4063
+ const endpointIsTradingStop = method === 'privatePostV5PositionTradingStop';
4067
4064
  const amountString = this.getAmount(symbol, amount);
4068
4065
  const priceString = (price !== undefined) ? this.getPrice(symbol, this.numberToString(price)) : undefined;
4069
- if (isTrailingAmountOrder || isAlternativeEndpoint) {
4070
- if (isStopLoss || isTakeProfit || isTriggerOrder || market['spot']) {
4066
+ if (isTrailingOrder || endpointIsTradingStop) {
4067
+ if (hasStopLoss || isTakeProfit || isTriggerOrder || market['spot']) {
4071
4068
  throw new InvalidOrder(this.id + ' the API endpoint used only supports contract trailingAmount, stopLossPrice and takeProfitPrice orders');
4072
4069
  }
4073
- if (isStopLossTriggerOrder || isTakeProfitTriggerOrder) {
4070
+ if (isStopLossOrder || isTakeProfitOrder) {
4074
4071
  const tpslMode = this.safeString(params, 'tpslMode', 'Partial');
4075
4072
  const isFullTpsl = tpslMode === 'Full';
4076
4073
  const isPartialTpsl = tpslMode === 'Partial';
@@ -4078,7 +4075,7 @@ export default class bybit extends Exchange {
4078
4075
  throw new InvalidOrder(this.id + ' tpsl orders with "full" tpslMode only support "market" type');
4079
4076
  }
4080
4077
  request['tpslMode'] = tpslMode;
4081
- if (isStopLossTriggerOrder) {
4078
+ if (isStopLossOrder) {
4082
4079
  request['stopLoss'] = this.getPrice(symbol, stopLossTriggerPrice);
4083
4080
  if (isPartialTpsl) {
4084
4081
  request['slSize'] = amountString;
@@ -4088,7 +4085,7 @@ export default class bybit extends Exchange {
4088
4085
  request['slLimitPrice'] = priceString;
4089
4086
  }
4090
4087
  }
4091
- else if (isTakeProfitTriggerOrder) {
4088
+ else if (isTakeProfitOrder) {
4092
4089
  request['takeProfit'] = this.getPrice(symbol, takeProfitTriggerPrice);
4093
4090
  if (isPartialTpsl) {
4094
4091
  request['tpSize'] = amountString;
@@ -4123,7 +4120,7 @@ export default class bybit extends Exchange {
4123
4120
  if (triggerPrice !== undefined) {
4124
4121
  request['orderFilter'] = 'StopOrder';
4125
4122
  }
4126
- else if (isStopLossTriggerOrder || isTakeProfitTriggerOrder) {
4123
+ else if (isStopLossOrder || isTakeProfitOrder) {
4127
4124
  request['orderFilter'] = 'tpslOrder';
4128
4125
  }
4129
4126
  }
@@ -4194,17 +4191,17 @@ export default class bybit extends Exchange {
4194
4191
  }
4195
4192
  }
4196
4193
  else {
4197
- if (!isTrailingAmountOrder && !isAlternativeEndpoint) {
4194
+ if (!isTrailingOrder && !endpointIsTradingStop) {
4198
4195
  request['qty'] = amountString;
4199
4196
  }
4200
4197
  }
4201
- if (isTrailingAmountOrder) {
4198
+ if (isTrailingOrder) {
4202
4199
  if (trailingTriggerPrice !== undefined) {
4203
4200
  request['activePrice'] = this.getPrice(symbol, trailingTriggerPrice);
4204
4201
  }
4205
4202
  request['trailingStop'] = trailingAmount;
4206
4203
  }
4207
- else if (isTriggerOrder && !isAlternativeEndpoint) {
4204
+ else if (isTriggerOrder && !endpointIsTradingStop) {
4208
4205
  const triggerDirection = this.safeString(params, 'triggerDirection');
4209
4206
  params = this.omit(params, ['triggerPrice', 'stopPrice', 'triggerDirection']);
4210
4207
  if (market['spot']) {
@@ -4221,19 +4218,19 @@ export default class bybit extends Exchange {
4221
4218
  }
4222
4219
  request['triggerPrice'] = this.getPrice(symbol, triggerPrice);
4223
4220
  }
4224
- else if ((isStopLossTriggerOrder || isTakeProfitTriggerOrder) && !isAlternativeEndpoint) {
4221
+ else if ((isStopLossOrder || isTakeProfitOrder) && !endpointIsTradingStop) {
4225
4222
  if (isBuy) {
4226
- request['triggerDirection'] = isStopLossTriggerOrder ? 1 : 2;
4223
+ request['triggerDirection'] = isStopLossOrder ? 1 : 2;
4227
4224
  }
4228
4225
  else {
4229
- request['triggerDirection'] = isStopLossTriggerOrder ? 2 : 1;
4226
+ request['triggerDirection'] = isStopLossOrder ? 2 : 1;
4230
4227
  }
4231
- triggerPrice = isStopLossTriggerOrder ? stopLossTriggerPrice : takeProfitTriggerPrice;
4228
+ triggerPrice = isStopLossOrder ? stopLossTriggerPrice : takeProfitTriggerPrice;
4232
4229
  request['triggerPrice'] = this.getPrice(symbol, triggerPrice);
4233
4230
  request['reduceOnly'] = true;
4234
4231
  }
4235
- if ((isStopLoss || isTakeProfit) && !isAlternativeEndpoint) {
4236
- if (isStopLoss) {
4232
+ if ((hasStopLoss || isTakeProfit) && !endpointIsTradingStop) {
4233
+ if (hasStopLoss) {
4237
4234
  const slTriggerPrice = this.safeValue2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss);
4238
4235
  request['stopLoss'] = this.getPrice(symbol, slTriggerPrice);
4239
4236
  const slLimitPrice = this.safeValue(stopLoss, 'price');
@@ -4412,12 +4409,12 @@ export default class bybit extends Exchange {
4412
4409
  const takeProfitTriggerPrice = this.safeString(params, 'takeProfitPrice');
4413
4410
  const stopLoss = this.safeValue(params, 'stopLoss');
4414
4411
  const takeProfit = this.safeValue(params, 'takeProfit');
4415
- const isStopLossTriggerOrder = stopLossTriggerPrice !== undefined;
4416
- const isTakeProfitTriggerOrder = takeProfitTriggerPrice !== undefined;
4417
- const isStopLoss = stopLoss !== undefined;
4418
- const isTakeProfit = takeProfit !== undefined;
4419
- if (isStopLossTriggerOrder || isTakeProfitTriggerOrder) {
4420
- triggerPrice = isStopLossTriggerOrder ? stopLossTriggerPrice : takeProfitTriggerPrice;
4412
+ const isStopLossOrder = stopLossTriggerPrice !== undefined;
4413
+ const isTakeProfitOrder = takeProfitTriggerPrice !== undefined;
4414
+ const hasStopLoss = stopLoss !== undefined;
4415
+ const hasTakeProfit = takeProfit !== undefined;
4416
+ if (isStopLossOrder || isTakeProfitOrder) {
4417
+ triggerPrice = isStopLossOrder ? stopLossTriggerPrice : takeProfitTriggerPrice;
4421
4418
  }
4422
4419
  if (triggerPrice !== undefined) {
4423
4420
  const triggerPriceRequest = (triggerPrice === '0') ? triggerPrice : this.getPrice(symbol, triggerPrice);
@@ -4425,15 +4422,15 @@ export default class bybit extends Exchange {
4425
4422
  const triggerBy = this.safeString(params, 'triggerBy', 'LastPrice');
4426
4423
  request['triggerBy'] = triggerBy;
4427
4424
  }
4428
- if (isStopLoss || isTakeProfit) {
4429
- if (isStopLoss) {
4425
+ if (hasStopLoss || hasTakeProfit) {
4426
+ if (hasStopLoss) {
4430
4427
  const slTriggerPrice = this.safeString2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss);
4431
4428
  const stopLossRequest = (slTriggerPrice === '0') ? slTriggerPrice : this.getPrice(symbol, slTriggerPrice);
4432
4429
  request['stopLoss'] = stopLossRequest;
4433
4430
  const slTriggerBy = this.safeString(params, 'slTriggerBy', 'LastPrice');
4434
4431
  request['slTriggerBy'] = slTriggerBy;
4435
4432
  }
4436
- if (isTakeProfit) {
4433
+ if (hasTakeProfit) {
4437
4434
  const tpTriggerPrice = this.safeString2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit);
4438
4435
  const takeProfitRequest = (tpTriggerPrice === '0') ? tpTriggerPrice : this.getPrice(symbol, tpTriggerPrice);
4439
4436
  request['takeProfit'] = takeProfitRequest;
package/js/src/gate.js CHANGED
@@ -1086,7 +1086,6 @@ export default class gate extends Exchange {
1086
1086
  'LOAN_RECORD_NOT_FOUND': OrderNotFound,
1087
1087
  'NO_MATCHED_LOAN': ExchangeError,
1088
1088
  'NOT_MERGEABLE': ExchangeError,
1089
- 'NO_CHANGE': ExchangeError,
1090
1089
  'REPAY_TOO_MUCH': ExchangeError,
1091
1090
  'TOO_MANY_CURRENCY_PAIRS': InvalidOrder,
1092
1091
  'TOO_MANY_ORDERS': InvalidOrder,
@@ -1128,7 +1127,8 @@ export default class gate extends Exchange {
1128
1127
  'AUTO_TRIGGER_PRICE_LESS_LAST': InvalidOrder,
1129
1128
  'AUTO_TRIGGER_PRICE_GREATE_LAST': InvalidOrder,
1130
1129
  'POSITION_HOLDING': BadRequest,
1131
- 'USER_LOAN_EXCEEDED': BadRequest, // {"label":"USER_LOAN_EXCEEDED","message":"Max loan amount per user would be exceeded"}
1130
+ 'USER_LOAN_EXCEEDED': BadRequest,
1131
+ 'NO_CHANGE': InvalidOrder, // {"label":"NO_CHANGE","message":"No change is made"}
1132
1132
  },
1133
1133
  'broad': {},
1134
1134
  },
package/js/src/htx.js CHANGED
@@ -927,6 +927,7 @@ export default class htx extends Exchange {
927
927
  'base-symbol-error': BadSymbol,
928
928
  'system-maintenance': OnMaintenance,
929
929
  'base-request-exceed-frequency-limit': RateLimitExceeded,
930
+ 'rate-too-many-requests': RateLimitExceeded,
930
931
  // err-msg
931
932
  'invalid symbol': BadSymbol,
932
933
  'symbol trade not open now': BadSymbol,
@@ -5552,7 +5553,9 @@ export default class htx extends Exchange {
5552
5553
  params = this.omit(params, ['clientOrderId']);
5553
5554
  }
5554
5555
  if (type === 'limit' || type === 'ioc' || type === 'fok' || type === 'post_only') {
5555
- request['price'] = this.priceToPrecision(symbol, price);
5556
+ if (price !== undefined) {
5557
+ request['price'] = this.priceToPrecision(symbol, price);
5558
+ }
5556
5559
  }
5557
5560
  }
5558
5561
  const reduceOnly = this.safeBool2(params, 'reduceOnly', 'reduce_only', false);
@@ -9,6 +9,28 @@ export default class hyperliquid extends Exchange {
9
9
  setSandboxMode(enabled: any): void;
10
10
  market(symbol: string): MarketInterface;
11
11
  safeMarket(marketId?: Str, market?: Market, delimiter?: Str, marketType?: Str): MarketInterface;
12
+ /**
13
+ * @method
14
+ * @name hyperliquid#fetchStatus
15
+ * @description the latest known information on the availability of the exchange API
16
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
17
+ * @returns {object} a [status structure]{@link https://docs.ccxt.com/#/?id=exchange-status-structure}
18
+ */
19
+ fetchStatus(params?: {}): Promise<{
20
+ status: string;
21
+ updated: number;
22
+ eta: any;
23
+ url: any;
24
+ info: any;
25
+ }>;
26
+ /**
27
+ * @method
28
+ * @name hyperliquid#fetchTime
29
+ * @description fetches the current integer timestamp in milliseconds from the exchange server
30
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
31
+ * @returns {int} the current integer timestamp in milliseconds from the exchange server
32
+ */
33
+ fetchTime(params?: {}): Promise<number>;
12
34
  /**
13
35
  * @method
14
36
  * @name hyperliquid#fetchCurrencies
@@ -77,6 +99,7 @@ export default class hyperliquid extends Exchange {
77
99
  * @param {string} [params.user] user address, will default to this.walletAddress if not provided
78
100
  * @param {string} [params.type] wallet type, ['spot', 'swap'], defaults to swap
79
101
  * @param {string} [params.marginMode] 'cross' or 'isolated', for margin trading, uses this.options.defaultMarginMode if not passed, defaults to undefined/None/null
102
+ * @param {string} [params.dex] for hip3 markets, the dex name, eg: 'xyz'
80
103
  * @param {string} [params.subAccountAddress] sub account user address
81
104
  * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
82
105
  */
@@ -101,6 +124,7 @@ export default class hyperliquid extends Exchange {
101
124
  * @param {string[]} [symbols] unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
102
125
  * @param {object} [params] extra parameters specific to the exchange API endpoint
103
126
  * @param {string} [params.type] 'spot' or 'swap', by default fetches both
127
+ * @param {boolean} [params.hip3] set to true to fetch hip3 markets only
104
128
  * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
105
129
  */
106
130
  fetchTickers(symbols?: Strings, params?: {}): Promise<Tickers>;
@@ -97,9 +97,10 @@ export default class hyperliquid extends Exchange {
97
97
  'fetchPositions': true,
98
98
  'fetchPositionsRisk': false,
99
99
  'fetchPremiumIndexOHLCV': false,
100
+ 'fetchStatus': true,
100
101
  'fetchTicker': 'emulated',
101
102
  'fetchTickers': true,
102
- 'fetchTime': false,
103
+ 'fetchTime': true,
103
104
  'fetchTrades': true,
104
105
  'fetchTradingFee': true,
105
106
  'fetchTradingFees': false,
@@ -215,6 +216,7 @@ export default class hyperliquid extends Exchange {
215
216
  'defaultType': 'swap',
216
217
  'sandboxMode': false,
217
218
  'defaultSlippage': 0.05,
219
+ 'marketHelperProps': ['hip3TokensByName', 'cachedCurrenciesById'],
218
220
  'zeroAddress': '0x0000000000000000000000000000000000000000',
219
221
  'spotCurrencyMapping': {
220
222
  'UDZ': '2Z',
@@ -402,6 +404,49 @@ export default class hyperliquid extends Exchange {
402
404
  }
403
405
  return super.safeMarket(marketId, market, delimiter, marketType);
404
406
  }
407
+ /**
408
+ * @method
409
+ * @name hyperliquid#fetchStatus
410
+ * @description the latest known information on the availability of the exchange API
411
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
412
+ * @returns {object} a [status structure]{@link https://docs.ccxt.com/#/?id=exchange-status-structure}
413
+ */
414
+ async fetchStatus(params = {}) {
415
+ const request = {
416
+ 'type': 'exchangeStatus',
417
+ };
418
+ const response = await this.publicPostInfo(this.extend(request, params));
419
+ //
420
+ // {
421
+ // "status": "ok"
422
+ // }
423
+ //
424
+ const status = this.safeString(response, 'specialStatuses');
425
+ return {
426
+ 'status': (status === undefined) ? 'ok' : 'maintenance',
427
+ 'updated': this.safeInteger(response, 'time'),
428
+ 'eta': undefined,
429
+ 'url': undefined,
430
+ 'info': response,
431
+ };
432
+ }
433
+ /**
434
+ * @method
435
+ * @name hyperliquid#fetchTime
436
+ * @description fetches the current integer timestamp in milliseconds from the exchange server
437
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
438
+ * @returns {int} the current integer timestamp in milliseconds from the exchange server
439
+ */
440
+ async fetchTime(params = {}) {
441
+ const request = {
442
+ 'type': 'exchangeStatus',
443
+ };
444
+ const response = await this.publicPostInfo(this.extend(request, params));
445
+ //
446
+ // { specialStatuses: null, time: '1764617438643' }
447
+ //
448
+ return this.safeInteger(response, 'time');
449
+ }
405
450
  /**
406
451
  * @method
407
452
  * @name hyperliquid#fetchCurrencies
@@ -415,7 +460,8 @@ export default class hyperliquid extends Exchange {
415
460
  await this.initializeClient();
416
461
  }
417
462
  const request = {
418
- 'type': 'meta',
463
+ // 'type': 'meta',
464
+ 'type': 'spotMeta',
419
465
  };
420
466
  const response = await this.publicPostInfo(this.extend(request, params));
421
467
  //
@@ -432,18 +478,23 @@ export default class hyperliquid extends Exchange {
432
478
  // }
433
479
  // ]
434
480
  //
435
- const meta = this.safeList(response, 'universe', []);
481
+ // const spotMeta = await this.publicPostInfo ({ 'type': 'spotMeta' });
482
+ const tokens = this.safeList(response, 'tokens', []);
483
+ // const meta = this.safeList (response, 'universe', []);
484
+ this.options['cachedCurrenciesById'] = {}; // used to map hip3 markets
436
485
  const result = {};
437
- for (let i = 0; i < meta.length; i++) {
438
- const data = this.safeDict(meta, i, {});
439
- const id = i;
486
+ for (let i = 0; i < tokens.length; i++) {
487
+ const data = this.safeDict(tokens, i, {});
488
+ // const id = i;
489
+ const id = this.safeString(data, 'index');
440
490
  const name = this.safeString(data, 'name');
441
491
  const code = this.safeCurrencyCode(name);
492
+ this.options['cachedCurrenciesById'][id] = name;
442
493
  result[code] = this.safeCurrencyStructure({
443
494
  'id': id,
444
495
  'name': name,
445
496
  'code': code,
446
- 'precision': undefined,
497
+ 'precision': this.parsePrecision(this.safeString(data, 'weiDecimals')),
447
498
  'info': data,
448
499
  'active': undefined,
449
500
  'deposit': undefined,
@@ -565,18 +616,38 @@ export default class hyperliquid extends Exchange {
565
616
  rawPromises.push(this.publicPostInfo(this.extend(request, params)));
566
617
  }
567
618
  const promises = await Promise.all(rawPromises);
619
+ this.options['hip3TokensByName'] = {};
568
620
  let markets = [];
569
621
  for (let i = 0; i < promises.length; i++) {
570
622
  const dexName = fetchDexesList[i];
571
623
  const offset = perpDexesOffset[dexName];
572
624
  const response = promises[i];
573
625
  const meta = this.safeDict(response, 0, {});
626
+ const collateralToken = this.safeString(meta, 'collateralToken');
574
627
  const universe = this.safeList(meta, 'universe', []);
575
628
  const assetCtxs = this.safeList(response, 1, []);
576
629
  const result = [];
630
+ // helper because some endpoints return just the coin name like: flx:crcl
631
+ // and we don't have the base/settle information and we can't assume it's USDC for hip3 markets
577
632
  for (let j = 0; j < universe.length; j++) {
578
633
  const data = this.extend(this.safeDict(universe, j, {}), this.safeDict(assetCtxs, j, {}));
579
634
  data['baseId'] = j + offset;
635
+ data['collateralToken'] = collateralToken;
636
+ data['hip3'] = true;
637
+ data['dex'] = dexName;
638
+ const cachedCurrencies = this.safeDict(this.options, 'cachedCurrenciesById', {});
639
+ // injecting collateral token name for further usage in parseMarket, already converted from like '0' to 'USDC', etc
640
+ if (collateralToken in cachedCurrencies) {
641
+ const name = this.safeString(data, 'name');
642
+ const collateralTokenCode = this.safeString(cachedCurrencies, collateralToken);
643
+ data['collateralTokenName'] = collateralTokenCode;
644
+ // eg: 'flx:crcl' => {'quote': 'USDC', 'code': 'FLX-CRCL'}
645
+ const safeCode = this.safeCurrencyCode(name);
646
+ this.options['hip3TokensByName'][name] = {
647
+ 'quote': collateralTokenCode,
648
+ 'code': safeCode.replace(':', '-'),
649
+ };
650
+ }
580
651
  result.push(data);
581
652
  }
582
653
  markets = this.arrayConcat(markets, this.parseMarkets(result));
@@ -909,16 +980,19 @@ export default class hyperliquid extends Exchange {
909
980
  // "oraclePx": "2367.3",
910
981
  // "premium": "0.00090821",
911
982
  // "prevDayPx": "2381.5"
983
+ // "collateralToken": "0" hip3 tokens only
912
984
  // }
913
985
  //
914
- const quoteId = 'USDC';
986
+ const collateralTokenCode = this.safeString(market, 'collateralTokenName');
987
+ const quoteId = (collateralTokenCode === undefined) ? 'USDC' : collateralTokenCode;
988
+ const settleId = (collateralTokenCode === undefined) ? 'USDC' : collateralTokenCode;
915
989
  const baseName = this.safeString(market, 'name');
916
- const base = this.safeCurrencyCode(baseName);
990
+ let base = this.safeCurrencyCode(baseName);
991
+ base = base.replace(':', '-'); // handle hip3 tokens and converts from like flx:crcl to FLX-CRCL
917
992
  const quote = this.safeCurrencyCode(quoteId);
918
993
  const baseId = this.safeString(market, 'baseId');
919
- const settleId = 'USDC';
920
994
  const settle = this.safeCurrencyCode(settleId);
921
- let symbol = base.replace(':', '-') + '/' + quote;
995
+ let symbol = base + '/' + quote;
922
996
  const contract = true;
923
997
  const swap = true;
924
998
  if (contract) {
@@ -1005,6 +1079,7 @@ export default class hyperliquid extends Exchange {
1005
1079
  * @param {string} [params.user] user address, will default to this.walletAddress if not provided
1006
1080
  * @param {string} [params.type] wallet type, ['spot', 'swap'], defaults to swap
1007
1081
  * @param {string} [params.marginMode] 'cross' or 'isolated', for margin trading, uses this.options.defaultMarginMode if not passed, defaults to undefined/None/null
1082
+ * @param {string} [params.dex] for hip3 markets, the dex name, eg: 'xyz'
1008
1083
  * @param {string} [params.subAccountAddress] sub account user address
1009
1084
  * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
1010
1085
  */
@@ -1147,6 +1222,7 @@ export default class hyperliquid extends Exchange {
1147
1222
  * @param {string[]} [symbols] unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1148
1223
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1149
1224
  * @param {string} [params.type] 'spot' or 'swap', by default fetches both
1225
+ * @param {boolean} [params.hip3] set to true to fetch hip3 markets only
1150
1226
  * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
1151
1227
  */
1152
1228
  async fetchTickers(symbols = undefined, params = {}) {
@@ -1156,7 +1232,21 @@ export default class hyperliquid extends Exchange {
1156
1232
  let response = [];
1157
1233
  const type = this.safeString(params, 'type');
1158
1234
  params = this.omit(params, 'type');
1159
- if (type === 'spot') {
1235
+ let hip3 = false;
1236
+ [hip3, params] = this.handleOptionAndParams(params, 'fetchTickers', 'hip3', false);
1237
+ if (symbols !== undefined) {
1238
+ // infer from first symbol
1239
+ const firstSymbol = this.safeString(symbols, 0);
1240
+ const market = this.market(firstSymbol);
1241
+ if (this.safeBool(this.safeDict(market, 'info'), 'hip3')) {
1242
+ hip3 = true;
1243
+ }
1244
+ }
1245
+ if (hip3) {
1246
+ params = this.omit(params, 'hip3');
1247
+ response = await this.fetchHip3Markets(params);
1248
+ }
1249
+ else if (type === 'spot') {
1160
1250
  response = await this.fetchSpotMarkets(params);
1161
1251
  }
1162
1252
  else if (type === 'swap') {
@@ -1296,6 +1386,9 @@ export default class hyperliquid extends Exchange {
1296
1386
  // "circulatingSupply": "998949190.03400207", // only in spot
1297
1387
  // },
1298
1388
  //
1389
+ const name = this.safeString(ticker, 'name');
1390
+ const marketId = this.coinToMarketId(name);
1391
+ market = this.safeMarket(marketId, market);
1299
1392
  const bidAsk = this.safeList(ticker, 'impactPxs');
1300
1393
  return this.safeTicker({
1301
1394
  'symbol': market['symbol'],
@@ -4227,6 +4320,16 @@ export default class hyperliquid extends Exchange {
4227
4320
  throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a user parameter inside \'params\' or the wallet address set');
4228
4321
  }
4229
4322
  coinToMarketId(coin) {
4323
+ // handle also hip3 tokens like flx:CRCL
4324
+ if (coin === undefined) {
4325
+ return undefined;
4326
+ }
4327
+ if (this.safeDict(this.options['hip3TokensByName'], coin)) {
4328
+ const hip3Dict = this.options['hip3TokensByName'][coin];
4329
+ const quote = this.safeString(hip3Dict, 'quote', 'USDC');
4330
+ const code = this.safeString(hip3Dict, 'code', coin);
4331
+ return code + '/' + quote + ':' + quote;
4332
+ }
4230
4333
  if (coin.indexOf('/') > -1 || coin.indexOf('@') > -1) {
4231
4334
  return coin; // spot
4232
4335
  }
package/js/src/kucoin.js CHANGED
@@ -164,6 +164,9 @@ export default class kucoin extends Exchange {
164
164
  'margin/config': 25,
165
165
  'announcements': 20,
166
166
  'margin/collateralRatio': 10,
167
+ // convert
168
+ 'convert/symbol': 5,
169
+ 'convert/currencies': 5,
167
170
  },
168
171
  'post': {
169
172
  // ws
@@ -249,6 +252,13 @@ export default class kucoin extends Exchange {
249
252
  'broker/queryUser': 3,
250
253
  'broker/queryDetailByUid': 3,
251
254
  'migrate/user/account/status': 3,
255
+ // convert
256
+ 'convert/quote': 20,
257
+ 'convert/order/detail': 5,
258
+ 'convert/order/history': 5,
259
+ 'convert/limit/quote': 20,
260
+ 'convert/limit/order/detail': 5,
261
+ 'convert/limit/orders': 5,
252
262
  // affiliate
253
263
  'affiliate/inviter/statistics': 30,
254
264
  },
@@ -288,6 +298,9 @@ export default class kucoin extends Exchange {
288
298
  'purchase': 15,
289
299
  'redeem': 15,
290
300
  'lend/purchase/update': 10,
301
+ // convert
302
+ 'convert/order': 20,
303
+ 'convert/limit/order': 20,
291
304
  // ws
292
305
  'bullet-private': 10,
293
306
  'position/update-user-leverage': 5,
@@ -318,7 +331,9 @@ export default class kucoin extends Exchange {
318
331
  // margin trading
319
332
  'hf/margin/orders/{orderId}': 5,
320
333
  'hf/margin/orders/client-order/{clientOid}': 5,
321
- 'hf/margin/orders': 10, // 10SW
334
+ 'hf/margin/orders': 10,
335
+ // convert
336
+ 'convert/limit/order/cancel': 5,
322
337
  },
323
338
  },
324
339
  'futuresPublic': {
@@ -436,6 +451,7 @@ export default class kucoin extends Exchange {
436
451
  },
437
452
  'earn': {
438
453
  'get': {
454
+ 'otc-loan/discount-rate-configs': 10,
439
455
  'otc-loan/loan': 1,
440
456
  'otc-loan/accounts': 1,
441
457
  'earn/redeem-preview': 7.5,
@@ -444,10 +460,13 @@ export default class kucoin extends Exchange {
444
460
  'earn/promotion/products': 7.5,
445
461
  'earn/kcs-staking/products': 7.5,
446
462
  'earn/staking/products': 7.5,
447
- 'earn/eth-staking/products': 7.5, // 5EW
463
+ 'earn/eth-staking/products': 7.5,
464
+ 'struct-earn/dual/products': 4.5,
465
+ 'struct-earn/orders': 7.5,
448
466
  },
449
467
  'post': {
450
- 'earn/orders': 7.5, // 5EW
468
+ 'earn/orders': 7.5,
469
+ 'struct-earn/orders': 7.5,
451
470
  },
452
471
  'delete': {
453
472
  'earn/orders': 7.5, // 5EW
package/js/src/mexc.js CHANGED
@@ -169,6 +169,7 @@ export default class mexc extends Exchange {
169
169
  'get': {
170
170
  'ping': 1,
171
171
  'time': 1,
172
+ 'defaultSymbols': 1,
172
173
  'exchangeInfo': 10,
173
174
  'depth': 1,
174
175
  'trades': 5,
@@ -184,14 +185,19 @@ export default class mexc extends Exchange {
184
185
  },
185
186
  'private': {
186
187
  'get': {
188
+ 'kyc/status': 1,
189
+ 'uid': 1,
187
190
  'order': 2,
188
191
  'openOrders': 3,
189
192
  'allOrders': 10,
190
193
  'account': 10,
191
194
  'myTrades': 10,
195
+ 'strategy/group': 20,
196
+ 'strategy/group/uid': 20,
192
197
  'tradeFee': 10,
193
198
  'sub-account/list': 1,
194
199
  'sub-account/apiKey': 1,
200
+ 'sub-account/asset': 1,
195
201
  'capital/config/getall': 10,
196
202
  'capital/deposit/hisrec': 1,
197
203
  'capital/withdraw/history': 1,
@@ -237,6 +243,7 @@ export default class mexc extends Exchange {
237
243
  'sub-account/futures': 1,
238
244
  'sub-account/margin': 1,
239
245
  'batchOrders': 10,
246
+ 'strategy/group': 20,
240
247
  'capital/withdraw/apply': 1,
241
248
  'capital/withdraw': 1,
242
249
  'capital/transfer': 1,