@subwallet/extension-base 1.3.26-0 → 1.3.27-0

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 (50) hide show
  1. package/background/KoniTypes.d.ts +4 -3
  2. package/background/warnings/TransactionWarning.d.ts +2 -0
  3. package/background/warnings/TransactionWarning.js +16 -1
  4. package/cjs/background/warnings/TransactionWarning.js +15 -0
  5. package/cjs/core/logic-validation/index.js +32 -1
  6. package/cjs/core/utils.js +25 -3
  7. package/cjs/koni/background/handlers/Extension.js +86 -94
  8. package/cjs/packageInfo.js +1 -1
  9. package/cjs/services/swap-service/handler/asset-hub/handler.js +182 -40
  10. package/cjs/services/swap-service/handler/asset-hub/utils.js +3 -0
  11. package/cjs/services/swap-service/handler/base-handler.js +326 -12
  12. package/cjs/services/swap-service/handler/chainflip-handler.js +80 -16
  13. package/cjs/services/swap-service/handler/hydradx-handler.js +174 -30
  14. package/cjs/services/swap-service/handler/simpleswap-handler.js +50 -1
  15. package/cjs/services/swap-service/handler/uniswap-handler.js +47 -1
  16. package/cjs/services/swap-service/index.js +191 -27
  17. package/cjs/services/swap-service/interface.js +14 -0
  18. package/cjs/services/swap-service/utils.js +81 -5
  19. package/core/logic-validation/index.d.ts +4 -0
  20. package/core/logic-validation/index.js +22 -1
  21. package/core/utils.d.ts +3 -0
  22. package/core/utils.js +22 -2
  23. package/koni/background/handlers/Extension.d.ts +2 -2
  24. package/koni/background/handlers/Extension.js +20 -28
  25. package/package.json +12 -7
  26. package/packageInfo.js +1 -1
  27. package/services/balance-service/helpers/process.d.ts +3 -3
  28. package/services/balance-service/index.d.ts +2 -3
  29. package/services/swap-service/handler/asset-hub/handler.d.ts +6 -3
  30. package/services/swap-service/handler/asset-hub/handler.js +170 -28
  31. package/services/swap-service/handler/asset-hub/utils.js +3 -0
  32. package/services/swap-service/handler/base-handler.d.ts +12 -3
  33. package/services/swap-service/handler/base-handler.js +329 -15
  34. package/services/swap-service/handler/chainflip-handler.d.ts +4 -3
  35. package/services/swap-service/handler/chainflip-handler.js +74 -10
  36. package/services/swap-service/handler/hydradx-handler.d.ts +8 -3
  37. package/services/swap-service/handler/hydradx-handler.js +176 -32
  38. package/services/swap-service/handler/simpleswap-handler.d.ts +4 -2
  39. package/services/swap-service/handler/simpleswap-handler.js +50 -1
  40. package/services/swap-service/handler/uniswap-handler.d.ts +4 -2
  41. package/services/swap-service/handler/uniswap-handler.js +47 -1
  42. package/services/swap-service/index.d.ts +15 -5
  43. package/services/swap-service/index.js +182 -18
  44. package/services/swap-service/interface.d.ts +9 -0
  45. package/services/swap-service/interface.js +8 -0
  46. package/services/swap-service/utils.d.ts +9 -1
  47. package/services/swap-service/utils.js +74 -4
  48. package/types/service-base.d.ts +6 -2
  49. package/types/swap/index.d.ts +34 -6
  50. package/types/transaction/process.d.ts +0 -6
@@ -6,15 +6,21 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.SwapBaseHandler = void 0;
8
8
  var _TransactionError = require("@subwallet/extension-base/background/errors/TransactionError");
9
+ var _KoniTypes = require("@subwallet/extension-base/background/KoniTypes");
10
+ var _logicValidation = require("@subwallet/extension-base/core/logic-validation");
9
11
  var _swap = require("@subwallet/extension-base/core/logic-validation/swap");
10
- var _utils = require("@subwallet/extension-base/services/chain-service/utils");
11
- var _utils2 = require("@subwallet/extension-base/services/swap-service/utils");
12
+ var _systemPallet = require("@subwallet/extension-base/core/substrate/system-pallet");
13
+ var _xcmParser = require("@subwallet/extension-base/core/substrate/xcm-parser");
14
+ var _utils = require("@subwallet/extension-base/core/utils");
15
+ var _utils2 = require("@subwallet/extension-base/services/chain-service/utils");
16
+ var _utils3 = require("@subwallet/extension-base/services/swap-service/utils");
12
17
  var _types = require("@subwallet/extension-base/types");
13
18
  var _serviceBase = require("@subwallet/extension-base/types/service-base");
14
19
  var _swap2 = require("@subwallet/extension-base/types/swap");
15
- var _utils3 = require("@subwallet/extension-base/utils");
20
+ var _utils4 = require("@subwallet/extension-base/utils");
16
21
  var _bignumber = _interopRequireDefault(require("bignumber.js"));
17
22
  var _i18next = require("i18next");
23
+ var _utilCrypto = require("@polkadot/util-crypto");
18
24
  // Copyright 2019-2022 @subwallet/extension-base
19
25
  // SPDX-License-Identifier: Apache-2.0
20
26
 
