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
@@ -2482,7 +2482,7 @@ class ace extends _abstract_ace_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
2482
2482
  'timeStamp': nonce,
2483
2483
  }, params);
2484
2484
  const dataKeys = Object.keys(data);
2485
- const sortedDataKeys = this.sortBy(dataKeys, 0);
2485
+ const sortedDataKeys = this.sortBy(dataKeys, 0, false, '');
2486
2486
  for (let i = 0; i < sortedDataKeys.length; i++) {
2487
2487
  const key = sortedDataKeys[i];
2488
2488
  auth += this.safeString(data, key);
@@ -6868,6 +6868,7 @@ class Exchange {
6868
6868
  'createLimitOrder': true,
6869
6869
  'createMarketOrder': true,
6870
6870
  'createOrder': true,
6871
+ 'createOrders': undefined,
6871
6872
  'createPostOnlyOrder': undefined,
6872
6873
  'createReduceOnlyOrder': undefined,
6873
6874
  'createStopOrder': undefined,
@@ -8142,7 +8143,7 @@ class Exchange {
8142
8143
  this.markets_by_id = {};
8143
8144
  // handle marketId conflicts
8144
8145
  // we insert spot markets first
8145
- const marketValues = this.sortBy(this.toArray(markets), 'spot', true);
8146
+ const marketValues = this.sortBy(this.toArray(markets), 'spot', true, true);
8146
8147
  for (let i = 0; i < marketValues.length; i++) {
8147
8148
  const value = marketValues[i];
8148
8149
  if (value['id'] in this.markets_by_id) {
@@ -8192,8 +8193,8 @@ class Exchange {
8192
8193
  quoteCurrencies.push(currency);
8193
8194
  }
8194
8195
  }
8195
- baseCurrencies = this.sortBy(baseCurrencies, 'code');
8196
- quoteCurrencies = this.sortBy(quoteCurrencies, 'code');
8196
+ baseCurrencies = this.sortBy(baseCurrencies, 'code', false, '');
8197
+ quoteCurrencies = this.sortBy(quoteCurrencies, 'code', false, '');
8197
8198
  this.baseCurrencies = this.indexBy(baseCurrencies, 'code');
8198
8199
  this.quoteCurrencies = this.indexBy(quoteCurrencies, 'code');
8199
8200
  const allCurrencies = this.arrayConcat(baseCurrencies, quoteCurrencies);
@@ -9855,6 +9856,9 @@ class Exchange {
9855
9856
  async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
9856
9857
  throw new _errors_js__WEBPACK_IMPORTED_MODULE_3__.NotSupported(this.id + ' createOrder() is not supported yet');
9857
9858
  }
9859
+ async createOrders(orders, params = {}) {
9860
+ throw new _errors_js__WEBPACK_IMPORTED_MODULE_3__.NotSupported(this.id + ' createOrders() is not supported yet');
9861
+ }
9858
9862
  async createOrderWs(symbol, type, side, amount, price = undefined, params = {}) {
9859
9863
  throw new _errors_js__WEBPACK_IMPORTED_MODULE_3__.NotSupported(this.id + ' createOrderWs() is not supported yet');
9860
9864
  }
@@ -11633,6 +11637,7 @@ __webpack_require__.r(__webpack_exports__);
11633
11637
  /* harmony export */ "arrayConcat": () => (/* reexport safe */ _functions_generic_js__WEBPACK_IMPORTED_MODULE_1__.oE),
11634
11638
  /* harmony export */ "asFloat": () => (/* reexport safe */ _functions_type_js__WEBPACK_IMPORTED_MODULE_3__.GX),
11635
11639
  /* harmony export */ "asInteger": () => (/* reexport safe */ _functions_type_js__WEBPACK_IMPORTED_MODULE_3__.xJ),
11640
+ /* harmony export */ "axolotl": () => (/* reexport safe */ _functions_crypto_js__WEBPACK_IMPORTED_MODULE_6__.gC),
11636
11641
  /* harmony export */ "base16ToBinary": () => (/* reexport safe */ _functions_encode_js__WEBPACK_IMPORTED_MODULE_5__.aj),
11637
11642
  /* harmony export */ "base58ToBinary": () => (/* reexport safe */ _functions_encode_js__WEBPACK_IMPORTED_MODULE_5__.ZA),
11638
11643
  /* harmony export */ "base64ToBinary": () => (/* reexport safe */ _functions_encode_js__WEBPACK_IMPORTED_MODULE_5__.R5),
@@ -11790,14 +11795,17 @@ __webpack_require__.r(__webpack_exports__);
11790
11795
  /* harmony export */ "UZ": () => (/* binding */ eddsa),
11791
11796
  /* harmony export */ "bD": () => (/* binding */ hmac),
11792
11797
  /* harmony export */ "bu": () => (/* binding */ ecdsa),
11798
+ /* harmony export */ "gC": () => (/* binding */ axolotl),
11793
11799
  /* harmony export */ "kn": () => (/* binding */ crc32),
11794
11800
  /* harmony export */ "vp": () => (/* binding */ hash)
11795
11801
  /* harmony export */ });
11796
11802
  /* harmony import */ var _static_dependencies_noble_hashes_hmac_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(138);
11797
11803
  /* harmony import */ var _static_dependencies_scure_base_index_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9651);
11804
+ /* harmony import */ var _static_dependencies_jsencrypt_lib_asn1js_base64_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9285);
11798
11805
  /* ------------------------------------------------------------------------ */
11799
11806
 
11800
11807
 
11808
+
11801
11809
  /* ------------------------------------------------------------------------ */
11802
11810
  const encoders = {
11803
11811
  binary: x => x,
@@ -11826,11 +11834,18 @@ function ecdsa(request, secret, curve, prehash = null) {
11826
11834
  'v': signature.recovery,
11827
11835
  };
11828
11836
  }
