ccxt 4.1.23 → 4.1.25

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 +3 -3
  2. package/dist/ccxt.browser.js +1249 -232
  3. package/dist/ccxt.browser.min.js +4 -4
  4. package/dist/cjs/ccxt.js +1 -1
  5. package/dist/cjs/src/ace.js +1 -1
  6. package/dist/cjs/src/base/Exchange.js +7 -3
  7. package/dist/cjs/src/base/functions/crypto.js +11 -2
  8. package/dist/cjs/src/base/functions/generic.js +5 -3
  9. package/dist/cjs/src/base/functions.js +1 -0
  10. package/dist/cjs/src/binance.js +112 -34
  11. package/dist/cjs/src/bitget.js +289 -21
  12. package/dist/cjs/src/bitmart.js +1 -1
  13. package/dist/cjs/src/bybit.js +132 -15
  14. package/dist/cjs/src/cryptocom.js +262 -15
  15. package/dist/cjs/src/gate.js +191 -88
  16. package/dist/cjs/src/krakenfutures.js +158 -22
  17. package/dist/cjs/src/oceanex.js +0 -12
  18. package/dist/cjs/src/okx.js +60 -1
  19. package/dist/cjs/src/pro/bybit.js +1 -1
  20. package/dist/cjs/src/static_dependencies/noble-curves/abstract/edwards.js +8 -6
  21. package/dist/cjs/src/wavesexchange.js +6 -6
  22. package/js/ccxt.d.ts +1 -1
  23. package/js/ccxt.js +1 -1
  24. package/js/src/abstract/binance.d.ts +1 -14
  25. package/js/src/abstract/binancecoinm.d.ts +1 -14
  26. package/js/src/abstract/binanceus.d.ts +1 -14
  27. package/js/src/abstract/binanceusdm.d.ts +1 -14
  28. package/js/src/abstract/gate.d.ts +2 -7
  29. package/js/src/abstract/gateio.d.ts +2 -7
  30. package/js/src/ace.js +1 -1
  31. package/js/src/base/Exchange.d.ts +4 -2
  32. package/js/src/base/Exchange.js +7 -3
  33. package/js/src/base/functions/crypto.d.ts +3 -2
  34. package/js/src/base/functions/crypto.js +11 -3
  35. package/js/src/base/functions/generic.d.ts +1 -1
  36. package/js/src/base/functions/generic.js +5 -3
  37. package/js/src/base/types.d.ts +8 -0
  38. package/js/src/binance.d.ts +2 -1
  39. package/js/src/binance.js +112 -34
  40. package/js/src/bitget.d.ts +15 -1
  41. package/js/src/bitget.js +289 -21
  42. package/js/src/bitmart.js +1 -1
  43. package/js/src/bybit.d.ts +4 -2
  44. package/js/src/bybit.js +132 -15
  45. package/js/src/cryptocom.d.ts +4 -1
  46. package/js/src/cryptocom.js +262 -15
  47. package/js/src/gate.d.ts +3 -1
  48. package/js/src/gate.js +191 -88
  49. package/js/src/krakenfutures.d.ts +4 -1
  50. package/js/src/krakenfutures.js +158 -22
  51. package/js/src/oceanex.d.ts +0 -1
  52. package/js/src/oceanex.js +0 -12
  53. package/js/src/okx.d.ts +2 -1
  54. package/js/src/okx.js +60 -1
  55. package/js/src/pro/bybit.js +1 -1
  56. package/js/src/static_dependencies/noble-curves/abstract/edwards.d.ts +1 -0
  57. package/js/src/static_dependencies/noble-curves/abstract/edwards.js +5 -3
  58. package/js/src/wavesexchange.js +7 -7
  59. package/package.json +1 -1
  60. package/skip-tests.json +2 -3
  61. package/js/src/bkex.d.ts +0 -95
  62. package/js/src/bkex.js +0 -1962
  63. package/js/src/pro/btcex.d.ts +0 -32
  64. package/js/src/pro/btcex.js +0 -776
  65. package/js/src/pro/ripio.d.ts +0 -18
  66. package/js/src/pro/ripio.js +0 -296
  67. package/js/src/pro/zb.d.ts +0 -22
  68. package/js/src/pro/zb.js +0 -605