@@ -38,7 +44,30 @@ class SwapBaseHandler {
38
44
  async generateOptimalProcess(params, genStepFuncList) {
39
45
  const result = {
40
46
  totalFee: [_serviceBase.MOCK_STEP_FEE],
41
- steps: [_serviceBase.DEFAULT_FIRST_STEP]
47
+ steps: [_serviceBase.DEFAULT_FIRST_STEP],
48
+ path: []
49
+ };
50
+ try {
51
+ for (const genStepFunc of genStepFuncList) {
52
+ const step = await genStepFunc(params);
53
+ if (step) {
54
+ result.steps.push({
55
+ id: result.steps.length,
56
+ ...step[0]
57
+ });
58
+ result.totalFee.push(step[1]);
59
+ }
60
+ }
61
+ return result;
62
+ } catch (e) {
63
+ return result;
64
+ }
65
+ }
66
+ async generateOptimalProcessV2(params, genStepFuncList) {
67
+ const result = {
68
+ totalFee: [_serviceBase.MOCK_STEP_FEE],
69
+ steps: [_serviceBase.DEFAULT_FIRST_STEP],
70
+ path: params.path
42
71
  };
43
72
  try {
44
73
  for (const genStepFunc of genStepFuncList) {
@@ -59,7 +88,7 @@ class SwapBaseHandler {
59
88
  async validateXcmStep(params, stepIndex) {
60
89
  const bnAmount = new _bignumber.default(params.selectedQuote.fromAmount);
61
90
  const swapPair = params.selectedQuote.pair;
62
- const alternativeAssetSlug = (0, _utils2.getSwapAlternativeAsset)(swapPair);
91
+ const alternativeAssetSlug = (0, _utils3.getSwapAlternativeAsset)(swapPair);
63
92
  if (!alternativeAssetSlug) {
64
93
  return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
65
94
  }
@@ -72,22 +101,22 @@ class SwapBaseHandler {
72
101
  const xcmFee = new _bignumber.default(xcmFeeComponent.amount || '0');
73
102
  let xcmAmount = bnAmount.minus(bnFromAssetBalance);
74
103
  let editedXcmFee = new _bignumber.default(0);
75
- if ((0, _utils._isNativeToken)(alternativeAsset)) {
104
+ if ((0, _utils2._isNativeToken)(alternativeAsset)) {
76
105
  xcmAmount = xcmAmount.plus(xcmFee);
77
106
  editedXcmFee = xcmFee.times(2);
78
107
  }
79
- if (!bnAlternativeAssetBalance.minus((0, _utils._isNativeToken)(alternativeAsset) ? xcmAmount.plus(xcmFee) : xcmFee).gt(0)) {
80
- const maxBn = bnFromAssetBalance.plus(new _bignumber.default(alternativeAssetBalance.value)).minus((0, _utils._isNativeToken)(alternativeAsset) ? editedXcmFee : xcmFee);
81
- const maxValue = (0, _utils3.formatNumber)(maxBn.toString(), fromAsset.decimals || 0);
108
+ if (!bnAlternativeAssetBalance.minus((0, _utils2._isNativeToken)(alternativeAsset) ? xcmAmount.plus(xcmFee) : xcmFee).gt(0)) {
109
+ const maxBn = bnFromAssetBalance.plus(new _bignumber.default(alternativeAssetBalance.value)).minus((0, _utils2._isNativeToken)(alternativeAsset) ? editedXcmFee : xcmFee);
110
+ const maxValue = (0, _utils4.formatNumber)(maxBn.toString(), fromAsset.decimals || 0);
82
111
  const altInputTokenInfo = this.chainService.getAssetBySlug(alternativeAssetSlug);
83
112
  const symbol = altInputTokenInfo.symbol;
84
113
  const alternativeChain = this.chainService.getChainInfoByKey(altInputTokenInfo.originChain);
85
114
  const chain = this.chainService.getChainInfoByKey(fromAsset.originChain);
86
115
  const inputNetworkName = chain.name;
87
116
  const altNetworkName = alternativeChain.name;
88
- const currentValue = (0, _utils3.formatNumber)(bnFromAssetBalance.toString(), fromAsset.decimals || 0);
89
- const bnMaxXCM = new _bignumber.default(alternativeAssetBalance.value).minus((0, _utils._isNativeToken)(alternativeAsset) ? editedXcmFee : xcmFee);
90
- const maxXCMValue = (0, _utils3.formatNumber)(bnMaxXCM.toString(), fromAsset.decimals || 0);
117
+ const currentValue = (0, _utils4.formatNumber)(bnFromAssetBalance.toString(), fromAsset.decimals || 0);
118
+ const bnMaxXCM = new _bignumber.default(alternativeAssetBalance.value).minus((0, _utils2._isNativeToken)(alternativeAsset) ? editedXcmFee : xcmFee);
119
+ const maxXCMValue = (0, _utils4.formatNumber)(bnMaxXCM.toString(), fromAsset.decimals || 0);
91
120
  if (maxBn.lte(0) || bnFromAssetBalance.lte(0) || bnMaxXCM.lte(0)) {
92
121
  return [new _TransactionError.TransactionError(_types.BasicTxErrorType.NOT_ENOUGH_BALANCE, (0, _i18next.t)(`Insufficient balance. Deposit ${fromAsset.symbol} and try again.`))];
93
122
  }
@@ -104,6 +133,108 @@ class SwapBaseHandler {
104
133
  }
105
134
  return [];
106
135
  }
136
+ async validateXcmStepV2(params, stepIndex) {
137
+ var _currentFee$feeCompon, _params$recipient;
138
+ const currentStep = params.process.steps[stepIndex];
139
+ const currentFee = params.process.totalFee[stepIndex];
140
+ const feeToken = currentFee.selectedFeeToken || currentFee.defaultFeeToken;
141
+ const feeAmount = (_currentFee$feeCompon = currentFee.feeComponent.find(fee => fee.feeType === _swap2.SwapFeeType.NETWORK_FEE)) === null || _currentFee$feeCompon === void 0 ? void 0 : _currentFee$feeCompon.amount;
142
+ if (!feeAmount) {
143
+ throw new Error('Fee not found for XCM step');
144
+ }
145
+ const metadata = currentStep.metadata;
146
+ const sendingAmount = metadata.sendingValue;
147
+ const bnAmount = new _bignumber.default(sendingAmount);
148
+ const fromAsset = metadata === null || metadata === void 0 ? void 0 : metadata.originTokenInfo;
149
+ const toAsset = metadata === null || metadata === void 0 ? void 0 : metadata.destinationTokenInfo;
150
+ if (!fromAsset || !toAsset) {
151
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
152
+ }
153
+ const fromChain = this.chainService.getChainInfoByKey(fromAsset.originChain);
154
+ const toChain = this.chainService.getChainInfoByKey(toAsset.originChain);
155
+ const toChainNativeAsset = this.chainService.getNativeTokenInfo(toAsset.originChain);
156
+ const sender = (0, _utils4._reformatAddressWithChain)(params.address, fromChain);
157
+ const receiver = (0, _utils4._reformatAddressWithChain)((_params$recipient = params.recipient) !== null && _params$recipient !== void 0 ? _params$recipient : sender, toChain);
158
+
159
+ /* Get transferable balance */
160
+ const [fromAssetBalance, feeTokenBalance] = await Promise.all([this.balanceService.getTransferableBalance(sender, fromAsset.originChain, fromAsset.slug, _KoniTypes.ExtrinsicType.TRANSFER_XCM), this.balanceService.getTransferableBalance(sender, fromAsset.originChain, feeToken, _KoniTypes.ExtrinsicType.TRANSFER_XCM)]);
161
+ const bnFromAssetBalance = new _bignumber.default(fromAssetBalance.value);
162
+ const bnFeeTokenBalance = new _bignumber.default(feeTokenBalance.value);
163
+
164
+ /* Compare transferable balance with amount xcm */
165
+ if (bnFromAssetBalance.lt(bnAmount)) {
166
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.NOT_ENOUGH_BALANCE, (0, _i18next.t)(`Insufficient balance. Deposit ${fromAsset.symbol} and try again.`))];
167
+ }
168
+
169
+ /**
170
+ * Calculate fee token keep alive after xcm
171
+ * If fee token is the same as from token, need to subtract sending amount
172
+ * @TODO: Need to update logic if change fee token (multi with rate)
173
+ * */
174
+ const feeBalanceAfterTransfer = bnFeeTokenBalance.minus(feeAmount).minus(fromAsset.slug === feeToken ? bnAmount : 0);
175
+
176
+ /**
177
+ * Check fee token balance after transfer.
178
+ * Because the balance had subtracted with existence deposit, so only need to check if it's less than 0
179
+ * */
180
+ if (feeBalanceAfterTransfer.lt(0)) {
181
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.NOT_ENOUGH_EXISTENTIAL_DEPOSIT, (0, _i18next.t)(`Insufficient balance. Deposit ${fromAsset.symbol} and try again.`))];
182
+ }
183
+ const destMinAmount = (0, _utils2._getTokenMinAmount)(toAsset);
184
+ // TODO: Need to update with new logic, calculate fee to claim on dest chain
185
+ const minSendingRequired = new _bignumber.default(destMinAmount).multipliedBy(_utils3.FEE_RATE_MULTIPLIER.high);
186
+
187
+ // Check sending token ED for receiver
188
+ if (bnAmount.lt(minSendingRequired)) {
189
+ const atLeastStr = (0, _utils4.formatNumber)(minSendingRequired, (0, _utils2._getAssetDecimals)(toAsset), _utils4.balanceFormatter, {
190
+ maxNumberFormat: (0, _utils2._getAssetDecimals)(toAsset) || 6
191
+ });
192
+ return [new _TransactionError.TransactionError(_types.TransferTxErrorType.RECEIVER_NOT_ENOUGH_EXISTENTIAL_DEPOSIT, (0, _i18next.t)('You must transfer at least {{amount}} {{symbol}} to keep the destination account alive', {
193
+ replace: {
194
+ amount: atLeastStr,
195
+ symbol: fromAsset.symbol
196
+ }
197
+ }))];
198
+ }
199
+
200
+ // Check keepAlive on dest chain for receiver
201
+ if (!(0, _utils2._isNativeToken)(toAsset)) {
202
+ const toChainApi = this.chainService.getSubstrateApi(toAsset.originChain);
203
+
204
+ // TODO: Need to update, currently only support substrate xcm
205
+ if (!toChainApi) {
206
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR, (0, _i18next.t)('Destination chain is not active'))];
207
+ }
208
+ const isSendingTokenSufficient = await (0, _utils._isSufficientToken)(toAsset, toChainApi);
209
+ if (!isSendingTokenSufficient) {
210
+ const toChainNativeAssetBalance = await this.balanceService.getTotalBalance(receiver, toAsset.originChain, toChainNativeAsset.slug, _KoniTypes.ExtrinsicType.TRANSFER_BALANCE);
211
+ const isReceiverAliveByNativeToken = (0, _systemPallet._isAccountActive)(toChainNativeAssetBalance.metadata);
212
+ if (!isReceiverAliveByNativeToken) {
213
+ // TODO: Update message
214
+ return [new _TransactionError.TransactionError(_types.TransferTxErrorType.RECEIVER_NOT_ENOUGH_EXISTENTIAL_DEPOSIT, (0, _i18next.t)('The recipient account has less than {{amount}} {{nativeSymbol}}, which can lead to your {{localSymbol}} being lost. Change recipient account and try again', {
215
+ replace: {
216
+ amount: toChainNativeAssetBalance.value,
217
+ nativeSymbol: toChainNativeAsset.symbol,
218
+ localSymbol: toAsset.symbol
219
+ }
220
+ }))];
221
+ }
222
+ }
223
+ }
224
+
225
+ // SKIP: BECAUSE CURRENTLY NOT SUPPORT SNOWBRIDGE FOR SWAP FEATURE
226
+ // check native token ED on dest chain for receiver
227
+ // const bnKeepAliveBalance = _isNativeToken(destinationTokenInfo) ? new BigN(receiverNativeBalance).plus(sendingAmount) : new BigN(receiverNativeBalance);
228
+ //
229
+ // if (isSnowBridge && bnKeepAliveBalance.lt(_getChainExistentialDeposit(destChainInfo))) {
230
+ // const { decimals, symbol } = _getChainNativeTokenBasicInfo(destChainInfo);
231
+ // const atLeastStr = formatNumber(_getChainExistentialDeposit(destChainInfo), decimals || 0, balanceFormatter, { maxNumberFormat: 6 });
232
+ //
233
+ // error = new TransactionError(TransferTxErrorType.RECEIVER_NOT_ENOUGH_EXISTENTIAL_DEPOSIT, t(' Insufficient {{symbol}} on {{chain}} to cover min balance ({{amount}} {{symbol}})', { replace: { amount: atLeastStr, symbol, chain: destChainInfo.name } }));
234
+ // }
235
+
236
+ return [];
237
+ }
107
238
  async validateTokenApproveStep(params, stepIndex) {
108
239
  return Promise.resolve([]);
109
240
  }
@@ -162,6 +293,189 @@ class SwapBaseHandler {
162
293
  }
163
294
  return Promise.resolve([]);
164
295
  }
296
+ async validateBridgeStep(receiver, fromToken, toToken, selectedFeeToken, toChainNativeToken, bnBridgeAmount, bnFromTokenBalance, bnBridgeFeeAmount, bnFeeTokenBalance, bnBridgeDeliveryFee) {
297
+ const minBridgeAmountRequired = new _bignumber.default((0, _utils2._getTokenMinAmount)(toToken)).multipliedBy(_utils3.FEE_RATE_MULTIPLIER.high);
298
+ const spendingAndFeePaymentValidation = (0, _logicValidation.validateSpendingAndFeePayment)(fromToken, selectedFeeToken, bnBridgeAmount, bnFromTokenBalance, bnBridgeFeeAmount, bnFeeTokenBalance);
299
+ if (spendingAndFeePaymentValidation.length > 0) {
300
+ return spendingAndFeePaymentValidation;
301
+ }
302
+ if (bnBridgeAmount.lte(minBridgeAmountRequired.plus(bnBridgeDeliveryFee))) {
303
+ const atLeastStr = (0, _utils4.formatNumber)(minBridgeAmountRequired.plus(bnBridgeDeliveryFee), (0, _utils2._getAssetDecimals)(toToken), _utils4.balanceFormatter, {
304
+ maxNumberFormat: (0, _utils2._getAssetDecimals)(toToken) || 6
305
+ });
306
+ return [new _TransactionError.TransactionError(_types.TransferTxErrorType.RECEIVER_NOT_ENOUGH_EXISTENTIAL_DEPOSIT, (0, _i18next.t)('You must transfer at least {{amount}} {{symbol}} to keep the destination account alive', {
307
+ replace: {
308
+ amount: atLeastStr,
309
+ symbol: fromToken.symbol
310
+ }
311
+ }))];
312
+ }
313
+
314
+ // By here, we know that the user is receiving a valid amount of toToken
315
+ const toChainApi = this.chainService.getSubstrateApi(toToken.originChain);
316
+ if (!toChainApi) {
317
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
318
+ }
319
+
320
+ // Only need to check if account is alive with the receiving toToken
321
+ const isToTokenSufficient = await (0, _utils._isSufficientToken)(toToken, toChainApi);
322
+ if (!isToTokenSufficient && !(0, _utils2._isNativeToken)(toToken)) {
323
+ // sending token cannot keep account alive, must check with native token
324
+ const toChainNativeTokenBalance = await this.balanceService.getTotalBalance(receiver, toToken.originChain, toChainNativeToken.slug, _KoniTypes.ExtrinsicType.TRANSFER_BALANCE);
325
+ if (!(0, _systemPallet._isAccountActive)(toChainNativeTokenBalance.metadata)) {
326
+ return [new _TransactionError.TransactionError(_types.TransferTxErrorType.RECEIVER_NOT_ENOUGH_EXISTENTIAL_DEPOSIT, (0, _i18next.t)('The recipient account has less than {{amount}} {{nativeSymbol}}, which can lead to your {{localSymbol}} being lost. Change recipient account and try again', {
327
+ replace: {
328
+ amount: toChainNativeTokenBalance.value,
329
+ nativeSymbol: toChainNativeToken.symbol,
330
+ localSymbol: toToken.symbol
331
+ }
332
+ }))];
333
+ }
334
+ }
335
+ return [];
336
+ }
337
+ validateSwapStepV2(swapToChain, swapToken, receivingToken, swapFeeToken, bnSwapValue, bnExpectedReceivingAmount, bnSwapFromTokenBalance, bnSwapFeeAmount, bnSwapFeeTokenBalance, recipient) {
338
+ const spendingAndFeePaymentValidation = (0, _logicValidation.validateSpendingAndFeePayment)(swapToken, swapFeeToken, bnSwapValue, bnSwapFromTokenBalance, bnSwapFeeAmount, bnSwapFeeTokenBalance);
339
+ if (spendingAndFeePaymentValidation.length > 0) {
340
+ return spendingAndFeePaymentValidation;
341
+ }
342
+ if (bnExpectedReceivingAmount.lte((0, _utils2._getTokenMinAmount)(receivingToken))) {
343
+ const atLeastStr = (0, _utils4.formatNumber)((0, _utils2._getTokenMinAmount)(receivingToken), (0, _utils2._getAssetDecimals)(receivingToken), _utils4.balanceFormatter, {
344
+ maxNumberFormat: (0, _utils2._getAssetDecimals)(receivingToken) || 6
345
+ });
346
+ return [new _TransactionError.TransactionError(_swap2.SwapErrorType.NOT_MEET_MIN_SWAP, (0, _i18next.t)('You can\'t receive less than {{number}} {{symbol}}', {
347
+ replace: {
348
+ number: atLeastStr,
349
+ symbol: (0, _utils2._getAssetSymbol)(receivingToken)
350
+ }
351
+ }))];
352
+ }
353
+ if (recipient) {
354
+ const isEvmAddress = (0, _utilCrypto.isEthereumAddress)(recipient);
355
+ const isEvmDestChain = (0, _utils2._isChainEvmCompatible)(swapToChain);
356
+ if (isEvmAddress && !isEvmDestChain || !isEvmAddress && isEvmDestChain) {
357
+ // todo: update this condition
358
+ return [new _TransactionError.TransactionError(_swap2.SwapErrorType.INVALID_RECIPIENT)];
359
+ }
360
+ }
361
+ return [];
362
+ }
363
+ async validateSwapOnlyProcess(params, swapIndex) {
364
+ const swapStepInfo = params.process.steps[swapIndex];
365
+ const swapMetadata = swapStepInfo.metadata; // todo
366
+ const swapFee = params.process.totalFee[swapIndex];
367
+ if (!swapMetadata || !swapMetadata.destinationTokenInfo || !swapMetadata.originTokenInfo || !swapMetadata.sendingValue) {
368
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
369
+ }
370
+
371
+ // Validate quote
372
+ if (!params.selectedQuote) {
373
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
374
+ }
375
+ if (params.selectedQuote.aliveUntil <= +Date.now()) {
376
+ return [new _TransactionError.TransactionError(_swap2.SwapErrorType.QUOTE_TIMEOUT)];
377
+ }
378
+ const swapNetworkFee = swapFee.feeComponent.find(fee => fee.feeType === _swap2.SwapFeeType.NETWORK_FEE);
379
+ if (!swapNetworkFee) {
380
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
381
+ }
382
+ const swapToken = swapMetadata.originTokenInfo;
383
+ const swapReceivingToken = swapMetadata.destinationTokenInfo;
384
+ const bnSwapReceivingAmount = (0, _bignumber.default)(params.selectedQuote.toAmount);
385
+ const bnSwapValue = (0, _bignumber.default)(swapMetadata.sendingValue);
386
+ const bnSwapFeeAmount = (0, _bignumber.default)(swapNetworkFee.amount);
387
+ const swapFeeToken = this.chainService.getAssetBySlug(swapFee.selectedFeeToken || swapFee.defaultFeeToken);
388
+ const swapToChain = this.chainService.getChainInfoByKey(swapMetadata.destinationTokenInfo.originChain);
389
+ const [swapFeeTokenBalance, swapFromTokenBalance] = await Promise.all([this.balanceService.getTransferableBalance(params.address, swapFeeToken.originChain, swapFeeToken.slug, _KoniTypes.ExtrinsicType.SWAP), this.balanceService.getTransferableBalance(params.address, swapToken.originChain, swapToken.slug, _KoniTypes.ExtrinsicType.SWAP)]);
390
+ const bnSwapFromTokenBalance = (0, _bignumber.default)(swapFromTokenBalance.value);
391
+ const bnSwapFeeTokenBalance = (0, _bignumber.default)(swapFeeTokenBalance.value);
392
+ return this.validateSwapStepV2(swapToChain, swapToken, swapReceivingToken, swapFeeToken, bnSwapValue, bnSwapReceivingAmount, bnSwapFromTokenBalance, bnSwapFeeAmount, bnSwapFeeTokenBalance, params.recipient);
393
+ }
394
+ async validateXcmSwapProcess(params, swapIndex, xcmIndex) {
395
+ var _currentFee$feeCompon2, _params$recipient2;
396
+ // Bridge
397
+ const currentStep = params.process.steps[xcmIndex];
398
+ const xcmMetadata = currentStep.metadata;
399
+ const currentFee = params.process.totalFee[xcmIndex];
400
+ const bridgeFeeAmount = (_currentFee$feeCompon2 = currentFee.feeComponent.find(fee => fee.feeType === _swap2.SwapFeeType.NETWORK_FEE)) === null || _currentFee$feeCompon2 === void 0 ? void 0 : _currentFee$feeCompon2.amount;
401
+ if (!xcmMetadata || !xcmMetadata.destinationTokenInfo || !xcmMetadata.originTokenInfo || !xcmMetadata.sendingValue) {
402
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
403
+ }
404
+ if (!bridgeFeeAmount) {
405
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
406
+ }
407
+ const bridgeFromToken = xcmMetadata.originTokenInfo;
408
+ const bridgeToToken = xcmMetadata.destinationTokenInfo;
409
+ const fromChain = this.chainService.getChainInfoByKey(bridgeFromToken.originChain);
410
+ const toChain = this.chainService.getChainInfoByKey(bridgeToToken.originChain);
411
+ if ((0, _xcmParser._isSnowBridgeXcm)(fromChain, toChain)) {
412
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.UNSUPPORTED)];
413
+ }
414
+ const bnBridgeFeeAmount = (0, _bignumber.default)(bridgeFeeAmount);
415
+ const bnBridgeAmount = new _bignumber.default(xcmMetadata.sendingValue);
416
+ const bridgeToChainNativeToken = this.chainService.getNativeTokenInfo(bridgeToToken.originChain);
417
+ const bridgeSelectedFeeToken = this.chainService.getAssetBySlug(currentFee.selectedFeeToken || currentFee.defaultFeeToken);
418
+ const bnBridgeDeliveryFee = (0, _bignumber.default)(0); // todo
419
+
420
+ const bridgeSender = (0, _utils4._reformatAddressWithChain)(params.address, this.chainService.getChainInfoByKey(bridgeFromToken.originChain));
421
+ const bridgeReceiver = (0, _utils4._reformatAddressWithChain)((_params$recipient2 = params.recipient) !== null && _params$recipient2 !== void 0 ? _params$recipient2 : bridgeSender, this.chainService.getChainInfoByKey(bridgeToToken.originChain));
422
+ const [bridgeFromTokenBalance, bridgeFeeTokenBalance] = await Promise.all([this.balanceService.getTransferableBalance(bridgeSender, bridgeFromToken.originChain, bridgeFromToken.slug, _KoniTypes.ExtrinsicType.TRANSFER_XCM), this.balanceService.getTransferableBalance(bridgeSender, bridgeFromToken.originChain, bridgeSelectedFeeToken.slug, _KoniTypes.ExtrinsicType.TRANSFER_XCM)]);
423
+
424
+ // Native token balance has already accounted for ED aka strict mode
425
+ const bnBridgeFromTokenBalance = new _bignumber.default(bridgeFromTokenBalance.value);
426
+ const bnBridgeFeeTokenBalance = new _bignumber.default(bridgeFeeTokenBalance.value);
427
+ const bridgeStepValidation = await this.validateBridgeStep(bridgeReceiver, bridgeFromToken, bridgeToToken, bridgeSelectedFeeToken, bridgeToChainNativeToken, bnBridgeAmount, bnBridgeFromTokenBalance, bnBridgeFeeAmount, bnBridgeFeeTokenBalance, bnBridgeDeliveryFee);
428
+ if (bridgeStepValidation.length > 0) {
429
+ return bridgeStepValidation;
430
+ }
431
+
432
+ // Swap
433
+ const swapStepInfo = params.process.steps[swapIndex];
434
+ const swapMetadata = swapStepInfo.metadata; // todo
435
+ const swapFee = params.process.totalFee[swapIndex];
436
+ if (!swapMetadata || !swapMetadata.destinationTokenInfo || !swapMetadata.originTokenInfo || !swapMetadata.sendingValue) {
437
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
438
+ }
439
+
440
+ // Validate quote
441
+ if (!params.selectedQuote) {
442
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
443
+ }
444
+ if (params.selectedQuote.aliveUntil <= +Date.now()) {
445
+ return [new _TransactionError.TransactionError(_swap2.SwapErrorType.QUOTE_TIMEOUT)];
446
+ }
447
+ const swapNetworkFee = swapFee.feeComponent.find(fee => fee.feeType === _swap2.SwapFeeType.NETWORK_FEE);
448
+ if (!swapNetworkFee) {
449
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
450
+ }
451
+ const swapToken = swapMetadata.originTokenInfo;
452
+ const swapReceivingToken = swapMetadata.destinationTokenInfo;
453
+ const bnSwapReceivingAmount = (0, _bignumber.default)(params.selectedQuote.toAmount);
454
+ if (swapToken.slug !== bridgeToToken.slug) {
455
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
456
+ }
457
+ const bnSwapValue = (0, _bignumber.default)(swapMetadata.sendingValue);
458
+ const bnSwapFeeAmount = (0, _bignumber.default)(swapNetworkFee.amount);
459
+ if (bnSwapValue.gt(bnBridgeAmount)) {
460
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
461
+ }
462
+ if (bnSwapValue.lte((0, _utils2._getTokenMinAmount)(swapToken))) {
463
+ const atLeastString = (0, _utils4.formatNumber)((0, _utils2._getTokenMinAmount)(swapToken), (0, _utils2._getAssetDecimals)(swapToken), _utils4.balanceFormatter, {
464
+ maxNumberFormat: (0, _utils2._getAssetDecimals)(swapToken) || 6
465
+ });
466
+ return [new _TransactionError.TransactionError(_swap2.SwapErrorType.NOT_MEET_MIN_SWAP, (0, _i18next.t)(`Swap amount too small. Increase to more than ${atLeastString} ${(0, _utils2._getAssetSymbol)(swapToken)} and try again`))];
467
+ }
468
+ const swapFeeToken = this.chainService.getAssetBySlug(swapFee.selectedFeeToken || swapFee.defaultFeeToken);
469
+ const swapToChain = this.chainService.getChainInfoByKey(swapMetadata.destinationTokenInfo.originChain);
470
+ const [swapFeeTokenBalance, swapFromTokenBalance] = await Promise.all([this.balanceService.getTransferableBalance(params.address, swapFeeToken.originChain, swapFeeToken.slug, _KoniTypes.ExtrinsicType.SWAP), this.balanceService.getTransferableBalance(params.address, swapToken.originChain, swapToken.slug, _KoniTypes.ExtrinsicType.SWAP)]);
471
+ const bnSwapFromTokenBalance = (0, _bignumber.default)(swapFromTokenBalance.value).plus(bnBridgeAmount);
472
+ const bnSwapFeeTokenBalance = (0, _bignumber.default)(swapFeeTokenBalance.value);
473
+ const swapStepValidation = this.validateSwapStepV2(swapToChain, swapToken, swapReceivingToken, swapFeeToken, bnSwapValue, bnSwapReceivingAmount, bnSwapFromTokenBalance, bnSwapFeeAmount, bnSwapFeeTokenBalance, params.recipient);
474
+ if (swapStepValidation.length > 0) {
475
+ return swapStepValidation;
476
+ }
477
+ return [];
478
+ }
165
479
  get name() {
166
480
  return this.providerName;
167
481
  }