11829
- function eddsa(request, secret, curve) {
11837
+ function axolotl(request, secret, curve) {
11830
11838
  // used for waves.exchange (that's why the output is base58)
11831
- const signature = curve.sign(request, secret);
11839
+ const signature = curve.signModified(request, secret);
11832
11840
  return _static_dependencies_scure_base_index_js__WEBPACK_IMPORTED_MODULE_0__/* .base58.encode */ .Jq.encode(signature);
11833
11841
  }
11842
+ function eddsa(request, secret, curve) {
11843
+ // secret is the base64 pem encoded key
11844
+ // we get the last 32 bytes
11845
+ const privateKey = new Uint8Array(_static_dependencies_jsencrypt_lib_asn1js_base64_js__WEBPACK_IMPORTED_MODULE_2__/* .Base64.unarmor */ .D.unarmor(secret).slice(16));
11846
+ const signature = curve.sign(request, privateKey);
11847
+ return _static_dependencies_scure_base_index_js__WEBPACK_IMPORTED_MODULE_0__/* .base64.encode */ .US.encode(signature);
11848
+ }
11834
11849
  /* ------------------------------------------------------------------------ */
11835
11850
  // source: https://stackoverflow.com/a/18639975/1067003
11836
11851
  function crc32(str, signed = false) {
@@ -12009,11 +12024,13 @@ const filterBy = (x, k, value = undefined, out = []) => {
12009
12024
  }
12010
12025
  return out;
12011
12026
  };
12012
- const sortBy = (array, key, descending = false, direction = descending ? -1 : 1) => array.sort((a, b) => {
12013
- if (a[key] < b[key]) {
12027
+ const sortBy = (array, key, descending = false, defaultValue = 0, direction = descending ? -1 : 1) => array.sort((a, b) => {
12028
+ const first = (key in a) ? a[key] : defaultValue;
12029
+ const second = (key in b) ? b[key] : defaultValue;
12030
+ if (first < second) {
12014
12031
  return -direction;
12015
12032
  }
12016
- else if (a[key] > b[key]) {
12033
+ else if (first > second) {
12017
12034
  return direction;
12018
12035
  }
12019
12036
  else {
@@ -16133,6 +16150,8 @@ class bigone extends _abstract_bigone_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
16133
16150
  /* harmony import */ var _base_functions_number_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9292);
16134
16151
  /* harmony import */ var _static_dependencies_noble_hashes_sha256_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(1372);
16135
16152
  /* harmony import */ var _base_functions_rsa_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(5981);
16153
+ /* harmony import */ var _base_functions_crypto_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(6890);
16154
+ /* harmony import */ var _static_dependencies_noble_curves_ed25519_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(8817);
16136
16155
  // ---------------------------------------------------------------------------
16137
16156
 
16138
16157
 
@@ -16140,6 +16159,8 @@ class bigone extends _abstract_bigone_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
16140
16159
 
16141
16160
 
16142
16161
 
16162
+
16163
+
16143
16164
  // ---------------------------------------------------------------------------
16144
16165
  /**
16145
16166
  * @class binance
@@ -16169,6 +16190,7 @@ class binance extends _abstract_binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
16169
16190
  'cancelOrders': true,
16170
16191
  'createDepositAddress': false,
16171
16192
  'createOrder': true,
16193
+ 'createOrders': true,
16172
16194
  'createPostOnlyOrder': true,
16173
16195
  'createReduceOnlyOrder': true,
16174
16196
  'createStopLimitOrder': true,
@@ -20397,7 +20419,17 @@ class binance extends _abstract_binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
20397
20419
  // "lastTrade": {"id":"69","time":"1676084430567","price":"24.9","qty":"1.00"},
20398
20420
  // "mmp": false
20399
20421
  // }
20422
+ // {
20423
+ // cancelOrders/createOrders
20424
+ // "code": -4005,
20425
+ // "msg": "Quantity greater than max quantity."
20426
+ // },
20400
20427
  //
20428
+ const code = this.safeString(order, 'code');
20429
+ if (code !== undefined) {
20430
+ // cancelOrders/createOrders might have a partial success
20431
+ return this.safeOrder({ 'info': order, 'status': 'rejected' }, market);
20432
+ }
20401
20433
  const status = this.parseOrderStatus(this.safeString(order, 'status'));
20402
20434
  const marketId = this.safeString(order, 'symbol');
20403
20435
  const marketType = ('closePosition' in order) ? 'contract' : 'spot';
@@ -20471,6 +20503,85 @@ class binance extends _abstract_binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
20471
20503
  'trades': fills,
20472
20504
  }, market);
20473
20505
  }
20506
+ async createOrders(orders, params = {}) {
20507
+ /**
20508
+ * @method
20509
+ * @name binance#createOrders
20510
+ * @description *contract only* create a list of trade orders
20511
+ * @see https://binance-docs.github.io/apidocs/futures/en/#place-multiple-orders-trade
20512
+ * @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
20513
+ * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
20514
+ */
20515
+ await this.loadMarkets();
20516
+ const ordersRequests = [];
20517
+ let orderSymbols = [];
20518
+ for (let i = 0; i < orders.length; i++) {
20519
+ const rawOrder = orders[i];
20520
+ const marketId = this.safeString(rawOrder, 'symbol');
20521
+ orderSymbols.push(marketId);
20522
+ const type = this.safeString(rawOrder, 'type');
20523
+ const side = this.safeString(rawOrder, 'side');
20524
+ const amount = this.safeValue(rawOrder, 'amount');
20525
+ const price = this.safeValue(rawOrder, 'price');
20526
+ const orderParams = this.safeValue(rawOrder, 'params', {});
20527
+ const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, orderParams);
20528
+ ordersRequests.push(orderRequest);
20529
+ }
20530
+ orderSymbols = this.marketSymbols(orderSymbols, undefined, false, true, true);
20531
+ const market = this.market(orderSymbols[0]);
20532
+ if (market['spot']) {
20533
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.NotSupported(this.id + ' createOrders() does not support ' + market['type'] + ' orders');
20534
+ }
20535
+ let response = undefined;
20536
+ let request = {
20537
+ 'batchOrders': ordersRequests,
20538
+ };
20539
+ request = this.extend(request, params);
20540
+ if (market['linear']) {
20541
+ response = await this.fapiPrivatePostBatchOrders(request);
20542
+ }
20543
+ else if (market['option']) {
20544
+ response = await this.eapiPrivatePostBatchOrders(request);
20545
+ }
20546
+ else {
20547
+ response = await this.dapiPrivatePostBatchOrders(request);
20548
+ }
20549
+ //
20550
+ // [
20551
+ // {
20552
+ // "code": -4005,
20553
+ // "msg": "Quantity greater than max quantity."
20554
+ // },
20555
+ // {
20556
+ // "orderId": 650640530,
20557
+ // "symbol": "LTCUSDT",
20558
+ // "status": "NEW",
20559
+ // "clientOrderId": "x-xcKtGhcu32184eb13585491289bbaf",
20560
+ // "price": "54.00",
20561
+ // "avgPrice": "0.00",
20562
+ // "origQty": "0.100",
20563
+ // "executedQty": "0.000",
20564
+ // "cumQty": "0.000",
20565
+ // "cumQuote": "0.00000",
20566
+ // "timeInForce": "GTC",
20567
+ // "type": "LIMIT",
20568
+ // "reduceOnly": false,
20569
+ // "closePosition": false,
20570
+ // "side": "BUY",
20571
+ // "positionSide": "BOTH",
20572
+ // "stopPrice": "0.00",
20573
+ // "workingType": "CONTRACT_PRICE",
20574
+ // "priceProtect": false,
20575
+ // "origType": "LIMIT",
20576
+ // "priceMatch": "NONE",
20577
+ // "selfTradePreventionMode": "NONE",
20578
+ // "goodTillDate": 0,
20579
+ // "updateTime": 1698073926929
20580
+ // }
20581
+ // ]
20582
+ //
20583
+ return this.parseOrders(response);
20584
+ }
20474
20585
  async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
20475
20586
  /**
20476
20587
  * @method
@@ -24566,6 +24677,12 @@ class binance extends _abstract_binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
24566
24677
  }
24567
24678
  }
24568
24679
  let query = undefined;
24680
+ // handle batchOrders
24681
+ if ((path === 'batchOrders') && (method === 'POST')) {
24682
+ const batchOrders = this.safeValue(params, 'batchOrders');
24683
+ const queryBatch = (this.json(batchOrders));
24684
+ params['batchOrders'] = queryBatch;
24685
+ }
24569
24686
  const defaultRecvWindow = this.safeInteger(this.options, 'recvWindow');
24570
24687
  let extendedParams = this.extend({
24571
24688
  'timestamp': this.nonce(),
@@ -24604,7 +24721,12 @@ class binance extends _abstract_binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
24604
24721
  }
24605
24722
  let signature = undefined;
24606
24723
  if (this.secret.indexOf('PRIVATE KEY') > -1) {
24607
- signature = this.encodeURIComponent((0,_base_functions_rsa_js__WEBPACK_IMPORTED_MODULE_4__/* .rsa */ .j)(query, this.secret, _static_dependencies_noble_hashes_sha256_js__WEBPACK_IMPORTED_MODULE_5__/* .sha256 */ .J));
24724
+ if (this.secret.length > 120) {
24725
+ signature = this.encodeURIComponent((0,_base_functions_rsa_js__WEBPACK_IMPORTED_MODULE_4__/* .rsa */ .j)(query, this.secret, _static_dependencies_noble_hashes_sha256_js__WEBPACK_IMPORTED_MODULE_5__/* .sha256 */ .J));
24726
+ }
24727
+ else {
24728
+ signature = this.encodeURIComponent((0,_base_functions_crypto_js__WEBPACK_IMPORTED_MODULE_6__/* .eddsa */ .UZ)(this.encode(query), this.secret, _static_dependencies_noble_curves_ed25519_js__WEBPACK_IMPORTED_MODULE_7__/* .ed25519 */ .UN));
24729
+ }
24608
24730
  }
24609
24731
  else {
24610
24732
  signature = this.hmac(this.encode(query), this.encode(this.secret), _static_dependencies_noble_hashes_sha256_js__WEBPACK_IMPORTED_MODULE_5__/* .sha256 */ .J);
@@ -24703,10 +24825,10 @@ class binance extends _abstract_binance_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
24703
24825
  }
24704
24826
  if (Array.isArray(response)) {
24705
24827
  // cancelOrders returns an array like this: [{"code":-2011,"msg":"Unknown order sent."}]
24706
- const numElements = response.length;
24707
- if (numElements > 0) {
24708
- const firstElement = response[0];
24709
- const errorCode = this.safeString(firstElement, 'code');
24828
+ const arrayLength = response.length;
24829
+ if (arrayLength === 1) { // when there's a single error we can throw, otherwise we have a partial success
24830
+ const element = response[0];
24831
+ const errorCode = this.safeString(element, 'code');
24710
24832
  if (errorCode !== undefined) {
24711
24833
  this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, this.id + ' ' + body);
24712
24834
  }
@@ -38711,11 +38833,12 @@ class bitget extends _abstract_bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
38711
38833
  'cancelOrder': true,
38712
38834
  'cancelOrders': true,
38713
38835
  'createOrder': true,
38836
+ 'createOrders': true,
38714
38837
  'createReduceOnlyOrder': false,
38715
38838
  'editOrder': true,
38716
38839
  'fetchAccounts': false,
38717
38840
  'fetchBalance': true,
38718
- 'fetchBorrowRate': false,
38841
+ 'fetchBorrowRate': true,
38719
38842
  'fetchBorrowRateHistories': false,
38720
38843
  'fetchBorrowRateHistory': false,
38721
38844
  'fetchBorrowRates': false,
@@ -38736,10 +38859,12 @@ class bitget extends _abstract_bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
38736
38859
  'fetchLedger': true,
38737
38860
  'fetchLeverage': true,
38738
38861
  'fetchLeverageTiers': false,
38862
+ 'fetchLiquidations': false,
38739
38863
  'fetchMarginMode': undefined,
38740
38864
  'fetchMarketLeverageTiers': true,
38741
38865
  'fetchMarkets': true,
38742
38866
  'fetchMarkOHLCV': true,
38867
+ 'fetchMyLiquidations': true,
38743
38868
  'fetchMyTrades': true,
38744
38869
  'fetchOHLCV': true,
38745
38870
  'fetchOpenInterest': true,
@@ -41657,7 +41782,23 @@ class bitget extends _abstract_bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
41657
41782
  // "fillTotalAmount": "0",
41658
41783
  // "ctime": "1697773902588"
41659
41784
  // }
41785
+ // cancelOrders failing
41660
41786
  //
41787
+ // {
41788
+ // "orderId": "1627293504611",
41789
+ // "clientOid": "BITGET#1627293504611",
41790
+ // "errorMsg":"Duplicate clientOid"
41791
+ // }
41792
+ //
41793
+ const errorMessage = this.safeString(order, 'errorMsg');
41794
+ if (errorMessage !== undefined) {
41795
+ return this.safeOrder({
41796
+ 'info': order,
41797
+ 'id': this.safeString(order, 'orderId'),
41798
+ 'clientOrderId': this.safeString(order, 'clientOrderId'),
41799
+ 'status': 'rejected',
41800
+ }, market);
41801
+ }
41661
41802
  const marketId = this.safeString(order, 'symbol');
41662
41803
  market = this.safeMarket(marketId, market);
41663
41804
  const timestamp = this.safeInteger2(order, 'cTime', 'ctime');
@@ -41748,9 +41889,60 @@ class bitget extends _abstract_bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
41748
41889
  */
41749
41890
  await this.loadMarkets();
41750
41891
  const market = this.market(symbol);
41751
- let marketType = undefined;
41752
41892
  let marginMode = undefined;
41893
+ [marginMode, params] = this.handleMarginModeAndParams('createOrder', params);
41894
+ const triggerPrice = this.safeValue2(params, 'stopPrice', 'triggerPrice');
41895
+ const stopLossTriggerPrice = this.safeValue(params, 'stopLossPrice');
41896
+ const takeProfitTriggerPrice = this.safeValue(params, 'takeProfitPrice');
41897
+ const isTriggerOrder = triggerPrice !== undefined;
41898
+ const isStopLossTriggerOrder = stopLossTriggerPrice !== undefined;
41899
+ const isTakeProfitTriggerOrder = takeProfitTriggerPrice !== undefined;
41900
+ const isStopLossOrTakeProfitTrigger = isStopLossTriggerOrder || isTakeProfitTriggerOrder;
41901
+ const request = this.createOrderRequest(symbol, type, side, amount, price, params);
41753
41902
  let response = undefined;
41903
+ if (market['spot']) {
41904
+ if (isTriggerOrder) {
41905
+ response = await this.privateSpotPostPlanPlacePlan(request);
41906
+ }
41907
+ else if (marginMode === 'isolated') {
41908
+ response = await this.privateMarginPostIsolatedOrderPlaceOrder(request);
41909
+ }
41910
+ else if (marginMode === 'cross') {
41911
+ response = await this.privateMarginPostCrossOrderPlaceOrder(request);
41912
+ }
41913
+ else {
41914
+ response = await this.privateSpotPostTradeOrders(request);
41915
+ }
41916
+ }
41917
+ else {
41918
+ if (isTriggerOrder) {
41919
+ response = await this.privateMixPostPlanPlacePlan(request);
41920
+ }
41921
+ else if (isStopLossOrTakeProfitTrigger) {
41922
+ response = await this.privateMixPostPlanPlacePositionsTPSL(request);
41923
+ }
41924
+ else {
41925
+ response = await this.privateMixPostOrderPlaceOrder(request);
41926
+ }
41927
+ }
41928
+ //
41929
+ // {
41930
+ // "code": "00000",
41931
+ // "msg": "success",
41932
+ // "requestTime": 1645932209602,
41933
+ // "data": {
41934
+ // "orderId": "881669078313766912",
41935
+ // "clientOrderId": "iauIBf#a45b595f96474d888d0ada"
41936
+ // }
41937
+ // }
41938
+ //
41939
+ const data = this.safeValue(response, 'data', {});
41940
+ return this.parseOrder(data, market);
41941
+ }
41942
+ createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
41943
+ const market = this.market(symbol);
41944
+ let marketType = undefined;
41945
+ let marginMode = undefined;
41754
41946
  [marketType, params] = this.handleMarketTypeAndParams('createOrder', market, params);
41755
41947
  [marginMode, params] = this.handleMarginModeAndParams('createOrder', params);
41756
41948
  const marketId = market['id'];
@@ -41848,7 +42040,6 @@ class bitget extends _abstract_bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
41848
42040
  if (price !== undefined) {
41849
42041
  request['executePrice'] = this.priceToPrecision(symbol, price);
41850
42042
  }
41851
- response = await this.privateMixPostPlanPlacePlan(this.extend(request, params));
41852
42043
  }
41853
42044
  else if (isStopLossOrTakeProfitTrigger) {
41854
42045
  if (isStopLossTriggerOrder) {
@@ -41859,7 +42050,6 @@ class bitget extends _abstract_bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
41859
42050
  request['triggerPrice'] = this.priceToPrecision(symbol, takeProfitTriggerPrice);
41860
42051
  request['planType'] = 'pos_profit';
41861
42052
  }
41862
- response = await this.privateMixPostPlanPlacePositionsTPSL(this.extend(request, params));
41863
42053
  }
41864
42054
  else {
41865
42055
  if (isStopLoss) {
@@ -41870,7 +42060,6 @@ class bitget extends _abstract_bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
41870
42060
  const tpTriggerPrice = this.safeValue2(takeProfit, 'triggerPrice', 'stopPrice');
41871
42061
  request['presetTakeProfitPrice'] = this.priceToPrecision(symbol, tpTriggerPrice);
41872
42062
  }
41873
- response = await this.privateMixPostOrderPlaceOrder(this.extend(request, params));
41874
42063
  }
41875
42064
  }
41876
42065
  else if (marketType === 'spot') {
@@ -41906,7 +42095,6 @@ class bitget extends _abstract_bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
41906
42095
  if (clientOrderId !== undefined) {
41907
42096
  request['clientOrderId'] = clientOrderId;
41908
42097
  }
41909
- response = await this.privateSpotPostPlanPlacePlan(this.extend(request, params));
41910
42098
  }
41911
42099
  else if (marginMode !== undefined) {
41912
42100
  request['loanType'] = 'normal';
@@ -41919,12 +42107,6 @@ class bitget extends _abstract_bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
41919
42107
  else {
41920
42108
  request['baseQuantity'] = quantity;
41921
42109
  }
41922
- if (marginMode === 'isolated') {
41923
- response = await this.privateMarginPostIsolatedOrderPlaceOrder(this.extend(request, params));
41924
- }
41925
- else if (marginMode === 'cross') {
41926
- response = await this.privateMarginPostCrossOrderPlaceOrder(this.extend(request, params));
41927
- }
41928
42110
  }
41929
42111
  else {
41930
42112
  if (clientOrderId !== undefined) {
@@ -41933,25 +42115,86 @@ class bitget extends _abstract_bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
41933
42115
  if (quantity !== undefined) {
41934
42116
  request['quantity'] = quantity;
41935
42117
  }
41936
- response = await this.privateSpotPostTradeOrders(this.extend(request, params));
41937
42118
  }
41938
42119
  }
41939
42120
  else {
41940
42121
  throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.NotSupported(this.id + ' createOrder() does not support ' + marketType + ' orders');
41941
42122
  }
42123
+ return this.extend(request, params);
42124
+ }
42125
+ async createOrders(orders, params = {}) {
42126
+ /**
42127
+ * @method
42128
+ * @name bitget#createOrders
42129
+ * @description create a list of trade orders (all orders should be of the same symbol)
42130
+ * @see https://bitgetlimited.github.io/apidoc/en/spot/#batch-order
42131
+ * @see https://bitgetlimited.github.io/apidoc/en/mix/#batch-order
42132
+ * @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
42133
+ * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
42134
+ */
42135
+ await this.loadMarkets();
42136
+ const ordersRequests = [];
42137
+ let symbol = undefined;
42138
+ for (let i = 0; i < orders.length; i++) {
42139
+ const rawOrder = orders[i];
42140
+ const marketId = this.safeString(rawOrder, 'symbol');
42141
+ if (symbol === undefined) {
42142
+ symbol = marketId;
42143
+ }
42144
+ else {
42145
+ if (symbol !== marketId) {
42146
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.BadRequest(this.id + ' createOrders() requires all orders to have the same symbol');
42147
+ }
42148
+ }
42149
+ const type = this.safeString(rawOrder, 'type');
42150
+ const side = this.safeString(rawOrder, 'side');
42151
+ const amount = this.safeValue(rawOrder, 'amount');
42152
+ const price = this.safeValue(rawOrder, 'price');
42153
+ const orderParams = this.safeValue(rawOrder, 'params', {});
42154
+ const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, orderParams);
42155
+ ordersRequests.push(orderRequest);
42156
+ }
42157
+ const market = this.market(symbol);
42158
+ const request = {
42159
+ 'symbol': market['id'],
42160
+ };
42161
+ let response = undefined;
42162
+ if (market['spot']) {
42163
+ request['orderList'] = ordersRequests;
42164
+ response = await this.privateSpotPostTradeBatchOrders(request);
42165
+ }
42166
+ else {
42167
+ request['orderDataList'] = ordersRequests;
42168
+ request['marginCoin'] = market['settleId'];
42169
+ response = await this.privateMixPostOrderBatchOrders(request);
42170
+ }
41942
42171
  //
