ccxt 4.1.24 → 4.1.26

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 (54) hide show
  1. package/README.md +3 -3
  2. package/dist/ccxt.browser.js +1368 -201
  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 +108 -5
  11. package/dist/cjs/src/bitget.js +485 -22
  12. package/dist/cjs/src/bybit.js +132 -15
  13. package/dist/cjs/src/cryptocom.js +262 -15
  14. package/dist/cjs/src/gate.js +191 -88
  15. package/dist/cjs/src/krakenfutures.js +86 -20
  16. package/dist/cjs/src/oceanex.js +0 -12
  17. package/dist/cjs/src/okx.js +60 -1
  18. package/dist/cjs/src/pro/bybit.js +1 -1
  19. package/dist/cjs/src/static_dependencies/noble-curves/abstract/edwards.js +8 -6
  20. package/dist/cjs/src/wavesexchange.js +6 -6
  21. package/js/ccxt.d.ts +1 -1
  22. package/js/ccxt.js +1 -1
  23. package/js/src/abstract/gate.d.ts +2 -7
  24. package/js/src/abstract/gateio.d.ts +2 -7
  25. package/js/src/ace.js +1 -1
  26. package/js/src/base/Exchange.d.ts +4 -2
  27. package/js/src/base/Exchange.js +7 -3
  28. package/js/src/base/functions/crypto.d.ts +3 -2
  29. package/js/src/base/functions/crypto.js +11 -3
  30. package/js/src/base/functions/generic.d.ts +1 -1
  31. package/js/src/base/functions/generic.js +5 -3
  32. package/js/src/base/types.d.ts +8 -0
  33. package/js/src/binance.d.ts +2 -1
  34. package/js/src/binance.js +108 -5
  35. package/js/src/bitget.d.ts +31 -1
  36. package/js/src/bitget.js +485 -22
  37. package/js/src/bybit.d.ts +4 -2
  38. package/js/src/bybit.js +132 -15
  39. package/js/src/cryptocom.d.ts +4 -1
  40. package/js/src/cryptocom.js +262 -15
  41. package/js/src/gate.d.ts +3 -1
  42. package/js/src/gate.js +191 -88
  43. package/js/src/krakenfutures.d.ts +3 -1
  44. package/js/src/krakenfutures.js +86 -20
  45. package/js/src/oceanex.d.ts +0 -1
  46. package/js/src/oceanex.js +0 -12
  47. package/js/src/okx.d.ts +2 -1
  48. package/js/src/okx.js +60 -1
  49. package/js/src/pro/bybit.js +1 -1
  50. package/js/src/static_dependencies/noble-curves/abstract/edwards.d.ts +1 -0
  51. package/js/src/static_dependencies/noble-curves/abstract/edwards.js +5 -3
  52. package/js/src/wavesexchange.js +7 -7
  53. package/package.json +1 -1
  54. package/skip-tests.json +2 -3
@@ -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')) {
@@ -824,24 +824,7 @@ class krakenfutures extends krakenfutures$1 {
824
824
  'fee': undefined,
825
825
  });
826
826
  }
827
- async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
828
- /**
829
- * @method
830
- * @name krakenfutures#createOrder
831
- * @description Create an order on the exchange
832
- * @param {string} symbol market symbol
833
- * @param {string} type One of 'limit', 'market', 'take_profit'
834
- * @param {string} side buy or sell
835
- * @param {int} amount Contract quantity
836
- * @param {float} [price] Limit order price
837
- * @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,
838
- * @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,
839
- * @param {bool} [params.postOnly] Set as true if you wish to make a postOnly order, Default false
840
- * @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
841
- * @param {string} [params.cliOrdId] UUID The order identity that is specified from the user, It must be globally unique
842
- * @param {string} [params.clientOrderId] UUID The order identity that is specified from the user, It must be globally unique
843
- */
844
- await this.loadMarkets();
827
+ createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
845
828
  type = this.safeString(params, 'orderType', type);
846
829
  const timeInForce = this.safeString(params, 'timeInForce');
847
830
  const stopPrice = this.safeString(params, 'stopPrice');
