ccxt 4.2.39 → 4.2.40

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 (47) hide show
  1. package/README.md +3 -3
  2. package/dist/ccxt.browser.js +923 -310
  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 +372 -146
  8. package/dist/cjs/src/bingx.js +250 -23
  9. package/dist/cjs/src/bitget.js +13 -2
  10. package/dist/cjs/src/bybit.js +3 -1
  11. package/dist/cjs/src/coinbase.js +8 -6
  12. package/dist/cjs/src/coinbasepro.js +1 -0
  13. package/dist/cjs/src/coinlist.js +9 -7
  14. package/dist/cjs/src/coinmetro.js +2 -1
  15. package/dist/cjs/src/krakenfutures.js +126 -2
  16. package/dist/cjs/src/mexc.js +43 -43
  17. package/dist/cjs/src/okx.js +9 -15
  18. package/dist/cjs/src/phemex.js +1 -0
  19. package/dist/cjs/src/pro/bitmart.js +38 -20
  20. package/dist/cjs/src/pro/bybit.js +5 -5
  21. package/js/ccxt.d.ts +1 -1
  22. package/js/ccxt.js +1 -1
  23. package/js/src/abstract/bingx.d.ts +4 -0
  24. package/js/src/abstract/coinbasepro.d.ts +1 -0
  25. package/js/src/ascendex.js +28 -24
  26. package/js/src/base/Exchange.d.ts +8 -8
  27. package/js/src/base/Exchange.js +14 -14
  28. package/js/src/binance.d.ts +1 -1
  29. package/js/src/binance.js +372 -146
  30. package/js/src/bingx.d.ts +1 -0
  31. package/js/src/bingx.js +250 -23
  32. package/js/src/bitget.js +13 -2
  33. package/js/src/bybit.js +3 -1
  34. package/js/src/coinbase.js +8 -6
  35. package/js/src/coinbasepro.js +1 -0
  36. package/js/src/coinlist.js +9 -7
  37. package/js/src/coinmetro.js +2 -1
  38. package/js/src/krakenfutures.d.ts +2 -0
  39. package/js/src/krakenfutures.js +126 -2
  40. package/js/src/mexc.js +43 -43
  41. package/js/src/okx.js +9 -15
  42. package/js/src/phemex.js +1 -0
  43. package/js/src/pro/bitmart.d.ts +2 -0
  44. package/js/src/pro/bitmart.js +38 -20
  45. package/js/src/pro/bybit.d.ts +1 -1
  46. package/js/src/pro/bybit.js +5 -5
  47. package/package.json +1 -1