41943
- // {
41944
- // "code": "00000",
41945
- // "msg": "success",
41946
- // "requestTime": 1645932209602,
41947
- // "data": {
41948
- // "orderId": "881669078313766912",
41949
- // "clientOrderId": "iauIBf#a45b595f96474d888d0ada"
42172
+ // {
42173
+ // "code": "00000",
42174
+ // "data": {
42175
+ // "orderInfo": [
42176
+ // {
42177
+ // "orderId": "1627293504612",
42178
+ // "clientOid": "BITGET#1627293504612"
41950
42179
  // }
41951
- // }
42180
+ // ],
42181
+ // "failure":[
42182
+ // {
42183
+ // "orderId": "1627293504611",
42184
+ // "clientOid": "BITGET#1627293504611",
42185
+ // "errorMsg":"Duplicate clientOid"
42186
+ // }
42187
+ // ]
42188
+ // },
42189
+ // "msg": "success",
42190
+ // "requestTime": 1627293504612
42191
+ // }
41952
42192
  //
41953
42193
  const data = this.safeValue(response, 'data', {});
41954
- return this.parseOrder(data, market);
42194
+ const failure = this.safeValue(data, 'failure', []);
42195
+ const orderInfo = this.safeValue2(data, 'orderInfo', 'resultList', []);
42196
+ const both = this.arrayConcat(orderInfo, failure);
42197
+ return this.parseOrders(both);
41955
42198
  }
41956
42199
  async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
41957
42200
  /**
@@ -44587,6 +44830,348 @@ class bitget extends _abstract_bitget_js__WEBPACK_IMPORTED_MODULE_0__/* ["defaul
44587
44830
  'info': info,
44588
44831
  };
44589
44832
  }
44833
+ async fetchMyLiquidations(symbol = undefined, since = undefined, limit = undefined, params = {}) {
44834
+ /**
44835
+ * @method
44836
+ * @name bitget#fetchMyLiquidations
44837
+ * @description retrieves the users liquidated positions
44838
+ * @see https://bitgetlimited.github.io/apidoc/en/margin/#get-isolated-liquidation-records
44839
+ * @see https://bitgetlimited.github.io/apidoc/en/margin/#get-cross-liquidation-records
44840
+ * @param {string} [symbol] unified CCXT market symbol
44841
+ * @param {int} [since] the earliest time in ms to fetch liquidations for
44842
+ * @param {int} [limit] the maximum number of liquidation structures to retrieve
44843
+ * @param {object} [params] exchange specific parameters for the bitget api endpoint
44844
+ * @param {int} [params.until] timestamp in ms of the latest liquidation
44845
+ * @param {string} [params.marginMode] 'cross' or 'isolated' default value is 'cross'
44846
+ * @returns {object} an array of [liquidation structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure}
44847
+ */
44848
+ await this.loadMarkets();
44849
+ let market = undefined;
44850
+ if (symbol !== undefined) {
44851
+ market = this.market(symbol);
44852
+ }
44853
+ let type = undefined;
44854
+ [type, params] = this.handleMarketTypeAndParams('fetchMyLiquidations', market, params);
44855
+ if (type !== 'spot') {
44856
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.NotSupported(this.id + ' fetchMyLiquidations() supports spot margin markets only');
44857
+ }
44858
+ let request = {};
44859
+ [request, params] = this.handleUntilOption('endTime', request, params);
44860
+ if (since !== undefined) {
44861
+ request['startTime'] = since;
44862
+ }
44863
+ else {
44864
+ request['startTime'] = this.milliseconds() - 7776000000;
44865
+ }
44866
+ if (limit !== undefined) {
44867
+ request['pageSize'] = limit;
44868
+ }
44869
+ let response = undefined;
44870
+ let marginMode = undefined;
44871
+ [marginMode, params] = this.handleMarginModeAndParams('fetchMyLiquidations', params, 'cross');
44872
+ if (marginMode === 'isolated') {
44873
+ this.checkRequiredSymbol('fetchMyLiquidations', symbol);
44874
+ request['symbol'] = market['info']['symbolName'];
44875
+ response = await this.privateMarginGetIsolatedLiquidationList(this.extend(request, params));
44876
+ }
44877
+ else if (marginMode === 'cross') {
44878
+ response = await this.privateMarginGetCrossLiquidationList(this.extend(request, params));
44879
+ }
44880
+ //
44881
+ // isolated
44882
+ //
44883
+ // {
44884
+ // "code": "00000",
44885
+ // "msg": "success",
44886
+ // "requestTime": 1698114119193,
44887
+ // "data": {
44888
+ // "resultList": [
44889
+ // {
44890
+ // "liqId": "123",
44891
+ // "symbol": "BTCUSDT",
44892
+ // "liqStartTime": "1653453245342",
44893
+ // "liqEndTime": "16312423423432",
44894
+ // "liqRisk": "1.01",
44895
+ // "totalAssets": "1242.34",
44896
+ // "totalDebt": "1100",
44897
+ // "LiqFee": "1.2",
44898
+ // "cTime": "1653453245342"
44899
+ // }
44900
+ // ],
44901
+ // "maxId": "0",
44902
+ // "minId": "0"
44903
+ // }
44904
+ // }
44905
+ //
44906
+ // cross
44907
+ //
44908
+ // {
44909
+ // "code": "00000",
44910
+ // "msg": "success",
44911
+ // "requestTime": 1698114119193,
44912
+ // "data": {
44913
+ // "resultList": [
44914
+ // {
44915
+ // "liqId": "123",
44916
+ // "liqStartTime": "1653453245342",
44917
+ // "liqEndTime": "16312423423432",
44918
+ // "liqRisk": "1.01",
44919
+ // "totalAssets": "1242.34",
44920
+ // "totalDebt": "1100",
44921
+ // "LiqFee": "1.2",
44922
+ // "cTime": "1653453245342"
44923
+ // }
44924
+ // ],
44925
+ // "maxId": "0",
44926
+ // "minId": "0"
44927
+ // }
44928
+ // }
44929
+ //
44930
+ const data = this.safeValue(response, 'data', {});
44931
+ const liquidations = this.safeValue(data, 'resultList', []);
44932
+ return this.parseLiquidations(liquidations, market, since, limit);
44933
+ }
44934
+ parseLiquidation(liquidation, market = undefined) {
44935
+ //
44936
+ // isolated
44937
+ //
44938
+ // {
44939
+ // "liqId": "123",
44940
+ // "symbol": "BTCUSDT",
44941
+ // "liqStartTime": "1653453245342",
44942
+ // "liqEndTime": "16312423423432",
44943
+ // "liqRisk": "1.01",
44944
+ // "totalAssets": "1242.34",
44945
+ // "totalDebt": "1100",
44946
+ // "LiqFee": "1.2",
44947
+ // "cTime": "1653453245342"
44948
+ // }
44949
+ //
44950
+ // cross
44951
+ //
44952
+ // {
44953
+ // "liqId": "123",
44954
+ // "liqStartTime": "1653453245342",
44955
+ // "liqEndTime": "16312423423432",
44956
+ // "liqRisk": "1.01",
44957
+ // "totalAssets": "1242.34",
44958
+ // "totalDebt": "1100",
44959
+ // "LiqFee": "1.2",
44960
+ // "cTime": "1653453245342"
44961
+ // }
44962
+ //
44963
+ const marketId = this.safeString(liquidation, 'symbol');
44964
+ const timestamp = this.safeInteger(liquidation, 'liqEndTime');
44965
+ const liquidationFee = this.safeString(liquidation, 'LiqFee');
44966
+ const totalDebt = this.safeString(liquidation, 'totalDebt');
44967
+ const quoteValueString = _base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringAdd */ .O.stringAdd(liquidationFee, totalDebt);
44968
+ return {
44969
+ 'info': liquidation,
44970
+ 'symbol': this.safeSymbol(marketId, market),
44971
+ 'contracts': undefined,
44972
+ 'contractSize': undefined,
44973
+ 'price': undefined,
44974
+ 'baseValue': undefined,
44975
+ 'quoteValue': this.parseNumber(quoteValueString),
44976
+ 'timestamp': timestamp,
44977
+ 'datetime': this.iso8601(timestamp),
44978
+ };
44979
+ }
44980
+ async fetchBorrowRate(code, params = {}) {
44981
+ /**
44982
+ * @method
44983
+ * @name bitget#fetchBorrowRate
44984
+ * @description fetch the rate of interest to borrow a currency for margin trading
44985
+ * @see https://bitgetlimited.github.io/apidoc/en/margin/#get-isolated-margin-interest-rate-and-max-borrowable-amount
44986
+ * @see https://bitgetlimited.github.io/apidoc/en/margin/#get-cross-margin-interest-rate-and-borrowable
44987
+ * @param {string} code unified currency code
44988
+ * @param {object} [params] extra parameters specific to the bitget api endpoint
44989
+ * @param {string} [params.symbol] required for isolated margin
44990
+ * @returns {object} a [borrow rate structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#borrow-rate-structure}
44991
+ */
44992
+ await this.loadMarkets();
44993
+ const currency = this.currency(code);
44994
+ let market = undefined;
44995
+ const symbol = this.safeString(params, 'symbol');
44996
+ params = this.omit(params, 'symbol');
44997
+ if (symbol !== undefined) {
44998
+ market = this.market(symbol);
44999
+ }
45000
+ const request = {};
45001
+ let response = undefined;
45002
+ let marginMode = undefined;
45003
+ [marginMode, params] = this.handleMarginModeAndParams('fetchBorrowRate', params, 'cross');
45004
+ if ((symbol !== undefined) || (marginMode === 'isolated')) {
45005
+ this.checkRequiredSymbol('fetchBorrowRate', symbol);
45006
+ request['symbol'] = market['info']['symbolName'];
45007
+ response = await this.publicMarginGetIsolatedPublicInterestRateAndLimit(this.extend(request, params));
45008
+ }
45009
+ else if (marginMode === 'cross') {
45010
+ request['coin'] = currency['code'];
45011
+ response = await this.publicMarginGetCrossPublicInterestRateAndLimit(this.extend(request, params));
45012
+ }
45013
+ //
45014
+ // isolated
45015
+ //
45016
+ // {
45017
+ // "code": "00000",
45018
+ // "msg": "success",
45019
+ // "requestTime": 1698208075332,
45020
+ // "data": [
45021
+ // {
45022
+ // "symbol": "BTCUSDT",
45023
+ // "leverage": "10",
45024
+ // "baseCoin": "BTC",
45025
+ // "baseTransferInAble": true,
45026
+ // "baseBorrowAble": true,
45027
+ // "baseDailyInterestRate": "0.00007",
45028
+ // "baseYearlyInterestRate": "0.02555",
45029
+ // "baseMaxBorrowableAmount": "35",
45030
+ // "baseVips": [
45031
+ // {
45032
+ // "level": "0",
45033
+ // "dailyInterestRate": "0.00007",
45034
+ // "yearlyInterestRate": "0.02555",
45035
+ // "discountRate": "1"
45036
+ // },
45037
+ // ],
45038
+ // "quoteCoin": "USDT",
45039
+ // "quoteTransferInAble": true,
45040
+ // "quoteBorrowAble": true,
45041
+ // "quoteDailyInterestRate": "0.00012627",
45042
+ // "quoteYearlyInterestRate": "0.04608855",
45043
+ // "quoteMaxBorrowableAmount": "300000",
45044
+ // "quoteVips": [
45045
+ // {
45046
+ // "level": "0",
45047
+ // "dailyInterestRate": "0.000126279",
45048
+ // "yearlyInterestRate": "0.046091835",
45049
+ // "discountRate": "1"
45050
+ // },
45051
+ // ]
45052
+ // }
45053
+ // ]
45054
+ // }
45055
+ //
45056
+ // cross
45057
+ //
45058
+ // {
45059
+ // "code": "00000",
45060
+ // "msg": "success",
45061
+ // "requestTime": 1698208150986,
45062
+ // "data": [
45063
+ // {
45064
+ // "coin": "BTC",
45065
+ // "leverage": "3",
45066
+ // "transferInAble": true,
45067
+ // "borrowAble": true,
45068
+ // "dailyInterestRate": "0.00007",
45069
+ // "yearlyInterestRate": "0.02555",
45070
+ // "maxBorrowableAmount": "26",
45071
+ // "vips": [
45072
+ // {
45073
+ // "level": "0",
45074
+ // "dailyInterestRate": "0.00007",
45075
+ // "yearlyInterestRate": "0.02555",
45076
+ // "discountRate": "1"
45077
+ // },
45078
+ // ]
45079
+ // }
45080
+ // ]
45081
+ // }
45082
+ //
45083
+ const timestamp = this.safeInteger(response, 'requestTime');
45084
+ const data = this.safeValue(response, 'data', []);
45085
+ const first = this.safeValue(data, 0, {});
45086
+ first['timestamp'] = timestamp;
45087
+ return this.parseBorrowRate(first, currency);
45088
+ }
45089
+ parseBorrowRate(info, currency = undefined) {
45090
+ //
45091
+ // isolated
45092
+ //
45093
+ // {
45094
+ // "symbol": "BTCUSDT",
45095
+ // "leverage": "10",
45096
+ // "baseCoin": "BTC",
45097
+ // "baseTransferInAble": true,
45098
+ // "baseBorrowAble": true,
45099
+ // "baseDailyInterestRate": "0.00007",
45100
+ // "baseYearlyInterestRate": "0.02555",
45101
+ // "baseMaxBorrowableAmount": "35",
45102
+ // "baseVips": [
45103
+ // {
45104
+ // "level": "0",
45105
+ // "dailyInterestRate": "0.00007",
45106
+ // "yearlyInterestRate": "0.02555",
45107
+ // "discountRate": "1"
45108
+ // },
45109
+ // ],
45110
+ // "quoteCoin": "USDT",
45111
+ // "quoteTransferInAble": true,
45112
+ // "quoteBorrowAble": true,
45113
+ // "quoteDailyInterestRate": "0.00012627",
45114
+ // "quoteYearlyInterestRate": "0.04608855",
45115
+ // "quoteMaxBorrowableAmount": "300000",
45116
+ // "quoteVips": [
45117
+ // {
45118
+ // "level": "0",
45119
+ // "dailyInterestRate": "0.000126279",
45120
+ // "yearlyInterestRate": "0.046091835",
45121
+ // "discountRate": "1"
45122
+ // },
45123
+ // ]
45124
+ // }
45125
+ //
45126
+ // cross
45127
+ //
45128
+ // {
45129
+ // "coin": "BTC",
45130
+ // "leverage": "3",
45131
+ // "transferInAble": true,
45132
+ // "borrowAble": true,
45133
+ // "dailyInterestRate": "0.00007",
45134
+ // "yearlyInterestRate": "0.02555",
45135
+ // "maxBorrowableAmount": "26",
45136
+ // "vips": [
45137
+ // {
45138
+ // "level": "0",
45139
+ // "dailyInterestRate": "0.00007",
45140
+ // "yearlyInterestRate": "0.02555",
45141
+ // "discountRate": "1"
45142
+ // },
45143
+ // ]
45144
+ // }
45145
+ //
45146
+ const code = currency['code'];
45147
+ const baseCoin = this.safeString(info, 'baseCoin');
45148
+ const quoteCoin = this.safeString(info, 'quoteCoin');
45149
+ let currencyId = undefined;
45150
+ let interestRate = undefined;
45151
+ if (baseCoin !== undefined) {
45152
+ if (code === baseCoin) {
45153
+ currencyId = baseCoin;
45154
+ interestRate = this.safeNumber(info, 'baseDailyInterestRate');
45155
+ }
45156
+ else if (code === quoteCoin) {
45157
+ currencyId = quoteCoin;
45158
+ interestRate = this.safeNumber(info, 'quoteDailyInterestRate');
45159
+ }
45160
+ }
45161
+ else {
45162
+ currencyId = this.safeString(info, 'coin');
45163
+ interestRate = this.safeNumber(info, 'dailyInterestRate');
45164
+ }
45165
+ const timestamp = this.safeInteger(info, 'timestamp');
45166
+ return {
45167
+ 'currency': this.safeCurrencyCode(currencyId, currency),
45168
+ 'rate': interestRate,
45169
+ 'period': 86400000,
45170
+ 'timestamp': timestamp,
45171
+ 'datetime': this.iso8601(timestamp),
45172
+ 'info': info,
45173
+ };
45174
+ }
44590
45175
  handleErrors(code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
44591
45176
  if (!response) {
44592
45177
  return undefined; // fallback to default error handler
@@ -73044,6 +73629,7 @@ class bybit extends _abstract_bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"
73044
73629
  'cancelAllOrders': true,
73045
73630
  'cancelOrder': true,
73046
73631
  'createOrder': true,
73632
+ 'createOrders': true,
73047
73633
  'createPostOnlyOrder': true,
73048
73634
  'createReduceOnlyOrder': true,
73049
73635
  'createStopLimitOrder': true,
@@ -74459,7 +75045,7 @@ class bybit extends _abstract_bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"
74459
75045
  }
74460
75046
  return super.safeMarket(marketId, market, delimiter, marketType);
74461
75047
  }