@@ -79,6 +79,7 @@ class gate extends gate$1 {
79
79
  'cancelOrder': true,
80
80
  'createMarketOrder': true,
81
81
  'createOrder': true,
82
+ 'createOrders': true,
82
83
  'createPostOnlyOrder': true,
83
84
  'createReduceOnlyOrder': true,
84
85
  'createStopLimitOrder': true,
@@ -284,8 +285,6 @@ class gate extends gate$1 {
284
285
  },
285
286
  'portfolio': {
286
287
  'get': {
287
- 'spot/currency_pairs': 20 / 15,
288
- 'spot/currency_pairs/{currency_pair}': 20 / 15,
289
288
  'accounts': 20 / 15,
290
289
  'account_mode': 20 / 15,
291
290
  'borrowable': 20 / 15,
@@ -293,19 +292,10 @@ class gate extends gate$1 {
293
292
  'loans': 20 / 15,
294
293
  'loan_records': 20 / 15,
295
294
  'interest_records': 20 / 15,
296
- 'spot/orders': 20 / 15,
297
- 'spot/orders/{order_id}': 20 / 15,
298
295
  },
299
296
  'post': {
300
297
  'account_mode': 20 / 15,
301
- 'loans': 200 / 15,
302
- 'spot/orders': 20 / 15,
303
- },
304
- 'delete': {
305
- 'spot/orders/{order_id}': 20 / 15,
306
- },
307
- 'patch': {
308
- 'spot/orders/{order_id}': 20 / 15,
298
+ 'loans': 200 / 15, // 15r/10s cost = 20 / 1.5 = 13.33
309
299
  },
310
300
  },
311
301
  'spot': {
@@ -328,6 +318,7 @@ class gate extends gate$1 {
328
318
  'orders': 0.4,
329
319
  'cancel_batch_orders': 20 / 75,
330
320
  'countdown_cancel_all': 20 / 75,
321
+ 'amend_batch_orders': 0.4,
331
322
  'price_orders': 0.4,
332
323
  },
333
324
  'delete': {
@@ -498,6 +489,9 @@ class gate extends gate$1 {
498
489
  'post': {
499
490
  'uni/lends': 20 / 15,
500
491
  },
492
+ 'put': {
493
+ 'uni/interest_reinvest': 20 / 15,
494
+ },
501
495
  'patch': {
502
496
  'uni/lends': 20 / 15,
503
497
  },
@@ -3662,6 +3656,156 @@ class gate extends gate$1 {
3662
3656
  * @returns {object|undefined} [An order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
3663
3657
  */
3664
3658
  await this.loadMarkets();
3659
+ const market = this.market(symbol);
3660
+ const trigger = this.safeValue(params, 'trigger');
3661
+ const triggerPrice = this.safeValue2(params, 'triggerPrice', 'stopPrice');
3662
+ const stopLossPrice = this.safeValue(params, 'stopLossPrice', triggerPrice);
3663
+ const takeProfitPrice = this.safeValue(params, 'takeProfitPrice');
3664
+ const isStopLossOrder = stopLossPrice !== undefined;
3665
+ const isTakeProfitOrder = takeProfitPrice !== undefined;
3666
+ const isStopOrder = isStopLossOrder || isTakeProfitOrder;
3667
+ const nonTriggerOrder = !isStopOrder && (trigger === undefined);
3668
+ const orderRequest = this.createOrderRequest(symbol, type, side, amount, price, params);
3669
+ let response = undefined;
3670
+ if (market['spot'] || market['margin']) {
3671
+ if (nonTriggerOrder) {
3672
+ response = await this.privateSpotPostOrders(orderRequest);
3673
+ }
3674
+ else {
3675
+ response = await this.privateSpotPostPriceOrders(orderRequest);
3676
+ }
3677
+ }
3678
+ else if (market['swap']) {
3679
+ if (nonTriggerOrder) {
3680
+ response = await this.privateFuturesPostSettleOrders(orderRequest);
3681
+ }
3682
+ else {
3683
+ response = await this.privateFuturesPostSettlePriceOrders(orderRequest);
3684
+ }
3685
+ }
3686
+ else if (market['future']) {
3687
+ if (nonTriggerOrder) {
3688
+ response = await this.privateDeliveryPostSettleOrders(orderRequest);
3689
+ }
3690
+ else {
3691
+ response = await this.privateDeliveryPostSettlePriceOrders(orderRequest);
3692
+ }
3693
+ }
3694
+ else {
3695
+ response = await this.privateOptionsPostOrders(orderRequest);
3696
+ }
3697
+ // const response = await this[method] (this.deepExtend (request, params));
3698
+ //
3699
+ // spot
3700
+ //
3701
+ // {
3702
+ // "id": "95282841887",
3703
+ // "text": "apiv4",
3704
+ // "create_time": "1637383156",
3705
+ // "update_time": "1637383156",
3706
+ // "create_time_ms": 1637383156017,
3707
+ // "update_time_ms": 1637383156017,
3708
+ // "status": "open",
3709
+ // "currency_pair": "ETH_USDT",
3710
+ // "type": "limit",
3711
+ // "account": "spot",
3712
+ // "side": "buy",
3713
+ // "amount": "0.01",
3714
+ // "price": "3500",
3715
+ // "time_in_force": "gtc",
3716
+ // "iceberg": "0",
3717
+ // "left": "0.01",
3718
+ // "fill_price": "0",
3719
+ // "filled_total": "0",
3720
+ // "fee": "0",
3721
+ // "fee_currency": "ETH",
3722
+ // "point_fee": "0",
3723
+ // "gt_fee": "0",
3724
+ // "gt_discount": false,
3725
+ // "rebated_fee": "0",
3726
+ // "rebated_fee_currency": "USDT"
3727
+ // }
3728
+ //
3729
+ // spot conditional
3730
+ //
3731
+ // {"id": 5891843}
3732
+ //
3733
+ // futures, perpetual swaps and options
3734
+ //
3735
+ // {
3736
+ // "id": 95938572327,
3737
+ // "contract": "ETH_USDT",
3738
+ // "mkfr": "0",
3739
+ // "tkfr": "0.0005",
3740
+ // "tif": "gtc",
3741
+ // "is_reduce_only": false,
3742
+ // "create_time": 1637384600.08,
3743
+ // "price": "3000",
3744
+ // "size": 1,
3745
+ // "refr": "0",
3746
+ // "left": 1,
3747
+ // "text": "api",
3748
+ // "fill_price": "0",
3749
+ // "user": 2436035,
3750
+ // "status": "open",
3751
+ // "is_liq": false,
3752
+ // "refu": 0,
3753
+ // "is_close": false,
3754
+ // "iceberg": 0
3755
+ // }
3756
+ //
3757
+ // futures and perpetual swaps conditionals
3758
+ //
3759
+ // {"id": 7615567}
3760
+ //
3761
+ return this.parseOrder(response, market);
3762
+ }
3763
+ async createOrders(orders, params = {}) {
3764
+ /**
3765
+ * @method
3766
+ * @name gate#createOrders
3767
+ * @description create a list of trade orders
3768
+ * @see https://www.gate.io/docs/developers/apiv4/en/#get-a-single-order-2
3769
+ * @see https://www.gate.io/docs/developers/apiv4/en/#create-a-batch-of-orders
3770
+ * @param {Array} orders list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
3771
+ * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
3772
+ */
3773
+ await this.loadMarkets();
3774
+ const ordersRequests = [];
3775
+ const orderSymbols = [];
3776
+ for (let i = 0; i < orders.length; i++) {
3777
+ const rawOrder = orders[i];
3778
+ const marketId = this.safeString(rawOrder, 'symbol');
3779
+ orderSymbols.push(marketId);
3780
+ const type = this.safeString(rawOrder, 'type');
3781
+ const side = this.safeString(rawOrder, 'side');
3782
+ const amount = this.safeValue(rawOrder, 'amount');
3783
+ const price = this.safeValue(rawOrder, 'price');
3784
+ const orderParams = this.safeValue(rawOrder, 'params', {});
3785
+ const extendedParams = this.extend(orderParams, params); // the request does not accept extra params since it's a list, so we're extending each order with the common params
3786
+ const triggerValue = this.safeValueN(orderParams, ['triggerPrice', 'stopPrice', 'takeProfitPrice', 'stopLossPrice']);
3787
+ if (triggerValue !== undefined) {
3788
+ throw new errors.NotSupported(this.id + ' createOrders() does not support advanced order properties (stopPrice, takeProfitPrice, stopLossPrice)');
3789
+ }
3790
+ extendedParams['textIsRequired'] = true; // Gate.io requires a text parameter for each order here
3791
+ const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, extendedParams);
3792
+ ordersRequests.push(orderRequest);
3793
+ }
3794
+ const symbols = this.marketSymbols(orderSymbols, undefined, false, true, true);
3795
+ const market = this.market(symbols[0]);
3796
+ if (market['future'] || market['option']) {
3797
+ throw new errors.NotSupported(this.id + ' createOrders() does not support futures or options markets');
3798
+ }
3799
+ let response = undefined;
3800
+ if (market['spot']) {
3801
+ response = await this.privateSpotPostBatchOrders(ordersRequests);
3802
+ }
3803
+ else if (market['swap']) {
3804
+ response = await this.privateFuturesPostSettleBatchOrders(ordersRequests);
3805
+ }
3806
+ return this.parseOrders(response);
3807
+ }
3808
+ createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
3665
3809
  const market = this.market(symbol);
3666
3810
  const contract = market['contract'];
3667
3811
  const trigger = this.safeValue(params, 'trigger');
@@ -3674,7 +3818,6 @@ class gate extends gate$1 {
3674
3818
  if (isStopLossOrder && isTakeProfitOrder) {
3675
3819
  throw new errors.ExchangeError(this.id + ' createOrder() stopLossPrice and takeProfitPrice cannot both be defined');
3676
3820
  }
3677
- let methodTail = 'Orders';
3678
3821
  const reduceOnly = this.safeValue(params, 'reduceOnly');
3679
3822
  const exchangeSpecificTimeInForce = this.safeStringLowerN(params, ['timeInForce', 'tif', 'time_in_force']);
3680
3823
  let postOnly = undefined;
@@ -3787,6 +3930,7 @@ class gate extends gate$1 {
3787
3930
  }
3788
3931
  }
3789
3932
  let clientOrderId = this.safeString2(params, 'text', 'clientOrderId');
3933
+ const textIsRequired = this.safeValue(params, 'textIsRequired', false);
3790
3934
  if (clientOrderId !== undefined) {
3791
3935
  // user-defined, must follow the rules if not empty
3792
3936
  // prefixed with t-
@@ -3795,12 +3939,18 @@ class gate extends gate$1 {
3795
3939
  if (clientOrderId.length > 28) {
3796
3940
  throw new errors.BadRequest(this.id + ' createOrder () clientOrderId or text param must be up to 28 characters');
3797
3941
  }
3798
- params = this.omit(params, ['text', 'clientOrderId']);
3942
+ params = this.omit(params, ['text', 'clientOrderId', 'textIsRequired']);
3799
3943
  if (clientOrderId[0] !== 't') {
3800
3944
  clientOrderId = 't-' + clientOrderId;
3801
3945
  }
3802
3946
  request['text'] = clientOrderId;
3803
3947
  }
3948
+ else {
3949
+ if (textIsRequired) {
3950
+ // batchOrders requires text in the request
3951
+ request['text'] = 't-' + this.uuid16();
3952
+ }
3953
+ }
3804
3954
  }
3805
3955
  else {
3806
3956
  if (market['option']) {
@@ -3894,80 +4044,8 @@ class gate extends gate$1 {
3894
4044
  };
3895
4045
  }
3896
4046
  }
3897
- methodTail = 'PriceOrders';
3898
4047
  }
3899
- const method = this.getSupportedMapping(market['type'], {
3900
- 'spot': 'privateSpotPost' + methodTail,
3901
- 'margin': 'privateSpotPost' + methodTail,
3902
- 'swap': 'privateFuturesPostSettle' + methodTail,
3903
- 'future': 'privateDeliveryPostSettle' + methodTail,
3904
- 'option': 'privateOptionsPostOrders',
3905
- });
3906
- const response = await this[method](this.deepExtend(request, params));
3907
- //
3908
- // spot
3909
- //
3910
- // {
3911
- // "id": "95282841887",
3912
- // "text": "apiv4",
3913
- // "create_time": "1637383156",
3914
- // "update_time": "1637383156",
3915
- // "create_time_ms": 1637383156017,
3916
- // "update_time_ms": 1637383156017,
3917
- // "status": "open",
3918
- // "currency_pair": "ETH_USDT",
3919
- // "type": "limit",
3920
- // "account": "spot",
3921
- // "side": "buy",
3922
- // "amount": "0.01",
3923
- // "price": "3500",
3924
- // "time_in_force": "gtc",
3925
- // "iceberg": "0",
3926
- // "left": "0.01",
3927
- // "fill_price": "0",
3928
- // "filled_total": "0",
3929
- // "fee": "0",
3930
- // "fee_currency": "ETH",
3931
- // "point_fee": "0",
3932
- // "gt_fee": "0",
3933
- // "gt_discount": false,
3934
- // "rebated_fee": "0",
3935
- // "rebated_fee_currency": "USDT"
3936
- // }
3937
- //
3938
- // spot conditional
3939
- //
3940
- // {"id": 5891843}
3941
- //
3942
- // futures, perpetual swaps and options
3943
- //
3944
- // {
3945
- // "id": 95938572327,
3946
- // "contract": "ETH_USDT",
3947
- // "mkfr": "0",
3948
- // "tkfr": "0.0005",
3949
- // "tif": "gtc",
3950
- // "is_reduce_only": false,
3951
- // "create_time": 1637384600.08,
3952
- // "price": "3000",
3953
- // "size": 1,
3954
- // "refr": "0",
3955
- // "left": 1,
3956
- // "text": "api",
3957
- // "fill_price": "0",
3958
- // "user": 2436035,
3959
- // "status": "open",
3960
- // "is_liq": false,
3961
- // "refu": 0,
3962
- // "is_close": false,
3963
- // "iceberg": 0
3964
- // }
3965
- //
3966
- // futures and perpetual swaps conditionals
3967
- //
3968
- // {"id": 7615567}
3969
- //
3970
- return this.parseOrder(response, market);
4048
+ return this.extend(request, params);
3971
4049
  }
3972
4050
  async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
3973
4051
  /**
@@ -4193,6 +4271,22 @@ class gate extends gate$1 {
4193
4271
  // "order_type": ""
4194
4272
  // }
4195
4273
  //
4274
+ // {
4275
+ // "text": "t-d18baf9ac44d82e2",
4276
+ // "succeeded": false,
4277
+ // "label": "BALANCE_NOT_ENOUGH",
4278
+ // "message": "Not enough balance"
4279
+ // }
4280
+ //
4281
+ const succeeded = this.safeValue(order, 'succeeded', true);
4282
+ if (!succeeded) {
4283
+ // cancelOrders response
4284
+ return this.safeOrder({
4285
+ 'clientOrderId': this.safeString(order, 'text'),
4286
+ 'info': order,
4287
+ 'status': 'rejected',
4288
+ });
4289
+ }
4196
4290
  const put = this.safeValue2(order, 'put', 'initial', {});
4197
4291
  const trigger = this.safeValue(order, 'trigger', {});
4198
4292
  let contract = this.safeString(put, 'contract');
@@ -5632,7 +5726,16 @@ class gate extends gate$1 {
5632
5726
  const authentication = api[0]; // public, private
5633
5727
  const type = api[1]; // spot, margin, future, delivery
5634
5728
  let query = this.omit(params, this.extractParams(path));
5635
- path = this.implodeParams(path, params);
5729
+ if (Array.isArray(params)) {
5730
+ // endpoints like createOrders use an array instead of an object
5731
+ // so we infer the settle from one of the elements
5732
+ // they have to be all the same so relying on the first one is fine
5733
+ const first = this.safeValue(params, 0, {});
5734
+ path = this.implodeParams(path, first);
5735
+ }
5736
+ else {
5737
+ path = this.implodeParams(path, params);
5738
+ }
5636
5739
  const endPart = (path === '') ? '' : ('/' + path);
5637
5740
  let entirePath = '/' + type + endPart;
5638
5741
  if ((type === 'subAccounts') || (type === 'withdrawals')) {
@@ -32,6 +32,7 @@ class krakenfutures extends krakenfutures$1 {
32
32
  'option': false,
33
33
  'cancelAllOrders': true,
34
34
  'cancelOrder': true,
35
+ 'cancelOrders': true,
35
36
  'createMarketOrder': false,
36
37
  'createOrder': true,
37
38
  'editOrder': true,
@@ -823,24 +824,7 @@ class krakenfutures extends krakenfutures$1 {
823
824
  'fee': undefined,
824
825
  });
825
826
  }
826
- async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
827
- /**
828
- * @method
829
- * @name krakenfutures#createOrder
830
- * @description Create an order on the exchange
831
- * @param {string} symbol market symbol
832
- * @param {string} type One of 'limit', 'market', 'take_profit'
833
- * @param {string} side buy or sell
834
- * @param {int} amount Contract quantity
835
- * @param {float} [price] Limit order price
836
- * @param {float} [params.stopPrice] The stop price associated with a stop or take profit order, Required if orderType is stp or take_profit, Must not have more than 2 decimal places, Note that for stop orders, limitPrice denotes the worst price at which the stop or take_profit order can get filled at. If no limitPrice is provided the stop or take_profit order will trigger a market order,
837
- * @param {bool} [params.reduceOnly] Set as true if you wish the order to only reduce an existing position, Any order which increases an existing position will be rejected, Default false,
838
- * @param {bool} [params.postOnly] Set as true if you wish to make a postOnly order, Default false
839
- * @param {string} [params.triggerSignal] If placing a stp or take_profit, the signal used for trigger, One of: 'mark', 'index', 'last', last is market price
840
- * @param {string} [params.cliOrdId] UUID The order identity that is specified from the user, It must be globally unique
841
- * @param {string} [params.clientOrderId] UUID The order identity that is specified from the user, It must be globally unique
842
- */
843
- await this.loadMarkets();
827
+ createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
844
828
  type = this.safeString(params, 'orderType', type);
845
829
  const timeInForce = this.safeString(params, 'timeInForce');
846
830
  const stopPrice = this.safeString(params, 'stopPrice');
@@ -878,7 +862,28 @@ class krakenfutures extends krakenfutures$1 {
878
862
  if (clientOrderId !== undefined) {
879
863
  request['cliOrdId'] = clientOrderId;
880
864
  }
881
- const response = await this.privatePostSendorder(this.extend(request, params));
865
+ return this.extend(request, params);
866
+ }
867
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
868
+ /**
869
+ * @method
870
+ * @name krakenfutures#createOrder
871
+ * @description Create an order on the exchange
872
+ * @param {string} symbol market symbol
873
+ * @param {string} type One of 'limit', 'market', 'take_profit'
874
+ * @param {string} side buy or sell
875
+ * @param {int} amount Contract quantity
876
+ * @param {float} [price] Limit order price
877
+ * @param {float} [params.stopPrice] The stop price associated with a stop or take profit order, Required if orderType is stp or take_profit, Must not have more than 2 decimal places, Note that for stop orders, limitPrice denotes the worst price at which the stop or take_profit order can get filled at. If no limitPrice is provided the stop or take_profit order will trigger a market order,
878
+ * @param {bool} [params.reduceOnly] Set as true if you wish the order to only reduce an existing position, Any order which increases an existing position will be rejected, Default false,
879
+ * @param {bool} [params.postOnly] Set as true if you wish to make a postOnly order, Default false
880
+ * @param {string} [params.triggerSignal] If placing a stp or take_profit, the signal used for trigger, One of: 'mark', 'index', 'last', last is market price
881
+ * @param {string} [params.cliOrdId] UUID The order identity that is specified from the user, It must be globally unique
882
+ * @param {string} [params.clientOrderId] UUID The order identity that is specified from the user, It must be globally unique
883
+ */
884
+ await this.loadMarkets();
885
+ const orderRequest = this.createOrderRequest(symbol, type, side, amount, price, params);
886
+ const response = await this.privatePostSendorder(orderRequest);
882
887
  //
883
888
  // {
884
889
  // "result": "success",
@@ -914,6 +919,57 @@ class krakenfutures extends krakenfutures$1 {
914
919
  this.verifyOrderActionSuccess(status, 'createOrder', ['filled']);
915
920
  return this.parseOrder(sendStatus);
916
921
  }
922
+ async createOrders(orders, params = {}) {
923
+ /**
924
+ * @method
925
+ * @name krakenfutures#createOrders
926
+ * @description create a list of trade orders
927
+ * @see https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-batch-order-management
928
+ * @param {array} orders list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
929
+ * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
930
+ */
931
+ await this.loadMarkets();
932
+ const ordersRequests = [];
933
+ for (let i = 0; i < orders.length; i++) {
934
+ const rawOrder = orders[i];
935
+ const marketId = this.safeString(rawOrder, 'symbol');
936
+ const type = this.safeString(rawOrder, 'type');
937
+ const side = this.safeString(rawOrder, 'side');
938
+ const amount = this.safeValue(rawOrder, 'amount');
939
+ const price = this.safeValue(rawOrder, 'price');
940
+ const orderParams = this.safeValue(rawOrder, 'params', {});
941
+ const extendedParams = this.extend(orderParams, params); // the request does not accept extra params since it's a list, so we're extending each order with the common params
942
+ if (!('order_tag' in extendedParams)) {
943
+ // order tag is mandatory so we will generate one if not provided
944
+ extendedParams['order_tag'] = this.sum(i, 1).toString(); // sequential counter
945
+ }
946
+ extendedParams['order'] = 'send';
947
+ const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, extendedParams);
948
+ ordersRequests.push(orderRequest);
949
+ }
950
+ const request = {
951
+ 'batchOrder': ordersRequests,
952
+ };
953
+ const response = await this.privatePostBatchorder(this.extend(request, params));
954
+ //
955
+ // {
956
+ // "result": "success",
957
+ // "serverTime": "2023-10-24T08:40:57.339Z",
958
+ // "batchStatus": [
959
+ // {
960
+ // "status": "requiredArgumentMissing",
961
+ // "orderEvents": []
962
+ // },
963
+ // {
964
+ // "status": "requiredArgumentMissing",
965
+ // "orderEvents": []
966
+ // }
967
+ // ]
968
+ // }
969
+ //
970
+ const data = this.safeValue(response, 'batchStatus', []);
971
+ return this.parseOrders(data);
972
+ }
917
973
  async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
918
974
  /**
919
975
  * @method
@@ -962,6 +1018,70 @@ class krakenfutures extends krakenfutures$1 {
962
1018
  }
963
1019
  return this.extend({ 'info': response }, order);
964
1020
  }
1021
+ async cancelOrders(ids, symbol = undefined, params = {}) {
1022
+ /**
1023
+ * @method
1024
+ * @name krakenfutures#cancelOrders
1025
+ * @description cancel multiple orders
1026
+ * @see https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-batch-order-management
1027
+ * @param {[string]} ids order ids
1028
+ * @param {string} [symbol] unified market symbol
1029
+ * @param {object} [params] extra parameters specific to the bingx api endpoint
1030
+ *
1031
+ * EXCHANGE SPECIFIC PARAMETERS
1032
+ * @param {[string]} [params.clientOrderIds] max length 10 e.g. ["my_id_1","my_id_2"]
1033
+ * @returns {object} an list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1034
+ */
1035
+ await this.loadMarkets();
1036
+ const orders = [];
1037
+ const clientOrderIds = this.safeValue(params, 'clientOrderIds', []);
1038
+ const clientOrderIdsLength = clientOrderIds.length;
1039
+ if (clientOrderIdsLength > 0) {
1040
+ for (let i = 0; i < clientOrderIds.length; i++) {
1041
+ orders.push({ 'order': 'cancel', 'cliOrdId': clientOrderIds[i] });
1042
+ }
1043
+ }
1044
+ else {
1045
+ for (let i = 0; i < ids.length; i++) {
1046
+ orders.push({ 'order': 'cancel', 'order_id': ids[i] });
1047
+ }
1048
+ }
1049
+ const request = {
1050
+ 'batchOrder': orders,
1051
+ };
1052
+ const response = await this.privatePostBatchorder(this.extend(request, params));
1053
+ // {
1054
+ // result: 'success',
1055
+ // serverTime: '2023-10-23T16:36:51.327Z',
1056
+ // batchStatus: [
1057
+ // {
1058
+ // status: 'cancelled',
1059
+ // order_id: '101c2327-f12e-45f2-8445-7502b87afc0b',
1060
+ // orderEvents: [
1061
+ // {
1062
+ // uid: '101c2327-f12e-45f2-8445-7502b87afc0b',
1063
+ // order: {
1064
+ // orderId: '101c2327-f12e-45f2-8445-7502b87afc0b',
1065
+ // cliOrdId: null,
1066
+ // type: 'lmt',
1067
+ // symbol: 'PF_LTCUSD',
1068
+ // side: 'buy',
1069
+ // quantity: '0.10000000000',
1070
+ // filled: '0E-11',
1071
+ // limitPrice: '50.00000000000',
1072
+ // reduceOnly: false,
1073
+ // timestamp: '2023-10-20T10:29:13.005Z',
1074
+ // lastUpdateTimestamp: '2023-10-20T10:29:13.005Z'
1075
+ // },
1076
+ // type: 'CANCEL'
1077
+ // }
1078
+ // ]
1079
+ // }
1080
+ // ]
1081
+ // }
1082
+ const batchStatus = this.safeValue(response, 'batchStatus', []);
1083
+ return this.parseOrders(batchStatus);
1084
+ }
965
1085
  async cancelAllOrders(symbol = undefined, params = {}) {
966
1086
  /**
967
1087
  * @method
@@ -1236,14 +1356,25 @@ class krakenfutures extends krakenfutures$1 {
1236
1356
  // "lastUpdateTime": "2019-09-05T17:01:17.410Z"
1237
1357
  // }
1238
1358
  //
1359
+ // createOrders error
1360
+ // {
1361
+ // "status": "requiredArgumentMissing",
1362
+ // "orderEvents": []
1363
+ // }
1364
+ //
1239
1365
  const orderEvents = this.safeValue(order, 'orderEvents', []);
1366
+ const errorStatus = this.safeString(order, 'status');
1367
+ const orderEventsLength = orderEvents.length;
1368
+ if (('orderEvents' in order) && (errorStatus !== undefined) && (orderEventsLength === 0)) {
1369
+ // creteOrders error response
1370
+ return this.safeOrder({ 'info': order, 'status': 'rejected' });
1371
+ }
1240
1372
  let details = undefined;
1241
1373
  let isPrior = false;
1242
1374
  let fixed = false;
1243
1375
  let statusId = undefined;
1244
1376
  let price = undefined;
1245
1377
  let trades = [];
1246
- const orderEventsLength = orderEvents.length;
1247
1378
  if (orderEventsLength) {
1248
1379
  const executions = [];
1249
1380
  for (let i = 0; i < orderEvents.length; i++) {
@@ -2148,7 +2279,11 @@ class krakenfutures extends krakenfutures$1 {
2148
2279
  params = this.omit(params, this.extractParams(path));
2149
2280
  let query = endpoint;
2150
2281
  let postData = '';
2151
- if (Object.keys(params).length) {
2282
+ if (path === 'batchorder') {
2283
+ postData = 'json=' + this.json(params);
2284
+ body = postData;
2285
+ }
2286
+ else if (Object.keys(params).length) {
2152
2287
  postData = this.urlencode(params);
2153
2288
  query += '?' + postData;
2154
2289
  }
@@ -2163,7 +2298,8 @@ class krakenfutures extends krakenfutures$1 {
2163
2298
  const secret = this.base64ToBinary(this.secret); // 3
2164
2299
  const signature = this.hmac(hash, secret, sha512.sha512, 'base64'); // 4-5
2165
2300
  headers = {
2166
- 'Content-Type': 'application/json',
2301
+ 'Content-Type': 'application/x-www-form-urlencoded',
2302
+ 'Accept': 'application/json',
2167
2303
  'APIKey': this.apiKey,
2168
2304
  'Authent': signature,
2169
2305
  };
@@ -861,18 +861,6 @@ class oceanex extends oceanex$1 {
861
861
  };
862
862
  return this.safeString(statuses, status, status);
863
863
  }
864
- async createOrders(symbol, orders, params = {}) {
865
- await this.loadMarkets();
866
- const market = this.market(symbol);
867
- const request = {
868
- 'market': market['id'],
869
- 'orders': orders,
870
- };
871
- // orders: [{"side":"buy", "volume":.2, "price":1001}, {"side":"sell", "volume":0.2, "price":1002}]
872
- const response = await this.privatePostOrdersMulti(this.extend(request, params));
873
- const data = response['data'];
874
- return this.parseOrders(data);
875
- }
876
864
  async cancelOrder(id, symbol = undefined, params = {}) {
877
865
  /**
878
866
  * @method