ccxt 4.5.29 → 4.5.31

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 (85) 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/base/Exchange.js +16 -1
  5. package/dist/cjs/src/base/ws/WsClient.js +1 -0
  6. package/dist/cjs/src/bingx.js +1 -1
  7. package/dist/cjs/src/bullish.js +1 -1
  8. package/dist/cjs/src/bybit.js +2 -0
  9. package/dist/cjs/src/bydfi.js +2907 -0
  10. package/dist/cjs/src/coinbase.js +34 -1
  11. package/dist/cjs/src/dydx.js +3 -3
  12. package/dist/cjs/src/gate.js +55 -8
  13. package/dist/cjs/src/hyperliquid.js +19 -4
  14. package/dist/cjs/src/kucoin.js +175 -68
  15. package/dist/cjs/src/pro/apex.js +7 -5
  16. package/dist/cjs/src/pro/ascendex.js +1 -1
  17. package/dist/cjs/src/pro/binance.js +10 -6
  18. package/dist/cjs/src/pro/bingx.js +6 -4
  19. package/dist/cjs/src/pro/bitmart.js +5 -3
  20. package/dist/cjs/src/pro/bybit.js +6 -4
  21. package/dist/cjs/src/pro/bydfi.js +1077 -0
  22. package/dist/cjs/src/pro/cryptocom.js +6 -4
  23. package/dist/cjs/src/pro/gate.js +5 -3
  24. package/dist/cjs/src/pro/hashkey.js +5 -3
  25. package/dist/cjs/src/pro/htx.js +1 -1
  26. package/dist/cjs/src/pro/hyperliquid.js +1 -1
  27. package/dist/cjs/src/pro/kucoinfutures.js +5 -3
  28. package/dist/cjs/src/pro/modetrade.js +5 -3
  29. package/dist/cjs/src/pro/p2b.js +1 -1
  30. package/dist/cjs/src/pro/toobit.js +12 -8
  31. package/dist/cjs/src/pro/woo.js +5 -3
  32. package/dist/cjs/src/pro/woofipro.js +5 -3
  33. package/dist/cjs/src/pro/xt.js +5 -3
  34. package/dist/cjs/src/toobit.js +2 -1
  35. package/js/ccxt.d.ts +8 -5
  36. package/js/ccxt.js +6 -4
  37. package/js/src/abstract/bydfi.d.ts +52 -0
  38. package/js/src/abstract/kucoin.d.ts +2 -0
  39. package/js/src/abstract/kucoinfutures.d.ts +2 -0
  40. package/js/src/base/Exchange.d.ts +3 -0
  41. package/js/src/base/Exchange.js +16 -1
  42. package/js/src/base/ws/WsClient.js +1 -0
  43. package/js/src/binance.d.ts +1 -1
  44. package/js/src/bingx.js +1 -1
  45. package/js/src/bullish.js +1 -1
  46. package/js/src/bybit.js +2 -0
  47. package/js/src/bydfi.d.ts +472 -0
  48. package/js/src/bydfi.js +2905 -0
  49. package/js/src/coinbase.d.ts +11 -0
  50. package/js/src/coinbase.js +34 -1
  51. package/js/src/dydx.js +3 -3
  52. package/js/src/exmo.d.ts +1 -1
  53. package/js/src/gate.js +55 -8
  54. package/js/src/hyperliquid.d.ts +1 -0
  55. package/js/src/hyperliquid.js +19 -4
  56. package/js/src/kucoin.d.ts +19 -3
  57. package/js/src/kucoin.js +175 -68
  58. package/js/src/pro/apex.js +7 -5
  59. package/js/src/pro/ascendex.js +1 -1
  60. package/js/src/pro/binance.js +10 -6
  61. package/js/src/pro/bingx.js +6 -4
  62. package/js/src/pro/bitmart.js +5 -3
  63. package/js/src/pro/bybit.js +6 -4
  64. package/js/src/pro/bydfi.d.ts +206 -0
  65. package/js/src/pro/bydfi.js +1076 -0
  66. package/js/src/pro/cryptocom.js +6 -4
  67. package/js/src/pro/gate.js +5 -3
  68. package/js/src/pro/hashkey.js +5 -3
  69. package/js/src/pro/htx.js +1 -1
  70. package/js/src/pro/hyperliquid.js +1 -1
  71. package/js/src/pro/kucoinfutures.js +5 -3
  72. package/js/src/pro/modetrade.js +5 -3
  73. package/js/src/pro/p2b.js +1 -1
  74. package/js/src/pro/toobit.js +12 -8
  75. package/js/src/pro/woo.js +5 -3
  76. package/js/src/pro/woofipro.js +5 -3
  77. package/js/src/pro/xt.js +5 -3
  78. package/js/src/toobit.js +2 -1
  79. package/package.json +1 -1
  80. package/dist/cjs/src/oceanex.js +0 -1125
  81. package/js/src/abstract/oceanex.d.ts +0 -30
  82. package/js/src/oceanex.d.ts +0 -231
  83. package/js/src/oceanex.js +0 -1124
  84. /package/dist/cjs/src/abstract/{oceanex.js → bydfi.js} +0 -0
  85. /package/js/src/abstract/{oceanex.js → bydfi.js} +0 -0
