ccxt 4.4.34 → 4.4.36

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 (78) hide show
  1. package/README.md +6 -5
  2. package/dist/ccxt.browser.min.js +3 -3
  3. package/dist/cjs/ccxt.js +6 -1
  4. package/dist/cjs/src/abstract/defx.js +9 -0
  5. package/dist/cjs/src/bingx.js +339 -144
  6. package/dist/cjs/src/bitfinex2.js +20 -12
  7. package/dist/cjs/src/bitmex.js +104 -2
  8. package/dist/cjs/src/bitopro.js +22 -4
  9. package/dist/cjs/src/bitrue.js +2 -2
  10. package/dist/cjs/src/bitso.js +2 -1
  11. package/dist/cjs/src/btcmarkets.js +3 -3
  12. package/dist/cjs/src/btcturk.js +19 -19
  13. package/dist/cjs/src/bybit.js +20 -0
  14. package/dist/cjs/src/defx.js +2048 -0
  15. package/dist/cjs/src/deribit.js +34 -14
  16. package/dist/cjs/src/gate.js +158 -41
  17. package/dist/cjs/src/hashkey.js +1 -1
  18. package/dist/cjs/src/htx.js +14 -2
  19. package/dist/cjs/src/hyperliquid.js +73 -11
  20. package/dist/cjs/src/idex.js +3 -3
  21. package/dist/cjs/src/kraken.js +110 -102
  22. package/dist/cjs/src/kucoin.js +1 -1
  23. package/dist/cjs/src/okx.js +1 -0
  24. package/dist/cjs/src/onetrading.js +20 -395
  25. package/dist/cjs/src/pro/bitrue.js +13 -11
  26. package/dist/cjs/src/pro/defx.js +864 -0
  27. package/dist/cjs/src/pro/probit.js +58 -66
  28. package/dist/cjs/src/xt.js +5 -5
  29. package/js/ccxt.d.ts +8 -2
  30. package/js/ccxt.js +6 -2
  31. package/js/src/abstract/bingx.d.ts +1 -0
  32. package/js/src/abstract/bitopro.d.ts +1 -0
  33. package/js/src/abstract/bitpanda.d.ts +0 -12
  34. package/js/src/abstract/bitrue.d.ts +3 -3
  35. package/js/src/abstract/bybit.d.ts +15 -0
  36. package/js/src/abstract/defx.d.ts +72 -0
  37. package/js/src/abstract/defx.js +11 -0
  38. package/js/src/abstract/deribit.d.ts +1 -0
  39. package/js/src/abstract/gate.d.ts +14 -0
  40. package/js/src/abstract/gateio.d.ts +14 -0
  41. package/js/src/abstract/okx.d.ts +1 -0
  42. package/js/src/abstract/onetrading.d.ts +0 -12
  43. package/js/src/bingx.d.ts +8 -0
  44. package/js/src/bingx.js +339 -144
  45. package/js/src/bitfinex2.js +21 -13
  46. package/js/src/bitmex.js +104 -2
  47. package/js/src/bitopro.d.ts +11 -0
  48. package/js/src/bitopro.js +22 -4
  49. package/js/src/bitrue.js +2 -2
  50. package/js/src/bitso.js +2 -1
  51. package/js/src/btcmarkets.js +3 -3
  52. package/js/src/btcturk.js +19 -19
  53. package/js/src/bybit.js +20 -0
  54. package/js/src/defx.d.ts +349 -0
  55. package/js/src/defx.js +2049 -0
  56. package/js/src/deribit.d.ts +2 -0
  57. package/js/src/deribit.js +34 -14
  58. package/js/src/gate.d.ts +5 -5
  59. package/js/src/gate.js +158 -41
  60. package/js/src/hashkey.js +1 -1
  61. package/js/src/htx.d.ts +3 -0
  62. package/js/src/htx.js +14 -2
  63. package/js/src/hyperliquid.d.ts +10 -0
  64. package/js/src/hyperliquid.js +75 -13
  65. package/js/src/idex.js +4 -4
  66. package/js/src/kraken.d.ts +11 -8
  67. package/js/src/kraken.js +110 -102
  68. package/js/src/kucoin.js +1 -1
  69. package/js/src/okx.js +1 -0
  70. package/js/src/onetrading.d.ts +15 -67
  71. package/js/src/onetrading.js +20 -395
  72. package/js/src/pro/bitrue.js +13 -11
  73. package/js/src/pro/defx.d.ts +236 -0
  74. package/js/src/pro/defx.js +865 -0
  75. package/js/src/pro/probit.d.ts +2 -1
  76. package/js/src/pro/probit.js +58 -66
  77. package/js/src/xt.js +5 -5
  78. package/package.json +2 -1