74462
- getBybitType(method, market, params) {
75048
+ getBybitType(method, market, params = {}) {
74463
75049
  let type = undefined;
74464
75050
  [type, params] = this.handleMarketTypeAndParams(method, market, params);
74465
75051
  let subType = undefined;
@@ -76522,7 +77108,31 @@ class bybit extends _abstract_bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"
76522
77108
  // "createdTime": "1684476068369",
76523
77109
  // "updatedTime": "1684476068372"
76524
77110
  // }
77111
+ // createOrders failed order
77112
+ // {
77113
+ // category: 'linear',
77114
+ // symbol: 'LTCUSDT',
77115
+ // orderId: '',
77116
+ // orderLinkId: '',
77117
+ // createAt: '',
77118
+ // code: '10001',
77119
+ // msg: 'The number of contracts exceeds maximum limit allowed: too large'
77120
+ // }
76525
77121
  //
77122
+ const code = this.safeString(order, 'code');
77123
+ if (code !== undefined) {
77124
+ if (code !== '0') {
77125
+ const category = this.safeString(order, 'category');
77126
+ const inferedMarketType = (category === 'spot') ? 'spot' : 'contract';
77127
+ return this.safeOrder({
77128
+ 'info': order,
77129
+ 'status': 'rejected',
77130
+ 'id': this.safeString(order, 'orderId'),
77131
+ 'clientOrderId': this.safeString(order, 'orderLinkId'),
77132
+ 'symbol': this.safeSymbol(this.safeString(order, 'symbol'), undefined, undefined, inferedMarketType),
77133
+ });
77134
+ }
77135
+ }
76526
77136
  const marketId = this.safeString(order, 'symbol');
76527
77137
  const isContract = ('tpslMode' in order);
76528
77138
  let marketType = undefined;
@@ -76682,13 +77292,32 @@ class bybit extends _abstract_bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"
76682
77292
  */
76683
77293
  await this.loadMarkets();
76684
77294
  const market = this.market(symbol);
76685
- symbol = market['symbol'];
76686
77295
  const [enableUnifiedMargin, enableUnifiedAccount] = await this.isUnifiedEnabled();
76687
77296
  const isUnifiedAccount = (enableUnifiedMargin || enableUnifiedAccount);
76688
77297
  const isUsdcSettled = market['settle'] === 'USDC';
76689
77298
  if (isUsdcSettled && !isUnifiedAccount) {
76690
77299
  return await this.createUsdcOrder(symbol, type, side, amount, price, params);
76691
77300
  }
77301
+ const orderRequest = this.createOrderRequest(symbol, type, side, amount, price, params);
77302
+ const response = await this.privatePostV5OrderCreate(orderRequest); // already extended inside createOrderRequest
77303
+ //
77304
+ // {
77305
+ // "retCode": 0,
77306
+ // "retMsg": "OK",
77307
+ // "result": {
77308
+ // "orderId": "1321003749386327552",
77309
+ // "orderLinkId": "spot-test-postonly"
77310
+ // },
77311
+ // "retExtInfo": {},
77312
+ // "time": 1672211918471
77313
+ // }
77314
+ //
77315
+ const order = this.safeValue(response, 'result', {});
77316
+ return this.parseOrder(order, market);
77317
+ }
77318
+ createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
77319
+ const market = this.market(symbol);
77320
+ symbol = market['symbol'];
76692
77321
  const lowerCaseType = type.toLowerCase();
76693
77322
  if ((price === undefined) && (lowerCaseType === 'limit')) {
76694
77323
  throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.ArgumentsRequired(this.id + ' createOrder requires a price argument for limit orders');
@@ -76830,21 +77459,94 @@ class bybit extends _abstract_bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"
76830
77459
  request['orderLinkId'] = this.uuid16();
76831
77460
  }
76832
77461
  params = this.omit(params, ['stopPrice', 'timeInForce', 'stopLossPrice', 'takeProfitPrice', 'postOnly', 'clientOrderId', 'triggerPrice', 'stopLoss', 'takeProfit']);
76833
- const response = await this.privatePostV5OrderCreate(this.extend(request, params));
77462
+ return this.extend(request, params);
77463
+ }
77464
+ async createOrders(orders, params = {}) {
77465
+ /**
77466
+ * @method
77467
+ * @name bybit#createOrders
77468
+ * @description create a list of trade orders
77469
+ * @see https://bybit-exchange.github.io/docs/v5/order/batch-place
77470
+ * @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
77471
+ * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
77472
+ */
77473
+ await this.loadMarkets();
77474
+ const ordersRequests = [];
77475
+ const orderSymbols = [];
77476
+ for (let i = 0; i < orders.length; i++) {
77477
+ const rawOrder = orders[i];
77478
+ const marketId = this.safeString(rawOrder, 'symbol');
77479
+ orderSymbols.push(marketId);
77480
+ const type = this.safeString(rawOrder, 'type');
77481
+ const side = this.safeString(rawOrder, 'side');
77482
+ const amount = this.safeValue(rawOrder, 'amount');
77483
+ const price = this.safeValue(rawOrder, 'price');
77484
+ const orderParams = this.safeValue(rawOrder, 'params', {});
77485
+ const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, orderParams);
77486
+ ordersRequests.push(orderRequest);
77487
+ }
77488
+ const symbols = this.marketSymbols(orderSymbols, undefined, false, true, true);
77489
+ const market = this.market(symbols[0]);
77490
+ let category = undefined;
77491
+ [category, params] = this.getBybitType('createOrders', market, params);
77492
+ if ((category === 'spot') || (category === 'inverse')) {
77493
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_1__.NotSupported(this.id + ' createOrders does not allow spot or inverse orders');
77494
+ }
77495
+ const request = {
77496
+ 'category': category,
77497
+ 'request': ordersRequests,
77498
+ };
77499
+ const response = await this.privatePostV5OrderCreateBatch(this.extend(request, params));
77500
+ const result = this.safeValue(response, 'result', {});
77501
+ const data = this.safeValue(result, 'list', []);
77502
+ const retInfo = this.safeValue(response, 'retExtInfo', {});
77503
+ const codes = this.safeValue(retInfo, 'list', []);
77504
+ // extend the error with the unsuccessful orders
77505
+ for (let i = 0; i < codes.length; i++) {
77506
+ const code = codes[i];
77507
+ const retCode = this.safeInteger(code, 'code');
77508
+ if (retCode !== 0) {
77509
+ data[i] = this.extend(data[i], code);
77510
+ }
77511
+ }
76834
77512
  //
76835
- // {
76836
- // "retCode": 0,
76837
- // "retMsg": "OK",
76838
- // "result": {
76839
- // "orderId": "1321003749386327552",
76840
- // "orderLinkId": "spot-test-postonly"
76841
- // },
76842
- // "retExtInfo": {},
76843
- // "time": 1672211918471
76844
- // }
77513
+ // {
77514
+ // "retCode":0,
77515
+ // "retMsg":"OK",
77516
+ // "result":{
77517
+ // "list":[
77518
+ // {
77519
+ // "category":"linear",
77520
+ // "symbol":"LTCUSDT",
77521
+ // "orderId":"",
77522
+ // "orderLinkId":"",
77523
+ // "createAt":""
77524
+ // },
77525
+ // {
77526
+ // "category":"linear",
77527
+ // "symbol":"LTCUSDT",
77528
+ // "orderId":"3c9f65b6-01ad-4ac0-9741-df17e02a4223",
77529
+ // "orderLinkId":"",
77530
+ // "createAt":"1698075516029"
77531
+ // }
77532
+ // ]
77533
+ // },
77534
+ // "retExtInfo":{
77535
+ // "list":[
77536
+ // {
77537
+ // "code":10001,
77538
+ // "msg":"The number of contracts exceeds maximum limit allowed: too large"
77539
+ // },
77540
+ // {
77541
+ // "code":0,
77542
+ // "msg":"OK"
77543
+ // }
77544
+ // ]
77545
+ // },
77546
+ // "time":1698075516029
77547
+ // }
76845
77548
  //
76846
- const order = this.safeValue(response, 'result', {});
76847
- return this.parseOrder(order, market);
77549
+ return this.parseOrders(data);
76848
77550
  }