@@ -12,10 +12,9 @@ var _smartContract = require("@subwallet/extension-base/services/balance-service
12
12
  var _token = require("@subwallet/extension-base/services/balance-service/transfer/token");
13
13
  var _utils = require("@subwallet/extension-base/services/chain-service/utils");
14
14
  var _baseHandler = require("@subwallet/extension-base/services/swap-service/handler/base-handler");
15
+ var _interface = require("@subwallet/extension-base/services/swap-service/interface");
15
16
  var _utils2 = require("@subwallet/extension-base/services/swap-service/utils");
16
17
  var _types = require("@subwallet/extension-base/types");
17
- var _serviceBase = require("@subwallet/extension-base/types/service-base");
18
- var _swap = require("@subwallet/extension-base/types/swap");
19
18
  var _utils3 = require("@subwallet/extension-base/utils");
20
19
  var _getId = require("@subwallet/extension-base/utils/getId");
21
20
  var _bignumber = _interopRequireDefault(require("bignumber.js"));
@@ -34,10 +33,10 @@ class ChainflipSwapHandler {
34
33
  balanceService,
35
34
  feeService,
36
35
  providerName: isTestnet ? 'Chainflip Testnet' : 'Chainflip',
37
- providerSlug: isTestnet ? _swap.SwapProviderId.CHAIN_FLIP_TESTNET : _swap.SwapProviderId.CHAIN_FLIP_MAINNET
36
+ providerSlug: isTestnet ? _types.SwapProviderId.CHAIN_FLIP_TESTNET : _types.SwapProviderId.CHAIN_FLIP_MAINNET
38
37
  });
