ccxt 4.2.89 → 4.2.91

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 (90) hide show
  1. package/CHANGELOG.md +44 -16
  2. package/README.md +3 -3
  3. package/build.sh +1 -1
  4. package/dist/ccxt.browser.js +1167 -274
  5. package/dist/ccxt.browser.min.js +6 -4
  6. package/dist/cjs/ccxt.js +1 -1
  7. package/dist/cjs/src/ascendex.js +1 -0
  8. package/dist/cjs/src/base/Exchange.js +39 -9
  9. package/dist/cjs/src/base/functions/crypto.js +37 -0
  10. package/dist/cjs/src/base/functions/rsa.js +19 -4
  11. package/dist/cjs/src/binance.js +90 -9
  12. package/dist/cjs/src/bingx.js +101 -1
  13. package/dist/cjs/src/bitfinex2.js +1 -0
  14. package/dist/cjs/src/bitget.js +2 -0
  15. package/dist/cjs/src/bitmex.js +1 -0
  16. package/dist/cjs/src/bitrue.js +1 -0
  17. package/dist/cjs/src/bybit.js +61 -0
  18. package/dist/cjs/src/coinbase.js +51 -25
  19. package/dist/cjs/src/coinbaseinternational.js +1 -0
  20. package/dist/cjs/src/coinex.js +102 -8
  21. package/dist/cjs/src/cryptocom.js +1 -0
  22. package/dist/cjs/src/delta.js +1 -0
  23. package/dist/cjs/src/digifinex.js +1 -0
  24. package/dist/cjs/src/exmo.js +1 -0
  25. package/dist/cjs/src/gate.js +2 -0
  26. package/dist/cjs/src/gemini.js +12 -10
  27. package/dist/cjs/src/hitbtc.js +1 -0
  28. package/dist/cjs/src/htx.js +1 -0
  29. package/dist/cjs/src/hyperliquid.js +1 -0
  30. package/dist/cjs/src/kraken.js +11 -9
  31. package/dist/cjs/src/kucoin.js +1 -0
  32. package/dist/cjs/src/kucoinfutures.js +34 -3
  33. package/dist/cjs/src/mexc.js +1 -0
  34. package/dist/cjs/src/okx.js +187 -38
  35. package/dist/cjs/src/phemex.js +1 -0
  36. package/dist/cjs/src/pro/bitmex.js +39 -18
  37. package/dist/cjs/src/pro/kucoin.js +91 -0
  38. package/dist/cjs/src/pro/kucoinfutures.js +151 -82
  39. package/dist/cjs/src/static_dependencies/noble-curves/p256.js +48 -0
  40. package/dist/cjs/src/woo.js +1 -0
  41. package/js/ccxt.d.ts +1 -1
  42. package/js/ccxt.js +1 -1
  43. package/js/src/abstract/bingx.d.ts +2 -0
  44. package/js/src/abstract/bybit.d.ts +2 -0
  45. package/js/src/ascendex.js +1 -0
  46. package/js/src/base/Exchange.d.ts +5 -0
  47. package/js/src/base/Exchange.js +39 -9
  48. package/js/src/base/functions/crypto.js +37 -0
  49. package/js/src/base/functions/rsa.d.ts +1 -1
  50. package/js/src/base/functions/rsa.js +21 -5
  51. package/js/src/base/types.d.ts +1 -0
  52. package/js/src/binance.d.ts +1 -0
  53. package/js/src/binance.js +90 -9
  54. package/js/src/bingx.d.ts +1 -0
  55. package/js/src/bingx.js +101 -1
  56. package/js/src/bitfinex2.js +1 -0
  57. package/js/src/bitget.js +2 -0
  58. package/js/src/bitmex.js +1 -0
  59. package/js/src/bitrue.js +1 -0
  60. package/js/src/bybit.d.ts +2 -0
  61. package/js/src/bybit.js +61 -0
  62. package/js/src/coinbase.js +51 -25
  63. package/js/src/coinbaseinternational.js +1 -0
  64. package/js/src/coinex.d.ts +2 -0
  65. package/js/src/coinex.js +102 -8
  66. package/js/src/cryptocom.js +1 -0
  67. package/js/src/delta.js +1 -0
  68. package/js/src/digifinex.js +1 -0
  69. package/js/src/exmo.js +1 -0
  70. package/js/src/gate.js +2 -0
  71. package/js/src/gemini.js +12 -10
  72. package/js/src/hitbtc.js +1 -0
  73. package/js/src/htx.js +1 -0
  74. package/js/src/hyperliquid.js +1 -0
  75. package/js/src/kraken.js +11 -9
  76. package/js/src/kucoin.js +1 -0
  77. package/js/src/kucoinfutures.d.ts +2 -9
  78. package/js/src/kucoinfutures.js +34 -3
  79. package/js/src/mexc.js +1 -0
  80. package/js/src/okx.d.ts +1 -0
  81. package/js/src/okx.js +187 -38
  82. package/js/src/phemex.js +1 -0
  83. package/js/src/pro/bitmex.d.ts +1 -0
  84. package/js/src/pro/bitmex.js +39 -18
  85. package/js/src/pro/kucoin.d.ts +4 -0
  86. package/js/src/pro/kucoin.js +91 -0
  87. package/js/src/pro/kucoinfutures.d.ts +9 -5
  88. package/js/src/pro/kucoinfutures.js +151 -82
  89. package/js/src/woo.js +1 -0
  90. package/package.json +1 -1