@@ -879,7 +862,28 @@ class krakenfutures extends krakenfutures$1 {
879
862
  if (clientOrderId !== undefined) {
880
863
  request['cliOrdId'] = clientOrderId;
881
864
  }
882
- 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);
883
887
  //
884
888
  // {
885
889
  // "result": "success",
@@ -915,6 +919,57 @@ class krakenfutures extends krakenfutures$1 {
915
919
  this.verifyOrderActionSuccess(status, 'createOrder', ['filled']);
916
920
  return this.parseOrder(sendStatus);
917
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
+ }
918
973
  async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
919
974
  /**
920
975
  * @method
@@ -1301,14 +1356,25 @@ class krakenfutures extends krakenfutures$1 {
1301
1356
  // "lastUpdateTime": "2019-09-05T17:01:17.410Z"
1302
1357
  // }
1303
1358
  //
1359
+ // createOrders error
1360
+ // {
1361
+ // "status": "requiredArgumentMissing",
1362
+ // "orderEvents": []
1363
+ // }
1364
+ //
1304
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
+ }
1305
1372
  let details = undefined;
1306
1373
  let isPrior = false;
1307
1374
  let fixed = false;
1308
1375
  let statusId = undefined;
1309
1376
  let price = undefined;
1310
1377
  let trades = [];
1311
- const orderEventsLength = orderEvents.length;
1312
1378
  if (orderEventsLength) {
1313
1379
  const executions = [];
1314
1380
  for (let i = 0; i < orderEvents.length; i++) {
@@ -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
@@ -36,6 +36,7 @@ class okx extends okx$1 {
36
36
  'cancelOrders': true,
37
37
  'createDepositAddress': false,
38
38
  'createOrder': true,
39
+ 'createOrders': true,
39
40
  'createPostOnlyOrder': true,
40
41
  'createReduceOnlyOrder': true,
41
42
  'createStopLimitOrder': true,
@@ -2769,6 +2770,55 @@ class okx extends okx$1 {
2769
2770
  order['side'] = side;
2770
2771
  return order;
2771
2772
  }
2773
+ async createOrders(orders, params = {}) {
2774
+ /**
2775
+ * @method
2776
+ * @name okx#createOrders
2777
+ * @description create a list of trade orders
2778
+ * @see https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-place-multiple-orders
2779
+ * @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
2780
+ * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
2781
+ */
2782
+ await this.loadMarkets();
2783
+ const ordersRequests = [];
2784
+ for (let i = 0; i < orders.length; i++) {
2785
+ const rawOrder = orders[i];
2786
+ const marketId = this.safeString(rawOrder, 'symbol');
2787
+ const type = this.safeString(rawOrder, 'type');
2788
+ const side = this.safeString(rawOrder, 'side');
2789
+ const amount = this.safeValue(rawOrder, 'amount');
2790
+ const price = this.safeValue(rawOrder, 'price');
2791
+ const orderParams = this.safeValue(rawOrder, 'params', {});
2792
+ 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
2793
+ const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, extendedParams);
2794
+ ordersRequests.push(orderRequest);
2795
+ }
2796
+ const response = await this.privatePostTradeBatchOrders(ordersRequests);
2797
+ // {
2798
+ // "code": "0",
2799
+ // "data": [
2800
+ // {
2801
+ // "clOrdId": "e847386590ce4dBCc7f2a1b4c4509f82",
2802
+ // "ordId": "636305438765568000",
2803
+ // "sCode": "0",
2804
+ // "sMsg": "Order placed",
2805
+ // "tag": "e847386590ce4dBC"
2806
+ // },
2807
+ // {
2808
+ // "clOrdId": "e847386590ce4dBC0b9993fe642d8f62",
2809
+ // "ordId": "636305438765568001",
2810
+ // "sCode": "0",
2811
+ // "sMsg": "Order placed",
2812
+ // "tag": "e847386590ce4dBC"
2813
+ // }
2814
+ // ],
2815
+ // "inTime": "1697979038584486",
2816
+ // "msg": "",
2817
+ // "outTime": "1697979038586493"
2818
+ // }
2819
+ const data = this.safeValue(response, 'data', []);
2820
+ return this.parseOrders(data);
2821
+ }
2772
2822
  editOrderRequest(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
2773
2823
  const market = this.market(symbol);
2774
2824
  const request = {
@@ -3147,6 +3197,15 @@ class okx extends okx$1 {
3147
3197
  // "uly": "BTC-USDT"
3148
3198
  // }
3149
3199
  //
3200
+ const scode = this.safeString(order, 'sCode');
3201
+ if ((scode !== undefined) && (scode !== '0')) {
3202
+ return this.safeOrder({
3203
+ 'id': this.safeString(order, 'ordId'),
3204
+ 'clientOrderId': this.safeString(order, 'clOrdId'),
3205
+ 'status': 'rejected',
3206
+ 'info': order,
3207
+ });
3208
+ }
3150
3209
  const id = this.safeString2(order, 'algoId', 'ordId');
3151
3210
  const timestamp = this.safeInteger(order, 'cTime');
3152
3211
  const lastUpdateTimestamp = this.safeInteger(order, 'uTime');
@@ -6889,7 +6948,7 @@ class okx extends okx$1 {
6889
6948
  // }
6890
6949
  //
6891
6950
  const code = this.safeString(response, 'code');
6892
- if (code !== '0') {
6951
+ if ((code !== '0') && (code !== '2')) { // 2 means that bulk operation partially succeeded
6893
6952
  const feedback = this.id + ' ' + body;
6894
6953
  const data = this.safeValue(response, 'data', []);
6895
6954
  for (let i = 0; i < data.length; i++) {
@@ -316,7 +316,7 @@ class bybit extends bybit$1 {
316
316
  const topic = this.safeString(message, 'topic', '');
317
317
  const updateType = this.safeString(message, 'type', '');
318
318
  const data = this.safeValue(message, 'data', {});
319
- const isSpot = this.safeString(data, 'openInterestValue') === undefined;
319
+ const isSpot = this.safeString(data, 'fundingRate') === undefined;
320
320
  const type = isSpot ? 'spot' : 'contract';
321
321
  let symbol = undefined;
322
322
  let parsed = undefined;
@@ -354,18 +354,19 @@ function twistedEdwards(curveDef) {
354
354
  }
355
355
  /** Signs message with privateKey. RFC8032 5.1.6 */
356
356
  function sign(msg, privKey, context) {
357
- /*
358
- msg = ensureBytes('message', msg);
359
- if (preHash) msg = preHash(msg); // for ed25519ph etc.
357
+ msg = utils.ensureBytes('message', msg);
358
+ if (preHash)
359
+ msg = preHash(msg); // for ed25519ph etc.
360
360
  const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey);
361
361
  const r = hashDomainToScalar(context, prefix, msg); // r = dom2(F, C) || prefix || PH(M)
362
362
  const R = G.multiply(r).toRawBytes(); // R = rG
363
363
  const k = hashDomainToScalar(context, R, pointBytes, msg); // R || A || PH(M)
364
364
  const s = modN(r + k * scalar); // S = (r + k * s) mod L
365
365
  assertGE0(s); // 0 <= s < l
366
- const res = ut.concatBytes(R, ut.numberToBytesLE(s, Fp.BYTES));
367
- return ensureBytes('result', res, nByteLength * 2); // 64-byte signature
368
- */
366
+ const res = utils.concatBytes(R, utils.numberToBytesLE(s, Fp.BYTES));
367
+ return utils.ensureBytes('result', res, nByteLength * 2); // 64-byte signature
368
+ }
369
+ function signModified(msg, privKey, context) {
369
370
  msg = utils.ensureBytes('message', msg);
370
371
  const privKeyBytes = utils.ensureBytes('privKey', privKey);
371
372
  const privKeyNumber = utils.bytesToNumberLE(privKeyBytes);
@@ -418,6 +419,7 @@ function twistedEdwards(curveDef) {
418
419
  CURVE,
419
420
  getPublicKey,
420
421
  sign,
422
+ signModified,
421
423
  verify,
422
424
  ExtendedPoint: Point,
423
425
  utils: utils$1,