ccxt 4.5.30 → 4.5.32

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 (73) hide show
  1. package/README.md +4 -4
  2. package/dist/ccxt.browser.min.js +18 -18
  3. package/dist/cjs/ccxt.js +6 -4
  4. package/dist/cjs/src/aster.js +3802 -0
  5. package/dist/cjs/src/backpack.js +1 -1
  6. package/dist/cjs/src/base/Exchange.js +35 -2
  7. package/dist/cjs/src/base/ws/WsClient.js +1 -0
  8. package/dist/cjs/src/bigone.js +1 -1
  9. package/dist/cjs/src/binance.js +1 -0
  10. package/dist/cjs/src/bingx.js +73 -0
  11. package/dist/cjs/src/cryptomus.js +1 -1
  12. package/dist/cjs/src/gate.js +52 -6
  13. package/dist/cjs/src/hyperliquid.js +9 -1
  14. package/dist/cjs/src/kucoin.js +63 -64
  15. package/dist/cjs/src/okx.js +14 -5
  16. package/dist/cjs/src/pro/apex.js +2 -2
  17. package/dist/cjs/src/pro/ascendex.js +1 -1
  18. package/dist/cjs/src/pro/aster.js +1046 -0
  19. package/dist/cjs/src/pro/bingx.js +1 -1
  20. package/dist/cjs/src/pro/bybit.js +1 -1
  21. package/dist/cjs/src/pro/cryptocom.js +1 -1
  22. package/dist/cjs/src/pro/dydx.js +1 -1
  23. package/dist/cjs/src/pro/htx.js +1 -1
  24. package/dist/cjs/src/pro/hyperliquid.js +1 -1
  25. package/dist/cjs/src/pro/p2b.js +1 -1
  26. package/dist/cjs/src/pro/toobit.js +1 -1
  27. package/js/ccxt.d.ts +8 -5
  28. package/js/ccxt.js +6 -4
  29. package/js/src/abstract/aster.d.ts +88 -0
  30. package/js/src/abstract/binance.d.ts +1 -0
  31. package/js/src/abstract/binancecoinm.d.ts +1 -0
  32. package/js/src/abstract/binanceus.d.ts +1 -0
  33. package/js/src/abstract/binanceusdm.d.ts +1 -0
  34. package/js/src/abstract/kucoin.d.ts +2 -0
  35. package/js/src/abstract/kucoinfutures.d.ts +2 -0
  36. package/js/src/aster.d.ts +563 -0
  37. package/js/src/aster.js +3801 -0
  38. package/js/src/backpack.js +1 -1
  39. package/js/src/base/Exchange.d.ts +4 -0
  40. package/js/src/base/Exchange.js +35 -1
  41. package/js/src/base/ws/WsClient.js +1 -0
  42. package/js/src/bigone.js +1 -1
  43. package/js/src/binance.d.ts +1 -1
  44. package/js/src/binance.js +1 -0
  45. package/js/src/bingx.d.ts +12 -1
  46. package/js/src/bingx.js +73 -0
  47. package/js/src/cryptomus.js +1 -1
  48. package/js/src/exmo.d.ts +1 -1
  49. package/js/src/gate.js +52 -6
  50. package/js/src/hyperliquid.d.ts +1 -0
  51. package/js/src/hyperliquid.js +9 -1
  52. package/js/src/kucoin.d.ts +5 -3
  53. package/js/src/kucoin.js +63 -64
  54. package/js/src/okx.js +14 -5
  55. package/js/src/pro/apex.js +2 -2
  56. package/js/src/pro/ascendex.js +1 -1
  57. package/js/src/pro/aster.d.ts +273 -0
  58. package/js/src/pro/aster.js +1045 -0
  59. package/js/src/pro/bingx.js +1 -1
  60. package/js/src/pro/bybit.js +1 -1
  61. package/js/src/pro/cryptocom.js +1 -1
  62. package/js/src/pro/dydx.js +1 -1
  63. package/js/src/pro/htx.js +1 -1
  64. package/js/src/pro/hyperliquid.js +1 -1
  65. package/js/src/pro/p2b.js +1 -1
  66. package/js/src/pro/toobit.js +1 -1
  67. package/package.json +1 -1
  68. package/dist/cjs/src/oceanex.js +0 -1125
  69. package/js/src/abstract/oceanex.d.ts +0 -30
  70. package/js/src/oceanex.d.ts +0 -231
  71. package/js/src/oceanex.js +0 -1124
  72. /package/dist/cjs/src/abstract/{oceanex.js → aster.js} +0 -0
  73. /package/js/src/abstract/{oceanex.js → aster.js} +0 -0