76849
77551
  async createUsdcOrder(symbol, type, side, amount, price = undefined, params = {}) {
76850
77552
  await this.loadMarkets();
@@ -98360,6 +99062,7 @@ class cryptocom extends _abstract_cryptocom_js__WEBPACK_IMPORTED_MODULE_0__/* ["
98360
99062
  'cancelAllOrders': true,
98361
99063
  'cancelOrder': true,
98362
99064
  'createOrder': true,
99065
+ 'createOrders': true,
98363
99066
  'fetchAccounts': true,
98364
99067
  'fetchBalance': true,
98365
99068
  'fetchBidsAsks': false,
@@ -99494,6 +100197,210 @@ class cryptocom extends _abstract_cryptocom_js__WEBPACK_IMPORTED_MODULE_0__/* ["
99494
100197
  const result = this.safeValue(response, 'result', {});
99495
100198
  return this.parseOrder(result, market);
99496
100199
  }
100200
+ async createOrders(orders, params = {}) {
100201
+ /**
100202
+ * @method
100203
+ * @name cryptocom#createOrders
100204
+ * @description create a list of trade orders
100205
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-create-order-list-list
100206
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-create-order-list-oco
100207
+ * @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
100208
+ * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
100209
+ */
100210
+ await this.loadMarkets();
100211
+ const ordersRequests = [];
100212
+ for (let i = 0; i < orders.length; i++) {
100213
+ const rawOrder = orders[i];
100214
+ const marketId = this.safeString(rawOrder, 'symbol');
100215
+ const type = this.safeString(rawOrder, 'type');
100216
+ const side = this.safeString(rawOrder, 'side');
100217
+ const amount = this.safeValue(rawOrder, 'amount');
100218
+ const price = this.safeValue(rawOrder, 'price');
100219
+ const orderParams = this.safeValue(rawOrder, 'params', {});
100220
+ const orderRequest = this.createAdvancedOrderRequest(marketId, type, side, amount, price, orderParams);
100221
+ ordersRequests.push(orderRequest);
100222
+ }
100223
+ const contigency = this.safeString(params, 'contingency_type', 'LIST');
100224
+ const request = {
100225
+ 'contingency_type': contigency,
100226
+ 'order_list': ordersRequests,
100227
+ };
100228
+ const response = await this.v1PrivatePostPrivateCreateOrderList(this.extend(request, params));
100229
+ //
100230
+ // {
100231
+ // "id": 12,
100232
+ // "method": "private/create-order-list",
100233
+ // "code": 10001,
100234
+ // "result": {
100235
+ // "result_list": [
100236
+ // {
100237
+ // "index": 0,
100238
+ // "code": 0,
100239
+ // "order_id": "2015106383706015873",
100240
+ // "client_oid": "my_order_0001"
100241
+ // },
100242
+ // {
100243
+ // "index": 1,
100244
+ // "code": 20007,
100245
+ // "message": "INVALID_REQUEST",
100246
+ // "client_oid": "my_order_0002"
100247
+ // }
100248
+ // ]
100249
+ // }
100250
+ // }
100251
+ //
100252
+ // {
100253
+ // "id" : 1698068111133,
100254
+ // "method" : "private/create-order-list",
100255
+ // "code" : 0,
100256
+ // "result" : [ {
100257
+ // "code" : 0,
100258
+ // "index" : 0,
100259
+ // "client_oid" : "1698068111133_0",
100260
+ // "order_id" : "6142909896519488206"
100261
+ // }, {
100262
+ // "code" : 306,
100263
+ // "index" : 1,
100264
+ // "client_oid" : "1698068111133_1",
100265
+ // "message" : "INSUFFICIENT_AVAILABLE_BALANCE",
100266
+ // "order_id" : "6142909896519488207"
100267
+ // } ]
100268
+ // }
100269
+ //
100270
+ const result = this.safeValue(response, 'result', []);
100271
+ const listId = this.safeString(result, 'list_id');
100272
+ if (listId !== undefined) {
100273
+ const ocoOrders = [{ 'order_id': listId }];
100274
+ return this.parseOrders(ocoOrders);
100275
+ }
100276
+ return this.parseOrders(result);
100277
+ }
100278
+ createAdvancedOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
100279
+ // differs slightly from createOrderRequest
100280
+ // since the advanced order endpoint requires a different set of parameters
100281
+ // namely here we don't support ref_price or spot_margin
100282
+ // and market-buy orders need to send notional instead of quantity
100283
+ const market = this.market(symbol);
100284
+ const uppercaseType = type.toUpperCase();
100285
+ const request = {
100286
+ 'instrument_name': market['id'],
100287
+ 'side': side.toUpperCase(),
100288
+ };
100289
+ if ((uppercaseType === 'LIMIT') || (uppercaseType === 'STOP_LIMIT') || (uppercaseType === 'TAKE_PROFIT_LIMIT')) {
100290
+ request['price'] = this.priceToPrecision(symbol, price);
100291
+ }
100292
+ const broker = this.safeString(this.options, 'broker', 'CCXT');
100293
+ request['broker_id'] = broker;
100294
+ const timeInForce = this.safeStringUpper2(params, 'timeInForce', 'time_in_force');
100295
+ if (timeInForce !== undefined) {
100296
+ if (timeInForce === 'GTC') {
100297
+ request['time_in_force'] = 'GOOD_TILL_CANCEL';
100298
+ }
100299
+ else if (timeInForce === 'IOC') {
100300
+ request['time_in_force'] = 'IMMEDIATE_OR_CANCEL';
100301
+ }
100302
+ else if (timeInForce === 'FOK') {
100303
+ request['time_in_force'] = 'FILL_OR_KILL';
100304
+ }
100305
+ else {
100306
+ request['time_in_force'] = timeInForce;
100307
+ }
100308
+ }
100309
+ const postOnly = this.safeValue(params, 'postOnly', false);
100310
+ if ((postOnly) || (timeInForce === 'PO')) {
100311
+ request['exec_inst'] = ['POST_ONLY'];
100312
+ request['time_in_force'] = 'GOOD_TILL_CANCEL';
100313
+ }
100314
+ const triggerPrice = this.safeStringN(params, ['stopPrice', 'triggerPrice', 'ref_price']);
100315
+ const stopLossPrice = this.safeNumber(params, 'stopLossPrice');
100316
+ const takeProfitPrice = this.safeNumber(params, 'takeProfitPrice');
100317
+ const isTrigger = (triggerPrice !== undefined);
100318
+ const isStopLossTrigger = (stopLossPrice !== undefined);
100319
+ const isTakeProfitTrigger = (takeProfitPrice !== undefined);
100320
+ if (isTrigger) {
100321
+ price = price.toString();
100322
+ if ((uppercaseType === 'LIMIT') || (uppercaseType === 'STOP_LIMIT') || (uppercaseType === 'TAKE_PROFIT_LIMIT')) {
100323
+ if (side === 'buy') {
100324
+ if (_base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringLt */ .O.stringLt(price, triggerPrice)) {
100325
+ request['type'] = 'TAKE_PROFIT_LIMIT';
100326
+ }
100327
+ else {
100328
+ request['type'] = 'STOP_LIMIT';
100329
+ }
100330
+ }
100331
+ else {
100332
+ if (_base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringLt */ .O.stringLt(price, triggerPrice)) {
100333
+ request['type'] = 'STOP_LIMIT';
100334
+ }
100335
+ else {
100336
+ request['type'] = 'TAKE_PROFIT_LIMIT';
100337
+ }
100338
+ }
100339
+ }
100340
+ else {
100341
+ if (side === 'buy') {
100342
+ if (_base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringLt */ .O.stringLt(price, triggerPrice)) {
100343
+ request['type'] = 'TAKE_PROFIT';
100344
+ }
100345
+ else {
100346
+ request['type'] = 'STOP_LOSS';
100347
+ }
100348
+ }
100349
+ else {
100350
+ if (_base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringLt */ .O.stringLt(price, triggerPrice)) {
100351
+ request['type'] = 'STOP_LOSS';
100352
+ }
100353
+ else {
100354
+ request['type'] = 'TAKE_PROFIT';
100355
+ }
100356
+ }
100357
+ }
100358
+ }
100359
+ else if (isStopLossTrigger) {
100360
+ if ((uppercaseType === 'LIMIT') || (uppercaseType === 'STOP_LIMIT')) {
100361
+ request['type'] = 'STOP_LIMIT';
100362
+ }
100363
+ else {
100364
+ request['type'] = 'STOP_LOSS';
100365
+ }
100366
+ }
100367
+ else if (isTakeProfitTrigger) {
100368
+ if ((uppercaseType === 'LIMIT') || (uppercaseType === 'TAKE_PROFIT_LIMIT')) {
100369
+ request['type'] = 'TAKE_PROFIT_LIMIT';
100370
+ }
100371
+ else {
100372
+ request['type'] = 'TAKE_PROFIT';
100373
+ }
100374
+ }
100375
+ else {
100376
+ request['type'] = uppercaseType;
100377
+ }
100378
+ if ((side === 'buy') && ((uppercaseType === 'MARKET') || (uppercaseType === 'STOP_LOSS') || (uppercaseType === 'TAKE_PROFIT'))) {
100379
+ // use createmarketBuy logic here
100380
+ if (this.options['createMarketBuyOrderRequiresPrice']) {
100381
+ const cost = this.safeNumber2(params, 'cost', 'notional');
100382
+ params = this.omit(params, 'cost');
100383
+ if (price === undefined && cost === undefined) {
100384
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.InvalidOrder(this.id + ' createOrder() requires the price argument with market buy orders to calculate total order cost (amount to spend), where cost = amount * price. Supply a price argument to createOrder() call if you want the cost to be calculated for you from price and amount, or, alternatively, add .options["createMarketBuyOrderRequiresPrice"] = false to supply the cost in the amount argument (the exchange-specific behaviour)');
100385
+ }
100386
+ else {
100387
+ const amountString = this.numberToString(amount);
100388
+ const priceString = this.numberToString(price);
100389
+ const quoteAmount = _base_Precise_js__WEBPACK_IMPORTED_MODULE_3__/* .Precise.stringMul */ .O.stringMul(amountString, priceString);
100390
+ amount = (cost !== undefined) ? cost : this.parseNumber(quoteAmount);
100391
+ request['notional'] = this.costToPrecision(symbol, amount);
100392
+ }
100393
+ }
100394
+ else {
100395
+ request['notional'] = this.costToPrecision(symbol, amount);
100396
+ }
100397
+ }
100398
+ else {
100399
+ request['quantity'] = this.amountToPrecision(symbol, amount);
100400
+ }
100401
+ params = this.omit(params, ['postOnly', 'clientOrderId', 'timeInForce', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice']);
100402
+ return this.extend(request, params);
100403
+ }
99497
100404
  async cancelAllOrders(symbol = undefined, params = {}) {
99498
100405
  /**
99499
100406
  * @method
@@ -100334,12 +101241,31 @@ class cryptocom extends _abstract_cryptocom_js__WEBPACK_IMPORTED_MODULE_0__/* ["
100334
101241
  // "update_time": 1686806053993
100335
101242
  // }
100336
101243
  //
101244
+ // createOrders
101245
+ // {
101246
+ // "code" : 306,
101247
+ // "index" : 1,
101248
+ // "client_oid" : "1698068111133_1",
101249
+ // "message" : "INSUFFICIENT_AVAILABLE_BALANCE",
101250
+ // "order_id" : "6142909896519488207"
101251
+ // }
101252
+ //
101253
+ const code = this.safeInteger(order, 'code');
101254
+ if ((code !== undefined) && (code !== 0)) {
101255
+ return this.safeOrder({
101256
+ 'id': this.safeString(order, 'order_id'),
101257
+ 'clientOrderId': this.safeString(order, 'client_oid'),
101258
+ 'info': order,
101259
+ 'status': 'rejected',
101260
+ });
101261
+ }
100337
101262
  const created = this.safeInteger(order, 'create_time');
100338
101263
  const marketId = this.safeString(order, 'instrument_name');
100339
101264
  const symbol = this.safeSymbol(marketId, market);
100340
101265
  const execInst = this.safeValue(order, 'exec_inst');
100341
- let postOnly = false;
101266
+ let postOnly = undefined;
100342
101267
  if (execInst !== undefined) {
101268
+ postOnly = false;
100343
101269
  for (let i = 0; i < execInst.length; i++) {
100344
101270
  const inst = execInst[i];
100345
101271
  if (inst === 'POST_ONLY') {
@@ -101261,6 +102187,41 @@ class cryptocom extends _abstract_cryptocom_js__WEBPACK_IMPORTED_MODULE_0__/* ["
101261
102187
  nonce() {
101262
102188
  return this.milliseconds();
101263
102189
  }
102190
+ paramsToString(object, level) {
102191
+ const maxLevel = 3;
102192
+ if (level >= maxLevel) {
102193
+ return object.toString();
102194
+ }
102195
+ if (typeof object === 'string') {
102196
+ return object;
102197
+ }
102198
+ let returnString = '';
102199
+ let paramsKeys = undefined;
102200
+ if (Array.isArray(object)) {
102201
+ paramsKeys = object;
102202
+ }
102203
+ else {
102204
+ const sorted = this.keysort(object);
102205
+ paramsKeys = Object.keys(sorted);
102206
+ }
102207
+ for (let i = 0; i < paramsKeys.length; i++) {
102208
+ const key = paramsKeys[i];
102209
+ returnString += key;
102210
+ const value = object[key];
102211
+ if (value === 'undefined') {
102212
+ returnString += 'null';
102213
+ }
102214
+ else if (Array.isArray(value)) {
102215
+ for (let j = 0; j < value.length; j++) {
102216
+ returnString += this.paramsToString(value[j], level + 1);
102217
+ }
102218
+ }
102219
+ else {
102220
+ returnString += value.toString();
102221
+ }
102222
+ }
102223
+ return returnString;
102224
+ }
101264
102225
  sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
101265
102226
  const type = this.safeString(api, 0);
101266
102227
  const access = this.safeString(api, 1);
@@ -101275,20 +102236,8 @@ class cryptocom extends _abstract_cryptocom_js__WEBPACK_IMPORTED_MODULE_0__/* ["
101275
102236
  this.checkRequiredCredentials();
101276
102237
  const nonce = this.nonce().toString();
101277
102238
  const requestParams = this.extend({}, params);
101278
- const keysorted = this.keysort(requestParams);
101279
- const paramsKeys = Object.keys(keysorted);
101280
- let strSortKey = '';
101281
- for (let i = 0; i < paramsKeys.length; i++) {
101282
- const key = paramsKeys[i].toString();
101283
- let value = requestParams[paramsKeys[i]];
101284
- if (Array.isArray(value)) {
101285
- value = value.join(',');
101286
- }
101287
- else {
101288
- value = value.toString();
101289
- }
101290
- strSortKey = strSortKey + key + value;
101291
- }
102239
+ const paramsKeys = Object.keys(requestParams);
102240
+ const strSortKey = this.paramsToString(requestParams, 0);
101292
102241
  const payload = path + nonce + this.apiKey + strSortKey + nonce;
101293
102242
  const signature = this.hmac(this.encode(payload), this.encode(this.secret), _static_dependencies_noble_hashes_sha256_js__WEBPACK_IMPORTED_MODULE_4__/* .sha256 */ .J);
101294
102243
  const paramsKeysLength = paramsKeys.length;
@@ -116251,6 +117200,7 @@ class gate extends _abstract_gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
116251
117200
  'cancelOrder': true,
116252
117201
  'createMarketOrder': true,
116253
117202
  'createOrder': true,
117203
+ 'createOrders': true,
116254
117204
  'createPostOnlyOrder': true,
116255
117205
  'createReduceOnlyOrder': true,
116256
117206
  'createStopLimitOrder': true,
@@ -116456,8 +117406,6 @@ class gate extends _abstract_gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
116456
117406
  },