@@ -202,9 +202,11 @@ class hyperliquid extends hyperliquid$1 {
202
202
  'User or API Wallet ': errors.InvalidOrder,
203
203
  'Order has invalid size': errors.InvalidOrder,
204
204
  'Order price cannot be more than 80% away from the reference price': errors.InvalidOrder,
205
+ 'Order has zero size.': errors.InvalidOrder,
206
+ 'Insufficient spot balance asset': errors.InsufficientFunds,
205
207
  },
206
208
  },
207
- 'precisionMode': number.DECIMAL_PLACES,
209
+ 'precisionMode': number.TICK_SIZE,
208
210
  'commonCurrencies': {},
209
211
  'options': {
210
212
  'defaultType': 'swap',
@@ -351,6 +353,55 @@ class hyperliquid extends hyperliquid$1 {
351
353
  }
352
354
  return this.parseMarkets(result);
353
355
  }
356
+ /**
357
+ * @method
358
+ * @name calculatePricePrecision
359
+ * @description Helper function to calculate the Hyperliquid DECIMAL_PLACES price precision
360
+ * @param {float} price the price to use in the calculation
361
+ * @param {int} amountPrecision the amountPrecision to use in the calculation
362
+ * @param {int} maxDecimals the maxDecimals to use in the calculation
363
+ * @returns {int} The calculated price precision
364
+ */
365
+ calculatePricePrecision(price, amountPrecision, maxDecimals) {
366
+ let pricePrecision = 0;
367
+ const priceStr = this.numberToString(price);
368
+ if (priceStr === undefined) {
369
+ return 0;
370
+ }
371
+ const priceSplitted = priceStr.split('.');
372
+ if (Precise["default"].stringEq(priceStr, '0')) {
373
+ // Significant digits is always 5 in this case
374
+ const significantDigits = 5;
375
+ // Integer digits is always 0 in this case (0 doesn't count)
376
+ const integerDigits = 0;
377
+ // Calculate the price precision
378
+ pricePrecision = Math.min(maxDecimals - amountPrecision, significantDigits - integerDigits);
379
+ }
380
+ else if (Precise["default"].stringGt(priceStr, '0') && Precise["default"].stringLt(priceStr, '1')) {
381
+ // Significant digits, always 5 in this case
382
+ const significantDigits = 5;
383
+ // Get the part after the decimal separator
384
+ const decimalPart = this.safeString(priceSplitted, 1, '');
385
+ // Count the number of leading zeros in the decimal part
386
+ let leadingZeros = 0;
387
+ while ((leadingZeros <= decimalPart.length) && (decimalPart[leadingZeros] === '0')) {
388
+ leadingZeros = leadingZeros + 1;
389
+ }
390
+ // Calculate price precision based on leading zeros and significant digits
391
+ pricePrecision = leadingZeros + significantDigits;
392
+ // Calculate the price precision based on maxDecimals - szDecimals and the calculated price precision from the previous step
393
+ pricePrecision = Math.min(maxDecimals - amountPrecision, pricePrecision);
394
+ }
395
+ else {
396
+ // Count the numbers before the decimal separator
397
+ const integerPart = this.safeString(priceSplitted, 0, '');
398
+ // Get significant digits, take the max() of 5 and the integer digits count
399
+ const significantDigits = Math.max(5, integerPart.length);
400
+ // Calculate price precision based on maxDecimals - szDecimals and significantDigits - integerPart.length
401
+ pricePrecision = Math.min(maxDecimals - amountPrecision, significantDigits - integerPart.length);
402
+ }
403
+ return this.parseToInt(pricePrecision);
404
+ }
354
405
  /**
355
406
  * @method
356
407
  * @name hyperliquid#fetchMarkets
@@ -440,7 +491,11 @@ class hyperliquid extends hyperliquid$1 {
440
491
  const symbol = base + '/' + quote;
441
492
  const innerBaseTokenInfo = this.safeDict(baseTokenInfo, 'spec', baseTokenInfo);
442
493
  // const innerQuoteTokenInfo = this.safeDict (quoteTokenInfo, 'spec', quoteTokenInfo);
443
- const amountPrecision = this.safeInteger(innerBaseTokenInfo, 'szDecimals');
494
+ const amountPrecisionStr = this.safeString(innerBaseTokenInfo, 'szDecimals');
495
+ const amountPrecision = parseInt(amountPrecisionStr);
496
+ const price = this.safeNumber(extraData, 'midPx');
497
+ const pricePrecision = this.calculatePricePrecision(price, amountPrecision, 8);
498
+ const pricePrecisionStr = this.numberToString(pricePrecision);
444
499
  // const quotePrecision = this.parseNumber (this.parsePrecision (this.safeString (innerQuoteTokenInfo, 'szDecimals')));
445
500
  const baseId = this.numberToString(i + 10000);
446
501
  markets.push(this.safeMarketStructure({
@@ -471,8 +526,8 @@ class hyperliquid extends hyperliquid$1 {
471
526
  'strike': undefined,
472
527
  'optionType': undefined,
473
528
  'precision': {
474
- 'amount': amountPrecision,
475
- 'price': 8 - amountPrecision, // MAX_DECIMALS is 8
529
+ 'amount': this.parseNumber(this.parsePrecision(amountPrecisionStr)),
530
+ 'price': this.parseNumber(this.parsePrecision(pricePrecisionStr)),
476
531
  },
477
532
  'limits': {
478
533
  'leverage': {
@@ -536,7 +591,11 @@ class hyperliquid extends hyperliquid$1 {
536
591
  const fees = this.safeDict(this.fees, 'swap', {});
537
592
  const taker = this.safeNumber(fees, 'taker');
538
593
  const maker = this.safeNumber(fees, 'maker');
539
- const amountPrecision = this.safeInteger(market, 'szDecimals');
594
+ const amountPrecisionStr = this.safeString(market, 'szDecimals');
595
+ const amountPrecision = parseInt(amountPrecisionStr);
596
+ const price = this.safeNumber(market, 'markPx', 0);
597
+ const pricePrecision = this.calculatePricePrecision(price, amountPrecision, 6);
598
+ const pricePrecisionStr = this.numberToString(pricePrecision);
540
599
  return this.safeMarketStructure({
541
600
  'id': baseId,
542
601
  'symbol': symbol,
@@ -564,8 +623,8 @@ class hyperliquid extends hyperliquid$1 {
564
623
  'strike': undefined,
565
624
  'optionType': undefined,
566
625
  'precision': {
567
- 'amount': amountPrecision,
568
- 'price': 6 - amountPrecision, // MAX_DECIMALS is 6
626
+ 'amount': this.parseNumber(this.parsePrecision(amountPrecisionStr)),
627
+ 'price': this.parseNumber(this.parsePrecision(pricePrecisionStr)),
569
628
  },
570
629
  'limits': {
571
630
  'leverage': {
@@ -1042,10 +1101,13 @@ class hyperliquid extends hyperliquid$1 {
1042
1101
  }
1043
1102
  priceToPrecision(symbol, price) {
1044
1103
  const market = this.market(symbol);
1045
- // https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/tick-and-lot-size
1046
- const result = this.decimalToPrecision(price, number.ROUND, 5, number.SIGNIFICANT_DIGITS, this.paddingMode);
1047
- const decimalParsedResult = this.decimalToPrecision(result, number.ROUND, market['precision']['price'], this.precisionMode, this.paddingMode);
1048
- return decimalParsedResult;
1104
+ const priceStr = this.numberToString(price);
1105
+ const integerPart = priceStr.split('.')[0];
1106
+ const significantDigits = Math.max(5, integerPart.length);
1107
+ const result = this.decimalToPrecision(price, number.ROUND, significantDigits, number.SIGNIFICANT_DIGITS, this.paddingMode);
1108
+ const maxDecimals = market['spot'] ? 8 : 6;
1109
+ const subtractedValue = maxDecimals - this.precisionFromString(this.safeString(market['precision'], 'amount'));
1110
+ return this.decimalToPrecision(result, number.ROUND, subtractedValue, number.DECIMAL_PLACES, this.paddingMode);
1049
1111
  }
1050
1112
  hashMessage(message) {
1051
1113
  return '0x' + this.hash(message, sha3.keccak_256, 'hex');
@@ -195,10 +195,8 @@ class idex extends idex$1 {
195
195
  // {"code":"INVALID_PARAMETER","message":"invalid value provided for request parameter \"price\": all quantities and prices must be below 100 billion, above 0, need to be provided as strings, and always require 4 decimals ending with 4 zeroes"}
196
196
  //
197
197
  const market = this.market(symbol);
198
- const info = this.safeValue(market, 'info', {});
199
- const quoteAssetPrecision = this.safeInteger(info, 'quoteAssetPrecision');
200
198
  price = this.decimalToPrecision(price, number.ROUND, market['precision']['price'], this.precisionMode);
201
- return this.decimalToPrecision(price, number.TRUNCATE, quoteAssetPrecision, number.DECIMAL_PLACES, number.PAD_WITH_ZERO);
199
+ return this.decimalToPrecision(price, number.TRUNCATE, market['precision']['quote'], number.TICK_SIZE, number.PAD_WITH_ZERO);
202
200
  }
203
201
  /**
204
202
  * @method
@@ -306,6 +304,8 @@ class idex extends idex$1 {
306
304
  'precision': {
307
305
  'amount': basePrecision,
308
306
  'price': this.safeNumber(entry, 'tickSize'),
307
+ 'base': basePrecision,
308
+ 'quote': quotePrecision,
309
309
  },
310
310
  'limits': {
311
311
  'leverage': {
@@ -429,31 +429,43 @@ class kraken extends kraken$1 {
429
429
  },
430
430
  'precisionMode': number.TICK_SIZE,
431
431
  'exceptions': {
432
- 'EQuery:Invalid asset pair': errors.BadSymbol,
433
- 'EAPI:Invalid key': errors.AuthenticationError,
434
- 'EFunding:Unknown withdraw key': errors.InvalidAddress,
435
- 'EFunding:Invalid amount': errors.InsufficientFunds,
436
- 'EService:Unavailable': errors.ExchangeNotAvailable,
437
- 'EDatabase:Internal error': errors.ExchangeNotAvailable,
438
- 'EService:Busy': errors.ExchangeNotAvailable,
439
- 'EQuery:Unknown asset': errors.BadSymbol,
440
- 'EAPI:Rate limit exceeded': errors.DDoSProtection,
441
- 'EOrder:Rate limit exceeded': errors.DDoSProtection,
442
- 'EGeneral:Internal error': errors.ExchangeNotAvailable,
443
- 'EGeneral:Temporary lockout': errors.DDoSProtection,
444
- 'EGeneral:Permission denied': errors.PermissionDenied,
445
- 'EGeneral:Invalid arguments:price': errors.InvalidOrder,
446
- 'EOrder:Unknown order': errors.InvalidOrder,
447
- 'EOrder:Invalid price:Invalid price argument': errors.InvalidOrder,
448
- 'EOrder:Order minimum not met': errors.InvalidOrder,
449
- 'EGeneral:Invalid arguments': errors.BadRequest,
450
- 'ESession:Invalid session': errors.AuthenticationError,
451
- 'EAPI:Invalid nonce': errors.InvalidNonce,
452
- 'EFunding:No funding method': errors.BadRequest,
453
- 'EFunding:Unknown asset': errors.BadSymbol,
454
- 'EService:Market in post_only mode': errors.OnMaintenance,
455
- 'EGeneral:Too many requests': errors.DDoSProtection,
456
- 'ETrade:User Locked': errors.AccountSuspended, // {"error":["ETrade:User Locked"]}
432
+ 'exact': {
433
+ 'EQuery:Invalid asset pair': errors.BadSymbol,
434
+ 'EAPI:Invalid key': errors.AuthenticationError,
435
+ 'EFunding:Unknown withdraw key': errors.InvalidAddress,
436
+ 'EFunding:Invalid amount': errors.InsufficientFunds,
437
+ 'EService:Unavailable': errors.ExchangeNotAvailable,
438
+ 'EDatabase:Internal error': errors.ExchangeNotAvailable,
439
+ 'EService:Busy': errors.ExchangeNotAvailable,
440
+ 'EQuery:Unknown asset': errors.BadSymbol,
441
+ 'EAPI:Rate limit exceeded': errors.DDoSProtection,
442
+ 'EOrder:Rate limit exceeded': errors.DDoSProtection,
443
+ 'EGeneral:Internal error': errors.ExchangeNotAvailable,
444
+ 'EGeneral:Temporary lockout': errors.DDoSProtection,
445
+ 'EGeneral:Permission denied': errors.PermissionDenied,
446
+ 'EGeneral:Invalid arguments:price': errors.InvalidOrder,
447
+ 'EOrder:Unknown order': errors.InvalidOrder,
448
+ 'EOrder:Invalid price:Invalid price argument': errors.InvalidOrder,
449
+ 'EOrder:Order minimum not met': errors.InvalidOrder,
450
+ 'EOrder:Insufficient funds': errors.InsufficientFunds,
451
+ 'EGeneral:Invalid arguments': errors.BadRequest,
452
+ 'ESession:Invalid session': errors.AuthenticationError,
453
+ 'EAPI:Invalid nonce': errors.InvalidNonce,
454
+ 'EFunding:No funding method': errors.BadRequest,
455
+ 'EFunding:Unknown asset': errors.BadSymbol,
456
+ 'EService:Market in post_only mode': errors.OnMaintenance,
457
+ 'EGeneral:Too many requests': errors.DDoSProtection,
458
+ 'ETrade:User Locked': errors.AccountSuspended, // {"error":["ETrade:User Locked"]}
459
+ },
460
+ 'broad': {
461
+ ':Invalid order': errors.InvalidOrder,
462
+ ':Invalid arguments:volume': errors.InvalidOrder,
463
+ ':Invalid arguments:viqc': errors.InvalidOrder,
464
+ ':Invalid nonce': errors.InvalidNonce,
465
+ ':IInsufficient funds': errors.InsufficientFunds,
466
+ ':Cancel pending': errors.CancelPending,
467
+ ':Rate limit exceeded': errors.RateLimitExceeded,
468
+ },
457
469
  },
458
470
  });
459
471
  }
@@ -1584,18 +1596,9 @@ class kraken extends kraken$1 {
1584
1596
  // editOrder
1585
1597
  //
1586
1598
  // {
1587
- // "status": "ok",
1588
- // "txid": "OAW2BO-7RWEK-PZY5UO",
1589
- // "originaltxid": "OXL6SS-UPNMC-26WBE7",
1590
- // "newuserref": 1234,
1591
- // "olduserref": 123,
1592
- // "volume": "0.00075000",
1593
- // "price": "13500.0",
1594
- // "orders_cancelled": 1,
1595
- // "descr": {
1596
- // "order": "buy 0.00075000 XBTUSDT @ limit 13500.0"
1597
- // }
1599
+ // "amend_id": "TJSMEH-AA67V-YUSQ6O"
1598
1600
  // }
1601
+ //
1599
1602
  // ws - createOrder
1600
1603
  // {
1601
1604
  // "descr": 'sell 0.00010000 XBTUSDT @ market',
@@ -1715,7 +1718,7 @@ class kraken extends kraken$1 {
1715
1718
  price = this.safeString(order, 'price', price);
1716
1719
  }
1717
1720
  const flags = this.safeString(order, 'oflags', '');
1718
- const isPostOnly = flags.indexOf('post') > -1;
1721
+ let isPostOnly = flags.indexOf('post') > -1;
1719
1722
  const average = this.safeNumber(order, 'price');
1720
1723
  if (market !== undefined) {
1721
1724
  symbol = market['symbol'];
@@ -1734,12 +1737,12 @@ class kraken extends kraken$1 {
1734
1737
  }
1735
1738
  }
1736
1739
  const status = this.parseOrderStatus(this.safeString(order, 'status'));
1737
- let id = this.safeString2(order, 'id', 'txid');
1740
+ let id = this.safeStringN(order, ['id', 'txid', 'amend_id']);
1738
1741
  if ((id === undefined) || (id.startsWith('['))) {
1739
1742
  const txid = this.safeList(order, 'txid');
1740
1743
  id = this.safeString(txid, 0);
1741
1744
  }
1742
- const clientOrderId = this.safeString2(order, 'userref', 'newuserref');
1745
+ const clientOrderId = this.safeString(order, 'userref');
1743
1746
  const rawTrades = this.safeValue(order, 'trades', []);
1744
1747
  const trades = [];
1745
1748
  for (let i = 0; i < rawTrades.length; i++) {
@@ -1757,19 +1760,21 @@ class kraken extends kraken$1 {
1757
1760
  let takeProfitPrice = undefined;
1758
1761
  // the dashed strings are not provided from fields (eg. fetch order)
1759
1762
  // while spaced strings from "order" sentence (when other fields not available)
1760
- if (rawType.startsWith('take-profit')) {
1761
- takeProfitPrice = this.safeString(description, 'price');
1762
- price = this.omitZero(this.safeString(description, 'price2'));
1763
- }
1764
- else if (rawType.startsWith('stop-loss')) {
1765
- stopLossPrice = this.safeString(description, 'price');
1766
- price = this.omitZero(this.safeString(description, 'price2'));
1767
- }
1768
- else if (rawType === 'take profit') {
1769
- takeProfitPrice = triggerPrice;
1770
- }
1771
- else if (rawType === 'stop loss') {
1772
- stopLossPrice = triggerPrice;
1763
+ if (rawType !== undefined) {
1764
+ if (rawType.startsWith('take-profit')) {
1765
+ takeProfitPrice = this.safeString(description, 'price');
1766
+ price = this.omitZero(this.safeString(description, 'price2'));
1767
+ }
1768
+ else if (rawType.startsWith('stop-loss')) {
1769
+ stopLossPrice = this.safeString(description, 'price');
1770
+ price = this.omitZero(this.safeString(description, 'price2'));
1771
+ }
1772
+ else if (rawType === 'take profit') {
1773
+ takeProfitPrice = triggerPrice;
1774
+ }
1775
+ else if (rawType === 'stop loss') {
1776
+ stopLossPrice = triggerPrice;
1777
+ }
1773
1778
  }
1774
1779
  let finalType = this.parseOrderType(rawType);
1775
1780
  // unlike from endpoints which provide eg: "take-profit-limit"
@@ -1778,6 +1783,10 @@ class kraken extends kraken$1 {
1778
1783
  if (this.inArray(finalType, ['stop loss', 'take profit'])) {
1779
1784
  finalType = (price === undefined) ? 'market' : 'limit';
1780
1785
  }
1786
+ const amendId = this.safeString(order, 'amend_id');
1787
+ if (amendId !== undefined) {
1788
+ isPostOnly = undefined;
1789
+ }
1781
1790
  return this.safeOrder({
1782
1791
  'id': id,
1783
1792
  'clientOrderId': clientOrderId,
@@ -1807,10 +1816,10 @@ class kraken extends kraken$1 {
1807
1816
  }, market);
1808
1817
  }
1809
1818
  orderRequest(method, symbol, type, request, amount, price = undefined, params = {}) {
1810
- const clientOrderId = this.safeString2(params, 'userref', 'clientOrderId');
1811
- params = this.omit(params, ['userref', 'clientOrderId']);
1819
+ const clientOrderId = this.safeString(params, 'clientOrderId');
1820
+ params = this.omit(params, ['clientOrderId']);
1812
1821
  if (clientOrderId !== undefined) {
1813
- request['userref'] = clientOrderId;
1822
+ request['cl_ord_id'] = clientOrderId;
1814
1823
  }
1815
1824
  const stopLossTriggerPrice = this.safeString(params, 'stopLossPrice');
1816
1825
  const takeProfitTriggerPrice = this.safeString(params, 'takeProfitPrice');
@@ -1940,20 +1949,23 @@ class kraken extends kraken$1 {
1940
1949
  * @method
1941
1950
  * @name kraken#editOrder
1942
1951
  * @description edit a trade order
1943
- * @see https://docs.kraken.com/rest/#tag/Spot-Trading/operation/editOrder
1952
+ * @see https://docs.kraken.com/api/docs/rest-api/amend-order
1944
1953
  * @param {string} id order id
1945
1954
  * @param {string} symbol unified symbol of the market to create an order in
1946
1955
  * @param {string} type 'market' or 'limit'
1947
1956
  * @param {string} side 'buy' or 'sell'
1948
- * @param {float} amount how much of the currency you want to trade in units of the base currency
1957
+ * @param {float} [amount] how much of the currency you want to trade in units of the base currency
1949
1958
  * @param {float} [price] the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1950
1959
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1951
- * @param {float} [params.stopLossPrice] *margin only* the price that a stop loss order is triggered at
1952
- * @param {float} [params.takeProfitPrice] *margin only* the price that a take profit order is triggered at
1953
- * @param {string} [params.trailingAmount] *margin only* the quote price away from the current market price
1954
- * @param {string} [params.trailingLimitAmount] *margin only* the quote amount away from the trailingAmount
1955
- * @param {string} [params.offset] *margin only* '+' or '-' whether you want the trailingLimitAmount value to be positive or negative, default is negative '-'
1956
- * @param {string} [params.trigger] *margin only* the activation price type, 'last' or 'index', default is 'last'
1960
+ * @param {float} [params.stopLossPrice] the price that a stop loss order is triggered at
1961
+ * @param {float} [params.takeProfitPrice] the price that a take profit order is triggered at
1962
+ * @param {string} [params.trailingAmount] the quote amount to trail away from the current market price
1963
+ * @param {string} [params.trailingPercent] the percent to trail away from the current market price
1964
+ * @param {string} [params.trailingLimitAmount] the quote amount away from the trailingAmount
1965
+ * @param {string} [params.trailingLimitPercent] the percent away from the trailingAmount
1966
+ * @param {string} [params.offset] '+' or '-' whether you want the trailingLimitAmount value to be positive or negative
1967
+ * @param {boolean} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately
1968
+ * @param {string} [params.clientOrderId] the orders client order id
1957
1969
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1958
1970
  */