39
38
  this.isTestnet = isTestnet;
40
- this.providerSlug = isTestnet ? _swap.SwapProviderId.CHAIN_FLIP_TESTNET : _swap.SwapProviderId.CHAIN_FLIP_MAINNET;
39
+ this.providerSlug = isTestnet ? _types.SwapProviderId.CHAIN_FLIP_TESTNET : _types.SwapProviderId.CHAIN_FLIP_MAINNET;
41
40
  this.baseUrl = (0, _utils2.getChainflipSwap)(isTestnet);
42
41
  }
43
42
  get chainService() {
@@ -72,9 +71,9 @@ class ChainflipSwapHandler {
72
71
  for (const [index, step] of params.process.steps.entries()) {
73
72
  const getErrors = async () => {
74
73
  switch (step.type) {
75
- case _serviceBase.CommonStepType.DEFAULT:
74
+ case _types.CommonStepType.DEFAULT:
76
75
  return Promise.resolve([]);
77
- case _serviceBase.CommonStepType.TOKEN_APPROVAL:
76
+ case _types.CommonStepType.TOKEN_APPROVAL:
78
77
  return Promise.reject(new _TransactionError.TransactionError(_types.BasicTxErrorType.UNSUPPORTED));
79
78
  default:
80
79
  return this.swapBaseHandler.validateSwapStep(params, isXcmOk, index);
@@ -83,7 +82,7 @@ class ChainflipSwapHandler {
83
82
  const errors = await getErrors();
84
83
  if (errors.length) {
85
84
  return errors;
86
- } else if (step.type === _serviceBase.CommonStepType.XCM) {
85
+ } else if (step.type === _types.CommonStepType.XCM) {
87
86
  isXcmOk = true;
88
87
  }
89
88
  }
@@ -106,9 +105,19 @@ class ChainflipSwapHandler {
106
105
  const fromAssetId = (0, _utils._getAssetSymbol)(fromAsset);
107
106
  const toAssetId = (0, _utils._getAssetSymbol)(toAsset);
108
107
  const minReceive = new _bignumber.default(quote.rate).times(1 - slippage).toString();
108
+ const processMetadata = params.process.steps[params.currentStep].metadata;
109
+ const quoteMetadata = params.quote.metadata;
110
+ if (!processMetadata || !quoteMetadata) {
111
+ throw new Error('Metadata for Chainflip not found');
112
+ }
113
+ if (processMetadata.destChain !== quoteMetadata.destChain || processMetadata.srcChain !== quoteMetadata.srcChain) {
114
+ throw new Error('Metadata for Chainflip not found');
115
+ }
109
116
  const depositParams = {
117
+ sourceChain: processMetadata.srcChain,
110
118
  destinationAddress: receiver,
111
119
  destinationAsset: toAssetId,
120
+ destinationChain: processMetadata.destChain,
112
121
  minimumPrice: minReceive,
113
122
  // minimum accepted price for swaps through the channel
114
123
  refundAddress: address,
@@ -122,6 +131,9 @@ class ChainflipSwapHandler {
122
131
  method: 'GET'
123
132
  });
124
133
  const data = await response.json();
134
+ if (!data.id || !data.address || data.address === '' || !data.issuedBlock || !data.network || !data.channelId) {
135
+ throw new Error('Error get Chainflip data');
136
+ }
125
137
  const depositChannelId = `${data.issuedBlock}-${data.network}-${data.channelId}`;
126
138
  const depositAddress = data.address;
127
139
  const txData = {
@@ -194,26 +206,78 @@ class ChainflipSwapHandler {
194
206
  } = params;
195
207
  const type = process.steps[currentStep].type;
196
208
  switch (type) {
197
- case _serviceBase.CommonStepType.DEFAULT:
209
+ case _types.CommonStepType.DEFAULT:
198
210
  return Promise.reject(new _TransactionError.TransactionError(_types.BasicTxErrorType.UNSUPPORTED));
199
- case _swap.SwapStepType.SWAP:
211
+ case _types.SwapStepType.SWAP:
200
212
  return this.handleSubmitStep(params);
201
213
  default:
202
214
  return this.handleSubmitStep(params);
203
215
  }
204
216
  }
205
217
  async getSubmitStep(params) {
206
- if (params.selectedQuote) {
207
- const submitStep = {
208
- name: 'Swap',
209
- type: _swap.SwapStepType.SWAP
210
- };
211
- return Promise.resolve([submitStep, params.selectedQuote.feeInfo]);
218
+ var _params$selectedQuote;
219
+ const metadata = (_params$selectedQuote = params.selectedQuote) === null || _params$selectedQuote === void 0 ? void 0 : _params$selectedQuote.metadata;
220
+ if (!params.selectedQuote) {
221
+ return Promise.resolve(undefined);
222
+ }
223
+ if (!metadata || !metadata.srcChain || !metadata.destChain) {
224
+ return Promise.resolve(undefined);
212
225
  }
213
- return Promise.resolve(undefined);
226
+ const submitStep = {
227
+ name: 'Swap',
228
+ type: _types.SwapStepType.SWAP,
229
+ metadata: {
230
+ sendingValue: params.request.fromAmount.toString(),
231
+ originTokenInfo: this.chainService.getAssetBySlug(params.selectedQuote.pair.from),
232
+ destinationTokenInfo: this.chainService.getAssetBySlug(params.selectedQuote.pair.to),
233
+ srcChain: metadata.srcChain,
234
+ destChain: metadata.destChain
235
+ }
236
+ };
237
+ return Promise.resolve([submitStep, params.selectedQuote.feeInfo]);
214
238
  }
215
239
  generateOptimalProcess(params) {
216
240
  return this.swapBaseHandler.generateOptimalProcess(params, [this.getSubmitStep.bind(this)]);
217
241
  }
242
+ generateOptimalProcessV2(params) {
243
+ return this.swapBaseHandler.generateOptimalProcessV2(params, [this.getSubmitStep.bind(this)]);
244
+ }
245
+ async validateSwapProcessV2(params) {
246
+ // todo: recheck address and recipient format in params
247
+ const {
248
+ process,
249
+ selectedQuote
250
+ } = params; // todo: review flow, currentStep param.
251
+
252
+ // todo: validate path with optimalProcess
253
+ // todo: review error message in case many step swap
254
+ if ((0, _bignumber.default)(selectedQuote.fromAmount).lte(0)) {
255
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INVALID_PARAMS, 'Amount must be greater than 0')];
256
+ }
257
+ const actionList = JSON.stringify(process.path.map(step => step.action));
258
+ const swap = actionList === JSON.stringify([_interface.DynamicSwapType.SWAP]);
259
+ const swapXcm = actionList === JSON.stringify([_interface.DynamicSwapType.SWAP, _interface.DynamicSwapType.BRIDGE]);
260
+ const xcmSwap = actionList === JSON.stringify([_interface.DynamicSwapType.BRIDGE, _interface.DynamicSwapType.SWAP]);
261
+ const xcmSwapXcm = actionList === JSON.stringify([_interface.DynamicSwapType.BRIDGE, _interface.DynamicSwapType.SWAP, _interface.DynamicSwapType.BRIDGE]);
262
+ const swapIndex = params.process.steps.findIndex(step => step.type === _types.SwapStepType.SWAP); // todo
263
+
264
+ if (swapIndex <= -1) {
265
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
266
+ }
267
+ if (swap) {
268
+ return this.swapBaseHandler.validateSwapOnlyProcess(params, swapIndex); // todo: create interface for input request
269
+ }
270
+
271
+ if (swapXcm) {
272
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
273
+ }
274
+ if (xcmSwap) {
275
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
276
+ }
277
+ if (xcmSwapXcm) {
278
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
279
+ }
280
+ return [new _TransactionError.TransactionError(_types.BasicTxErrorType.INTERNAL_ERROR)];
281
+ }
218
282
  }
219
283
  exports.ChainflipSwapHandler = ChainflipSwapHandler;