116457
117407
  'portfolio': {
116458
117408
  'get': {
116459
- 'spot/currency_pairs': 20 / 15,
116460
- 'spot/currency_pairs/{currency_pair}': 20 / 15,
116461
117409
  'accounts': 20 / 15,
116462
117410
  'account_mode': 20 / 15,
116463
117411
  'borrowable': 20 / 15,
@@ -116465,19 +117413,10 @@ class gate extends _abstract_gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
116465
117413
  'loans': 20 / 15,
116466
117414
  'loan_records': 20 / 15,
116467
117415
  'interest_records': 20 / 15,
116468
- 'spot/orders': 20 / 15,
116469
- 'spot/orders/{order_id}': 20 / 15,
116470
117416
  },
116471
117417
  'post': {
116472
117418
  'account_mode': 20 / 15,
116473
- 'loans': 200 / 15,
116474
- 'spot/orders': 20 / 15,
116475
- },
116476
- 'delete': {
116477
- 'spot/orders/{order_id}': 20 / 15,
116478
- },
116479
- 'patch': {
116480
- 'spot/orders/{order_id}': 20 / 15,
117419
+ 'loans': 200 / 15, // 15r/10s cost = 20 / 1.5 = 13.33
116481
117420
  },
116482
117421
  },
116483
117422
  'spot': {
@@ -116500,6 +117439,7 @@ class gate extends _abstract_gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
116500
117439
  'orders': 0.4,
116501
117440
  'cancel_batch_orders': 20 / 75,
116502
117441
  'countdown_cancel_all': 20 / 75,
117442
+ 'amend_batch_orders': 0.4,
116503
117443
  'price_orders': 0.4,
116504
117444
  },
116505
117445
  'delete': {
@@ -116670,6 +117610,9 @@ class gate extends _abstract_gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
116670
117610
  'post': {
116671
117611
  'uni/lends': 20 / 15,
116672
117612
  },
117613
+ 'put': {
117614
+ 'uni/interest_reinvest': 20 / 15,
117615
+ },
116673
117616
  'patch': {
116674
117617
  'uni/lends': 20 / 15,
116675
117618
  },
@@ -119834,6 +120777,156 @@ class gate extends _abstract_gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
119834
120777
  * @returns {object|undefined} [An order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
119835
120778
  */
119836
120779
  await this.loadMarkets();
120780
+ const market = this.market(symbol);
120781
+ const trigger = this.safeValue(params, 'trigger');
120782
+ const triggerPrice = this.safeValue2(params, 'triggerPrice', 'stopPrice');
120783
+ const stopLossPrice = this.safeValue(params, 'stopLossPrice', triggerPrice);
120784
+ const takeProfitPrice = this.safeValue(params, 'takeProfitPrice');
120785
+ const isStopLossOrder = stopLossPrice !== undefined;
120786
+ const isTakeProfitOrder = takeProfitPrice !== undefined;
120787
+ const isStopOrder = isStopLossOrder || isTakeProfitOrder;
120788
+ const nonTriggerOrder = !isStopOrder && (trigger === undefined);
120789
+ const orderRequest = this.createOrderRequest(symbol, type, side, amount, price, params);
120790
+ let response = undefined;
120791
+ if (market['spot'] || market['margin']) {
120792
+ if (nonTriggerOrder) {
120793
+ response = await this.privateSpotPostOrders(orderRequest);
120794
+ }
120795
+ else {
120796
+ response = await this.privateSpotPostPriceOrders(orderRequest);
120797
+ }
120798
+ }
120799
+ else if (market['swap']) {
120800
+ if (nonTriggerOrder) {
120801
+ response = await this.privateFuturesPostSettleOrders(orderRequest);
120802
+ }
120803
+ else {
120804
+ response = await this.privateFuturesPostSettlePriceOrders(orderRequest);
120805
+ }
120806
+ }
120807
+ else if (market['future']) {
120808
+ if (nonTriggerOrder) {
120809
+ response = await this.privateDeliveryPostSettleOrders(orderRequest);
120810
+ }
120811
+ else {
120812
+ response = await this.privateDeliveryPostSettlePriceOrders(orderRequest);
120813
+ }
120814
+ }
120815
+ else {
120816
+ response = await this.privateOptionsPostOrders(orderRequest);
120817
+ }
120818
+ // const response = await this[method] (this.deepExtend (request, params));
120819
+ //
120820
+ // spot
120821
+ //
120822
+ // {
120823
+ // "id": "95282841887",
120824
+ // "text": "apiv4",
120825
+ // "create_time": "1637383156",
120826
+ // "update_time": "1637383156",
120827
+ // "create_time_ms": 1637383156017,
120828
+ // "update_time_ms": 1637383156017,
120829
+ // "status": "open",
120830
+ // "currency_pair": "ETH_USDT",
120831
+ // "type": "limit",
120832
+ // "account": "spot",
120833
+ // "side": "buy",
120834
+ // "amount": "0.01",
120835
+ // "price": "3500",
120836
+ // "time_in_force": "gtc",
120837
+ // "iceberg": "0",
120838
+ // "left": "0.01",
120839
+ // "fill_price": "0",
120840
+ // "filled_total": "0",
120841
+ // "fee": "0",
120842
+ // "fee_currency": "ETH",
120843
+ // "point_fee": "0",
120844
+ // "gt_fee": "0",
120845
+ // "gt_discount": false,
120846
+ // "rebated_fee": "0",
120847
+ // "rebated_fee_currency": "USDT"
120848
+ // }
120849
+ //
120850
+ // spot conditional
120851
+ //
120852
+ // {"id": 5891843}
120853
+ //
120854
+ // futures, perpetual swaps and options
120855
+ //
120856
+ // {
120857
+ // "id": 95938572327,
120858
+ // "contract": "ETH_USDT",
120859
+ // "mkfr": "0",
120860
+ // "tkfr": "0.0005",
120861
+ // "tif": "gtc",
120862
+ // "is_reduce_only": false,
120863
+ // "create_time": 1637384600.08,
120864
+ // "price": "3000",
120865
+ // "size": 1,
120866
+ // "refr": "0",
120867
+ // "left": 1,
120868
+ // "text": "api",
120869
+ // "fill_price": "0",
120870
+ // "user": 2436035,
120871
+ // "status": "open",
120872
+ // "is_liq": false,
120873
+ // "refu": 0,
120874
+ // "is_close": false,
120875
+ // "iceberg": 0
120876
+ // }
120877
+ //
120878
+ // futures and perpetual swaps conditionals
120879
+ //
120880
+ // {"id": 7615567}
120881
+ //
120882
+ return this.parseOrder(response, market);
120883
+ }
120884
+ async createOrders(orders, params = {}) {
120885
+ /**
120886
+ * @method
120887
+ * @name gate#createOrders
120888
+ * @description create a list of trade orders
120889
+ * @see https://www.gate.io/docs/developers/apiv4/en/#get-a-single-order-2
120890
+ * @see https://www.gate.io/docs/developers/apiv4/en/#create-a-batch-of-orders
120891
+ * @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
120892
+ * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
120893
+ */
120894
+ await this.loadMarkets();
120895
+ const ordersRequests = [];
120896
+ const orderSymbols = [];
120897
+ for (let i = 0; i < orders.length; i++) {
120898
+ const rawOrder = orders[i];
120899
+ const marketId = this.safeString(rawOrder, 'symbol');
120900
+ orderSymbols.push(marketId);
120901
+ const type = this.safeString(rawOrder, 'type');
120902
+ const side = this.safeString(rawOrder, 'side');
120903
+ const amount = this.safeValue(rawOrder, 'amount');
120904
+ const price = this.safeValue(rawOrder, 'price');
120905
+ const orderParams = this.safeValue(rawOrder, 'params', {});
120906
+ 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
120907
+ const triggerValue = this.safeValueN(orderParams, ['triggerPrice', 'stopPrice', 'takeProfitPrice', 'stopLossPrice']);
120908
+ if (triggerValue !== undefined) {
120909
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.NotSupported(this.id + ' createOrders() does not support advanced order properties (stopPrice, takeProfitPrice, stopLossPrice)');
120910
+ }
120911
+ extendedParams['textIsRequired'] = true; // Gate.io requires a text parameter for each order here
120912
+ const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, extendedParams);
120913
+ ordersRequests.push(orderRequest);
120914
+ }
120915
+ const symbols = this.marketSymbols(orderSymbols, undefined, false, true, true);
120916
+ const market = this.market(symbols[0]);
120917
+ if (market['future'] || market['option']) {
120918
+ throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.NotSupported(this.id + ' createOrders() does not support futures or options markets');
120919
+ }
120920
+ let response = undefined;
120921
+ if (market['spot']) {
120922
+ response = await this.privateSpotPostBatchOrders(ordersRequests);
120923
+ }
120924
+ else if (market['swap']) {
120925
+ response = await this.privateFuturesPostSettleBatchOrders(ordersRequests);
120926
+ }
120927
+ return this.parseOrders(response);
120928
+ }
120929
+ createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
119837
120930
  const market = this.market(symbol);
119838
120931
  const contract = market['contract'];
119839
120932
  const trigger = this.safeValue(params, 'trigger');
@@ -119846,7 +120939,6 @@ class gate extends _abstract_gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
119846
120939
  if (isStopLossOrder && isTakeProfitOrder) {
119847
120940
  throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.ExchangeError(this.id + ' createOrder() stopLossPrice and takeProfitPrice cannot both be defined');
119848
120941
  }
119849
- let methodTail = 'Orders';
119850
120942
  const reduceOnly = this.safeValue(params, 'reduceOnly');
119851
120943
  const exchangeSpecificTimeInForce = this.safeStringLowerN(params, ['timeInForce', 'tif', 'time_in_force']);
119852
120944
  let postOnly = undefined;
@@ -119959,6 +121051,7 @@ class gate extends _abstract_gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
119959
121051
  }
119960
121052
  }
119961
121053
  let clientOrderId = this.safeString2(params, 'text', 'clientOrderId');
121054
+ const textIsRequired = this.safeValue(params, 'textIsRequired', false);
119962
121055
  if (clientOrderId !== undefined) {
119963
121056
  // user-defined, must follow the rules if not empty
119964
121057
  // prefixed with t-
@@ -119967,12 +121060,18 @@ class gate extends _abstract_gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
119967
121060
  if (clientOrderId.length > 28) {
119968
121061
  throw new _base_errors_js__WEBPACK_IMPORTED_MODULE_2__.BadRequest(this.id + ' createOrder () clientOrderId or text param must be up to 28 characters');
119969
121062
  }
119970
- params = this.omit(params, ['text', 'clientOrderId']);
121063
+ params = this.omit(params, ['text', 'clientOrderId', 'textIsRequired']);
119971
121064
  if (clientOrderId[0] !== 't') {
119972
121065
  clientOrderId = 't-' + clientOrderId;
119973
121066
  }
119974
121067
  request['text'] = clientOrderId;
119975
121068
  }
121069
+ else {
121070
+ if (textIsRequired) {
121071
+ // batchOrders requires text in the request
121072
+ request['text'] = 't-' + this.uuid16();
121073
+ }
121074
+ }
119976
121075
  }
119977
121076
  else {
119978
121077
  if (market['option']) {
@@ -120066,80 +121165,8 @@ class gate extends _abstract_gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
120066
121165
  };
120067
121166
  }