package/js/src/bingx.d.ts CHANGED
@@ -131,6 +131,7 @@ export default class bingx extends Exchange {
131
131
  closePosition(symbol: string, side?: OrderSide, params?: {}): Promise<Order>;
132
132
  closeAllPositions(params?: {}): Promise<Position[]>;
133
133
  setPositionMode(hedged: boolean, symbol?: Str, params?: {}): Promise<any>;
134
+ editOrder(id: string, symbol: string, type: OrderType, side: OrderSide, amount?: number, price?: number, params?: {}): Promise<Order>;
134
135
  sign(path: any, section?: string, method?: string, params?: {}, headers?: any, body?: any): {
135
136
  url: any;
136
137
  method: string;
package/js/src/bingx.js CHANGED
@@ -143,6 +143,7 @@ export default class bingx extends Exchange {
143
143
  'trade/order': 3,
144
144
  'trade/cancel': 3,
145
145
  'trade/batchOrders': 3,
146
+ 'trade/order/cancelReplace': 3,
146
147
  'trade/cancelOrders': 3,
147
148
  'trade/cancelOpenOrders': 3,
148
149
  },
@@ -164,12 +165,19 @@ export default class bingx extends Exchange {
164
165
  },
165
166
  'swap': {
166
167
  'v1': {
168
+ 'public': {
169
+ 'get': {
170
+ 'ticker/price': 1,
171
+ },
172
+ },
167
173
  'private': {
168
174
  'get': {
169
175
  'positionSide/dual': 1,
170
176
  'market/markPriceKlines': 1,
177
+ 'trade/batchCancelReplace': 1,
171
178
  },
172
179
  'post': {
180
+ 'trade/cancelReplace': 1,
173
181
  'positionSide/dual': 1,
174
182
  },
175
183
  },
@@ -2244,22 +2252,104 @@ export default class bingx extends Exchange {
2244
2252
  // reduceOnly: false
2245
2253
  // }
2246
2254
  //
2255
+ // editOrder (swap)
2256
+ //
2257
+ // {
2258
+ // cancelResult: 'true',
2259
+ // cancelMsg: '',
2260
+ // cancelResponse: {
2261
+ // cancelClientOrderId: '',
2262
+ // cancelOrderId: '1755336244265705472',
2263
+ // symbol: 'SOL-USDT',
2264
+ // orderId: '1755336244265705472',
2265
+ // side: 'SELL',
2266
+ // positionSide: 'SHORT',
2267
+ // type: 'LIMIT',
2268
+ // origQty: '1',
2269
+ // price: '100.000',
2270
+ // executedQty: '0',
2271
+ // avgPrice: '0.000',
2272
+ // cumQuote: '0',
2273
+ // stopPrice: '',
2274
+ // profit: '0.0000',
2275
+ // commission: '0.000000',
2276
+ // status: 'PENDING',
2277
+ // time: '1707339747860',
2278
+ // updateTime: '1707339747860',
2279
+ // clientOrderId: '',
2280
+ // leverage: '20X',
2281
+ // workingType: 'MARK_PRICE',
2282
+ // onlyOnePosition: false,
2283
+ // reduceOnly: false
2284
+ // },
2285
+ // replaceResult: 'true',
2286
+ // replaceMsg: '',
2287
+ // newOrderResponse: {
2288
+ // orderId: '1755338440612995072',
2289
+ // symbol: 'SOL-USDT',
2290
+ // positionSide: 'SHORT',
2291
+ // side: 'SELL',
2292
+ // type: 'LIMIT',
2293
+ // price: '99',
2294
+ // quantity: '2',
2295
+ // stopPrice: '0',
2296
+ // workingType: 'MARK_PRICE',
2297
+ // clientOrderID: '',
2298
+ // timeInForce: 'GTC',
2299
+ // priceRate: '0',
2300
+ // stopLoss: '',
2301
+ // takeProfit: '',
2302
+ // reduceOnly: false
2303
+ // }
2304
+ // }
2305
+ //
2306
+ // editOrder (spot)
2307
+ //
2308
+ // {
2309
+ // cancelResult: { code: '0', msg: '', result: true },
2310
+ // openResult: { code: '0', msg: '', result: true },
2311
+ // orderOpenResponse: {
2312
+ // symbol: 'SOL-USDT',
2313
+ // orderId: '1755334007697866752',
2314
+ // transactTime: '1707339214620',
2315
+ // price: '99',
2316
+ // stopPrice: '0',
2317
+ // origQty: '0.2',
2318
+ // executedQty: '0',
2319
+ // cummulativeQuoteQty: '0',
2320
+ // status: 'PENDING',
2321
+ // type: 'LIMIT',
2322
+ // side: 'SELL',
2323
+ // clientOrderID: ''
2324
+ // },
2325
+ // orderCancelResponse: {
2326
+ // symbol: 'SOL-USDT',
2327
+ // orderId: '1755117055251480576',
2328
+ // price: '100',
2329
+ // stopPrice: '0',
2330
+ // origQty: '0.2',
2331
+ // executedQty: '0',
2332
+ // cummulativeQuoteQty: '0',
2333
+ // status: 'CANCELED',
2334
+ // type: 'LIMIT',
2335
+ // side: 'SELL'
2336
+ // }
2337
+ // }
2338
+ //
2339
+ const info = order;
2340
+ const newOrder = this.safeDict2(order, 'newOrderResponse', 'orderOpenResponse');
2341
+ if (newOrder !== undefined) {
2342
+ order = newOrder;
2343
+ }
2247
2344
  const positionSide = this.safeString2(order, 'positionSide', 'ps');
2248
2345
  const marketType = (positionSide === undefined) ? 'spot' : 'swap';
2249
2346
  const marketId = this.safeString2(order, 'symbol', 's');
2250
2347
  if (market === undefined) {
2251
2348
  market = this.safeMarket(marketId, undefined, undefined, marketType);
2252
2349
  }
2253
- const symbol = this.safeSymbol(marketId, market, '-', marketType);
2254
- const orderId = this.safeString2(order, 'orderId', 'i');
2255
2350
  const side = this.safeStringLower2(order, 'side', 'S');
2256
- const type = this.safeStringLower2(order, 'type', 'o');
2257
2351
  const timestamp = this.safeIntegerN(order, ['time', 'transactTime', 'E']);
2258
2352
  const lastTradeTimestamp = this.safeInteger2(order, 'updateTime', 'T');
2259
- const price = this.safeString2(order, 'price', 'p');
2260
- const average = this.safeString2(order, 'avgPrice', 'ap');
2261
- const amount = this.safeString2(order, 'origQty', 'q');
2262
- const filled = this.safeString2(order, 'executedQty', 'z');
2263
2353
  const statusId = this.safeString2(order, 'status', 'X');
2264
2354
  let feeCurrencyCode = this.safeString2(order, 'feeAsset', 'N');
2265
2355
  const feeCost = this.safeStringN(order, ['fee', 'commission', 'n']);
@@ -2276,11 +2366,6 @@ export default class bingx extends Exchange {
2276
2366
  feeCurrencyCode = market['quote'];
2277
2367
  }
2278
2368
  }
2279
- const fee = {
2280
- 'currency': feeCurrencyCode,
2281
- 'cost': Precise.stringAbs(feeCost),
2282
- };
2283
- const clientOrderId = this.safeStringN(order, ['clientOrderID', 'origClientOrderId', 'c']);
2284
2369
  let stopLoss = this.safeValue(order, 'stopLoss');
2285
2370
  let stopLossPrice = undefined;
2286
2371
  if ((stopLoss !== undefined) && (stopLoss !== '')) {
@@ -2306,31 +2391,35 @@ export default class bingx extends Exchange {
2306
2391
  takeProfitPrice = this.safeNumber(takeProfit, 'stopPrice');
2307
2392
  }
2308
2393
  return this.safeOrder({
2309
- 'info': order,
2310
- 'id': orderId,
2311
- 'clientOrderId': clientOrderId,
2394
+ 'info': info,
2395
+ 'id': this.safeString2(order, 'orderId', 'i'),
2396
+ 'clientOrderId': this.safeStringN(order, ['clientOrderID', 'origClientOrderId', 'c']),
2397
+ 'symbol': this.safeSymbol(marketId, market, '-', marketType),
2312
2398
  'timestamp': timestamp,
2313
2399
  'datetime': this.iso8601(timestamp),
2314
2400
  'lastTradeTimestamp': lastTradeTimestamp,
2315
2401
  'lastUpdateTimestamp': this.safeInteger(order, 'updateTime'),
2316
- 'symbol': symbol,
2317
- 'type': type,
2318
- 'timeInForce': undefined,
2402
+ 'type': this.safeStringLower2(order, 'type', 'o'),
2403
+ 'timeInForce': this.safeString(order, 'timeInForce'),
2319
2404
  'postOnly': undefined,
2320
2405
  'side': this.parseOrderSide(side),
2321
- 'price': price,
2406
+ 'price': this.safeString2(order, 'price', 'p'),
2322
2407
  'stopPrice': this.safeNumber(order, 'stopPrice'),
2323
2408
  'triggerPrice': this.safeNumber(order, 'stopPrice'),
2324
2409
  'stopLossPrice': stopLossPrice,
2325
2410
  'takeProfitPrice': takeProfitPrice,
2326
- 'average': average,
2411
+ 'average': this.safeString2(order, 'avgPrice', 'ap'),
2327
2412
  'cost': undefined,
2328
- 'amount': amount,
2329
- 'filled': filled,
2413
+ 'amount': this.safeStringN(order, ['origQty', 'q', 'quantity']),
2414
+ 'filled': this.safeString2(order, 'executedQty', 'z'),
2330
2415
  'remaining': undefined,
2331
2416
  'status': this.parseOrderStatus(statusId),
2332
- 'fee': fee,
2417
+ 'fee': {
2418
+ 'currency': feeCurrencyCode,
2419
+ 'cost': Precise.stringAbs(feeCost),
2420
+ },
2333
2421
  'trades': undefined,
2422
+ 'reduceOnly': this.safeBool(order, 'reduceOnly'),
2334
2423
  }, market);
2335
2424
  }
2336
2425
  parseOrderStatus(status) {
@@ -3839,6 +3928,144 @@ export default class bingx extends Exchange {
3839
3928
  //
3840
3929
  return await this.swapV1PrivatePostPositionSideDual(this.extend(request, params));
3841
3930
  }
3931
+ async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
3932
+ /**
3933
+ * @method
3934
+ * @name bingx#editOrder
3935
+ * @description cancels an order and places a new order
3936
+ * @see https://bingx-api.github.io/docs/#/en-us/spot/trade-api.html#Cancel%20order%20and%20place%20a%20new%20order // spot
3937
+ * @see https://bingx-api.github.io/docs/#/en-us/swapV2/trade-api.html#Cancel%20an%20order%20and%20then%20Place%20a%20new%20order // swap
3938
+ * @param {string} id order id
3939
+ * @param {string} symbol unified symbol of the market to create an order in
3940
+ * @param {string} type 'market' or 'limit'
3941
+ * @param {string} side 'buy' or 'sell'
3942
+ * @param {float} amount how much of the currency you want to trade in units of the base currency
3943
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
3944
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3945
+ * @param {string} [params.stopPrice] Trigger price used for TAKE_STOP_LIMIT, TAKE_STOP_MARKET, TRIGGER_LIMIT, TRIGGER_MARKET order types.
3946
+ * @param {object} [params.takeProfit] *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered
3947
+ * @param {float} [params.takeProfit.triggerPrice] take profit trigger price
3948
+ * @param {object} [params.stopLoss] *stopLoss object in params* containing the triggerPrice at which the attached stop loss order will be triggered
3949
+ * @param {float} [params.stopLoss.triggerPrice] stop loss trigger price
3950
+ *
3951
+ * EXCHANGE SPECIFIC PARAMETERS
3952
+ * @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
3953
+ * @param {string} [params.cancelRestrictions] cancel orders with specified status, NEW: New order, PENDING: Pending order, PARTIALLY_FILLED: Partially filled
3954
+ * @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
3955
+ * @param {float} [params.quoteOrderQty] order amount
3956
+ * @param {string} [params.newClientOrderId] custom order id consisting of letters, numbers, and _, 1-40 characters, different orders cannot use the same newClientOrderId.
3957
+ * @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
3958
+ * @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
3959
+ * @param {float} [params.priceRate] *contract only* for type TRAILING_STOP_Market, Max = 1
3960
+ * @param {string} [params.workingType] *contract only* StopPrice trigger price types, MARK_PRICE (default), CONTRACT_PRICE, or INDEX_PRICE
3961
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
3962
+ */
3963
+ await this.loadMarkets();
3964
+ const market = this.market(symbol);
3965
+ const request = this.createOrderRequest(symbol, type, side, amount, price, params);
3966
+ request['cancelOrderId'] = id;
3967
+ request['cancelReplaceMode'] = 'STOP_ON_FAILURE';
3968
+ let response = undefined;
3969
+ if (market['swap']) {
3970
+ response = await this.swapV1PrivatePostTradeCancelReplace(this.extend(request, params));
3971
+ //
3972
+ // {
3973
+ // code: '0',
3974
+ // msg: '',
3975
+ // data: {
3976
+ // cancelResult: 'true',
3977
+ // cancelMsg: '',
3978
+ // cancelResponse: {
3979
+ // cancelClientOrderId: '',
3980
+ // cancelOrderId: '1755336244265705472',
3981
+ // symbol: 'SOL-USDT',
3982
+ // orderId: '1755336244265705472',
3983
+ // side: 'SELL',
3984
+ // positionSide: 'SHORT',
3985
+ // type: 'LIMIT',
3986
+ // origQty: '1',
3987
+ // price: '100.000',
3988
+ // executedQty: '0',
3989
+ // avgPrice: '0.000',
3990
+ // cumQuote: '0',
3991
+ // stopPrice: '',
3992
+ // profit: '0.0000',
3993
+ // commission: '0.000000',
3994
+ // status: 'PENDING',
3995
+ // time: '1707339747860',
3996
+ // updateTime: '1707339747860',
3997
+ // clientOrderId: '',
3998
+ // leverage: '20X',
3999
+ // workingType: 'MARK_PRICE',
4000
+ // onlyOnePosition: false,
4001
+ // reduceOnly: false
4002
+ // },
4003
+ // replaceResult: 'true',
4004
+ // replaceMsg: '',
4005
+ // newOrderResponse: {
4006
+ // orderId: '1755338440612995072',
4007
+ // symbol: 'SOL-USDT',
4008
+ // positionSide: 'SHORT',
4009
+ // side: 'SELL',
4010
+ // type: 'LIMIT',
4011
+ // price: '99',
4012
+ // quantity: '2',
4013
+ // stopPrice: '0',
4014
+ // workingType: 'MARK_PRICE',
4015
+ // clientOrderID: '',
4016
+ // timeInForce: 'GTC',
4017
+ // priceRate: '0',
4018
+ // stopLoss: '',
4019
+ // takeProfit: '',
4020
+ // reduceOnly: false
4021
+ // }
4022
+ // }
4023
+ // }
4024
+ //
4025
+ }
4026
+ else {
4027
+ response = await this.spotV1PrivatePostTradeOrderCancelReplace(this.extend(request, params));
4028
+ //
4029
+ // {
4030
+ // code: '0',
4031
+ // msg: '',
4032
+ // debugMsg: '',
4033
+ // data: {
4034
+ // cancelResult: { code: '0', msg: '', result: true },
4035
+ // openResult: { code: '0', msg: '', result: true },
4036
+ // orderOpenResponse: {
4037
+ // symbol: 'SOL-USDT',
4038
+ // orderId: '1755334007697866752',
4039
+ // transactTime: '1707339214620',
4040
+ // price: '99',
4041
+ // stopPrice: '0',
4042
+ // origQty: '0.2',
4043
+ // executedQty: '0',
4044
+ // cummulativeQuoteQty: '0',
4045
+ // status: 'PENDING',
4046
+ // type: 'LIMIT',
4047
+ // side: 'SELL',
4048
+ // clientOrderID: ''
4049
+ // },
4050
+ // orderCancelResponse: {
4051
+ // symbol: 'SOL-USDT',
4052
+ // orderId: '1755117055251480576',
4053
+ // price: '100',
4054
+ // stopPrice: '0',
4055
+ // origQty: '0.2',
4056
+ // executedQty: '0',
4057
+ // cummulativeQuoteQty: '0',
4058
+ // status: 'CANCELED',
4059
+ // type: 'LIMIT',
4060
+ // side: 'SELL'
4061
+ // }
4062
+ // }
4063
+ // }
4064
+ //
4065
+ }
4066
+ const data = this.safeDict(response, 'data');
4067
+ return this.parseOrder(data, market);
4068
+ }
3842
4069
  sign(path, section = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
3843
4070
  const type = section[0];
3844
4071
  const version = section[1];
package/js/src/bitget.js CHANGED
@@ -3952,6 +3952,13 @@ export default class bitget extends Exchange {
3952
3952
  size = this.safeString(order, 'size');
3953
3953
  filled = this.safeString(order, 'baseVolume');
3954
3954
  }
3955
+ let side = this.safeString(order, 'side');
3956
+ const posMode = this.safeString(order, 'posMode');
3957
+ if (posMode === 'hedge_mode' && reduceOnly) {
3958
+ side = (side === 'buy') ? 'sell' : 'buy';
3959
+ // 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
3960
+ // so the side of the reduceOnly order is inversed
3961
+ }
3955
3962
  return this.safeOrder({
3956
3963
  'info': order,
3957
3964
  'id': this.safeString2(order, 'orderId', 'data'),
@@ -3962,7 +3969,7 @@ export default class bitget extends Exchange {
3962
3969
  'lastUpdateTimestamp': updateTimestamp,
3963
3970
  'symbol': market['symbol'],
3964
3971
  'type': this.safeString(order, 'orderType'),
3965
- 'side': this.safeString(order, 'side'),
3972
+ 'side': side,
3966
3973
  'price': price,
3967
3974
  'amount': size,
3968
3975
  'cost': this.safeString2(order, 'quoteVolume', 'quoteSize'),
@@ -8289,7 +8296,11 @@ export default class bitget extends Exchange {
8289
8296
  }
8290
8297
  else {
8291
8298
  if (Object.keys(params).length) {
8292
- const queryInner = '?' + this.urlencode(this.keysort(params));
8299
+ let queryInner = '?' + this.urlencode(this.keysort(params));
8300
+ // check #21169 pr
8301
+ if (queryInner.indexOf('%24') > -1) {
8302
+ queryInner = queryInner.replace('%24', '$');
8303
+ }
8293
8304
  url += queryInner;
8294
8305
  auth += queryInner;
8295
8306
  }
package/js/src/bybit.js CHANGED
@@ -2220,6 +2220,7 @@ export default class bybit extends Exchange {
2220
2220
  * @param {int} [since] timestamp in ms of the earliest candle to fetch
2221
2221
  * @param {int} [limit] the maximum amount of candles to fetch
2222
2222
  * @param {object} [params] extra parameters specific to the exchange API endpoint
2223
+ * @param {int} [params.until] the latest time in ms to fetch orders for
2223
2224
  * @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)
2224
2225
  * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
2225
2226
  */
@@ -2233,7 +2234,7 @@ export default class bybit extends Exchange {
2233
2234
  return await this.fetchPaginatedCallDeterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 1000);
2234
2235
  }
2235
2236
  const market = this.market(symbol);
2236
- const request = {
2237
+ let request = {
2237
2238
  'symbol': market['id'],
2238
2239
  };
2239
2240
  if (limit === undefined) {
@@ -2245,6 +2246,7 @@ export default class bybit extends Exchange {
2245
2246
  if (limit !== undefined) {
2246
2247
  request['limit'] = limit; // max 1000, default 1000
2247
2248
  }
2249
+ [request, params] = this.handleUntilOption('end', request, params);
2248
2250
  request['interval'] = this.safeString(this.timeframes, timeframe, timeframe);
2249
2251
  let response = undefined;
2250
2252
  if (market['spot']) {
@@ -430,11 +430,12 @@ export default class coinbase extends Exchange {
430
430
  // ]
431
431
  // }
432
432
  //
433
- const data = this.safeValue(response, 'data', []);
434
- const pagination = this.safeValue(response, 'pagination', {});
433
+ const data = this.safeList(response, 'data', []);
434
+ const pagination = this.safeDict(response, 'pagination', {});
435
435
  const cursor = this.safeString(pagination, 'next_starting_after');
436
- const accounts = this.safeValue(response, 'data', []);
437
- const lastIndex = accounts.length - 1;
436
+ const accounts = this.safeList(response, 'data', []);
437
+ const length = accounts.length;
438
+ const lastIndex = length - 1;
438
439
  const last = this.safeValue(accounts, lastIndex);
439
440
  if ((cursor !== undefined) && (cursor !== '')) {
440
441
  last['next_starting_after'] = cursor;
@@ -483,8 +484,9 @@ export default class coinbase extends Exchange {
483
484
  // "size": 9
484
485
  // }
485
486
  //
486
- const accounts = this.safeValue(response, 'accounts', []);
487
- const lastIndex = accounts.length - 1;
487
+ const accounts = this.safeList(response, 'accounts', []);
488
+ const length = accounts.length;
489
+ const lastIndex = length - 1;
488
490
  const last = this.safeValue(accounts, lastIndex);
489
491
  const cursor = this.safeString(response, 'cursor');
490
492
  if ((cursor !== undefined) && (cursor !== '')) {
@@ -150,6 +150,7 @@ export default class coinbasepro extends Exchange {
150
150
  'users/self/trailing-volume',
151
151
  'withdrawals/fee-estimate',
152
152
  'conversions/{conversion_id}',
153
+ 'conversions/fees',
153
154
  ],
154
155
  'post': [
155
156
  'conversions',
@@ -1037,13 +1037,15 @@ export default class coinlist extends Exchange {
1037
1037
  }
1038
1038
  takerFees = this.sortBy(takerFees, 1, true);
1039
1039
  makerFees = this.sortBy(makerFees, 1, true);
1040
- const firstTier = this.safeValue(takerFees, 0, []);
1041
- const exchangeFees = this.safeValue(this, 'fees', {});
1042
- const exchangeFeesTrading = this.safeValue(exchangeFees, 'trading', {});
1043
- const exchangeFeesTradingTiers = this.safeValue(exchangeFeesTrading, 'tiers', {});
1044
- const exchangeFeesTradingTiersTaker = this.safeValue(exchangeFeesTradingTiers, 'taker', []);
1045
- const exchangeFeesTradingTiersMaker = this.safeValue(exchangeFeesTradingTiers, 'maker', []);
1046
- if ((keysLength === exchangeFeesTradingTiersTaker.length) && (firstTier.length > 0)) {
1040
+ const firstTier = this.safeDict(takerFees, 0, []);
1041
+ const exchangeFees = this.safeDict(this, 'fees', {});
1042
+ const exchangeFeesTrading = this.safeDict(exchangeFees, 'trading', {});
1043
+ const exchangeFeesTradingTiers = this.safeDict(exchangeFeesTrading, 'tiers', {});
1044
+ const exchangeFeesTradingTiersTaker = this.safeList(exchangeFeesTradingTiers, 'taker', []);
1045
+ const exchangeFeesTradingTiersMaker = this.safeList(exchangeFeesTradingTiers, 'maker', []);
1046
+ const exchangeFeesTradingTiersTakerLength = exchangeFeesTradingTiersTaker.length;
1047
+ const firstTierLength = firstTier.length;
1048
+ if ((keysLength === exchangeFeesTradingTiersTakerLength) && (firstTierLength > 0)) {
1047
1049
  for (let i = 0; i < keysLength; i++) {
1048
1050
  takerFees[i][0] = exchangeFeesTradingTiersTaker[i][0];
1049
1051
  makerFees[i][0] = exchangeFeesTradingTiersMaker[i][0];
@@ -1169,7 +1169,8 @@ export default class coinmetro extends Exchange {
1169
1169
  }
1170
1170
  let type = undefined;
1171
1171
  let referenceId = undefined;
1172
- if (descriptionArray.length > 1) {
1172
+ const length = descriptionArray.length;
1173
+ if (length > 1) {
1173
1174
  type = this.parseLedgerEntryType(descriptionArray[0]);
1174
1175
  if (descriptionArray[1] !== '-') {
1175
1176
  referenceId = descriptionArray[1];
@@ -22,6 +22,8 @@ export default class krakenfutures extends Exchange {
22
22
  cancelOrders(ids: string[], symbol?: Str, params?: {}): Promise<Order[]>;
23
23
  cancelAllOrders(symbol?: Str, params?: {}): Promise<any>;
24
24
  fetchOpenOrders(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
25
+ fetchClosedOrders(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
26
+ fetchCanceledOrders(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
25
27
  parseOrderType(orderType: any): string;
26
28
  verifyOrderActionSuccess(status: any, method: any, omit?: any[]): void;
27
29
  parseOrderStatus(status: any): string;
@@ -42,7 +42,8 @@ export default class krakenfutures extends Exchange {
42
42
  'fetchBalance': true,
43
43
  'fetchBorrowRateHistories': false,
44
44
  'fetchBorrowRateHistory': false,
45
- 'fetchClosedOrders': undefined,
45
+ 'fetchCanceledOrders': true,
46
+ 'fetchClosedOrders': true,
46
47
  'fetchCrossBorrowRate': false,
47
48
  'fetchCrossBorrowRates': false,
48
49
  'fetchDepositAddress': false,
@@ -1189,6 +1190,102 @@ export default class krakenfutures extends Exchange {
1189
1190
  const orders = this.safeValue(response, 'openOrders', []);
1190
1191
  return this.parseOrders(orders, market, since, limit);
1191
1192
  }
1193
+ async fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1194
+ /**
1195
+ * @method
1196
+ * @name krakenfutures#fetchClosedOrders
1197
+ * @see https://docs.futures.kraken.com/#http-api-history-account-history-get-order-events
1198
+ * @description Gets all closed orders, including trigger orders, for an account from the exchange api
1199
+ * @param {string} symbol Unified market symbol
1200
+ * @param {int} [since] Timestamp (ms) of earliest order.
1201
+ * @param {int} [limit] How many orders to return.
1202
+ * @param {object} [params] Exchange specific parameters
1203
+ * @returns An array of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1204
+ */
1205
+ await this.loadMarkets();
1206
+ let market = undefined;
1207
+ if (symbol !== undefined) {
1208
+ market = this.market(symbol);
1209
+ }
1210
+ const request = {};
1211
+ if (limit !== undefined) {
1212
+ request['count'] = limit;
1213
+ }
1214
+ if (since !== undefined) {
1215
+ request['from'] = since;
1216
+ }
1217
+ const response = await this.historyGetOrders(this.extend(request, params));
1218
+ const allOrders = this.safeList(response, 'elements', []);
1219
+ const closedOrders = [];
1220
+ for (let i = 0; i < allOrders.length; i++) {
1221
+ const order = allOrders[i];
1222
+ const event = this.safeDict(order, 'event', {});
1223
+ const orderPlaced = this.safeDict(event, 'OrderPlaced');
1224
+ if (orderPlaced !== undefined) {
1225
+ const innerOrder = this.safeDict(orderPlaced, 'order', {});
1226
+ const filled = this.safeString(innerOrder, 'filled');
1227
+ if (filled !== '0') {
1228
+ innerOrder['status'] = 'closed'; // status not available in the response
1229
+ closedOrders.push(innerOrder);
1230
+ }
1231
+ }
1232
+ }
1233
+ return this.parseOrders(closedOrders, market, since, limit);
1234
+ }
1235
+ async fetchCanceledOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1236
+ /**
1237
+ * @method
1238
+ * @name krakenfutures#fetchCanceledOrders
1239
+ * @see https://docs.futures.kraken.com/#http-api-history-account-history-get-order-events
1240
+ * @description Gets all canceled orders, including trigger orders, for an account from the exchange api
1241
+ * @param {string} symbol Unified market symbol
1242
+ * @param {int} [since] Timestamp (ms) of earliest order.
1243
+ * @param {int} [limit] How many orders to return.
1244
+ * @param {object} [params] Exchange specific parameters
1245
+ * @returns An array of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1246
+ */
1247
+ await this.loadMarkets();
1248
+ let market = undefined;
1249
+ if (symbol !== undefined) {
1250
+ market = this.market(symbol);
1251
+ }
1252
+ const request = {};
1253
+ if (limit !== undefined) {
1254
+ request['count'] = limit;
1255
+ }
1256
+ if (since !== undefined) {
1257
+ request['from'] = since;
1258
+ }
1259
+ const response = await this.historyGetOrders(this.extend(request, params));
1260
+ const allOrders = this.safeList(response, 'elements', []);
1261
+ const canceledAndRejected = [];
1262
+ for (let i = 0; i < allOrders.length; i++) {
1263
+ const order = allOrders[i];
1264
+ const event = this.safeDict(order, 'event', {});
1265
+ const orderPlaced = this.safeDict(event, 'OrderPlaced');
1266
+ if (orderPlaced !== undefined) {
1267
+ const innerOrder = this.safeDict(orderPlaced, 'order', {});
1268
+ const filled = this.safeString(innerOrder, 'filled');
1269
+ if (filled === '0') {
1270
+ innerOrder['status'] = 'canceled'; // status not available in the response
1271
+ canceledAndRejected.push(innerOrder);
1272
+ }
1273
+ }
1274
+ const orderCanceled = this.safeDict(event, 'OrderCancelled');
1275
+ if (orderCanceled !== undefined) {
1276
+ const innerOrder = this.safeDict(orderCanceled, 'order', {});
1277
+ innerOrder['status'] = 'canceled'; // status not available in the response
1278
+ canceledAndRejected.push(innerOrder);
1279
+ }
1280
+ const orderRejected = this.safeDict(event, 'OrderRejected');
1281
+ if (orderRejected !== undefined) {
1282
+ const innerOrder = this.safeDict(orderRejected, 'order', {});
1283
+ innerOrder['status'] = 'rejected'; // status not available in the response
1284
+ canceledAndRejected.push(innerOrder);
1285
+ }
1286
+ }
1287
+ return this.parseOrders(canceledAndRejected, market, since, limit);
1288
+ }
1192
1289
  parseOrderType(orderType) {
1193
1290
  const map = {
1194
1291
  'lmt': 'limit',
@@ -1432,6 +1529,32 @@ export default class krakenfutures extends Exchange {
1432
1529
  // "status": "requiredArgumentMissing",
1433
1530
  // "orderEvents": []
1434
1531
  // }
1532
+ // closed orders
1533
+ // {
1534
+ // uid: '2f00cd63-e61d-44f8-8569-adabde885941',
1535
+ // timestamp: '1707258274849',
1536
+ // event: {
1537
+ // OrderPlaced: {
1538
+ // order: {
1539
+ // uid: '85805e01-9eed-4395-8360-ed1a228237c9',
1540
+ // accountUid: '406142dd-7c5c-4a8b-acbc-5f16eca30009',
1541
+ // tradeable: 'PF_LTCUSD',
1542
+ // direction: 'Buy',
1543
+ // quantity: '0',
1544
+ // filled: '0.1',
1545
+ // timestamp: '1707258274849',
1546
+ // limitPrice: '69.2200000000',
1547
+ // orderType: 'IoC',
1548
+ // clientId: '',
1549
+ // reduceOnly: false,
1550
+ // lastUpdateTimestamp: '1707258274849'
1551
+ // },
1552
+ // reason: 'new_user_order',
1553
+ // reducedQuantity: '',
1554
+ // algoId: ''
1555
+ // }
1556
+ // }
1557
+ // }
1435
1558
  //
1436
1559
  const orderEvents = this.safeValue(order, 'orderEvents', []);
1437
1560
  const errorStatus = this.safeString(order, 'status');
@@ -1494,7 +1617,8 @@ export default class krakenfutures extends Exchange {
1494
1617
  let remaining = this.safeString(details, 'unfilledSize');
1495
1618
  let average = undefined;
1496
1619
  let filled2 = '0.0';
1497
- if (trades.length) {
1620
+ const tradesLength = trades.length;
1621
+ if (tradesLength > 0) {
1498
1622
  let vwapSum = '0.0';
1499
1623
  for (let i = 0; i < trades.length; i++) {
1500
1624
  const trade = trades[i];