@@ -521,7 +521,7 @@ class backpack extends backpack$1["default"] {
521
521
  // "depositEnabled": true,
522
522
  // "displayName": "Jito",
523
523
  // "maximumWithdrawal": null,
524
- // "minimumDeposit": "0.29",
524
+ // "minimumDeposit": "0.28",
525
525
  // "minimumWithdrawal": "0.58",
526
526
  // "withdrawEnabled": true,
527
527
  // "withdrawalFee": "0.29"
@@ -17,10 +17,11 @@ require('../static_dependencies/ethers/utils/events.js');
17
17
  require('../static_dependencies/ethers/utils/fixednumber.js');
18
18
  require('../static_dependencies/ethers/utils/maths.js');
19
19
  require('../static_dependencies/ethers/utils/utf8.js');
20
- require('../static_dependencies/noble-hashes/sha3.js');
20
+ var sha3 = require('../static_dependencies/noble-hashes/sha3.js');
21
21
  var sha256 = 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 secp256k1 = require('../static_dependencies/noble-curves/secp256k1.js');
24
25
  var rng = require('../static_dependencies/jsencrypt/lib/jsbn/rng.js');
25
26
  var index$1 = require('../static_dependencies/scure-starknet/index.js');
26
27
  var zklinkSdkWeb = require('../static_dependencies/zklink/zklink-sdk-web.js');
@@ -615,12 +616,16 @@ class Exchange {
615
616
  return undefined;
616
617
  }
617
618
  isBinaryMessage(msg) {
618
- return msg instanceof Uint8Array;
619
+ return msg instanceof Uint8Array || msg instanceof ArrayBuffer;
619
620
  }
620
621
  decodeProtoMsg(data) {
621
622
  if (!protobufMexc) {
622
623
  throw new errors.NotSupported(this.id + ' requires protobuf to decode messages, please install it with `npm install protobufjs`');
623
624
  }
625
+ if (data instanceof ArrayBuffer) {
626
+ // browser case
627
+ data = new Uint8Array(data);
628
+ }
624
629
  if (data instanceof Uint8Array) {
625
630
  const decoded = protobufMexc.default.PushDataV3ApiWrapper.decode(data);
626
631
  const dict = decoded.toJSON();
@@ -1291,6 +1296,11 @@ class Exchange {
1291
1296
  setProperty(obj, property, defaultValue = undefined) {
1292
1297
  obj[property] = defaultValue;
1293
1298
  }
1299
+ exceptionMessage(exc, includeStack = true) {
1300
+ const message = '[' + exc.constructor.name + '] ' + (!includeStack ? exc.message : exc.stack);
1301
+ const length = Math.min(100000, message.length);
1302
+ return message.slice(0, length);
1303
+ }
1294
1304
  axolotl(payload, hexKey, ed25519) {
1295
1305
  return crypto.axolotl(payload, hexKey, ed25519);
1296
1306
  }
@@ -1311,6 +1321,23 @@ class Exchange {
1311
1321
  ethEncodeStructuredData(domain, messageTypes, messageData) {
1312
1322
  return this.base16ToBinary(typedData.TypedDataEncoder.encode(domain, messageTypes, messageData).slice(-132));
1313
1323
  }
1324
+ ethGetAddressFromPrivateKey(privateKey) {
1325
+ // Accepts a "0x"-prefixed hexstring private key and returns the corresponding Ethereum address
1326
+ // Removes the "0x" prefix if present
1327
+ const cleanPrivateKey = this.remove0xPrefix(privateKey);
1328
+ // Get the public key from the private key using secp256k1 curve
1329
+ const publicKeyBytes = secp256k1.secp256k1.getPublicKey(cleanPrivateKey);
1330
+ // For Ethereum, we need to use the uncompressed public key (without the first byte which indicates compression)
1331
+ // secp256k1.getPublicKey returns compressed key, we need uncompressed
1332
+ const publicKeyUncompressed = secp256k1.secp256k1.ProjectivePoint.fromHex(publicKeyBytes).toRawBytes(false).slice(1); // Remove 0x04 prefix
1333
+ // Hash the public key with Keccak256
1334
+ const publicKeyHash = sha3.keccak_256(publicKeyUncompressed);
1335
+ // Take the last 20 bytes (40 hex chars)
1336
+ const addressBytes = publicKeyHash.slice(-20);
1337
+ // Convert to hex and add 0x prefix
1338
+ const addressHex = '0x' + this.binaryToBase16(addressBytes);
1339
+ return addressHex;
1340
+ }
1314
1341
  retrieveStarkAccount(signature, accountClassHash, accountProxyClassHash) {
1315
1342
  const privateKey = index$1.ethSigToPrivate(signature);
1316
1343
  const publicKey = index$1.getStarkKey(privateKey);
@@ -5983,6 +6010,9 @@ class Exchange {
5983
6010
  }
5984
6011
  throw new errors.NotSupported(this.id + ' fetchClosedOrders() is not supported yet');
5985
6012
  }
6013
+ async fetchCanceledOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
6014
+ throw new errors.NotSupported(this.id + ' fetchCanceledOrders() is not supported yet');
6015
+ }
5986
6016
  async fetchCanceledAndClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
5987
6017
  throw new errors.NotSupported(this.id + ' fetchCanceledAndClosedOrders() is not supported yet');
5988
6018
  }
@@ -7733,6 +7763,9 @@ class Exchange {
7733
7763
  throw new errors.NotSupported(this.id + ' fetchPositionHistory () is not supported yet');
7734
7764
  }
7735
7765
  }
7766
+ async loadMarketsAndSignIn() {
7767
+ await Promise.all([this.loadMarkets(), this.signIn()]);
7768
+ }
7736
7769
  async fetchPositionsHistory(symbols = undefined, since = undefined, limit = undefined, params = {}) {
7737
7770
  /**
7738
7771
  * @method
@@ -49,6 +49,7 @@ class WsClient extends Client["default"] {
49
49
  }
50
50
  else {
51
51
  this.connection = new WebSocketPlatform(this.url, this.protocols);
52
+ this.connection.binaryType = "arraybuffer"; // for browsers not to use blob by default
52
53
  }
53
54
  this.connection.onopen = this.onOpen.bind(this);
54
55
  this.connection.onmessage = this.onMessage.bind(this);
@@ -856,7 +856,7 @@ class bigone extends bigone$1["default"] {
856
856
  'close': close,
857
857
  'last': close,
858
858
  'previousClose': undefined,
859
- 'change': this.safeString2(ticker, 'daily_change', 'last24hPriceChange'),
859
+ 'change': this.safeString(ticker, 'daily_change'),
860
860
  'percentage': undefined,
861
861
  'average': undefined,
862
862
  'baseVolume': this.safeString2(ticker, 'volume', 'volume24h'),
@@ -1003,6 +1003,7 @@ class binance extends binance$1["default"] {
1003
1003
  'block/order/execute': 5,
1004
1004
  'block/user-trades': 5,
1005
1005
  'blockTrades': 5,
1006
+ 'comission': 5,
1006
1007
  },
1007
1008
  'post': {
1008
1009
  'order': 1,
@@ -84,6 +84,7 @@ class bingx extends bingx$1["default"] {
84
84
  'fetchLiquidations': false,
85
85
  'fetchMarginAdjustmentHistory': false,
86
86
  'fetchMarginMode': true,
87
+ 'fetchMarketLeverageTiers': true,
87
88
  'fetchMarkets': true,
88
89
  'fetchMarkOHLCV': true,
89
90
  'fetchMarkPrice': true,
@@ -6660,6 +6661,78 @@ class bingx extends bingx$1["default"] {
6660
6661
  }
6661
6662
  return result;
6662
6663
  }
6664
+ /**
6665
+ * @method
6666
+ * @name bingx#fetchMarketLeverageTiers
6667
+ * @description retrieve information on the maximum leverage, for different trade sizes for a single market
6668
+ * @see https://bingx-api.github.io/docs-v3/#/en/Swap/Trades%20Endpoints/Position%20and%20Maintenance%20Margin%20Ratio
6669
+ * @param {string} symbol unified market symbol
6670
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
6671
+ * @returns {object} a [leverage tiers structure]{@link https://docs.ccxt.com/?id=leverage-tiers-structure}
6672
+ */
6673
+ async fetchMarketLeverageTiers(symbol, params = {}) {
6674
+ await this.loadMarkets();
6675
+ const market = this.market(symbol);
6676
+ if (!market['swap']) {
6677
+ throw new errors.BadRequest(this.id + ' fetchMarketLeverageTiers() supports swap markets only');
6678
+ }
6679
+ const request = {
6680
+ 'symbol': market['id'],
6681
+ };
6682
+ const response = await this.swapV1PrivateGetMaintMarginRatio(this.extend(request, params));
6683
+ //
6684
+ // {
6685
+ // "code": 0,
6686
+ // "msg": "",
6687
+ // "timestamp": 1767789967284,
6688
+ // "data": [
6689
+ // {
6690
+ // "tier": "Tier 1",
6691
+ // "symbol": "ETH-USDT",
6692
+ // "minPositionVal": "0",
6693
+ // "maxPositionVal": "900000",
6694
+ // "maintMarginRatio": "0.003300",
6695
+ // "maintAmount": "0.000000"
6696
+ // }
6697
+ // ]
6698
+ // }
6699
+ //
6700
+ const data = this.safeList(response, 'data', []);
6701
+ return this.parseMarketLeverageTiers(data, market);
6702
+ }
6703
+ parseMarketLeverageTiers(info, market = undefined) {
6704
+ //
6705
+ // [
6706
+ // {
6707
+ // "tier": "Tier 1",
6708
+ // "symbol": "ETH-USDT",
6709
+ // "minPositionVal": "0",
6710
+ // "maxPositionVal": "900000",
6711
+ // "maintMarginRatio": "0.003300",
6712
+ // "maintAmount": "0.000000"
6713
+ // }
6714
+ // ]
6715
+ //
6716
+ const tiers = [];
6717
+ for (let i = 0; i < info.length; i++) {
6718
+ const tier = this.safeDict(info, i);
6719
+ const tierString = this.safeString(tier, 'tier');
6720
+ const tierParts = tierString.split(' ');
6721
+ const marketId = this.safeString(tier, 'symbol');
6722
+ market = this.safeMarket(marketId, market, undefined, 'swap');
6723
+ tiers.push({
6724
+ 'tier': this.safeNumber(tierParts, 1),
6725
+ 'symbol': this.safeSymbol(marketId, market),
6726
+ 'currency': this.safeString(market, 'settle'),
6727
+ 'minNotional': this.safeNumber(tier, 'minPositionVal'),
6728
+ 'maxNotional': this.safeNumber(tier, 'maxPositionVal'),
6729
+ 'maintenanceMarginRate': this.safeNumber(tier, 'maintMarginRatio'),
6730
+ 'maxLeverage': undefined,
6731
+ 'info': tier,
6732
+ });
6733
+ }
6734
+ return tiers;
6735
+ }
6663
6736
  sign(path, section = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
6664
6737
  let type = section[0];
6665
6738
  let version = section[1];
@@ -79,7 +79,7 @@ class cryptomus extends cryptomus$1["default"] {
79
79
  'fetchConvertTradeHistory': false,
80
80
  'fetchCrossBorrowRate': false,
81
81
  'fetchCrossBorrowRates': false,
82
- 'fetchCurrencies': true,
82
+ 'fetchCurrencies': false,
83
83
  'fetchDepositAddress': false,
84
84
  'fetchDeposits': false,
85
85
  'fetchDepositsWithdrawals': false,
@@ -4972,6 +4972,24 @@ class gate extends gate$1["default"] {
4972
4972
  //
4973
4973
  // {"user_id":10406147,"id":"id","succeeded":false,"message":"INVALID_PROTOCOL","label":"INVALID_PROTOCOL"}
4974
4974
  //
4975
+ // cancel trigger order returns timestamps in ms
4976
+ // id: '2007047737421336576',
4977
+ // id_string: '2007047737421336576',
4978
+ // trigger_time: '0',
4979
+ // trade_id: '0',
4980
+ // trade_id_string: '',
4981
+ // status: 'finished',
4982
+ // finish_as: 'cancelled',
4983
+ // reason: '',
4984
+ // create_time: '1767352444402496'
4985
+ // finish_time: '1767352509535790',
4986
+ // is_stop_order: false,
4987
+ // stop_trigger: { rule: '0', trigger_price: '', order_price: '' },
4988
+ // me_order_id: '0',
4989
+ // me_order_id_string: '',
4990
+ // order_type: '',
4991
+ // in_dual_mode: false,
4992
+ // parent_id: '0',
4975
4993
  const succeeded = this.safeBool(order, 'succeeded', true);
4976
4994
  if (!succeeded) {
4977
4995
  // cancelOrders response
@@ -5014,13 +5032,33 @@ class gate extends gate$1["default"] {
5014
5032
  side = Precise["default"].stringGt(amount, '0') ? 'buy' : 'sell';
5015
5033
  }
5016
5034
  const rawStatus = this.safeStringN(order, ['finish_as', 'status', 'open']);
5017
- let timestamp = this.safeInteger(order, 'create_time_ms');
5018
- if (timestamp === undefined) {
5019
- timestamp = this.safeTimestamp2(order, 'create_time', 'ctime');
5035
+ let timestampStr = this.safeString(order, 'create_time_ms');
5036
+ if (timestampStr === undefined) {
5037
+ timestampStr = this.safeString2(order, 'create_time', 'ctime');
5038
+ if (timestampStr !== undefined) {
5039
+ if (timestampStr.length === 10 || timestampStr.indexOf('.') >= 0) {
5040
+ // ts in seconds, multiply to ms
5041
+ timestampStr = Precise["default"].stringMul(timestampStr, '1000');
5042
+ }
5043
+ else if (timestampStr.length === 16) {
5044
+ // ts in microseconds, divide to ms
5045
+ timestampStr = Precise["default"].stringDiv(timestampStr, '1000');
5046
+ }
5047
+ }
5020
5048
  }
5021
- let lastTradeTimestamp = this.safeInteger(order, 'update_time_ms');
5022
- if (lastTradeTimestamp === undefined) {
5023
- lastTradeTimestamp = this.safeTimestamp2(order, 'update_time', 'finish_time');
5049
+ let lastTradeTimestampStr = this.safeString(order, 'update_time_ms');
5050
+ if (lastTradeTimestampStr === undefined) {
5051
+ lastTradeTimestampStr = this.safeString2(order, 'update_time', 'finish_time');
5052
+ if (lastTradeTimestampStr !== undefined) {
5053
+ if (lastTradeTimestampStr.length === 10 || lastTradeTimestampStr.indexOf('.') >= 0) {
5054
+ // ts in seconds, multiply to ms
5055
+ lastTradeTimestampStr = Precise["default"].stringMul(lastTradeTimestampStr, '1000');
5056
+ }
5057
+ else if (lastTradeTimestampStr.length === 16) {
5058
+ // ts in microseconds, divide to ms
5059
+ lastTradeTimestampStr = Precise["default"].stringDiv(lastTradeTimestampStr, '1000');
5060
+ }
5061
+ }
5024
5062
  }
5025
5063
  let marketType = 'contract';
5026
5064
  if (('currency_pair' in order) || ('market' in order)) {
@@ -5067,6 +5105,14 @@ class gate extends gate$1["default"] {
5067
5105
  amount = Precise["default"].stringDiv(amount, averageString);
5068
5106
  }
5069
5107
  }
5108
+ let timestamp = undefined;
5109
+ let lastTradeTimestamp = undefined;
5110
+ if (timestampStr !== undefined) {
5111
+ timestamp = this.parseToInt(timestampStr);
5112
+ }
5113
+ if (lastTradeTimestampStr !== undefined) {
5114
+ lastTradeTimestamp = this.parseToInt(lastTradeTimestampStr);
5115
+ }
5070
5116
  return this.safeOrder({
5071
5117
  'id': this.safeString(order, 'id'),
5072
5118
  'clientOrderId': this.safeString(order, 'text'),
@@ -1062,6 +1062,13 @@ class hyperliquid extends hyperliquid$1["default"] {
1062
1062
  'info': market,
1063
1063
  });
1064
1064
  }
1065
+ updateSpotCurrencyCode(code) {
1066
+ if (code === undefined) {
1067
+ return code;
1068
+ }
1069
+ const spotCurrencyMapping = this.safeDict(this.options, 'spotCurrencyMapping', {});
1070
+ return this.safeString(spotCurrencyMapping, code, code);
1071
+ }
1065
1072
  /**
1066
1073
  * @method
1067
1074
  * @name hyperliquid#fetchBalance
@@ -1129,7 +1136,8 @@ class hyperliquid extends hyperliquid$1["default"] {
1129
1136
  const spotBalances = { 'info': response };
1130
1137
  for (let i = 0; i < balances.length; i++) {
1131
1138
  const balance = balances[i];
1132
- const code = this.safeCurrencyCode(this.safeString(balance, 'coin'));
1139
+ const unifiedCode = this.safeCurrencyCode(this.safeString(balance, 'coin'));
1140
+ const code = isSpot ? this.updateSpotCurrencyCode(unifiedCode) : unifiedCode;
1133
1141
  const account = this.account();
1134
1142
  const total = this.safeString(balance, 'total');
1135
1143
  const used = this.safeString(balance, 'hold');
@@ -182,6 +182,7 @@ class kucoin extends kucoin$1["default"] {
182
182
  'get': {
183
183
  // account
184
184
  'user-info': 30,
185
+ 'user/api-key': 30,
185
186
  'accounts': 7.5,
186
187
  'accounts/{accountId}': 7.5,
187
188
  'accounts/ledgers': 3,
@@ -266,6 +267,8 @@ class kucoin extends kucoin$1["default"] {
266
267
  'convert/limit/orders': 5,
267
268
  // affiliate
268
269
  'affiliate/inviter/statistics': 30,
270
+ // earn
271
+ 'earn/redeem-preview': 5, // 5EW
269
272
  },
270
273
  'post': {
271
274
  // account
@@ -713,6 +716,9 @@ class kucoin extends kucoin$1["default"] {
713
716
  'withdraw': {
714
717
  'includeFee': false,
715
718
  },
719
+ 'transfer': {
720
+ 'fillResponseFromRequest': true,
721
+ },
716
722
  // endpoint versions
717
723
  'versions': {
718
724
  'public': {
@@ -4583,96 +4589,89 @@ class kucoin extends kucoin$1["default"] {
4583
4589
  * @method
4584
4590
  * @name kucoin#transfer
4585
4591
  * @description transfer currency internally between wallets on the same account
4586
- * @see https://www.kucoin.com/docs/rest/funding/transfer/inner-transfer
4587
- * @see https://docs.kucoin.com/futures/#transfer-funds-to-kucoin-main-account-2
4588
- * @see https://docs.kucoin.com/spot-hf/#internal-funds-transfers-in-high-frequency-trading-accounts
4592
+ * @see https://www.kucoin.com/docs-new/rest/account-info/transfer/flex-transfer?lang=en_US&
4589
4593
  * @param {string} code unified currency code
4590
4594
  * @param {float} amount amount to transfer
4591
4595
  * @param {string} fromAccount account to transfer from
4592
4596
  * @param {string} toAccount account to transfer to
4593
4597
  * @param {object} [params] extra parameters specific to the exchange API endpoint
4598
+ * @param {string} [params.transferType] INTERNAL, PARENT_TO_SUB, SUB_TO_PARENT (default is INTERNAL)
4599
+ * @param {string} [params.fromUserId] required if transferType is SUB_TO_PARENT
4600
+ * @param {string} [params.toUserId] required if transferType is PARENT_TO_SUB
4594
4601
  * @returns {object} a [transfer structure]{@link https://docs.ccxt.com/?id=transfer-structure}
4595
4602
  */
4596
4603
  async transfer(code, amount, fromAccount, toAccount, params = {}) {
4597
4604
  await this.loadMarkets();
4598
4605
  const currency = this.currency(code);
4599
4606
  const requestedAmount = this.currencyToPrecision(code, amount);
4607
+ const request = {
4608
+ 'currency': currency['id'],
4609
+ 'amount': requestedAmount,
4610
+ };
4611
+ let transferType = 'INTERNAL';
4612
+ [transferType, params] = this.handleParamString2(params, 'transferType', 'type', transferType);
4613
+ if (transferType === 'PARENT_TO_SUB') {
4614
+ if (!('toUserId' in params)) {
4615
+ throw new errors.ExchangeError(this.id + ' transfer() requires a toUserId param for PARENT_TO_SUB transfers');
4616
+ }
4617
+ }
4618
+ else if (transferType === 'SUB_TO_PARENT') {
4619
+ if (!('fromUserId' in params)) {
4620
+ throw new errors.ExchangeError(this.id + ' transfer() requires a fromUserId param for SUB_TO_PARENT transfers');
4621
+ }
4622
+ }
4623
+ if (!('clientOid' in params)) {
4624
+ request['clientOid'] = this.uuid();
4625
+ }
4600
4626
  let fromId = this.convertTypeToAccount(fromAccount);
4601
4627
  let toId = this.convertTypeToAccount(toAccount);
4602
4628
  const fromIsolated = this.inArray(fromId, this.ids);
4603
4629
  const toIsolated = this.inArray(toId, this.ids);
4604
- if (fromId === 'contract') {
4605
- if (toId !== 'main') {
4606
- throw new errors.ExchangeError(this.id + ' transfer() only supports transferring from futures account to main account');
4607
- }
4608
- const request = {
4609
- 'currency': currency['id'],
4610
- 'amount': requestedAmount,
4611
- };
4612
- if (!('bizNo' in params)) {
4613
- // it doesn't like more than 24 characters
4614
- request['bizNo'] = this.uuid22();
4615
- }
4616
- const response = await this.futuresPrivatePostTransferOut(this.extend(request, params));
4617
- //
4618
- // {
4619
- // "code": "200000",
4620
- // "data": {
4621
- // "applyId": "605a87217dff1500063d485d",
4622
- // "bizNo": "bcd6e5e1291f4905af84dc",
4623
- // "payAccountType": "CONTRACT",
4624
- // "payTag": "DEFAULT",
4625
- // "remark": '',
4626
- // "recAccountType": "MAIN",
4627
- // "recTag": "DEFAULT",
4628
- // "recRemark": '',
4629
- // "recSystem": "KUCOIN",
4630
- // "status": "PROCESSING",
4631
- // "currency": "XBT",
4632
- // "amount": "0.00001",
4633
- // "fee": "0",
4634
- // "sn": "573688685663948",
4635
- // "reason": '',
4636
- // "createdAt": 1616545569000,
4637
- // "updatedAt": 1616545569000
4638
- // }
4639
- // }
4640
- //
4641
- const data = this.safeDict(response, 'data');
4642
- return this.parseTransfer(data, currency);
4630
+ if (fromIsolated) {
4631
+ request['fromAccountTag'] = fromId;
4632
+ fromId = 'isolated';
4643
4633
  }
4644
- else {
4645
- const request = {
4646
- 'currency': currency['id'],
4647
- 'amount': requestedAmount,
4648
- };
4649
- if (fromIsolated || toIsolated) {
4650
- if (this.inArray(fromId, this.ids)) {
4651
- request['fromTag'] = fromId;
4652
- fromId = 'isolated';
4653
- }
4654
- if (this.inArray(toId, this.ids)) {
4655
- request['toTag'] = toId;
4656
- toId = 'isolated';
4657
- }
4658
- }
4634
+ if (toIsolated) {
4635
+ request['toAccountTag'] = toId;
4636
+ toId = 'isolated';
4637
+ }
4638
+ const hfOrMining = this.isHfOrMining(fromId, toId);
4639
+ let response = undefined;
4640
+ if (hfOrMining) {
4641
+ // new endpoint does not support hf and mining transfers
4642
+ // use old endpoint for hf and mining transfers
4659
4643
  request['from'] = fromId;
4660
4644
  request['to'] = toId;
4661
- if (!('clientOid' in params)) {
4662
- request['clientOid'] = this.uuid();
4663
- }
4664
- const response = await this.privatePostAccountsInnerTransfer(this.extend(request, params));
4645
+ response = await this.privatePostAccountsInnerTransfer(this.extend(request, params));
4646
+ }
4647
+ else {
4648
+ request['type'] = transferType;
4649
+ request['fromAccountType'] = fromId.toUpperCase();
4650
+ request['toAccountType'] = toId.toUpperCase();
4665
4651
  //
4666
4652
  // {
4667
4653
  // "code": "200000",
4668
4654
  // "data": {
4669
- // "orderId": "605a6211e657f00006ad0ad6"
4655
+ // "orderId": "694fcb5b08bb1600015cda75"
4670
4656
  // }
4671
4657
  // }
4672
4658
  //
4673
- const data = this.safeDict(response, 'data');
4674
- return this.parseTransfer(data, currency);
4659
+ response = await this.privatePostAccountsUniversalTransfer(this.extend(request, params));
4675
4660
  }
4661
+ const data = this.safeDict(response, 'data');
4662
+ const transfer = this.parseTransfer(data, currency);
4663
+ const transferOptions = this.safeDict(this.options, 'transfer', {});
4664
+ const fillResponseFromRequest = this.safeBool(transferOptions, 'fillResponseFromRequest', true);
4665
+ if (fillResponseFromRequest) {
4666
+ transfer['amount'] = amount;
4667
+ transfer['fromAccount'] = fromAccount;
4668
+ transfer['toAccount'] = toAccount;
4669
+ transfer['status'] = 'ok';
4670
+ }
4671
+ return transfer;
4672
+ }
4673
+ isHfOrMining(fromId, toId) {
4674
+ return (fromId === 'trade_hf' || toId === 'trade_hf' || fromId === 'pool' || toId === 'pool');
4676
4675
  }
4677
4676
  parseTransfer(transfer, currency = undefined) {
4678
4677
  //
@@ -3010,6 +3010,9 @@ class okx extends okx$1["default"] {
3010
3010
  }
3011
3011
  createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
3012
3012
  const market = this.market(symbol);
3013
+ const takeProfitPrice = this.safeValue2(params, 'takeProfitPrice', 'tpTriggerPx');
3014
+ const stopLossPrice = this.safeValue2(params, 'stopLossPrice', 'slTriggerPx');
3015
+ const conditional = (stopLossPrice !== undefined) || (takeProfitPrice !== undefined) || (type === 'conditional');
3013
3016
  let request = {
3014
3017
  'instId': market['id'],
3015
3018
  // 'ccy': currency['id'], // only applicable to cross MARGIN orders in single-currency margin
@@ -3020,7 +3023,7 @@ class okx extends okx$1["default"] {
3020
3023
  'ordType': type,
3021
3024
  // 'ordType': type, // privatePostTradeOrder: market, limit, post_only, fok, ioc, optimal_limit_ioc
3022
3025
  // 'ordType': type, // privatePostTradeOrderAlgo: conditional, oco, trigger, move_order_stop, iceberg, twap
3023
- 'sz': this.amountToPrecision(symbol, amount),
3026
+ // 'sz': this.amountToPrecision (symbol, amount),
3024
3027
  // 'px': this.priceToPrecision (symbol, price), // limit orders only
3025
3028
  // 'reduceOnly': false,
3026
3029
  //
@@ -3036,14 +3039,20 @@ class okx extends okx$1["default"] {
3036
3039
  // 'slTriggerPxType': 'last', // Conditional default is last, mark or index (conditional orders)
3037
3040
  // 'slOrdPx': 10, // Order price for Stop-Loss orders, if -1 will be executed at market price (conditional orders)
3038
3041
  };
3042
+ const isConditionalOrOCO = conditional || (type === 'oco');
3043
+ const closeFraction = this.safeString(params, 'closeFraction');
3044
+ const shouldOmitSize = isConditionalOrOCO && closeFraction !== undefined;
3045
+ if (!shouldOmitSize) {
3046
+ request['sz'] = this.amountToPrecision(symbol, amount);
3047
+ }
3039
3048
  const spot = market['spot'];
3040
3049
  const contract = market['contract'];
3041
3050
  const triggerPrice = this.safeValueN(params, ['triggerPrice', 'stopPrice', 'triggerPx']);
3042
3051
  const timeInForce = this.safeString(params, 'timeInForce', 'GTC');
3043
- const takeProfitPrice = this.safeValue2(params, 'takeProfitPrice', 'tpTriggerPx');
3052
+ // const takeProfitPrice = this.safeValue2 (params, 'takeProfitPrice', 'tpTriggerPx');
3044
3053
  const tpOrdPx = this.safeValue(params, 'tpOrdPx', price);
3045
3054
  const tpTriggerPxType = this.safeString(params, 'tpTriggerPxType', 'last');
3046
- const stopLossPrice = this.safeValue2(params, 'stopLossPrice', 'slTriggerPx');
3055
+ // const stopLossPrice = this.safeValue2 (params, 'stopLossPrice', 'slTriggerPx');
3047
3056
  const slOrdPx = this.safeValue(params, 'slOrdPx', price);
3048
3057
  const slTriggerPxType = this.safeString(params, 'slTriggerPxType', 'last');
3049
3058
  const clientOrderId = this.safeString2(params, 'clOrdId', 'clientOrderId');
@@ -3056,7 +3065,7 @@ class okx extends okx$1["default"] {
3056
3065
  const trailingPrice = this.safeString2(params, 'trailingPrice', 'callbackSpread');
3057
3066
  const isTrailingPriceOrder = trailingPrice !== undefined;
3058
3067
  const trigger = (triggerPrice !== undefined) || (type === 'trigger');
3059
- const isReduceOnly = this.safeValue(params, 'reduceOnly', false);
3068
+ const isReduceOnly = this.safeValue(params, 'reduceOnly', false) || (closeFraction !== undefined);
3060
3069
  const defaultMarginMode = this.safeString2(this.options, 'defaultMarginMode', 'marginMode', 'cross');
3061
3070
  let marginMode = this.safeString2(params, 'marginMode', 'tdMode'); // cross or isolated, tdMode not ommited so as to be extended into the request
3062
3071
  let margin = false;
@@ -3111,7 +3120,7 @@ class okx extends okx$1["default"] {
3111
3120
  params = this.omit(params, ['currency', 'ccy', 'marginMode', 'timeInForce', 'stopPrice', 'triggerPrice', 'clientOrderId', 'stopLossPrice', 'takeProfitPrice', 'slOrdPx', 'tpOrdPx', 'margin', 'stopLoss', 'takeProfit', 'trailingPercent']);
3112
3121
  const ioc = (timeInForce === 'IOC') || (type === 'ioc');
3113
3122
  const fok = (timeInForce === 'FOK') || (type === 'fok');
3114
- const conditional = (stopLossPrice !== undefined) || (takeProfitPrice !== undefined) || (type === 'conditional');
3123
+ // const conditional = (stopLossPrice !== undefined) || (takeProfitPrice !== undefined) || (type === 'conditional');
3115
3124
  const marketIOC = (isMarketOrder && ioc) || (type === 'optimal_limit_ioc');
3116
3125
  const defaultTgtCcy = this.safeString(this.options, 'tgtCcy', 'base_ccy');
3117
3126
  const tgtCcy = this.safeString(params, 'tgtCcy', defaultTgtCcy);
@@ -985,7 +985,7 @@ class apex extends apex$1["default"] {
985
985
  await client.send({ 'args': [timeStamp.toString()], 'op': 'pong' });
986
986
  }
987
987
  catch (e) {
988
- const error = new errors.NetworkError(this.id + ' handlePing failed with error ' + this.json(e));
988
+ const error = new errors.NetworkError(this.id + ' handlePing failed with error ' + this.exceptionMessage(e));
989
989
  client.reset(error);
990
990
  }
991
991
  }
@@ -1000,7 +1000,7 @@ class apex extends apex$1["default"] {
1000
1000
  //
1001
1001
  // { pong: 1653296711335 }
1002
1002
  //
1003
- client.lastPong = this.safeInteger(message, 'pong');
1003
+ client.lastPong = this.safeInteger(message, 'pong', this.milliseconds());
1004
1004
  return message;
1005
1005
  }
1006
1006
  handlePing(client, message) {
@@ -975,7 +975,7 @@ class ascendex extends ascendex$1["default"] {
975
975
  await client.send({ 'op': 'pong', 'hp': this.safeInteger(message, 'hp') });
976
976
  }
977
977
  catch (e) {
978
- const error = new errors.NetworkError(this.id + ' handlePing failed with error ' + this.json(e));
978
+ const error = new errors.NetworkError(this.id + ' handlePing failed with error ' + this.exceptionMessage(e));
979
979
  client.reset(error);
980
980
  }
981
981
  }