120068
121167
  }
120069
- methodTail = 'PriceOrders';
120070
121168
  }
120071
- const method = this.getSupportedMapping(market['type'], {
120072
- 'spot': 'privateSpotPost' + methodTail,
120073
- 'margin': 'privateSpotPost' + methodTail,
120074
- 'swap': 'privateFuturesPostSettle' + methodTail,
120075
- 'future': 'privateDeliveryPostSettle' + methodTail,
120076
- 'option': 'privateOptionsPostOrders',
120077
- });
120078
- const response = await this[method](this.deepExtend(request, params));
120079
- //
120080
- // spot
120081
- //
120082
- // {
120083
- // "id": "95282841887",
120084
- // "text": "apiv4",
120085
- // "create_time": "1637383156",
120086
- // "update_time": "1637383156",
120087
- // "create_time_ms": 1637383156017,
120088
- // "update_time_ms": 1637383156017,
120089
- // "status": "open",
120090
- // "currency_pair": "ETH_USDT",
120091
- // "type": "limit",
120092
- // "account": "spot",
120093
- // "side": "buy",
120094
- // "amount": "0.01",
120095
- // "price": "3500",
120096
- // "time_in_force": "gtc",
120097
- // "iceberg": "0",
120098
- // "left": "0.01",
120099
- // "fill_price": "0",
120100
- // "filled_total": "0",
120101
- // "fee": "0",
120102
- // "fee_currency": "ETH",
120103
- // "point_fee": "0",
120104
- // "gt_fee": "0",
120105
- // "gt_discount": false,
120106
- // "rebated_fee": "0",
120107
- // "rebated_fee_currency": "USDT"
120108
- // }
120109
- //
120110
- // spot conditional
120111
- //
120112
- // {"id": 5891843}
120113
- //
120114
- // futures, perpetual swaps and options
120115
- //
120116
- // {
120117
- // "id": 95938572327,
120118
- // "contract": "ETH_USDT",
120119
- // "mkfr": "0",
120120
- // "tkfr": "0.0005",
120121
- // "tif": "gtc",
120122
- // "is_reduce_only": false,
120123
- // "create_time": 1637384600.08,
120124
- // "price": "3000",
120125
- // "size": 1,
120126
- // "refr": "0",
120127
- // "left": 1,
120128
- // "text": "api",
120129
- // "fill_price": "0",
120130
- // "user": 2436035,
120131
- // "status": "open",
120132
- // "is_liq": false,
120133
- // "refu": 0,
120134
- // "is_close": false,
120135
- // "iceberg": 0
120136
- // }
120137
- //
120138
- // futures and perpetual swaps conditionals
120139
- //
120140
- // {"id": 7615567}
120141
- //
120142
- return this.parseOrder(response, market);
121169
+ return this.extend(request, params);
120143
121170
  }
120144
121171
  async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
120145
121172
  /**
@@ -120365,6 +121392,22 @@ class gate extends _abstract_gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
120365
121392
  // "order_type": ""
120366
121393
  // }
120367
121394
  //
121395
+ // {
121396
+ // "text": "t-d18baf9ac44d82e2",
121397
+ // "succeeded": false,
121398
+ // "label": "BALANCE_NOT_ENOUGH",
121399
+ // "message": "Not enough balance"
121400
+ // }
121401
+ //
121402
+ const succeeded = this.safeValue(order, 'succeeded', true);
121403
+ if (!succeeded) {
121404
+ // cancelOrders response
121405
+ return this.safeOrder({
121406
+ 'clientOrderId': this.safeString(order, 'text'),
121407
+ 'info': order,
121408
+ 'status': 'rejected',
121409
+ });
121410
+ }
120368
121411
  const put = this.safeValue2(order, 'put', 'initial', {});
120369
121412
  const trigger = this.safeValue(order, 'trigger', {});
120370
121413
  let contract = this.safeString(put, 'contract');
@@ -121804,7 +122847,16 @@ class gate extends _abstract_gate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]
121804
122847
  const authentication = api[0]; // public, private
121805
122848
  const type = api[1]; // spot, margin, future, delivery
121806
122849
  let query = this.omit(params, this.extractParams(path));
121807
- path = this.implodeParams(path, params);
122850
+ if (Array.isArray(params)) {
122851
+ // endpoints like createOrders use an array instead of an object
122852
+ // so we infer the settle from one of the elements
122853
+ // they have to be all the same so relying on the first one is fine
122854
+ const first = this.safeValue(params, 0, {});
122855
+ path = this.implodeParams(path, first);
122856
+ }
122857
+ else {
122858
+ path = this.implodeParams(path, params);
122859
+ }
121808
122860
  const endPart = (path === '') ? '' : ('/' + path);
121809
122861
  let entirePath = '/' + type + endPart;
121810
122862
  if ((type === 'subAccounts') || (type === 'withdrawals')) {
@@ -147008,24 +148060,7 @@ class krakenfutures extends _abstract_krakenfutures_js__WEBPACK_IMPORTED_MODULE_
147008
148060
  'fee': undefined,
147009
148061
  });
147010
148062
  }
147011
- async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
147012
- /**
147013
- * @method
147014
- * @name krakenfutures#createOrder
147015
- * @description Create an order on the exchange
147016
- * @param {string} symbol market symbol
147017
- * @param {string} type One of 'limit', 'market', 'take_profit'
147018
- * @param {string} side buy or sell
147019
- * @param {int} amount Contract quantity
147020
- * @param {float} [price] Limit order price
147021
- * @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,
147022
- * @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,
147023
- * @param {bool} [params.postOnly] Set as true if you wish to make a postOnly order, Default false
147024
- * @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
147025
- * @param {string} [params.cliOrdId] UUID The order identity that is specified from the user, It must be globally unique
147026
- * @param {string} [params.clientOrderId] UUID The order identity that is specified from the user, It must be globally unique
147027
- */
147028
- await this.loadMarkets();
148063
+ createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
147029
148064
  type = this.safeString(params, 'orderType', type);
147030
148065
  const timeInForce = this.safeString(params, 'timeInForce');
147031
148066
  const stopPrice = this.safeString(params, 'stopPrice');
@@ -147063,7 +148098,28 @@ class krakenfutures extends _abstract_krakenfutures_js__WEBPACK_IMPORTED_MODULE_
147063
148098
  if (clientOrderId !== undefined) {
147064
148099
  request['cliOrdId'] = clientOrderId;
147065
148100
  }
147066
- const response = await this.privatePostSendorder(this.extend(request, params));
148101
+ return this.extend(request, params);
148102
+ }
148103
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
148104
+ /**
148105
+ * @method
148106
+ * @name krakenfutures#createOrder
148107
+ * @description Create an order on the exchange
148108
+ * @param {string} symbol market symbol
148109
+ * @param {string} type One of 'limit', 'market', 'take_profit'
148110
+ * @param {string} side buy or sell
148111
+ * @param {int} amount Contract quantity
148112
+ * @param {float} [price] Limit order price
148113
+ * @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,
148114
+ * @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,
148115
+ * @param {bool} [params.postOnly] Set as true if you wish to make a postOnly order, Default false
148116
+ * @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
148117
+ * @param {string} [params.cliOrdId] UUID The order identity that is specified from the user, It must be globally unique
148118
+ * @param {string} [params.clientOrderId] UUID The order identity that is specified from the user, It must be globally unique
148119
+ */
148120
+ await this.loadMarkets();
148121
+ const orderRequest = this.createOrderRequest(symbol, type, side, amount, price, params);
148122
+ const response = await this.privatePostSendorder(orderRequest);
147067
148123
  //
147068
148124
  // {
147069
148125
  // "result": "success",
@@ -147099,6 +148155,57 @@ class krakenfutures extends _abstract_krakenfutures_js__WEBPACK_IMPORTED_MODULE_
147099
148155
  this.verifyOrderActionSuccess(status, 'createOrder', ['filled']);
147100
148156
  return this.parseOrder(sendStatus);
147101
148157
  }
148158
+ async createOrders(orders, params = {}) {
148159
+ /**
148160
+ * @method
148161
+ * @name krakenfutures#createOrders
148162
+ * @description create a list of trade orders
148163
+ * @see https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-batch-order-management
148164
+ * @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
148165
+ * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
148166
+ */
148167
+ await this.loadMarkets();
148168
+ const ordersRequests = [];
148169
+ for (let i = 0; i < orders.length; i++) {
148170
+ const rawOrder = orders[i];
148171
+ const marketId = this.safeString(rawOrder, 'symbol');
148172
+ const type = this.safeString(rawOrder, 'type');
148173
+ const side = this.safeString(rawOrder, 'side');
148174
+ const amount = this.safeValue(rawOrder, 'amount');
148175
+ const price = this.safeValue(rawOrder, 'price');
148176
+ const orderParams = this.safeValue(rawOrder, 'params', {});
148177
+ 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
148178
+ if (!('order_tag' in extendedParams)) {
148179
+ // order tag is mandatory so we will generate one if not provided
148180
+ extendedParams['order_tag'] = this.sum(i, 1).toString(); // sequential counter
148181
+ }
148182
+ extendedParams['order'] = 'send';
148183
+ const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, extendedParams);
148184
+ ordersRequests.push(orderRequest);
148185
+ }
148186
+ const request = {
148187
+ 'batchOrder': ordersRequests,
148188
+ };
148189
+ const response = await this.privatePostBatchorder(this.extend(request, params));
148190
+ //
148191
+ // {
148192
+ // "result": "success",
148193
+ // "serverTime": "2023-10-24T08:40:57.339Z",
148194
+ // "batchStatus": [
148195
+ // {
148196
+ // "status": "requiredArgumentMissing",
148197
+ // "orderEvents": []
148198
+ // },
148199
+ // {
148200
+ // "status": "requiredArgumentMissing",
148201
+ // "orderEvents": []
148202
+ // }
148203
+ // ]
148204
+ // }
148205
+ //
148206
+ const data = this.safeValue(response, 'batchStatus', []);
148207
+ return this.parseOrders(data);
148208
+ }
147102
148209
  async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