@@ -87,7 +87,7 @@ class coinbase extends coinbase$1["default"] {
87
87
  'fetchCurrencies': true,
88
88
  'fetchDeposit': true,
89
89
  'fetchDepositAddress': 'emulated',
90
- 'fetchDepositAddresses': false,
90
+ 'fetchDepositAddresses': true,
91
91
  'fetchDepositAddressesByNetwork': true,
92
92
  'fetchDepositMethodId': true,
93
93
  'fetchDepositMethodIds': true,
@@ -4301,6 +4301,19 @@ class coinbase extends coinbase$1["default"] {
4301
4301
  // }
4302
4302
  // }
4303
4303
  //
4304
+ // {
4305
+ // "id":"3f2434234943-8c1c-50ef-a5a1-342213bbf45d",
4306
+ // "address":"0x123123126F5921XXXXX",
4307
+ // "currency":"USDC",
4308
+ // "name":"",
4309
+ // "network":"ethereum",
4310
+ // "created_at":"2022-03-17T09:20:17.002Z",
4311
+ // "updated_at":"2022-03-17T09:20:17.002Z",
4312
+ // "resource":"addresses",
4313
+ // "resource_path":"v2/accounts/b1091c6e-9ef2-5e4d-b352-665d0cf8f742/addresses/32fd0943-8c1c-50ef-a5a1-342213bbf45d",
4314
+ // "destination_tag":""
4315
+ // }
4316
+ //
4304
4317
  const address = this.safeString(depositAddress, 'address');
4305
4318
  this.checkAddress(address);
4306
4319
  const networkId = this.safeString(depositAddress, 'network');
@@ -4311,6 +4324,9 @@ class coinbase extends coinbase$1["default"] {
4311
4324
  const splitAddressLabel = addressLabel.split(' ');
4312
4325
  currencyId = this.safeString(splitAddressLabel, 0);
4313
4326
  }
4327
+ else {
4328
+ currencyId = this.safeString(depositAddress, 'currency');
4329
+ }
4314
4330
  const addressInfo = this.safeDict(depositAddress, 'address_info');
4315
4331
  return {
4316
4332
  'info': depositAddress,
@@ -5235,6 +5251,23 @@ class coinbase extends coinbase$1["default"] {
5235
5251
  }
5236
5252
  return undefined;
5237
5253
  }
5254
+ /**
5255
+ * @method
5256
+ * @name coinbase#fetchDepositAddresses
5257
+ * @description fetch deposit addresses for multiple currencies (when available)
5258
+ * @see https://coinbase-migration.mintlify.app/coinbase-app/transfer-apis/onchain-addresses
5259
+ * @param {string[]} [codes] list of unified currency codes, default is undefined (all currencies)
5260
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
5261
+ * @param {string} [params.accountId] account ID to fetch deposit addresses for
5262
+ * @returns {object} a dictionary of [address structures]{@link https://docs.ccxt.com/#/?id=address-structure} indexed by currency code
5263
+ */
5264
+ async fetchDepositAddresses(codes = undefined, params = {}) {
5265
+ await this.loadMarkets();
5266
+ const request = this.prepareAccountRequest(undefined, params);
5267
+ const response = await this.v2PrivateGetAccountsAccountIdAddresses(this.extend(request, params));
5268
+ const data = this.safeList(response, 'data', []);
5269
+ return this.parseDepositAddresses(data, codes, false, {});
5270
+ }
5238
5271
  }
5239
5272
 
5240
5273
  exports["default"] = coinbase;
@@ -505,9 +505,9 @@ class dydx extends dydx$1["default"] {
505
505
  const marketId = this.safeString(market, 'ticker');
506
506
  const parts = marketId.split('-');
507
507
  const baseName = this.safeString(parts, 0);
508
- const base = this.safeCurrencyCode(baseName);
508
+ const baseId = this.safeString(market, 'baseId', baseName); // idk where 'baseId' comes from, but leaving as is
509
+ const base = this.safeCurrencyCode(baseId);
509
510
  const quote = this.safeCurrencyCode(quoteId);
510
- const baseId = this.safeString(market, 'baseId');
511
511
  const settleId = 'USDC';
512
512
  const settle = this.safeCurrencyCode(settleId);
513
513
  const symbol = base + '/' + quote + ':' + settle;
@@ -538,11 +538,11 @@ class dydx extends dydx$1["default"] {
538
538
  'option': false,
539
539
  'active': active,
540
540
  'contract': contract,
541
+ 'contractSize': this.parseNumber('1'),
541
542
  'linear': true,
542
543
  'inverse': false,
543
544
  'taker': undefined,
544
545
  'maker': undefined,
545
- 'contractSize': undefined,
546
546
  'expiry': undefined,
547
547
  'expiryDatetime': undefined,
548
548
  'strike': undefined,
@@ -1040,7 +1040,7 @@ class gate extends gate$1["default"] {
1040
1040
  // https://www.gate.com/docs/developers/apiv4/en/#label-list
1041
1041
  'exceptions': {
1042
1042
  'exact': {
1043
- 'INVALID_PARAM_VALUE': errors.BadRequest,
1043
+ 'INVALID_PARAM_VALUE': errors.InvalidOrder,
1044
1044
  'INVALID_PROTOCOL': errors.BadRequest,
1045
1045
  'INVALID_ARGUMENT': errors.BadRequest,
1046
1046
  'INVALID_REQUEST_BODY': errors.BadRequest,
@@ -1135,7 +1135,8 @@ class gate extends gate$1["default"] {
1135
1135
  'AUTO_TRIGGER_PRICE_GREATE_LAST': errors.InvalidOrder,
1136
1136
  'POSITION_HOLDING': errors.BadRequest,
1137
1137
  'USER_LOAN_EXCEEDED': errors.BadRequest,
1138
- 'NO_CHANGE': errors.InvalidOrder, // {"label":"NO_CHANGE","message":"No change is made"}
1138
+ 'NO_CHANGE': errors.InvalidOrder,
1139
+ 'PRICE_THRESHOLD_EXCEEDED': errors.InvalidOrder, // {"label":"PRICE_THRESHOLD_EXCEEDED","message":": 0.45288"}
1139
1140
  },
1140
1141
  'broad': {},
1141
1142
  },
@@ -4971,6 +4972,24 @@ class gate extends gate$1["default"] {
4971
4972
  //
4972
4973
  // {"user_id":10406147,"id":"id","succeeded":false,"message":"INVALID_PROTOCOL","label":"INVALID_PROTOCOL"}
4973
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',
4974
4993
  const succeeded = this.safeBool(order, 'succeeded', true);
4975
4994
  if (!succeeded) {
4976
4995
  // cancelOrders response
@@ -5013,13 +5032,33 @@ class gate extends gate$1["default"] {
5013
5032
  side = Precise["default"].stringGt(amount, '0') ? 'buy' : 'sell';
5014
5033
  }
5015
5034
  const rawStatus = this.safeStringN(order, ['finish_as', 'status', 'open']);
5016
- let timestamp = this.safeInteger(order, 'create_time_ms');
5017
- if (timestamp === undefined) {
5018
- 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
+ }
5019
5048
  }
5020
- let lastTradeTimestamp = this.safeInteger(order, 'update_time_ms');
5021
- if (lastTradeTimestamp === undefined) {
5022
- 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
+ }
5023
5062
  }
5024
5063
  let marketType = 'contract';
5025
5064
  if (('currency_pair' in order) || ('market' in order)) {
@@ -5066,6 +5105,14 @@ class gate extends gate$1["default"] {
5066
5105
  amount = Precise["default"].stringDiv(amount, averageString);
5067
5106
  }
5068
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
+ }
5069
5116
  return this.safeOrder({
5070
5117
  'id': this.safeString(order, 'id'),
5071
5118
  'clientOrderId': this.safeString(order, 'text'),
@@ -578,17 +578,24 @@ class hyperliquid extends hyperliquid$1["default"] {
578
578
  let fetchDexesList = [];
579
579
  const options = this.safeDict(this.options, 'fetchMarkets', {});
580
580
  const hip3 = this.safeDict(options, 'hip3', {});
581
- const dexesProvided = this.safeList(hip3, 'dexes'); // let users provide their own list of dexes to load
581
+ const dexesProvided = this.safeList(hip3, 'dexes', []); // let users provide their own list of dexes to load
582
582
  const maxLimit = this.safeInteger(hip3, 'limit', 10);
583
- if (dexesProvided !== undefined) {
584
- const userProvidedDexesLength = dexesProvided.length;
583
+ const userProvidedDexesLength = dexesProvided.length;
584
+ if (userProvidedDexesLength > 0) {
585
585
  if (userProvidedDexesLength > 0) {
586
586
  fetchDexesList = dexesProvided;
587
587
  }
588
588
  }
589
589
  else {
590
+ const fetchDexesLength = fetchDexes.length;
590
591
  for (let i = 1; i < maxLimit; i++) {
592
+ if (i >= fetchDexesLength) {
593
+ break;
594
+ }
591
595
  const dex = this.safeDict(fetchDexes, i, {});
596
+ if (dex === undefined) {
597
+ continue;
598
+ }
592
599
  const dexName = this.safeString(dex, 'name');
593
600
  fetchDexesList.push(dexName);
594
601
  }
@@ -1055,6 +1062,13 @@ class hyperliquid extends hyperliquid$1["default"] {
1055
1062
  'info': market,
1056
1063
  });
1057
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
+ }
1058
1072
  /**
1059
1073
  * @method
1060
1074
  * @name hyperliquid#fetchBalance
@@ -1122,7 +1136,8 @@ class hyperliquid extends hyperliquid$1["default"] {
1122
1136
  const spotBalances = { 'info': response };
1123
1137
  for (let i = 0; i < balances.length; i++) {
1124
1138
  const balance = balances[i];
1125
- 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;
1126
1141
  const account = this.account();
1127
1142
  const total = this.safeString(balance, 'total');
1128
1143
  const used = this.safeString(balance, 'hold');
@@ -105,7 +105,7 @@ class kucoin extends kucoin$1["default"] {
105
105
  'fetchTradingFee': true,
106
106
  'fetchTradingFees': false,
107
107
  'fetchTransactionFee': true,
108
- 'fetchTransfers': false,
108
+ 'fetchTransfers': true,
109
109
  'fetchWithdrawals': true,
110
110
  'repayCrossMargin': true,
111
111
  'repayIsolatedMargin': true,
@@ -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
@@ -524,6 +527,8 @@ class kucoin extends kucoin$1["default"] {
524
527
  'Unsuccessful! Exceeded the max. funds out-transfer limit': errors.InsufficientFunds,
525
528
  'The amount increment is invalid.': errors.BadRequest,
526
529
  'The quantity is below the minimum requirement.': errors.InvalidOrder,
530
+ 'not in the given range!': errors.BadRequest,
531
+ 'recAccountType not in the given range': errors.BadRequest,
527
532
  '400': errors.BadRequest,
528
533
  '401': errors.AuthenticationError,
529
534
  '403': errors.NotSupported,
@@ -711,6 +716,9 @@ class kucoin extends kucoin$1["default"] {
711
716
  'withdraw': {
712
717
  'includeFee': false,
713
718
  },
719
+ 'transfer': {
720
+ 'fillResponseFromRequest': true,
721
+ },
714
722
  // endpoint versions
715
723
  'versions': {
716
724
  'public': {
@@ -4581,96 +4589,89 @@ class kucoin extends kucoin$1["default"] {
4581
4589
  * @method
4582
4590
  * @name kucoin#transfer
4583
4591
  * @description transfer currency internally between wallets on the same account
4584
- * @see https://www.kucoin.com/docs/rest/funding/transfer/inner-transfer
4585
- * @see https://docs.kucoin.com/futures/#transfer-funds-to-kucoin-main-account-2
4586
- * @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&
4587
4593
  * @param {string} code unified currency code
4588
4594
  * @param {float} amount amount to transfer
4589
4595
  * @param {string} fromAccount account to transfer from
4590
4596
  * @param {string} toAccount account to transfer to
4591
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
4592
4601
  * @returns {object} a [transfer structure]{@link https://docs.ccxt.com/?id=transfer-structure}
4593
4602
  */
4594
4603
  async transfer(code, amount, fromAccount, toAccount, params = {}) {
4595
4604
  await this.loadMarkets();
4596
4605
  const currency = this.currency(code);
4597
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
+ }
4598
4626
  let fromId = this.convertTypeToAccount(fromAccount);
4599
4627
  let toId = this.convertTypeToAccount(toAccount);
4600
4628
  const fromIsolated = this.inArray(fromId, this.ids);
4601
4629
  const toIsolated = this.inArray(toId, this.ids);
4602
- if (fromId === 'contract') {
4603
- if (toId !== 'main') {
4604
- throw new errors.ExchangeError(this.id + ' transfer() only supports transferring from futures account to main account');
4605
- }
4606
- const request = {
4607
- 'currency': currency['id'],
4608
- 'amount': requestedAmount,
4609
- };
4610
- if (!('bizNo' in params)) {
4611
- // it doesn't like more than 24 characters
4612
- request['bizNo'] = this.uuid22();
4613
- }
4614
- const response = await this.futuresPrivatePostTransferOut(this.extend(request, params));
4615
- //
4616
- // {
4617
- // "code": "200000",
4618
- // "data": {
4619
- // "applyId": "605a87217dff1500063d485d",
4620
- // "bizNo": "bcd6e5e1291f4905af84dc",
4621
- // "payAccountType": "CONTRACT",
4622
- // "payTag": "DEFAULT",
4623
- // "remark": '',
4624
- // "recAccountType": "MAIN",
4625
- // "recTag": "DEFAULT",
4626
- // "recRemark": '',
4627
- // "recSystem": "KUCOIN",
4628
- // "status": "PROCESSING",
4629
- // "currency": "XBT",
4630
- // "amount": "0.00001",
4631
- // "fee": "0",
4632
- // "sn": "573688685663948",
4633
- // "reason": '',
4634
- // "createdAt": 1616545569000,
4635
- // "updatedAt": 1616545569000
4636
- // }
4637
- // }
4638
- //
4639
- const data = this.safeDict(response, 'data');
4640
- return this.parseTransfer(data, currency);
4630
+ if (fromIsolated) {
4631
+ request['fromAccountTag'] = fromId;
4632
+ fromId = 'isolated';
4641
4633
  }
4642
- else {
4643
- const request = {
4644
- 'currency': currency['id'],
4645
- 'amount': requestedAmount,
4646
- };
4647
- if (fromIsolated || toIsolated) {
4648
- if (this.inArray(fromId, this.ids)) {
4649
- request['fromTag'] = fromId;
4650
- fromId = 'isolated';
4651
- }
4652
- if (this.inArray(toId, this.ids)) {
4653
- request['toTag'] = toId;
4654
- toId = 'isolated';
4655
- }
4656
- }
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
4657
4643
  request['from'] = fromId;
4658
4644
  request['to'] = toId;
4659
- if (!('clientOid' in params)) {
4660
- request['clientOid'] = this.uuid();
4661
- }
4662
- 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();
4663
4651
  //
4664
4652
  // {
4665
4653
  // "code": "200000",
4666
4654
  // "data": {
4667
- // "orderId": "605a6211e657f00006ad0ad6"
4655
+ // "orderId": "694fcb5b08bb1600015cda75"
4668
4656
  // }
4669
4657
  // }
4670
4658
  //
4671
- const data = this.safeDict(response, 'data');
4672
- return this.parseTransfer(data, currency);
4659
+ response = await this.privatePostAccountsUniversalTransfer(this.extend(request, params));
4673
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');
4674
4675
  }
4675
4676
  parseTransfer(transfer, currency = undefined) {
4676
4677
  //
@@ -4707,16 +4708,49 @@ class kucoin extends kucoin$1["default"] {
4707
4708
  // "updatedAt": 1616545569000
4708
4709
  // }
4709
4710
  //
4711
+ // ledger entry - from account ledgers API (for fetchTransfers)
4712
+ //
4713
+ // {
4714
+ // "id": "611a1e7c6a053300067a88d9",
4715
+ // "currency": "USDT",
4716
+ // "amount": "10.00059547",
4717
+ // "fee": "0",
4718
+ // "balance": "0",
4719
+ // "accountType": "MAIN",
4720
+ // "bizType": "Transfer",
4721
+ // "direction": "in",
4722
+ // "createdAt": 1629101692950,
4723
+ // "context": "{\"orderId\":\"611a1e7c6a053300067a88d9\"}"
4724
+ // }
4725
+ //
4710
4726
  const timestamp = this.safeInteger(transfer, 'createdAt');
4711
4727
  const currencyId = this.safeString(transfer, 'currency');
4712
4728
  const rawStatus = this.safeString(transfer, 'status');
4713
- const accountFromRaw = this.safeStringLower(transfer, 'payAccountType');
4714
- const accountToRaw = this.safeStringLower(transfer, 'recAccountType');
4729
+ const bizType = this.safeString(transfer, 'bizType');
4730
+ const isLedgerEntry = (bizType !== undefined);
4731
+ let accountFromRaw = undefined;
4732
+ let accountToRaw = undefined;
4733
+ if (isLedgerEntry) {
4734
+ // Ledger entry format: uses accountType + direction
4735
+ const accountType = this.safeStringLower(transfer, 'accountType');
4736
+ const direction = this.safeString(transfer, 'direction');
4737
+ if (direction === 'out') {
4738
+ accountFromRaw = accountType;
4739
+ }
4740
+ else if (direction === 'in') {
4741
+ accountToRaw = accountType;
4742
+ }
4743
+ }
4744
+ else {
4745
+ // Transfer API format: uses payAccountType/recAccountType
4746
+ accountFromRaw = this.safeStringLower(transfer, 'payAccountType');
4747
+ accountToRaw = this.safeStringLower(transfer, 'recAccountType');
4748
+ }
4715
4749
  const accountsByType = this.safeDict(this.options, 'accountsByType');
4716
4750
  const accountFrom = this.safeString(accountsByType, accountFromRaw, accountFromRaw);
4717
4751
  const accountTo = this.safeString(accountsByType, accountToRaw, accountToRaw);
4718
4752
  return {
4719
- 'id': this.safeString2(transfer, 'applyId', 'orderId'),
4753
+ 'id': this.safeStringN(transfer, ['id', 'applyId', 'orderId']),
4720
4754
  'currency': this.safeCurrencyCode(currencyId, currency),
4721
4755
  'timestamp': timestamp,
4722
4756
  'datetime': this.iso8601(timestamp),
@@ -5809,6 +5843,79 @@ class kucoin extends kucoin$1["default"] {
5809
5843
  }
5810
5844
  return undefined;
5811
5845
  }
5846
+ /**
5847
+ * @method
5848
+ * @name kucoin#fetchTransfers
5849
+ * @description fetch a history of internal transfers made on an account
5850
+ * @see https://www.kucoin.com/docs-new/rest/account-info/account-funding/get-account-ledgers-spot-margin
5851
+ * @param {string} [code] unified currency code of the currency transferred
5852
+ * @param {int} [since] the earliest time in ms to fetch transfers for
5853
+ * @param {int} [limit] the maximum number of transfer structures to retrieve
5854
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
5855
+ * @param {int} [params.until] the latest time in ms to fetch transfers for
5856
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
5857
+ * @returns {object[]} a list of [transfer structures]{@link https://docs.ccxt.com/?id=transfer-structure}
5858
+ */
5859
+ async fetchTransfers(code = undefined, since = undefined, limit = undefined, params = {}) {
5860
+ await this.loadMarkets();
5861
+ let paginate = false;
5862
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchTransfers', 'paginate');
5863
+ if (paginate) {
5864
+ return await this.fetchPaginatedCallDynamic('fetchTransfers', code, since, limit, params);
5865
+ }
5866
+ let request = {
5867
+ 'bizType': 'TRANSFER',
5868
+ };
5869
+ const until = this.safeInteger(params, 'until');
5870
+ if (until !== undefined) {
5871
+ params = this.omit(params, 'until');
5872
+ request['endAt'] = until;
5873
+ }
5874
+ let currency = undefined;
5875
+ if (code !== undefined) {
5876
+ currency = this.currency(code);
5877
+ request['currency'] = currency['id'];
5878
+ }
5879
+ if (since !== undefined) {
5880
+ request['startAt'] = since;
5881
+ }
5882
+ if (limit !== undefined) {
5883
+ request['pageSize'] = limit;
5884
+ }
5885
+ else {
5886
+ request['pageSize'] = 500;
5887
+ }
5888
+ [request, params] = this.handleUntilOption('endAt', request, params);
5889
+ const response = await this.privateGetAccountsLedgers(this.extend(request, params));
5890
+ //
5891
+ // {
5892
+ // "code": "200000",
5893
+ // "data": {
5894
+ // "currentPage": 1,
5895
+ // "pageSize": 50,
5896
+ // "totalNum": 1,
5897
+ // "totalPage": 1,
5898
+ // "items": [
5899
+ // {
5900
+ // "id": "611a1e7c6a053300067a88d9",
5901
+ // "currency": "USDT",
5902
+ // "amount": "10.00059547",
5903
+ // "fee": "0",
5904
+ // "balance": "0",
5905
+ // "accountType": "MAIN",
5906
+ // "bizType": "Transfer",
5907
+ // "direction": "in",
5908
+ // "createdAt": 1629101692950,
5909
+ // "context": "{\"orderId\":\"611a1e7c6a053300067a88d9\"}"
5910
+ // }
5911
+ // ]
5912
+ // }
5913
+ // }
5914
+ //
5915
+ const data = this.safeDict(response, 'data', {});
5916
+ const items = this.safeList(data, 'items', []);
5917
+ return this.parseTransfers(items, currency, since, limit);
5918
+ }
5812
5919
  }
5813
5920
 
5814
5921
  exports["default"] = kucoin;
@@ -748,9 +748,11 @@ class apex extends apex$1["default"] {
748
748
  }
749
749
  }
750
750
  // don't remove the future from the .futures cache
751
- const future = client.futures[messageHash];
752
- future.resolve(cache);
753
- client.resolve(cache, 'positions');
751
+ if (messageHash in client.futures) {
752
+ const future = client.futures[messageHash];
753
+ future.resolve(cache);
754
+ client.resolve(cache, 'positions');
755
+ }
754
756
  }
755
757
  handlePositions(client, lists) {
756
758
  //
@@ -983,7 +985,7 @@ class apex extends apex$1["default"] {
983
985
  await client.send({ 'args': [timeStamp.toString()], 'op': 'pong' });
984
986
  }
985
987
  catch (e) {
986
- 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));
987
989
  client.reset(error);
988
990
  }
989
991
  }
@@ -998,7 +1000,7 @@ class apex extends apex$1["default"] {
998
1000
  //
999
1001
  // { pong: 1653296711335 }
1000
1002
  //
1001
- client.lastPong = this.safeInteger(message, 'pong');
1003
+ client.lastPong = this.safeInteger(message, 'pong', this.milliseconds());
1002
1004
  return message;
1003
1005
  }
1004
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
  }
@@ -2594,9 +2594,11 @@ class binance extends binance$1["default"] {
2594
2594
  const response = await this.fetchBalance(params);
2595
2595
  this.balance[type] = this.extend(response, this.safeValue(this.balance, type, {}));
2596
2596
  // don't remove the future from the .futures cache
2597
- const future = client.futures[messageHash];
2598
- future.resolve();
2599
- client.resolve(this.balance[type], type + ':balance');
2597
+ if (messageHash in client.futures) {
2598
+ const future = client.futures[messageHash];
2599
+ future.resolve();
2600
+ client.resolve(this.balance[type], type + ':balance');
2601
+ }
2600
2602
  }
2601
2603
  /**
2602
2604
  * @method
@@ -4037,9 +4039,11 @@ class binance extends binance$1["default"] {
4037
4039
  }
4038
4040
  }
4039
4041
  // don't remove the future from the .futures cache
4040
- const future = client.futures[messageHash];
4041
- future.resolve(cache);
4042
- client.resolve(cache, type + ':position');
4042
+ if (messageHash in client.futures) {
4043
+ const future = client.futures[messageHash];
4044
+ future.resolve(cache);
4045
+ client.resolve(cache, type + ':position');
4046
+ }
4043
4047
  }
4044
4048
  handlePositions(client, message) {
4045
4049
  //