ccxt 4.2.39 → 4.2.41

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 (57) hide show
  1. package/README.md +3 -3
  2. package/dist/ccxt.browser.js +1140 -341
  3. package/dist/ccxt.browser.min.js +2 -2
  4. package/dist/cjs/ccxt.js +1 -1
  5. package/dist/cjs/src/ascendex.js +28 -24
  6. package/dist/cjs/src/base/Exchange.js +14 -14
  7. package/dist/cjs/src/binance.js +561 -168
  8. package/dist/cjs/src/bingx.js +271 -25
  9. package/dist/cjs/src/bitforex.js +2 -2
  10. package/dist/cjs/src/bitget.js +13 -2
  11. package/dist/cjs/src/bybit.js +3 -1
  12. package/dist/cjs/src/coinbase.js +8 -6
  13. package/dist/cjs/src/coinbasepro.js +1 -0
  14. package/dist/cjs/src/coinlist.js +9 -7
  15. package/dist/cjs/src/coinmetro.js +2 -1
  16. package/dist/cjs/src/currencycom.js +1 -1
  17. package/dist/cjs/src/htx.js +1 -1
  18. package/dist/cjs/src/krakenfutures.js +126 -2
  19. package/dist/cjs/src/mexc.js +44 -44
  20. package/dist/cjs/src/okx.js +9 -15
  21. package/dist/cjs/src/phemex.js +1 -0
  22. package/dist/cjs/src/pro/bitmart.js +38 -20
  23. package/dist/cjs/src/pro/bybit.js +5 -5
  24. package/dist/cjs/src/pro/cex.js +1 -1
  25. package/dist/cjs/src/pro/gemini.js +1 -1
  26. package/js/ccxt.d.ts +1 -1
  27. package/js/ccxt.js +1 -1
  28. package/js/src/abstract/bingx.d.ts +4 -0
  29. package/js/src/abstract/coinbasepro.d.ts +1 -0
  30. package/js/src/ascendex.js +28 -24
  31. package/js/src/base/Exchange.d.ts +8 -8
  32. package/js/src/base/Exchange.js +14 -14
  33. package/js/src/binance.d.ts +1 -1
  34. package/js/src/binance.js +561 -168
  35. package/js/src/bingx.d.ts +2 -0
  36. package/js/src/bingx.js +271 -25
  37. package/js/src/bitforex.js +2 -2
  38. package/js/src/bitget.js +13 -2
  39. package/js/src/bybit.js +3 -1
  40. package/js/src/coinbase.js +8 -6
  41. package/js/src/coinbasepro.js +1 -0
  42. package/js/src/coinlist.js +9 -7
  43. package/js/src/coinmetro.js +2 -1
  44. package/js/src/currencycom.js +1 -1
  45. package/js/src/htx.js +1 -1
  46. package/js/src/krakenfutures.d.ts +2 -0
  47. package/js/src/krakenfutures.js +126 -2
  48. package/js/src/mexc.js +44 -44
  49. package/js/src/okx.js +9 -15
  50. package/js/src/phemex.js +1 -0
  51. package/js/src/pro/bitmart.d.ts +2 -0
  52. package/js/src/pro/bitmart.js +38 -20
  53. package/js/src/pro/bybit.d.ts +1 -1
  54. package/js/src/pro/bybit.js +5 -5
  55. package/js/src/pro/cex.js +1 -1
  56. package/js/src/pro/gemini.js +1 -1
  57. package/package.json +1 -1
@@ -140,6 +140,7 @@ class bingx extends bingx$1 {
140
140
  'trade/order': 3,
141
141
  'trade/cancel': 3,
142
142
  'trade/batchOrders': 3,
143
+ 'trade/order/cancelReplace': 3,
143
144
  'trade/cancelOrders': 3,
144
145
  'trade/cancelOpenOrders': 3,
145
146
  },
@@ -161,12 +162,19 @@ class bingx extends bingx$1 {
161
162
  },