147103
148210
  /**
147104
148211
  * @method
@@ -147485,14 +148592,25 @@ class krakenfutures extends _abstract_krakenfutures_js__WEBPACK_IMPORTED_MODULE_
147485
148592
  // "lastUpdateTime": "2019-09-05T17:01:17.410Z"
147486
148593
  // }
147487
148594
  //
148595
+ // createOrders error
148596
+ // {
148597
+ // "status": "requiredArgumentMissing",
148598
+ // "orderEvents": []
148599
+ // }
148600
+ //
147488
148601
  const orderEvents = this.safeValue(order, 'orderEvents', []);
148602
+ const errorStatus = this.safeString(order, 'status');
148603
+ const orderEventsLength = orderEvents.length;
148604
+ if (('orderEvents' in order) && (errorStatus !== undefined) && (orderEventsLength === 0)) {
148605
+ // creteOrders error response
148606
+ return this.safeOrder({ 'info': order, 'status': 'rejected' });
148607
+ }
147489
148608
  let details = undefined;
147490
148609
  let isPrior = false;
147491
148610
  let fixed = false;
147492
148611
  let statusId = undefined;
147493
148612
  let price = undefined;
147494
148613
  let trades = [];
147495
- const orderEventsLength = orderEvents.length;
147496
148614
  if (orderEventsLength) {
147497
148615
  const executions = [];
147498
148616
  for (let i = 0; i < orderEvents.length; i++) {
@@ -175007,18 +176125,6 @@ class oceanex extends _abstract_oceanex_js__WEBPACK_IMPORTED_MODULE_0__/* ["defa
175007
176125
  };
175008
176126
  return this.safeString(statuses, status, status);
175009
176127
  }
175010
- async createOrders(symbol, orders, params = {}) {
175011
- await this.loadMarkets();
175012
- const market = this.market(symbol);
175013
- const request = {
175014
- 'market': market['id'],
175015
- 'orders': orders,
175016
- };
175017
- // orders: [{"side":"buy", "volume":.2, "price":1001}, {"side":"sell", "volume":0.2, "price":1002}]
175018
- const response = await this.privatePostOrdersMulti(this.extend(request, params));
175019
- const data = response['data'];
175020
- return this.parseOrders(data);
175021
- }
175022
176128
  async cancelOrder(id, symbol = undefined, params = {}) {
175023
176129
  /**
175024
176130
  * @method
@@ -178276,6 +179382,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
178276
179382
  'cancelOrders': true,
178277
179383
  'createDepositAddress': false,
178278
179384
  'createOrder': true,
179385
+ 'createOrders': true,
178279
179386
  'createPostOnlyOrder': true,
178280
179387
  'createReduceOnlyOrder': true,
178281
179388
  'createStopLimitOrder': true,
@@ -181009,6 +182116,55 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
181009
182116
  order['side'] = side;
181010
182117
  return order;
181011
182118
  }
182119
+ async createOrders(orders, params = {}) {
182120
+ /**
182121
+ * @method
182122
+ * @name okx#createOrders
182123
+ * @description create a list of trade orders
182124
+ * @see https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-place-multiple-orders
182125
+ * @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
182126
+ * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
182127
+ */
182128
+ await this.loadMarkets();
182129
+ const ordersRequests = [];
182130
+ for (let i = 0; i < orders.length; i++) {
182131
+ const rawOrder = orders[i];
182132
+ const marketId = this.safeString(rawOrder, 'symbol');
182133
+ const type = this.safeString(rawOrder, 'type');
182134
+ const side = this.safeString(rawOrder, 'side');
182135
+ const amount = this.safeValue(rawOrder, 'amount');
182136
+ const price = this.safeValue(rawOrder, 'price');
182137
+ const orderParams = this.safeValue(rawOrder, 'params', {});
182138
+ 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
182139
+ const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, extendedParams);
182140
+ ordersRequests.push(orderRequest);
182141
+ }
182142
+ const response = await this.privatePostTradeBatchOrders(ordersRequests);
182143
+ // {
182144
+ // "code": "0",
182145
+ // "data": [
182146
+ // {
182147
+ // "clOrdId": "e847386590ce4dBCc7f2a1b4c4509f82",
182148
+ // "ordId": "636305438765568000",
182149
+ // "sCode": "0",
182150
+ // "sMsg": "Order placed",
182151
+ // "tag": "e847386590ce4dBC"
182152
+ // },
182153
+ // {
182154
+ // "clOrdId": "e847386590ce4dBC0b9993fe642d8f62",
182155
+ // "ordId": "636305438765568001",
182156
+ // "sCode": "0",
182157
+ // "sMsg": "Order placed",
182158
+ // "tag": "e847386590ce4dBC"
182159
+ // }
182160
+ // ],
182161
+ // "inTime": "1697979038584486",
182162
+ // "msg": "",
182163
+ // "outTime": "1697979038586493"
182164
+ // }
182165
+ const data = this.safeValue(response, 'data', []);
182166
+ return this.parseOrders(data);
182167
+ }
181012
182168
  editOrderRequest(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
181013
182169
  const market = this.market(symbol);
181014
182170
  const request = {
@@ -181387,6 +182543,15 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
181387
182543
  // "uly": "BTC-USDT"
181388
182544
  // }
181389
182545
  //
182546
+ const scode = this.safeString(order, 'sCode');
182547
+ if ((scode !== undefined) && (scode !== '0')) {
182548
+ return this.safeOrder({
182549
+ 'id': this.safeString(order, 'ordId'),
182550
+ 'clientOrderId': this.safeString(order, 'clOrdId'),
182551
+ 'status': 'rejected',
182552
+ 'info': order,
182553
+ });
182554
+ }
181390
182555
  const id = this.safeString2(order, 'algoId', 'ordId');
181391
182556
  const timestamp = this.safeInteger(order, 'cTime');
181392
182557
  const lastUpdateTimestamp = this.safeInteger(order, 'uTime');
@@ -185129,7 +186294,7 @@ class okx extends _abstract_okx_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */
185129
186294
  // }
185130
186295
  //
185131
186296
  const code = this.safeString(response, 'code');
185132
- if (code !== '0') {
186297
+ if ((code !== '0') && (code !== '2')) { // 2 means that bulk operation partially succeeded
185133
186298
  const feedback = this.id + ' ' + body;
185134
186299
  const data = this.safeValue(response, 'data', []);
185135
186300
  for (let i = 0; i < data.length; i++) {
@@ -210580,7 +211745,7 @@ class bybit extends _bybit_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z {
210580
211745
  const topic = this.safeString(message, 'topic', '');
210581
211746
  const updateType = this.safeString(message, 'type', '');
210582
211747
  const data = this.safeValue(message, 'data', {});
210583
- const isSpot = this.safeString(data, 'openInterestValue') === undefined;
211748
+ const isSpot = this.safeString(data, 'fundingRate') === undefined;
210584
211749
  const type = isSpot ? 'spot' : 'contract';
210585
211750
  let symbol = undefined;
210586
211751
  let parsed = undefined;
@@ -248097,18 +249262,19 @@ function twistedEdwards(curveDef) {
248097
249262
  }
248098
249263
  /** Signs message with privateKey. RFC8032 5.1.6 */
248099
249264
  function sign(msg, privKey, context) {
248100
- /*
248101
- msg = ensureBytes('message', msg);
248102
- if (preHash) msg = preHash(msg); // for ed25519ph etc.
249265
+ msg = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.ensureBytes)('message', msg);
249266
+ if (preHash)
249267
+ msg = preHash(msg); // for ed25519ph etc.
248103
249268
  const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey);
248104
249269
  const r = hashDomainToScalar(context, prefix, msg); // r = dom2(F, C) || prefix || PH(M)
248105
249270
  const R = G.multiply(r).toRawBytes(); // R = rG
248106
249271
  const k = hashDomainToScalar(context, R, pointBytes, msg); // R || A || PH(M)
248107
249272
  const s = modN(r + k * scalar); // S = (r + k * s) mod L
248108
249273
  assertGE0(s); // 0 <= s < l
248109
- const res = ut.concatBytes(R, ut.numberToBytesLE(s, Fp.BYTES));
248110
- return ensureBytes('result', res, nByteLength * 2); // 64-byte signature
248111
- */
249274
+ const res = _utils_js__WEBPACK_IMPORTED_MODULE_1__.concatBytes(R, _utils_js__WEBPACK_IMPORTED_MODULE_1__.numberToBytesLE(s, Fp.BYTES));
249275
+ return (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.ensureBytes)('result', res, nByteLength * 2); // 64-byte signature
249276
+ }
249277
+ function signModified(msg, privKey, context) {
248112
249278
  msg = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.ensureBytes)('message', msg);
248113
249279
  const privKeyBytes = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.ensureBytes)('privKey', privKey);
248114
249280
  const privKeyNumber = _utils_js__WEBPACK_IMPORTED_MODULE_1__.bytesToNumberLE(privKeyBytes);
@@ -248161,6 +249327,7 @@ function twistedEdwards(curveDef) {
248161
249327
  CURVE,
248162
249328
  getPublicKey,
248163
249329
  sign,
249330
+ signModified,
248164
249331
  verify,
248165
249332
  ExtendedPoint: Point,
248166
249333
  utils,
@@ -260511,7 +261678,7 @@ class wavesexchange extends _abstract_wavesexchange_js__WEBPACK_IMPORTED_MODULE_
260511
261678
  const messageHex = this.binaryToBase16(this.encode(message));
260512
261679
  const payload = prefix + messageHex;
260513
261680
  const hexKey = this.binaryToBase16(this.base58ToBinary(this.secret));
260514
- const signature = (0,_base_functions_crypto_js__WEBPACK_IMPORTED_MODULE_4__/* .eddsa */ .UZ)(payload, hexKey, _static_dependencies_noble_curves_ed25519_js__WEBPACK_IMPORTED_MODULE_5__/* .ed25519 */ .UN);
261681
+ const signature = (0,_base_functions_crypto_js__WEBPACK_IMPORTED_MODULE_4__/* .axolotl */ .gC)(payload, hexKey, _static_dependencies_noble_curves_ed25519_js__WEBPACK_IMPORTED_MODULE_5__/* .ed25519 */ .UN);
260515
261682
  const request = {
260516
261683
  'grant_type': 'password',
260517
261684
  'scope': 'general',
@@ -261180,7 +262347,7 @@ class wavesexchange extends _abstract_wavesexchange_js__WEBPACK_IMPORTED_MODULE_
261180
262347
  if ((serializedOrder[0] === '"') && (serializedOrder[(serializedOrder.length - 1)] === '"')) {
261181
262348
  serializedOrder = serializedOrder.slice(1, serializedOrder.length - 1);
261182
262349
  }
261183
- const signature = (0,_base_functions_crypto_js__WEBPACK_IMPORTED_MODULE_4__/* .eddsa */ .UZ)(this.binaryToBase16(this.base58ToBinary(serializedOrder)), this.binaryToBase16(this.base58ToBinary(this.secret)), _static_dependencies_noble_curves_ed25519_js__WEBPACK_IMPORTED_MODULE_5__/* .ed25519 */ .UN);
262350
+ const signature = (0,_base_functions_crypto_js__WEBPACK_IMPORTED_MODULE_4__/* .axolotl */ .gC)(this.binaryToBase16(this.base58ToBinary(serializedOrder)), this.binaryToBase16(this.base58ToBinary(this.secret)), _static_dependencies_noble_curves_ed25519_js__WEBPACK_IMPORTED_MODULE_5__/* .ed25519 */ .UN);
261184
262351
  body['signature'] = signature;
261185
262352
  //
261186
262353
  // {
@@ -261295,7 +262462,7 @@ class wavesexchange extends _abstract_wavesexchange_js__WEBPACK_IMPORTED_MODULE_
261295
262462
  ];
261296
262463
  const binary = this.binaryConcatArray(byteArray);
261297
262464
  const hexSecret = this.binaryToBase16(this.base58ToBinary(this.secret));
261298
- const signature = (0,_base_functions_crypto_js__WEBPACK_IMPORTED_MODULE_4__/* .eddsa */ .UZ)(this.binaryToBase16(binary), hexSecret, _static_dependencies_noble_curves_ed25519_js__WEBPACK_IMPORTED_MODULE_5__/* .ed25519 */ .UN);
262465
+ const signature = (0,_base_functions_crypto_js__WEBPACK_IMPORTED_MODULE_4__/* .axolotl */ .gC)(this.binaryToBase16(binary), hexSecret, _static_dependencies_noble_curves_ed25519_js__WEBPACK_IMPORTED_MODULE_5__/* .ed25519 */ .UN);
261299
262466
  const request = {
261300
262467
  'Timestamp': timestamp.toString(),
261301
262468
  'Signature': signature,
@@ -261330,7 +262497,7 @@ class wavesexchange extends _abstract_wavesexchange_js__WEBPACK_IMPORTED_MODULE_
261330
262497
  ];
261331
262498
  const binary = this.binaryConcatArray(byteArray);
261332
262499
  const hexSecret = this.binaryToBase16(this.base58ToBinary(this.secret));
261333
- const signature = (0,_base_functions_crypto_js__WEBPACK_IMPORTED_MODULE_4__/* .eddsa */ .UZ)(this.binaryToBase16(binary), hexSecret, _static_dependencies_noble_curves_ed25519_js__WEBPACK_IMPORTED_MODULE_5__/* .ed25519 */ .UN);
262500
+ const signature = (0,_base_functions_crypto_js__WEBPACK_IMPORTED_MODULE_4__/* .axolotl */ .gC)(this.binaryToBase16(binary), hexSecret, _static_dependencies_noble_curves_ed25519_js__WEBPACK_IMPORTED_MODULE_5__/* .ed25519 */ .UN);
261334
262501
  const request = {
261335
262502
  'Accept': 'application/json',
261336
262503
  'Timestamp': timestamp.toString(),
@@ -261694,7 +262861,7 @@ class wavesexchange extends _abstract_wavesexchange_js__WEBPACK_IMPORTED_MODULE_
261694
262861
  ];
261695
262862
  const binary = this.binaryConcatArray(byteArray);
261696
262863
  const hexSecret = this.binaryToBase16(this.base58ToBinary(this.secret));
261697
- const signature = (0,_base_functions_crypto_js__WEBPACK_IMPORTED_MODULE_4__/* .eddsa */ .UZ)(this.binaryToBase16(binary), hexSecret, _static_dependencies_noble_curves_ed25519_js__WEBPACK_IMPORTED_MODULE_5__/* .ed25519 */ .UN);
262864
+ const signature = (0,_base_functions_crypto_js__WEBPACK_IMPORTED_MODULE_4__/* .axolotl */ .gC)(this.binaryToBase16(binary), hexSecret, _static_dependencies_noble_curves_ed25519_js__WEBPACK_IMPORTED_MODULE_5__/* .ed25519 */ .UN);
261698
262865
  const matcherRequest = {
261699
262866
  'publicKey': this.apiKey,
261700
262867
  'signature': signature,
@@ -262292,7 +263459,7 @@ class wavesexchange extends _abstract_wavesexchange_js__WEBPACK_IMPORTED_MODULE_
262292
263459
  ];
262293
263460
  const binary = this.binaryConcatArray(byteArray);
262294
263461
  const hexSecret = this.binaryToBase16(this.base58ToBinary(this.secret));
262295
- const signature = (0,_base_functions_crypto_js__WEBPACK_IMPORTED_MODULE_4__/* .eddsa */ .UZ)(this.binaryToBase16(binary), hexSecret, _static_dependencies_noble_curves_ed25519_js__WEBPACK_IMPORTED_MODULE_5__/* .ed25519 */ .UN);
263462
+ const signature = (0,_base_functions_crypto_js__WEBPACK_IMPORTED_MODULE_4__/* .axolotl */ .gC)(this.binaryToBase16(binary), hexSecret, _static_dependencies_noble_curves_ed25519_js__WEBPACK_IMPORTED_MODULE_5__/* .ed25519 */ .UN);
262296
263463
  const request = {
262297
263464
  'senderPublicKey': this.apiKey,
262298
263465
  'amount': amountInteger,
@@ -277746,7 +278913,7 @@ SOFTWARE.
277746
278913
 
277747
278914
  //-----------------------------------------------------------------------------
277748
278915
  // this is updated by vss.js when building
277749
- const version = '4.1.24';
278916
+ const version = '4.1.26';
277750
278917
  _src_base_Exchange_js__WEBPACK_IMPORTED_MODULE_0__/* .Exchange.ccxtVersion */ .e.ccxtVersion = version;
277751
278918
  //-----------------------------------------------------------------------------
277752
278919