1959
1971
  async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
@@ -1962,33 +1974,50 @@ class kraken extends kraken$1 {
1962
1974
  if (!market['spot']) {
1963
1975
  throw new errors.NotSupported(this.id + ' editOrder() does not support ' + market['type'] + ' orders, only spot orders are accepted');
1964
1976
  }
1965
- const request = {
1977
+ let request = {
1966
1978
  'txid': id,
1967
- 'pair': market['id'],
1968
1979
  };
1980
+ const clientOrderId = this.safeString(params, 'clientOrderId');
1981
+ if (clientOrderId !== undefined) {
1982
+ request['cl_ord_id'] = clientOrderId;
1983
+ params = this.omit(params, 'clientOrderId');
1984
+ request = this.omit(request, 'txid');
1985
+ }
1986
+ const isMarket = (type === 'market');
1987
+ let postOnly = undefined;
1988
+ [postOnly, params] = this.handlePostOnly(isMarket, false, params);
1989
+ if (postOnly) {
1990
+ request['post_only'] = 'true'; // not using boolean in this case, because the urlencodedNested transforms it into 'True' string
1991
+ }
1969
1992
  if (amount !== undefined) {
1970
- request['volume'] = this.amountToPrecision(symbol, amount);
1993
+ request['order_qty'] = this.amountToPrecision(symbol, amount);
1994
+ }
1995
+ if (price !== undefined) {
1996
+ request['limit_price'] = this.priceToPrecision(symbol, price);
1997
+ }
1998
+ let allTriggerPrices = this.safeStringN(params, ['stopLossPrice', 'takeProfitPrice', 'trailingAmount', 'trailingPercent', 'trailingLimitAmount', 'trailingLimitPercent']);
1999
+ if (allTriggerPrices !== undefined) {
2000
+ const offset = this.safeString(params, 'offset');
2001
+ params = this.omit(params, ['stopLossPrice', 'takeProfitPrice', 'trailingAmount', 'trailingPercent', 'trailingLimitAmount', 'trailingLimitPercent', 'offset']);
2002
+ if (offset !== undefined) {
2003
+ allTriggerPrices = offset + allTriggerPrices;
2004
+ request['trigger_price'] = allTriggerPrices;
2005
+ }
2006
+ else {
2007
+ request['trigger_price'] = this.priceToPrecision(symbol, allTriggerPrices);
2008
+ }
1971
2009
  }
1972
- const orderRequest = this.orderRequest('editOrder', symbol, type, request, amount, price, params);
1973
- const response = await this.privatePostEditOrder(this.extend(orderRequest[0], orderRequest[1]));
2010
+ const response = await this.privatePostAmendOrder(this.extend(request, params));
1974
2011
  //
1975
2012
  // {
1976
2013
  // "error": [],
1977
2014
  // "result": {
1978
- // "status": "ok",
1979
- // "txid": "OAW2BO-7RWEK-PZY5UO",
1980
- // "originaltxid": "OXL6SS-UPNMC-26WBE7",
1981
- // "volume": "0.00075000",
1982
- // "price": "13500.0",
1983
- // "orders_cancelled": 1,
1984
- // "descr": {
1985
- // "order": "buy 0.00075000 XBTUSDT @ limit 13500.0"
1986
- // }
2015
+ // "amend_id": "TJSMEH-AA67V-YUSQ6O"
1987
2016
  // }
1988
2017
  // }
1989
2018
  //
1990
- const data = this.safeDict(response, 'result', {});
1991
- return this.parseOrder(data, market);
2019
+ const result = this.safeDict(response, 'result', {});
2020
+ return this.parseOrder(result, market);
1992
2021
  }
1993
2022
  /**
1994
2023
  * @method
@@ -3204,28 +3233,6 @@ class kraken extends kraken$1 {
3204
3233
  if (code === 520) {
3205
3234
  throw new errors.ExchangeNotAvailable(this.id + ' ' + code.toString() + ' ' + reason);
3206
3235
  }
3207
- // todo: rewrite this for "broad" exceptions matching
3208
- if (body.indexOf('Invalid order') >= 0) {
3209
- throw new errors.InvalidOrder(this.id + ' ' + body);
3210
- }
3211
- if (body.indexOf('Invalid nonce') >= 0) {
3212
- throw new errors.InvalidNonce(this.id + ' ' + body);
3213
- }
3214
- if (body.indexOf('Insufficient funds') >= 0) {
3215
- throw new errors.InsufficientFunds(this.id + ' ' + body);
3216
- }
3217
- if (body.indexOf('Cancel pending') >= 0) {
3218
- throw new errors.CancelPending(this.id + ' ' + body);
3219
- }
3220
- if (body.indexOf('Invalid arguments:volume') >= 0) {
3221
- throw new errors.InvalidOrder(this.id + ' ' + body);
3222
- }
3223
- if (body.indexOf('Invalid arguments:viqc') >= 0) {
3224
- throw new errors.InvalidOrder(this.id + ' ' + body);
3225
- }
3226
- if (body.indexOf('Rate limit exceeded') >= 0) {
3227
- throw new errors.RateLimitExceeded(this.id + ' ' + body);
3228
- }
3229
3236
  if (response === undefined) {
3230
3237
  return undefined;
3231
3238
  }
@@ -3237,7 +3244,8 @@ class kraken extends kraken$1 {
3237
3244
  const message = this.id + ' ' + body;
3238
3245
  for (let i = 0; i < response['error'].length; i++) {
3239
3246
  const error = response['error'][i];
3240
- this.throwExactlyMatchedException(this.exceptions, error, message);
3247
+ this.throwExactlyMatchedException(this.exceptions['exact'], error, message);
3248
+ this.throwExactlyMatchedException(this.exceptions['broad'], error, message);
3241
3249
  }
3242
3250
  throw new errors.ExchangeError(message);
3243
3251
  }
@@ -1183,7 +1183,7 @@ class kucoin extends kucoin$1 {
1183
1183
  'type': 'spot',
1184
1184
  'spot': true,
1185
1185
  'margin': isMarginable,
1186
- 'marginMode': {
1186
+ 'marginModes': {
1187
1187
  'cross': hasCrossMargin,
1188
1188
  'isolated': hasIsolatedMargin,
1189
1189
  },
@@ -325,6 +325,7 @@ class okx extends okx$1 {
325
325
  'asset/convert/history': 5 / 3,
326
326
  'asset/monthly-statement': 2,
327
327
  // account
328
+ 'account/instruments': 1,
328
329
  'account/balance': 2,
329
330
  'account/positions': 2,
330
331
  'account/positions-history': 100,