package/dist/cjs/ccxt.js CHANGED
@@ -182,7 +182,7 @@ var woo$1 = require('./src/pro/woo.js');
182
182
 
183
183
  //-----------------------------------------------------------------------------
184
184
  // this is updated by vss.js when building
185
- const version = '4.2.89';
185
+ const version = '4.2.91';
186
186
  Exchange["default"].ccxtVersion = version;
187
187
  const exchanges = {
188
188
  'ace': ace,
@@ -2888,6 +2888,7 @@ class ascendex extends ascendex$1 {
2888
2888
  'info': data,
2889
2889
  'symbol': market['symbol'],
2890
2890
  'type': undefined,
2891
+ 'marginMode': 'isolated',
2891
2892
  'amount': undefined,
2892
2893
  'total': undefined,
2893
2894
  'code': market['quote'],
@@ -21,6 +21,7 @@ require('../static_dependencies/noble-hashes/sha3.js');
21
21
  require('../static_dependencies/noble-hashes/sha256.js');
22
22
  require('../static_dependencies/ethers/address/address.js');
23
23
  var typedData = require('../static_dependencies/ethers/hash/typed-data.js');
24
+ var rng = require('../static_dependencies/jsencrypt/lib/jsbn/rng.js');
24
25
  var generic = require('./functions/generic.js');
25
26
  var misc = require('./functions/misc.js');
26
27
 
@@ -441,6 +442,7 @@ class Exchange {
441
442
  'fetchIndexOHLCV': undefined,
442
443
  'fetchIsolatedBorrowRate': undefined,
443
444
  'fetchIsolatedBorrowRates': undefined,
445
+ 'fetchMarginAdjustmentHistory': undefined,
444
446
  'fetchIsolatedPositions': undefined,
445
447
  'fetchL2OrderBook': true,
446
448
  'fetchL3OrderBook': undefined,
@@ -1445,6 +1447,13 @@ class Exchange {
1445
1447
  createSafeDictionary() {
1446
1448
  return {};
1447
1449
  }
1450
+ randomBytes(length) {
1451
+ const rng$1 = new rng.SecureRandom();
1452
+ const x = [];
1453
+ x.length = length;
1454
+ rng$1.nextBytes(x);
1455
+ return Buffer.from(x).toString('hex');
1456
+ }
1448
1457
  /* eslint-enable */
1449
1458
  // ------------------------------------------------------------------------
1450
1459
  // ########################################################################
@@ -2051,6 +2060,20 @@ class Exchange {
2051
2060
  async setMargin(symbol, amount, params = {}) {
2052
2061
  throw new errors.NotSupported(this.id + ' setMargin() is not supported yet');
2053
2062
  }
2063
+ async fetchMarginAdjustmentHistory(symbol = undefined, type = undefined, since = undefined, limit = undefined, params = {}) {
2064
+ /**
2065
+ * @method
2066
+ * @name exchange#fetchMarginAdjustmentHistory
2067
+ * @description fetches the history of margin added or reduced from contract isolated positions
2068
+ * @param {string} [symbol] unified market symbol
2069
+ * @param {string} [type] "add" or "reduce"
2070
+ * @param {int} [since] timestamp in ms of the earliest change to fetch
2071
+ * @param {int} [limit] the maximum amount of changes to fetch
2072
+ * @param {object} params extra parameters specific to the exchange api endpoint
2073
+ * @returns {object[]} a list of [margin structures]{@link https://docs.ccxt.com/#/?id=margin-loan-structure}
2074
+ */
2075
+ throw new errors.NotSupported(this.id + ' fetchMarginAdjustmentHistory() is not supported yet');
2076
+ }
2054
2077
  async setMarginMode(marginMode, symbol = undefined, params = {}) {
2055
2078
  throw new errors.NotSupported(this.id + ' setMarginMode() is not supported yet');
2056
2079
  }
@@ -2072,7 +2095,7 @@ class Exchange {
2072
2095
  parseToInt(number) {
2073
2096
  // Solve Common parseInt misuse ex: parseInt ((since / 1000).toString ())
2074
2097
  // using a number as parameter which is not valid in ts
2075
- const stringifiedNumber = number.toString();
2098
+ const stringifiedNumber = this.numberToString(number);
2076
2099
  const convertedNumber = parseFloat(stringifiedNumber);
2077
2100
  return parseInt(convertedNumber);
2078
2101
  }
@@ -4565,13 +4588,6 @@ class Exchange {
4565
4588
  if (!this.substituteCommonCurrencyCodes) {
4566
4589
  return code;
4567
4590
  }
4568
- // if the provided code already exists as a value in commonCurrencies dict, then we should not again transform it
4569
- // more details at: https://github.com/ccxt/ccxt/issues/21112#issuecomment-2031293691
4570
- const commonCurrencies = Object.values(this.commonCurrencies);
4571
- const exists = this.inArray(code, commonCurrencies);
4572
- if (exists) {
4573
- return code;
4574
- }
4575
4591
  return this.safeString(this.commonCurrencies, code, code);
4576
4592
  }
4577
4593
  currency(code) {
@@ -5222,7 +5238,6 @@ class Exchange {
5222
5238
  * @returns {object} objects with withdraw and deposit fees, indexed by currency codes
5223
5239
  */
5224
5240
  const depositWithdrawFees = {};
5225
- codes = this.marketCodes(codes);
5226
5241
  const isArray = Array.isArray(response);
5227
5242
  let responseKeys = response;
5228
5243
  if (!isArray) {
@@ -5814,6 +5829,21 @@ class Exchange {
5814
5829
  const reconstructedDate = day + month + year;
5815
5830
  return reconstructedDate;
5816
5831
  }
5832
+ parseMarginModification(data, market = undefined) {
5833
+ throw new errors.NotSupported(this.id + ' parseMarginModification() is not supported yet');
5834
+ }
5835
+ parseMarginModifications(response, symbols = undefined, symbolKey = undefined, marketType = undefined) {
5836
+ const marginModifications = [];
5837
+ for (let i = 0; i < response.length; i++) {
5838
+ const info = response[i];
5839
+ const marketId = this.safeString(info, symbolKey);
5840
+ const market = this.safeMarket(marketId, undefined, undefined, marketType);
5841
+ if ((symbols === undefined) || this.inArray(market['symbol'], symbols)) {
5842
+ marginModifications.push(this.parseMarginModification(info, market));
5843
+ }
5844
+ }
5845
+ return marginModifications;
5846
+ }
5817
5847
  }
5818
5848
 
5819
5849
  exports.Exchange = Exchange;
@@ -5,6 +5,9 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var hmac$1 = require('../../static_dependencies/noble-hashes/hmac.js');
6
6
  var index = require('../../static_dependencies/scure-base/index.js');
7
7
  var base64 = require('../../static_dependencies/jsencrypt/lib/asn1js/base64.js');
8
+ var asn1 = require('../../static_dependencies/jsencrypt/lib/asn1js/asn1.js');
9
+ var secp256k1 = require('../../static_dependencies/noble-curves/secp256k1.js');
10
+ var p256 = require('../../static_dependencies/noble-curves/p256.js');
8
11
 
9
12
  /* ------------------------------------------------------------------------ */
10
13
  /* ------------------------------------------------------------------------ */
@@ -13,6 +16,10 @@ const encoders = {
13
16
  hex: index.base16.encode,
14
17
  base64: index.base64.encode,
15
18
  };
19
+ const supportedCurve = {
20
+ '1.3.132.0.10': secp256k1.secp256k1,
21
+ '1.2.840.10045.3.1.7': p256.P256,
22
+ };
16
23
  /* ............................................. */
17
24
  const hash = (request, hash, digest = 'hex') => {
18
25
  const binary = hash(request);
@@ -28,6 +35,36 @@ function ecdsa(request, secret, curve, prehash = null) {
28
35
  if (prehash) {
29
36
  request = hash(request, prehash, 'hex');
30
37
  }
38
+ if (typeof secret === 'string' && secret.length > 64) {
39
+ // decode pem key
40
+ if (secret.startsWith('-----BEGIN EC PRIVATE KEY-----')) {
41
+ const der = base64.Base64.unarmor(secret);
42
+ let asn1$1 = asn1.ASN1.decode(der);
43
+ if (asn1$1.sub.length === 4) {
44
+ // ECPrivateKey ::= SEQUENCE {
45
+ // version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
46
+ // privateKey OCTET STRING,
47
+ // parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
48
+ // publicKey [1] BIT STRING OPTIONAL
49
+ // }
50
+ if (typeof asn1$1.sub[2].sub !== null && asn1$1.sub[2].sub.length > 0) {
51
+ const oid = asn1$1.sub[2].sub[0].content(undefined);
52
+ if (supportedCurve[oid] === undefined)
53
+ throw new Error('Unsupported curve');
54
+ curve = supportedCurve[oid];
55
+ }
56
+ secret = asn1$1.sub[1].getHexStringValue();
57
+ }
58
+ else {
59
+ // maybe return false
60
+ throw new Error('Unsupported key format');
61
+ }
62
+ }
63
+ else {
64
+ // maybe return false
65
+ throw new Error('Unsupported key format');
66
+ }
67
+ }
31
68
  const signature = curve.sign(request, secret);
32
69
  return {
33
70
  'r': signature.r.toString(16),
@@ -6,6 +6,7 @@ var JSEncrypt = require('../../static_dependencies/jsencrypt/JSEncrypt.js');
6
6
  var index = require('../../static_dependencies/scure-base/index.js');
7
7
  var encode = require('./encode.js');
8
8
  var crypto = require('./crypto.js');
9
+ var p256 = require('../../static_dependencies/noble-curves/p256.js');
9
10
 
10
11
  function rsa(request, secret, hash) {
11
12
  const RSA = new JSEncrypt.JSEncrypt();
@@ -14,9 +15,17 @@ function rsa(request, secret, hash) {
14
15
  const name = (hash.create()).constructor.name.toLowerCase();
15
16
  return RSA.sign(request, digester, name);
16
17
  }
17
- function jwt(request, secret, hash, isRSA = false) {
18
- const alg = (isRSA ? 'RS' : 'HS') + (hash.outputLen * 8);
19
- const encodedHeader = encode.urlencodeBase64(encode.stringToBase64(JSON.stringify({ 'alg': alg, 'typ': 'JWT' })));
18
+ function jwt(request, secret, hash, isRSA = false, opts = {}) {
19
+ let alg = (isRSA ? 'RS' : 'HS') + (hash.outputLen * 8);
20
+ if (opts['alg']) {
21
+ alg = opts['alg'].toUpperCase();
22
+ }
23
+ const header = Object.assign({ 'alg': alg, 'typ': 'JWT' }, opts);
24
+ if (header['iat'] !== undefined) {
25
+ request['iat'] = header['iat'];
26
+ delete header['iat'];
27
+ }
28
+ const encodedHeader = encode.urlencodeBase64(encode.stringToBase64(JSON.stringify(header)));
20
29
  const encodedData = encode.urlencodeBase64(encode.stringToBase64(JSON.stringify(request)));
21
30
  const token = [encodedHeader, encodedData].join('.');
22
31
  const algoType = alg.slice(0, 2);
@@ -24,9 +33,15 @@ function jwt(request, secret, hash, isRSA = false) {
24
33
  if (algoType === 'HS') {
25
34
  signature = encode.urlencodeBase64(crypto.hmac(token, secret, hash, 'base64'));
26
35
  }
27
- else if (algoType === 'RS') {
36
+ else if (isRSA || algoType === 'RS') {
28
37
  signature = encode.urlencodeBase64(rsa(token, index.utf8.encode(secret), hash));
29
38
  }
39
+ else if (algoType === 'ES') {
40
+ const signedHash = crypto.ecdsa(token, index.utf8.encode(secret), p256.P256, hash);
41
+ const r = (signedHash.r.length === 64) ? signedHash.r : '0' + signedHash.r;
42
+ const s = (signedHash.s.length === 64) ? signedHash.s : '0' + signedHash.s;
43
+ signature = encode.urlencodeBase64(encode.binaryToBase64(encode.base16ToBinary(r + s)));
44
+ }
30
45
  return [token, signature].join('.');
31
46
  }
32
47
 
@@ -98,6 +98,7 @@ class binance extends binance$1 {
98
98
  'fetchLeverages': true,
99
99
  'fetchLeverageTiers': true,
100
100
  'fetchLiquidations': false,
101
+ 'fetchMarginAdjustmentHistory': true,
101
102
  'fetchMarginMode': 'emulated',
102
103
  'fetchMarginModes': true,
103
104
  'fetchMarketLeverageTiers': 'emulated',
@@ -11228,21 +11229,37 @@ class binance extends binance$1 {
11228
11229
  // "type": 1
11229
11230
  // }
11230
11231
  //
11232
+ // fetchMarginAdjustmentHistory
11233
+ //
11234
+ // {
11235
+ // symbol: "XRPUSDT",
11236
+ // type: "1",
11237
+ // deltaType: "TRADE",
11238
+ // amount: "2.57148240",
11239
+ // asset: "USDT",
11240
+ // time: "1711046271555",
11241
+ // positionSide: "BOTH",
11242
+ // clientTranId: ""
11243
+ // }
11244
+ //
11231
11245
  const rawType = this.safeInteger(data, 'type');
11232
- const resultType = (rawType === 1) ? 'add' : 'reduce';
11233
- const resultAmount = this.safeNumber(data, 'amount');
11234
11246
  const errorCode = this.safeString(data, 'code');
11235
- const status = (errorCode === '200') ? 'ok' : 'failed';
11247
+ const marketId = this.safeString(data, 'symbol');
11248
+ const timestamp = this.safeInteger(data, 'time');
11249
+ market = this.safeMarket(marketId, market, undefined, 'swap');
11250
+ const noErrorCode = errorCode === undefined;
11251
+ const success = errorCode === '200';
11236
11252
  return {
11237
11253
  'info': data,
11238
11254
  'symbol': market['symbol'],
11239
- 'type': resultType,
11240
- 'amount': resultAmount,
11255
+ 'type': (rawType === 1) ? 'add' : 'reduce',
11256
+ 'marginMode': 'isolated',
11257
+ 'amount': this.safeNumber(data, 'amount'),
11258
+ 'code': this.safeString(data, 'asset'),
11241
11259
  'total': undefined,
11242
- 'code': undefined,
11243
- 'status': status,
11244
- 'timestamp': undefined,
11245
- 'datetime': undefined,
11260
+ 'status': (success || noErrorCode) ? 'ok' : 'failed',
11261
+ 'timestamp': timestamp,
11262
+ 'datetime': this.iso8601(timestamp),
11246
11263
  };
11247
11264
  }
11248
11265
  async reduceMargin(symbol, amount, params = {}) {
@@ -12505,6 +12522,70 @@ class binance extends binance$1 {
12505
12522
  'quoteVolume': undefined,
12506
12523
  };
12507
12524
  }
12525
+ async fetchMarginAdjustmentHistory(symbol = undefined, type = undefined, since = undefined, limit = undefined, params = {}) {
12526
+ /**
12527
+ * @method
12528
+ * @description fetches the history of margin added or reduced from contract isolated positions
12529
+ * @see https://binance-docs.github.io/apidocs/futures/en/#get-position-margin-change-history-trade
12530
+ * @see https://binance-docs.github.io/apidocs/delivery/en/#get-position-margin-change-history-trade
12531
+ * @param {string} symbol unified market symbol
12532
+ * @param {string} [type] "add" or "reduce"
12533
+ * @param {int} [since] timestamp in ms of the earliest change to fetch
12534
+ * @param {int} [limit] the maximum amount of changes to fetch
12535
+ * @param {object} params extra parameters specific to the exchange api endpoint
12536
+ * @param {int} [params.until] timestamp in ms of the latest change to fetch
12537
+ * @returns {object[]} a list of [margin structures]{@link https://docs.ccxt.com/#/?id=margin-loan-structure}
12538
+ */
12539
+ await this.loadMarkets();
12540
+ if (symbol === undefined) {
12541
+ throw new errors.ArgumentsRequired(this.id + ' fetchMarginAdjustmentHistory () requires a symbol argument');
12542
+ }
12543
+ const market = this.market(symbol);
12544
+ const until = this.safeInteger(params, 'until');
12545
+ params = this.omit(params, 'until');
12546
+ const request = {
12547
+ 'symbol': market['id'],
12548
+ };
12549
+ if (type !== undefined) {
12550
+ request['type'] = (type === 'add') ? 1 : 2;
12551
+ }
12552
+ if (since !== undefined) {
12553
+ request['startTime'] = since;
12554
+ }
12555
+ if (limit !== undefined) {
12556
+ request['limit'] = limit;
12557
+ }
12558
+ if (until !== undefined) {
12559
+ request['endTime'] = until;
12560
+ }
12561
+ let response = undefined;
12562
+ if (market['linear']) {
12563
+ response = await this.fapiPrivateGetPositionMarginHistory(this.extend(request, params));
12564
+ }
12565
+ else if (market['inverse']) {
12566
+ response = await this.dapiPrivateGetPositionMarginHistory(this.extend(request, params));
12567
+ }
12568
+ else {
12569
+ throw new errors.BadRequest(this.id + 'fetchMarginAdjustmentHistory () is not supported for markets of type ' + market['type']);
12570
+ }
12571
+ //
12572
+ // [
12573
+ // {
12574
+ // symbol: "XRPUSDT",
12575
+ // type: "1",
12576
+ // deltaType: "TRADE",
12577
+ // amount: "2.57148240",
12578
+ // asset: "USDT",
12579
+ // time: "1711046271555",
12580
+ // positionSide: "BOTH",
12581
+ // clientTranId: ""
12582
+ // }
12583
+ // ...
12584
+ // ]
12585
+ //
12586
+ const modifications = this.parseMarginModifications(response);
12587
+ return this.filterBySymbolSinceLimit(modifications, symbol, since, limit);
12588
+ }
12508
12589
  }
12509
12590
 
12510
12591
  module.exports = binance;
@@ -60,6 +60,7 @@ class bingx extends bingx$1 {
60
60
  'fetchFundingRates': true,
61
61
  'fetchLeverage': true,
62
62
  'fetchLiquidations': false,
63
+ 'fetchMarginAdjustmentHistory': false,
63
64
  'fetchMarginMode': true,
64
65
  'fetchMarkets': true,
65
66
  'fetchMarkOHLCV': true,
@@ -69,6 +70,7 @@ class bingx extends bingx$1 {
69
70
  'fetchOpenOrders': true,
70
71
  'fetchOrder': true,
71
72
  'fetchOrderBook': true,
73
+ 'fetchOrders': true,
72
74
  'fetchPositionMode': true,
73
75
  'fetchPositions': true,
74
76
  'fetchTicker': true,
@@ -180,6 +182,7 @@ class bingx extends bingx$1 {
180
182
  'positionSide/dual': 1,
181
183
  'market/markPriceKlines': 1,
182
184
  'trade/batchCancelReplace': 1,
185
+ 'trade/fullOrder': 1,
183
186
  },
184
187
  'post': {
185
188
  'trade/cancelReplace': 1,
@@ -327,6 +330,7 @@ class bingx extends bingx$1 {
327
330
  'post': {
328
331
  'swap/trace/closeTrackOrder': 1,
329
332
  'swap/trace/setTPSL': 1,
333
+ 'spot/trader/sellOrder': 1,
330
334
  },
331
335
  },
332
336
  },
@@ -2757,7 +2761,7 @@ class bingx extends bingx$1 {
2757
2761
  * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2758
2762
  */
2759
2763
  if (symbol === undefined) {
2760
- throw new errors.ArgumentsRequired(this.id + ' fetchOrders() requires a symbol argument');
2764
+ throw new errors.ArgumentsRequired(this.id + ' fetchOrder() requires a symbol argument');
2761
2765
  }
2762
2766
  await this.loadMarkets();
2763
2767
  const market = this.market(symbol);
@@ -2828,6 +2832,101 @@ class bingx extends bingx$1 {
2828
2832
  const first = this.safeDict(data, 'order', data);
2829
2833
  return this.parseOrder(first, market);
2830
2834
  }
2835
+ async fetchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2836
+ /**
2837
+ * @method
2838
+ * @name bingx#fetchOrders
2839
+ * @description fetches information on multiple orders made by the user
2840
+ * @see https://bingx-api.github.io/docs/#/en-us/swapV2/trade-api.html#User's%20All%20Orders
2841
+ * @param {string} symbol unified market symbol of the market orders were made in
2842
+ * @param {int} [since] the earliest time in ms to fetch orders for
2843
+ * @param {int} [limit] the maximum number of order structures to retrieve
2844
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2845
+ * @param {int} [params.until] the latest time in ms to fetch entries for
2846
+ * @param {int} [params.orderId] Only return subsequent orders, and return the latest order by default
2847
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
2848
+ */
2849
+ await this.loadMarkets();
2850
+ const request = {};
2851
+ let market = undefined;
2852
+ if (symbol !== undefined) {
2853
+ market = this.market(symbol);
2854
+ request['symbol'] = market['id'];
2855
+ }
2856
+ let type = undefined;
2857
+ [type, params] = this.handleMarketTypeAndParams('fetchOrders', market, params);
2858
+ if (type !== 'swap') {
2859
+ throw new errors.NotSupported(this.id + ' fetchOrders() is only supported for swap markets');
2860
+ }
2861
+ if (limit !== undefined) {
2862
+ request['limit'] = limit;
2863
+ }
2864
+ if (since !== undefined) {
2865
+ request['startTime'] = since;
2866
+ }
2867
+ const until = this.safeInteger2(params, 'until', 'till'); // unified in milliseconds
2868
+ const endTime = this.safeInteger(params, 'endTime', until); // exchange-specific in milliseconds
2869
+ params = this.omit(params, ['endTime', 'till', 'until']);
2870
+ if (endTime !== undefined) {
2871
+ request['endTime'] = endTime;
2872
+ }
2873
+ const response = await this.swapV1PrivateGetTradeFullOrder(this.extend(request, params));
2874
+ //
2875
+ // {
2876
+ // "code": 0,
2877
+ // "msg": "",
2878
+ // "data": {
2879
+ // "orders": [
2880
+ // {
2881
+ // "symbol": "PYTH-USDT",
2882
+ // "orderId": 1736007506620112100,
2883
+ // "side": "SELL",
2884
+ // "positionSide": "SHORT",
2885
+ // "type": "LIMIT",
2886
+ // "origQty": "33",
2887
+ // "price": "0.3916",
2888
+ // "executedQty": "33",
2889
+ // "avgPrice": "0.3916",
2890
+ // "cumQuote": "13",
2891
+ // "stopPrice": "",
2892
+ // "profit": "0.0000",
2893
+ // "commission": "-0.002585",
2894
+ // "status": "FILLED",
2895
+ // "time": 1702731418000,
2896
+ // "updateTime": 1702731470000,
2897
+ // "clientOrderId": "",
2898
+ // "leverage": "15X",
2899
+ // "takeProfit": {
2900
+ // "type": "TAKE_PROFIT",
2901
+ // "quantity": 0,
2902
+ // "stopPrice": 0,
2903
+ // "price": 0,
2904
+ // "workingType": ""
2905
+ // },
2906
+ // "stopLoss": {
2907
+ // "type": "STOP",
2908
+ // "quantity": 0,
2909
+ // "stopPrice": 0,
2910
+ // "price": 0,
2911
+ // "workingType": ""
2912
+ // },
2913
+ // "advanceAttr": 0,
2914
+ // "positionID": 0,
2915
+ // "takeProfitEntrustPrice": 0,
2916
+ // "stopLossEntrustPrice": 0,
2917
+ // "orderType": "",
2918
+ // "workingType": "MARK_PRICE",
2919
+ // "stopGuaranteed": false,
2920
+ // "triggerOrderId": 1736012449498123500
2921
+ // }
2922
+ // ]
2923
+ // }
2924
+ // }
2925
+ //
2926
+ const data = this.safeDict(response, 'data', {});
2927
+ const orders = this.safeList(data, 'orders', []);
2928
+ return this.parseOrders(orders, market, since, limit);
2929
+ }
2831
2930
  async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2832
2931
  /**
2833
2932
  * @method
@@ -3528,6 +3627,7 @@ class bingx extends bingx$1 {
3528
3627
  'info': data,
3529
3628
  'symbol': this.safeString(market, 'symbol'),
3530
3629
  'type': (type === '1') ? 'add' : 'reduce',
3630
+ 'marginMode': 'isolated',
3531
3631
  'amount': this.safeNumber(data, 'amount'),
3532
3632
  'total': this.safeNumber(data, 'margin'),
3533
3633
  'code': this.safeString(market, 'settle'),
@@ -3519,6 +3519,7 @@ class bitfinex2 extends bitfinex2$1 {
3519
3519
  'info': data,
3520
3520
  'symbol': market['symbol'],
3521
3521
  'type': undefined,
3522
+ 'marginMode': 'isolated',
3522
3523
  'amount': undefined,
3523
3524
  'total': undefined,
3524
3525
  'code': undefined,
@@ -84,6 +84,7 @@ class bitget extends bitget$1 {
84
84
  'fetchLeverage': true,
85
85
  'fetchLeverageTiers': false,
86
86
  'fetchLiquidations': false,
87
+ 'fetchMarginAdjustmentHistory': false,
87
88
  'fetchMarginMode': true,
88
89
  'fetchMarketLeverageTiers': true,
89
90
  'fetchMarkets': true,
@@ -6984,6 +6985,7 @@ class bitget extends bitget$1 {
6984
6985
  'info': data,
6985
6986
  'symbol': market['symbol'],
6986
6987
  'type': undefined,
6988
+ 'marginMode': 'isolated',
6987
6989
  'amount': undefined,
6988
6990
  'total': undefined,
6989
6991
  'code': market['settle'],
@@ -63,6 +63,7 @@ class bitmex extends bitmex$1 {
63
63
  'fetchLeverages': true,
64
64
  'fetchLeverageTiers': false,
65
65
  'fetchLiquidations': true,
66
+ 'fetchMarginAdjustmentHistory': false,
66
67
  'fetchMarketLeverageTiers': false,
67
68
  'fetchMarkets': true,
68
69
  'fetchMarkOHLCV': false,
@@ -3050,6 +3050,7 @@ class bitrue extends bitrue$1 {
3050
3050
  'info': data,
3051
3051
  'symbol': market['symbol'],
3052
3052
  'type': undefined,
3053
+ 'marginMode': 'isolated',
3053
3054
  'amount': undefined,
3054
3055
  'total': undefined,
3055
3056
  'code': undefined,
@@ -81,6 +81,7 @@ class bybit extends bybit$1 {
81
81
  'fetchLedger': true,
82
82
  'fetchLeverage': true,
83
83
  'fetchLeverageTiers': true,
84
+ 'fetchMarginAdjustmentHistory': false,
84
85
  'fetchMarketLeverageTiers': true,
85
86
  'fetchMarkets': true,
86
87
  'fetchMarkOHLCV': true,
@@ -151,6 +152,13 @@ class bybit extends bybit$1 {
151
152
  'public': 'https://api.{hostname}',
152
153
  'private': 'https://api.{hostname}',
153
154
  },
155
+ 'demotrading': {
156
+ 'spot': 'https://api-demo.{hostname}',
157
+ 'futures': 'https://api-demo.{hostname}',
158
+ 'v2': 'https://api-demo.{hostname}',
159
+ 'public': 'https://api-demo.{hostname}',
160
+ 'private': 'https://api-demo.{hostname}',
161
+ },
154
162
  'www': 'https://www.bybit.com',
155
163
  'doc': [
156
164
  'https://bybit-exchange.github.io/docs/inverse/',
@@ -339,6 +347,7 @@ class bybit extends bybit$1 {
339
347
  'v5/user/get-member-type': 5,
340
348
  'v5/user/aff-customer-info': 5,
341
349
  'v5/user/del-submember': 5,
350
+ 'v5/user/submembers': 5,
342
351
  // spot leverage token
343
352
  'v5/spot-lever-token/order-record': 1,
344
353
  // spot margin trade
@@ -499,6 +508,8 @@ class bybit extends bybit$1 {
499
508
  'v5/lending/redeem-cancel': 5,
500
509
  'v5/account/set-collateral-switch': 5,
501
510
  'v5/account/set-collateral-switch-batch': 5,
511
+ // demo trading
512
+ 'v5/account/demo-apply-money': 5,
502
513
  },
503
514
  },
504
515
  },
@@ -965,6 +976,8 @@ class bybit extends bybit$1 {
965
976
  },
966
977
  'precisionMode': number.TICK_SIZE,
967
978
  'options': {
979
+ 'sandboxMode': false,
980
+ 'enableDemoTrading': false,
968
981
  'fetchMarkets': ['spot', 'linear', 'inverse', 'option'],
969
982
  'createOrder': {
970
983
  'method': 'privatePostV5OrderCreate', // 'privatePostV5PositionTradingStop'
@@ -1048,6 +1061,39 @@ class bybit extends bybit$1 {
1048
1061
  },
1049
1062
  });
1050
1063
  }
1064
+ setSandboxMode(enable) {
1065
+ /**
1066
+ * @method
1067
+ * @name bybit#setSandboxMode
1068
+ * @description enables or disables sandbox mode
1069
+ * @param {boolean} [enable] true if demo trading should be enabled, false otherwise
1070
+ */
1071
+ super.setSandboxMode(enable);
1072
+ this.options['sandboxMode'] = enable;
1073
+ }
1074
+ enableDemoTrading(enable) {
1075
+ /**
1076
+ * @method
1077
+ * @name bybit#enableDemoTrading
1078
+ * @description enables or disables demo trading mode
1079
+ * @see https://bybit-exchange.github.io/docs/v5/demo
1080
+ * @param {boolean} [enable] true if demo trading should be enabled, false otherwise
1081
+ */
1082
+ if (this.options['sandboxMode']) {
1083
+ throw new errors.NotSupported(this.id + ' demo trading does not support in sandbox environment');
1084
+ }
1085
+ // enable demo trading in bybit, see: https://bybit-exchange.github.io/docs/v5/demo
1086
+ if (enable) {
1087
+ this.urls['apiBackupDemoTrading'] = this.urls['api'];
1088
+ this.urls['api'] = this.urls['demotrading'];
1089
+ }
1090
+ else if ('apiBackupDemoTrading' in this.urls) {
1091
+ this.urls['api'] = this.urls['apiBackupDemoTrading'];
1092
+ const newUrls = this.omit(this.urls, 'apiBackupDemoTrading');
1093
+ this.urls = newUrls;
1094
+ }
1095
+ this.options['enableDemoTrading'] = enable;
1096
+ }
1051
1097
  nonce() {
1052
1098
  return this.milliseconds() - this.options['timeDifference'];
1053
1099
  }
@@ -1064,12 +1110,24 @@ class bybit extends bybit$1 {
1064
1110
  return data;
1065
1111
  }
1066
1112
  async isUnifiedEnabled(params = {}) {
1113
+ /**
1114
+ * @method
1115
+ * @name bybit#isUnifiedEnabled
1116
+ * @description returns [enableUnifiedMargin, enableUnifiedAccount] so the user can check if unified account is enabled
1117
+ */
1067
1118
  // The API key of user id must own one of permissions will be allowed to call following API endpoints.
1068
1119
  // SUB UID: "Account Transfer"
1069
1120
  // MASTER UID: "Account Transfer", "Subaccount Transfer", "Withdrawal"
1070
1121
  const enableUnifiedMargin = this.safeValue(this.options, 'enableUnifiedMargin');
1071
1122
  const enableUnifiedAccount = this.safeValue(this.options, 'enableUnifiedAccount');
1072
1123
  if (enableUnifiedMargin === undefined || enableUnifiedAccount === undefined) {
1124
+ if (this.options['enableDemoTrading']) {
1125
+ // info endpoint is not available in demo trading
1126
+ // so we're assuming UTA is enabled
1127
+ this.options['enableUnifiedMargin'] = false;
1128
+ this.options['enableUnifiedAccount'] = true;
1129
+ return [this.options['enableUnifiedMargin'], this.options['enableUnifiedAccount']];
1130
+ }
1073
1131
  const response = await this.privateGetV5UserQueryApi(params);
1074
1132
  //
1075
1133
  // {
@@ -1239,6 +1297,9 @@ class bybit extends bybit$1 {
1239
1297
  if (!this.checkRequiredCredentials(false)) {
1240
1298
  return undefined;
1241
1299
  }
1300
+ if (this.options['enableDemoTrading']) {
1301
+ return undefined;
1302
+ }
1242
1303
  const response = await this.privateGetV5AssetCoinQueryInfo(params);
1243
1304
  //
1244
1305
  // {