162
163
  'swap': {
163
164
  'v1': {
165
+ 'public': {
166
+ 'get': {
167
+ 'ticker/price': 1,
168
+ },
169
+ },
164
170
  'private': {
165
171
  'get': {
166
172
  'positionSide/dual': 1,
167
173
  'market/markPriceKlines': 1,
174
+ 'trade/batchCancelReplace': 1,
168
175
  },
169
176
  'post': {
177
+ 'trade/cancelReplace': 1,
170
178
  'positionSide/dual': 1,
171
179
  },
172
180
  },
@@ -1789,6 +1797,7 @@ class bingx extends bingx$1 {
1789
1797
  if (timeInForce === 'IOC') {
1790
1798
  request['timeInForce'] = 'IOC';
1791
1799
  }
1800
+ const triggerPrice = this.safeString2(params, 'stopPrice', 'triggerPrice');
1792
1801
  if (isSpot) {
1793
1802
  [postOnly, params] = this.handlePostOnly(isMarketOrder, timeInForce === 'POC', params);
1794
1803
  if (postOnly || (timeInForce === 'POC')) {
@@ -1800,7 +1809,7 @@ class bingx extends bingx$1 {
1800
1809
  request['quoteOrderQty'] = this.parseToNumeric(this.costToPrecision(symbol, cost));
1801
1810
  }
1802
1811
  else {
1803
- if (market['spot'] && isMarketOrder && (price !== undefined)) {
1812
+ if (isMarketOrder && (price !== undefined)) {
1804
1813
  // keep the legacy behavior, to avoid breaking the old spot-market-buying code
1805
1814
  const calculatedCost = Precise["default"].stringMul(this.numberToString(amount), this.numberToString(price));
1806
1815
  request['quoteOrderQty'] = this.parseToNumeric(calculatedCost);
@@ -1812,6 +1821,18 @@ class bingx extends bingx$1 {
1812
1821
  if (!isMarketOrder) {
1813
1822
  request['price'] = this.parseToNumeric(this.priceToPrecision(symbol, price));
1814
1823
  }
1824
+ if (triggerPrice !== undefined) {
1825
+ if (isMarketOrder && this.safeString(request, 'quoteOrderQty') === undefined) {
1826
+ throw new errors.ArgumentsRequired(this.id + ' createOrder() requires the cost parameter (or the amount + price) for placing spot market-buy trigger orders');
1827
+ }
1828
+ request['stopPrice'] = this.priceToPrecision(symbol, triggerPrice);
1829
+ if (type === 'LIMIT') {
1830
+ request['type'] = 'TRIGGER_LIMIT';
1831
+ }
1832
+ else if (type === 'MARKET') {
1833
+ request['type'] = 'TRIGGER_MARKET';
1834
+ }
1835
+ }
1815
1836
  }
1816
1837
  else {
1817
1838
  [postOnly, params] = this.handlePostOnly(isMarketOrder, timeInForce === 'PostOnly', params);
@@ -1824,7 +1845,6 @@ class bingx extends bingx$1 {
1824
1845
  else if (timeInForce === 'FOK') {
1825
1846
  request['timeInForce'] = 'FOK';
1826
1847
  }
1827
- const triggerPrice = this.safeString2(params, 'stopPrice', 'triggerPrice');
1828
1848
  const stopLossPrice = this.safeString(params, 'stopLossPrice');
1829
1849
  const takeProfitPrice = this.safeString(params, 'takeProfitPrice');
1830
1850
  const trailingAmount = this.safeString(params, 'trailingAmount');
@@ -2124,6 +2144,13 @@ class bingx extends bingx$1 {
2124
2144
  };
2125
2145
  return this.safeString(sides, side, side);
2126
2146
  }
2147
+ parseOrderType(type) {
2148
+ const types = {
2149
+ 'trigger_market': 'market',
2150
+ 'trigger_limit': 'limit',
2151
+ };
2152
+ return this.safeString(types, type, type);
2153
+ }
2127
2154
  parseOrder(order, market = undefined) {
2128
2155
  //
2129
2156
  // spot
@@ -2241,22 +2268,104 @@ class bingx extends bingx$1 {
2241
2268
  // reduceOnly: false
2242
2269
  // }
2243
2270
  //
2271
+ // editOrder (swap)
2272
+ //
2273
+ // {
2274
+ // cancelResult: 'true',
2275
+ // cancelMsg: '',
2276
+ // cancelResponse: {
2277
+ // cancelClientOrderId: '',
2278
+ // cancelOrderId: '1755336244265705472',
2279
+ // symbol: 'SOL-USDT',
2280
+ // orderId: '1755336244265705472',
2281
+ // side: 'SELL',
2282
+ // positionSide: 'SHORT',
2283
+ // type: 'LIMIT',
2284
+ // origQty: '1',
2285
+ // price: '100.000',
2286
+ // executedQty: '0',
2287
+ // avgPrice: '0.000',
2288
+ // cumQuote: '0',
2289
+ // stopPrice: '',
2290
+ // profit: '0.0000',
2291
+ // commission: '0.000000',
2292
+ // status: 'PENDING',
2293
+ // time: '1707339747860',
2294
+ // updateTime: '1707339747860',
2295
+ // clientOrderId: '',
2296
+ // leverage: '20X',
2297
+ // workingType: 'MARK_PRICE',
2298
+ // onlyOnePosition: false,
2299
+ // reduceOnly: false
2300
+ // },
2301
+ // replaceResult: 'true',
2302
+ // replaceMsg: '',
2303
+ // newOrderResponse: {
2304
+ // orderId: '1755338440612995072',
2305
+ // symbol: 'SOL-USDT',
2306
+ // positionSide: 'SHORT',
2307
+ // side: 'SELL',
2308
+ // type: 'LIMIT',
2309
+ // price: '99',
2310
+ // quantity: '2',
2311
+ // stopPrice: '0',
2312
+ // workingType: 'MARK_PRICE',
2313
+ // clientOrderID: '',
2314
+ // timeInForce: 'GTC',
2315
+ // priceRate: '0',
2316
+ // stopLoss: '',
2317
+ // takeProfit: '',
2318
+ // reduceOnly: false
2319
+ // }
2320
+ // }
2321
+ //
2322
+ // editOrder (spot)
2323
+ //
2324
+ // {
2325
+ // cancelResult: { code: '0', msg: '', result: true },
2326
+ // openResult: { code: '0', msg: '', result: true },
2327
+ // orderOpenResponse: {
2328
+ // symbol: 'SOL-USDT',
2329
+ // orderId: '1755334007697866752',
2330
+ // transactTime: '1707339214620',
2331
+ // price: '99',
2332
+ // stopPrice: '0',
2333
+ // origQty: '0.2',
2334
+ // executedQty: '0',
2335
+ // cummulativeQuoteQty: '0',
2336
+ // status: 'PENDING',
2337
+ // type: 'LIMIT',
2338
+ // side: 'SELL',
2339
+ // clientOrderID: ''
2340
+ // },
2341
+ // orderCancelResponse: {
2342
+ // symbol: 'SOL-USDT',
2343
+ // orderId: '1755117055251480576',
2344
+ // price: '100',
2345
+ // stopPrice: '0',
2346
+ // origQty: '0.2',
2347
+ // executedQty: '0',
2348
+ // cummulativeQuoteQty: '0',
2349
+ // status: 'CANCELED',
2350
+ // type: 'LIMIT',
2351
+ // side: 'SELL'
2352
+ // }
2353
+ // }
2354
+ //
2355
+ const info = order;
2356
+ const newOrder = this.safeDict2(order, 'newOrderResponse', 'orderOpenResponse');
2357
+ if (newOrder !== undefined) {
2358
+ order = newOrder;
2359
+ }
2244
2360
  const positionSide = this.safeString2(order, 'positionSide', 'ps');
2245
2361
  const marketType = (positionSide === undefined) ? 'spot' : 'swap';
2246
2362
  const marketId = this.safeString2(order, 'symbol', 's');
2247
2363
  if (market === undefined) {
2248
2364
  market = this.safeMarket(marketId, undefined, undefined, marketType);
2249
2365
  }
2250
- const symbol = this.safeSymbol(marketId, market, '-', marketType);
2251
- const orderId = this.safeString2(order, 'orderId', 'i');
2252
2366
  const side = this.safeStringLower2(order, 'side', 'S');
2253
- const type = this.safeStringLower2(order, 'type', 'o');
2254
2367
  const timestamp = this.safeIntegerN(order, ['time', 'transactTime', 'E']);
2255
2368
  const lastTradeTimestamp = this.safeInteger2(order, 'updateTime', 'T');
2256
- const price = this.safeString2(order, 'price', 'p');
2257
- const average = this.safeString2(order, 'avgPrice', 'ap');
2258
- const amount = this.safeString2(order, 'origQty', 'q');
2259
- const filled = this.safeString2(order, 'executedQty', 'z');
2260
2369
  const statusId = this.safeString2(order, 'status', 'X');
2261
2370
  let feeCurrencyCode = this.safeString2(order, 'feeAsset', 'N');
2262
2371
  const feeCost = this.safeStringN(order, ['fee', 'commission', 'n']);
@@ -2273,11 +2382,6 @@ class bingx extends bingx$1 {
2273
2382
  feeCurrencyCode = market['quote'];
2274
2383
  }
2275
2384
  }
2276
- const fee = {
2277
- 'currency': feeCurrencyCode,
2278
- 'cost': Precise["default"].stringAbs(feeCost),
2279
- };
2280
- const clientOrderId = this.safeStringN(order, ['clientOrderID', 'origClientOrderId', 'c']);
2281
2385
  let stopLoss = this.safeValue(order, 'stopLoss');
2282
2386
  let stopLossPrice = undefined;
2283
2387
  if ((stopLoss !== undefined) && (stopLoss !== '')) {
@@ -2303,31 +2407,35 @@ class bingx extends bingx$1 {
2303
2407
  takeProfitPrice = this.safeNumber(takeProfit, 'stopPrice');
2304
2408
  }
2305
2409
  return this.safeOrder({
2306
- 'info': order,
2307
- 'id': orderId,
2308
- 'clientOrderId': clientOrderId,
2410
+ 'info': info,
2411
+ 'id': this.safeString2(order, 'orderId', 'i'),
2412
+ 'clientOrderId': this.safeStringN(order, ['clientOrderID', 'origClientOrderId', 'c']),
2413
+ 'symbol': this.safeSymbol(marketId, market, '-', marketType),
2309
2414
  'timestamp': timestamp,
2310
2415
  'datetime': this.iso8601(timestamp),
2311
2416
  'lastTradeTimestamp': lastTradeTimestamp,
2312
2417
  'lastUpdateTimestamp': this.safeInteger(order, 'updateTime'),
2313
- 'symbol': symbol,
2314
- 'type': type,
2315
- 'timeInForce': undefined,
2418
+ 'type': this.parseOrderType(this.safeStringLower2(order, 'type', 'o')),
2419
+ 'timeInForce': this.safeString(order, 'timeInForce'),
2316
2420
  'postOnly': undefined,
2317
2421
  'side': this.parseOrderSide(side),
2318
- 'price': price,
2422
+ 'price': this.safeString2(order, 'price', 'p'),
2319
2423
  'stopPrice': this.safeNumber(order, 'stopPrice'),
2320
2424
  'triggerPrice': this.safeNumber(order, 'stopPrice'),
2321
2425
  'stopLossPrice': stopLossPrice,
2322
2426
  'takeProfitPrice': takeProfitPrice,
2323
- 'average': average,
2427
+ 'average': this.safeString2(order, 'avgPrice', 'ap'),
2324
2428
  'cost': undefined,
2325
- 'amount': amount,
2326
- 'filled': filled,
2429
+ 'amount': this.safeStringN(order, ['origQty', 'q', 'quantity']),
2430
+ 'filled': this.safeString2(order, 'executedQty', 'z'),
2327
2431
  'remaining': undefined,
2328
2432
  'status': this.parseOrderStatus(statusId),
2329
- 'fee': fee,
2433
+ 'fee': {
2434
+ 'currency': feeCurrencyCode,
2435
+ 'cost': Precise["default"].stringAbs(feeCost),
2436
+ },
2330
2437
  'trades': undefined,
2438
+ 'reduceOnly': this.safeBool(order, 'reduceOnly'),
2331
2439
  }, market);
2332
2440
  }
2333
2441
  parseOrderStatus(status) {
@@ -3836,6 +3944,144 @@ class bingx extends bingx$1 {
3836
3944
  //
3837
3945
  return await this.swapV1PrivatePostPositionSideDual(this.extend(request, params));
3838
3946
  }
3947
+ async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
3948
+ /**
3949
+ * @method
3950
+ * @name bingx#editOrder
3951
+ * @description cancels an order and places a new order
3952
+ * @see https://bingx-api.github.io/docs/#/en-us/spot/trade-api.html#Cancel%20order%20and%20place%20a%20new%20order // spot
3953
+ * @see https://bingx-api.github.io/docs/#/en-us/swapV2/trade-api.html#Cancel%20an%20order%20and%20then%20Place%20a%20new%20order // swap
3954
+ * @param {string} id order id
3955
+ * @param {string} symbol unified symbol of the market to create an order in
3956
+ * @param {string} type 'market' or 'limit'
3957
+ * @param {string} side 'buy' or 'sell'
3958
+ * @param {float} amount how much of the currency you want to trade in units of the base currency
3959
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
3960
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3961
+ * @param {string} [params.stopPrice] Trigger price used for TAKE_STOP_LIMIT, TAKE_STOP_MARKET, TRIGGER_LIMIT, TRIGGER_MARKET order types.
3962
+ * @param {object} [params.takeProfit] *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered
3963
+ * @param {float} [params.takeProfit.triggerPrice] take profit trigger price
3964
+ * @param {object} [params.stopLoss] *stopLoss object in params* containing the triggerPrice at which the attached stop loss order will be triggered
3965
+ * @param {float} [params.stopLoss.triggerPrice] stop loss trigger price
3966
+ *
3967
+ * EXCHANGE SPECIFIC PARAMETERS
3968
+ * @param {string} [params.cancelClientOrderID] the user-defined id of the order to be canceled, 1-40 characters, different orders cannot use the same clientOrderID, only supports a query range of 2 hours
3969
+ * @param {string} [params.cancelRestrictions] cancel orders with specified status, NEW: New order, PENDING: Pending order, PARTIALLY_FILLED: Partially filled
3970
+ * @param {string} [params.cancelReplaceMode] STOP_ON_FAILURE - if the cancel order fails, it will not continue to place a new order, ALLOW_FAILURE - regardless of whether the cancel order succeeds or fails, it will continue to place a new order
3971
+ * @param {float} [params.quoteOrderQty] order amount
3972
+ * @param {string} [params.newClientOrderId] custom order id consisting of letters, numbers, and _, 1-40 characters, different orders cannot use the same newClientOrderId.
3973
+ * @param {string} [params.positionSide] *contract only* position direction, required for single position as BOTH, for both long and short positions only LONG or SHORT can be chosen, defaults to LONG if empty
3974
+ * @param {string} [params.reduceOnly] *contract only* true or false, default=false for single position mode. this parameter is not accepted for both long and short positions mode
3975
+ * @param {float} [params.priceRate] *contract only* for type TRAILING_STOP_Market, Max = 1
3976
+ * @param {string} [params.workingType] *contract only* StopPrice trigger price types, MARK_PRICE (default), CONTRACT_PRICE, or INDEX_PRICE
3977
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
3978
+ */
3979
+ await this.loadMarkets();
3980
+ const market = this.market(symbol);
3981
+ const request = this.createOrderRequest(symbol, type, side, amount, price, params);
3982
+ request['cancelOrderId'] = id;
3983
+ request['cancelReplaceMode'] = 'STOP_ON_FAILURE';
3984
+ let response = undefined;
3985
+ if (market['swap']) {
3986
+ response = await this.swapV1PrivatePostTradeCancelReplace(this.extend(request, params));
3987
+ //
3988
+ // {
3989
+ // code: '0',
3990
+ // msg: '',
3991
+ // data: {
3992
+ // cancelResult: 'true',
3993
+ // cancelMsg: '',
3994
+ // cancelResponse: {
3995
+ // cancelClientOrderId: '',
3996
+ // cancelOrderId: '1755336244265705472',
3997
+ // symbol: 'SOL-USDT',
3998
+ // orderId: '1755336244265705472',
3999
+ // side: 'SELL',
4000
+ // positionSide: 'SHORT',
4001
+ // type: 'LIMIT',
4002
+ // origQty: '1',
4003
+ // price: '100.000',
4004
+ // executedQty: '0',
4005
+ // avgPrice: '0.000',
4006
+ // cumQuote: '0',
4007
+ // stopPrice: '',
4008
+ // profit: '0.0000',
4009
+ // commission: '0.000000',
4010
+ // status: 'PENDING',
4011
+ // time: '1707339747860',
4012
+ // updateTime: '1707339747860',
4013
+ // clientOrderId: '',
4014
+ // leverage: '20X',
4015
+ // workingType: 'MARK_PRICE',
4016
+ // onlyOnePosition: false,
4017
+ // reduceOnly: false
4018
+ // },
4019
+ // replaceResult: 'true',
4020
+ // replaceMsg: '',
4021
+ // newOrderResponse: {
4022
+ // orderId: '1755338440612995072',
4023
+ // symbol: 'SOL-USDT',
4024
+ // positionSide: 'SHORT',
4025
+ // side: 'SELL',
4026
+ // type: 'LIMIT',
4027
+ // price: '99',
4028
+ // quantity: '2',
4029
+ // stopPrice: '0',
4030
+ // workingType: 'MARK_PRICE',
4031
+ // clientOrderID: '',
4032
+ // timeInForce: 'GTC',
4033
+ // priceRate: '0',
4034
+ // stopLoss: '',
4035
+ // takeProfit: '',
4036
+ // reduceOnly: false
4037
+ // }
4038
+ // }
4039
+ // }
4040
+ //
4041
+ }
4042
+ else {
4043
+ response = await this.spotV1PrivatePostTradeOrderCancelReplace(this.extend(request, params));
4044
+ //
4045
+ // {
4046
+ // code: '0',
4047
+ // msg: '',
4048
+ // debugMsg: '',
4049
+ // data: {
4050
+ // cancelResult: { code: '0', msg: '', result: true },
4051
+ // openResult: { code: '0', msg: '', result: true },
4052
+ // orderOpenResponse: {
4053
+ // symbol: 'SOL-USDT',
4054
+ // orderId: '1755334007697866752',
4055
+ // transactTime: '1707339214620',
4056
+ // price: '99',
4057
+ // stopPrice: '0',
4058
+ // origQty: '0.2',
4059
+ // executedQty: '0',
4060
+ // cummulativeQuoteQty: '0',
4061
+ // status: 'PENDING',
4062
+ // type: 'LIMIT',
4063
+ // side: 'SELL',
4064
+ // clientOrderID: ''
4065
+ // },
4066
+ // orderCancelResponse: {
4067
+ // symbol: 'SOL-USDT',
4068
+ // orderId: '1755117055251480576',
4069
+ // price: '100',
4070
+ // stopPrice: '0',
4071
+ // origQty: '0.2',
4072
+ // executedQty: '0',
4073
+ // cummulativeQuoteQty: '0',
4074
+ // status: 'CANCELED',
4075
+ // type: 'LIMIT',
4076
+ // side: 'SELL'
4077
+ // }
4078
+ // }
4079
+ // }
4080
+ //
4081
+ }
4082
+ const data = this.safeDict(response, 'data');
4083
+ return this.parseOrder(data, market);
4084
+ }
3839
4085
  sign(path, section = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
3840
4086
  const type = section[0];
3841
4087
  const version = section[1];
@@ -642,8 +642,8 @@ class bitforex extends bitforex$1 {
642
642
  }
643
643
  parseOrder(order, market = undefined) {
644
644
  const id = this.safeString(order, 'orderId');
645
- const timestamp = this.safeNumber(order, 'createTime');
646
- const lastTradeTimestamp = this.safeNumber(order, 'lastTime');
645
+ const timestamp = this.safeInteger(order, 'createTime');
646
+ const lastTradeTimestamp = this.safeInteger(order, 'lastTime');
647
647
  const symbol = market['symbol'];
648
648
  const sideId = this.safeInteger(order, 'tradeType');
649
649
  const side = this.parseSide(sideId);
@@ -3949,6 +3949,13 @@ class bitget extends bitget$1 {
3949
3949
  size = this.safeString(order, 'size');
3950
3950
  filled = this.safeString(order, 'baseVolume');
3951
3951
  }
3952
+ let side = this.safeString(order, 'side');
3953
+ const posMode = this.safeString(order, 'posMode');
3954
+ if (posMode === 'hedge_mode' && reduceOnly) {
3955
+ side = (side === 'buy') ? 'sell' : 'buy';
3956
+ // on bitget hedge mode if the position is long the side is always buy, and if the position is short the side is always sell
3957
+ // so the side of the reduceOnly order is inversed
3958
+ }
3952
3959
  return this.safeOrder({
3953
3960
  'info': order,
3954
3961
  'id': this.safeString2(order, 'orderId', 'data'),
@@ -3959,7 +3966,7 @@ class bitget extends bitget$1 {
3959
3966
  'lastUpdateTimestamp': updateTimestamp,
3960
3967
  'symbol': market['symbol'],
3961
3968
  'type': this.safeString(order, 'orderType'),
3962
- 'side': this.safeString(order, 'side'),
3969
+ 'side': side,
3963
3970
  'price': price,
3964
3971
  'amount': size,
3965
3972
  'cost': this.safeString2(order, 'quoteVolume', 'quoteSize'),
@@ -8286,7 +8293,11 @@ class bitget extends bitget$1 {
8286
8293
  }
8287
8294
  else {
8288
8295
  if (Object.keys(params).length) {
8289
- const queryInner = '?' + this.urlencode(this.keysort(params));
8296
+ let queryInner = '?' + this.urlencode(this.keysort(params));
8297
+ // check #21169 pr
8298
+ if (queryInner.indexOf('%24') > -1) {
8299
+ queryInner = queryInner.replace('%24', '$');
8300
+ }
8290
8301
  url += queryInner;
8291
8302
  auth += queryInner;
8292
8303
  }
@@ -2217,6 +2217,7 @@ class bybit extends bybit$1 {
2217
2217
  * @param {int} [since] timestamp in ms of the earliest candle to fetch
2218
2218
  * @param {int} [limit] the maximum amount of candles to fetch
2219
2219
  * @param {object} [params] extra parameters specific to the exchange API endpoint
2220
+ * @param {int} [params.until] the latest time in ms to fetch orders for
2220
2221
  * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
2221
2222
  * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
2222
2223
  */
@@ -2230,7 +2231,7 @@ class bybit extends bybit$1 {
2230
2231
  return await this.fetchPaginatedCallDeterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 1000);
2231
2232
  }
2232
2233
  const market = this.market(symbol);
2233
- const request = {
2234
+ let request = {
2234
2235
  'symbol': market['id'],
2235
2236
  };
2236
2237
  if (limit === undefined) {
@@ -2242,6 +2243,7 @@ class bybit extends bybit$1 {
2242
2243
  if (limit !== undefined) {
2243
2244
  request['limit'] = limit; // max 1000, default 1000
2244
2245
  }
2246
+ [request, params] = this.handleUntilOption('end', request, params);
2245
2247
  request['interval'] = this.safeString(this.timeframes, timeframe, timeframe);
2246
2248
  let response = undefined;
2247
2249
  if (market['spot']) {
@@ -427,11 +427,12 @@ class coinbase extends coinbase$1 {
427
427
  // ]
428
428
  // }
429
429
  //
430
- const data = this.safeValue(response, 'data', []);
431
- const pagination = this.safeValue(response, 'pagination', {});
430
+ const data = this.safeList(response, 'data', []);
431
+ const pagination = this.safeDict(response, 'pagination', {});
432
432
  const cursor = this.safeString(pagination, 'next_starting_after');
433
- const accounts = this.safeValue(response, 'data', []);
434
- const lastIndex = accounts.length - 1;
433
+ const accounts = this.safeList(response, 'data', []);
434
+ const length = accounts.length;
435
+ const lastIndex = length - 1;
435
436
  const last = this.safeValue(accounts, lastIndex);
436
437
  if ((cursor !== undefined) && (cursor !== '')) {
437
438
  last['next_starting_after'] = cursor;
@@ -480,8 +481,9 @@ class coinbase extends coinbase$1 {
480
481
  // "size": 9
481
482
  // }
482
483
  //
483
- const accounts = this.safeValue(response, 'accounts', []);
484
- const lastIndex = accounts.length - 1;
484
+ const accounts = this.safeList(response, 'accounts', []);
485
+ const length = accounts.length;
486
+ const lastIndex = length - 1;
485
487
  const last = this.safeValue(accounts, lastIndex);
486
488
  const cursor = this.safeString(response, 'cursor');
487
489
  if ((cursor !== undefined) && (cursor !== '')) {
@@ -147,6 +147,7 @@ class coinbasepro extends coinbasepro$1 {
147
147
  'users/self/trailing-volume',
148
148
  'withdrawals/fee-estimate',
149
149
  'conversions/{conversion_id}',
150
+ 'conversions/fees',
150
151
  ],
151
152
  'post': [
152
153
  'conversions',
@@ -1034,13 +1034,15 @@ class coinlist extends coinlist$1 {
1034
1034
  }
1035
1035
  takerFees = this.sortBy(takerFees, 1, true);
1036
1036
  makerFees = this.sortBy(makerFees, 1, true);
1037
- const firstTier = this.safeValue(takerFees, 0, []);
1038
- const exchangeFees = this.safeValue(this, 'fees', {});
1039
- const exchangeFeesTrading = this.safeValue(exchangeFees, 'trading', {});
1040
- const exchangeFeesTradingTiers = this.safeValue(exchangeFeesTrading, 'tiers', {});
1041
- const exchangeFeesTradingTiersTaker = this.safeValue(exchangeFeesTradingTiers, 'taker', []);
1042
- const exchangeFeesTradingTiersMaker = this.safeValue(exchangeFeesTradingTiers, 'maker', []);
1043
- if ((keysLength === exchangeFeesTradingTiersTaker.length) && (firstTier.length > 0)) {
1037
+ const firstTier = this.safeDict(takerFees, 0, []);
1038
+ const exchangeFees = this.safeDict(this, 'fees', {});
1039
+ const exchangeFeesTrading = this.safeDict(exchangeFees, 'trading', {});
1040
+ const exchangeFeesTradingTiers = this.safeDict(exchangeFeesTrading, 'tiers', {});
1041
+ const exchangeFeesTradingTiersTaker = this.safeList(exchangeFeesTradingTiers, 'taker', []);
1042
+ const exchangeFeesTradingTiersMaker = this.safeList(exchangeFeesTradingTiers, 'maker', []);
1043
+ const exchangeFeesTradingTiersTakerLength = exchangeFeesTradingTiersTaker.length;
1044
+ const firstTierLength = firstTier.length;
1045
+ if ((keysLength === exchangeFeesTradingTiersTakerLength) && (firstTierLength > 0)) {
1044
1046
  for (let i = 0; i < keysLength; i++) {
1045
1047
  takerFees[i][0] = exchangeFeesTradingTiersTaker[i][0];
1046
1048
  makerFees[i][0] = exchangeFeesTradingTiersMaker[i][0];
@@ -1166,7 +1166,8 @@ class coinmetro extends coinmetro$1 {
1166
1166
  }
1167
1167
  let type = undefined;
1168
1168
  let referenceId = undefined;
1169
- if (descriptionArray.length > 1) {
1169
+ const length = descriptionArray.length;
1170
+ if (length > 1) {
1170
1171
  type = this.parseLedgerEntryType(descriptionArray[0]);
1171
1172
  if (descriptionArray[1] !== '-') {
1172
1173
  referenceId = descriptionArray[1];
@@ -1936,7 +1936,7 @@ class currencycom extends currencycom$1 {
1936
1936
  //
1937
1937
  market = this.safeMarket(this.safeString(position, 'symbol'), market);
1938
1938
  const symbol = market['symbol'];
1939
- const timestamp = this.safeNumber(position, 'createdTimestamp');
1939
+ const timestamp = this.safeInteger(position, 'createdTimestamp');
1940
1940
  const quantityRaw = this.safeString(position, 'openQuantity');
1941
1941
  const side = Precise["default"].stringGt(quantityRaw, '0') ? 'long' : 'short';
1942
1942
  const quantity = Precise["default"].stringAbs(quantityRaw);
@@ -7088,7 +7088,7 @@ class htx extends htx$1 {
7088
7088
  const marginMode = (marketId === undefined) ? 'cross' : 'isolated';
7089
7089
  market = this.safeMarket(marketId);
7090
7090
  const symbol = this.safeString(market, 'symbol');
7091
- const timestamp = this.safeNumber(info, 'accrued-at');
7091
+ const timestamp = this.safeInteger(info, 'accrued-at');
7092
7092
  return {
7093
7093
  'account': (marginMode === 'isolated') ? symbol : 'cross',
7094
7094
  'symbol': symbol,