@subwallet/extension-base 1.2.3-0 → 1.2.4-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 (94) hide show
  1. package/background/KoniTypes.d.ts +4 -153
  2. package/background/KoniTypes.js +0 -21
  3. package/cjs/background/KoniTypes.js +1 -22
  4. package/cjs/core/logic-validation/earning.js +47 -0
  5. package/cjs/core/logic-validation/swap.js +99 -0
  6. package/cjs/core/logic-validation/transfer.js +212 -0
  7. package/cjs/core/substrate/nominationpools-pallet.js +22 -0
  8. package/cjs/core/substrate/system-pallet.js +77 -0
  9. package/cjs/core/substrate/xcm-parser.js +190 -0
  10. package/cjs/koni/api/dotsama/transfer.js +58 -122
  11. package/cjs/koni/api/staking/bonding/utils.js +1 -1
  12. package/cjs/koni/api/xcm/index.js +30 -2
  13. package/cjs/koni/api/xcm/polkadotXcm.js +12 -20
  14. package/cjs/koni/api/xcm/utils.js +8 -126
  15. package/cjs/koni/api/xcm/xTokens.js +10 -8
  16. package/cjs/koni/api/xcm/xcmPallet.js +6 -6
  17. package/cjs/koni/background/handlers/Extension.js +223 -356
  18. package/cjs/packageInfo.js +1 -1
  19. package/cjs/services/balance-service/helpers/group.js +4 -27
  20. package/cjs/services/balance-service/helpers/subscribe/index.js +2 -30
  21. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +46 -82
  22. package/cjs/services/balance-service/index.js +11 -9
  23. package/cjs/services/chain-service/constants.js +2 -2
  24. package/cjs/services/chain-service/index.js +0 -1
  25. package/cjs/services/chain-service/utils/index.js +13 -2
  26. package/cjs/services/earning-service/handlers/base.js +1 -1
  27. package/cjs/services/earning-service/handlers/special.js +11 -12
  28. package/cjs/services/migration-service/scripts/MigrateTransactionHistoryBySymbol.js +2 -1
  29. package/cjs/services/migration-service/scripts/databases/MigrateAssetSetting.js +2 -1
  30. package/cjs/services/migration-service/scripts/index.js +2 -2
  31. package/cjs/services/swap-service/handler/base-handler.js +30 -44
  32. package/cjs/services/swap-service/handler/chainflip-handler.js +23 -21
  33. package/cjs/services/swap-service/handler/hydradx-handler.js +41 -39
  34. package/cjs/services/swap-service/index.js +6 -0
  35. package/cjs/services/swap-service/utils.js +8 -49
  36. package/cjs/services/transaction-service/index.js +66 -155
  37. package/core/logic-validation/earning.d.ts +10 -0
  38. package/core/logic-validation/earning.js +37 -0
  39. package/core/logic-validation/swap.d.ts +8 -0
  40. package/core/logic-validation/swap.js +89 -0
  41. package/core/logic-validation/transfer.d.ts +16 -0
  42. package/core/logic-validation/transfer.js +199 -0
  43. package/core/substrate/nominationpools-pallet.d.ts +10 -0
  44. package/core/substrate/nominationpools-pallet.js +13 -0
  45. package/core/substrate/system-pallet.d.ts +27 -0
  46. package/core/substrate/system-pallet.js +70 -0
  47. package/core/substrate/xcm-parser.d.ts +49 -0
  48. package/core/substrate/xcm-parser.js +181 -0
  49. package/koni/api/dotsama/transfer.d.ts +3 -4
  50. package/koni/api/dotsama/transfer.js +54 -118
  51. package/koni/api/staking/bonding/relayChain.d.ts +2 -1
  52. package/koni/api/staking/bonding/utils.js +1 -1
  53. package/koni/api/xcm/index.d.ts +2 -0
  54. package/koni/api/xcm/index.js +27 -1
  55. package/koni/api/xcm/polkadotXcm.js +14 -22
  56. package/koni/api/xcm/utils.d.ts +3 -48
  57. package/koni/api/xcm/utils.js +5 -114
  58. package/koni/api/xcm/xTokens.js +12 -10
  59. package/koni/api/xcm/xcmPallet.js +7 -7
  60. package/koni/background/handlers/Extension.d.ts +6 -8
  61. package/koni/background/handlers/Extension.js +117 -247
  62. package/package.json +39 -9
  63. package/packageInfo.js +1 -1
  64. package/services/balance-service/helpers/group.js +4 -27
  65. package/services/balance-service/helpers/subscribe/index.d.ts +2 -1
  66. package/services/balance-service/helpers/subscribe/index.js +2 -30
  67. package/services/balance-service/helpers/subscribe/substrate/index.d.ts +2 -1
  68. package/services/balance-service/helpers/subscribe/substrate/index.js +31 -66
  69. package/services/balance-service/index.d.ts +7 -6
  70. package/services/balance-service/index.js +12 -10
  71. package/services/chain-service/constants.js +2 -2
  72. package/services/chain-service/index.js +0 -1
  73. package/services/chain-service/utils/index.d.ts +4 -2
  74. package/services/chain-service/utils/index.js +9 -2
  75. package/services/earning-service/handlers/base.js +1 -1
  76. package/services/earning-service/handlers/nomination-pool/index.d.ts +2 -1
  77. package/services/earning-service/handlers/special.js +11 -12
  78. package/services/migration-service/scripts/MigrateTransactionHistoryBySymbol.js +2 -1
  79. package/services/migration-service/scripts/databases/MigrateAssetSetting.js +2 -1
  80. package/services/migration-service/scripts/index.js +2 -2
  81. package/services/swap-service/handler/base-handler.d.ts +3 -2
  82. package/services/swap-service/handler/base-handler.js +28 -42
  83. package/services/swap-service/handler/chainflip-handler.d.ts +2 -1
  84. package/services/swap-service/handler/chainflip-handler.js +4 -2
  85. package/services/swap-service/handler/hydradx-handler.d.ts +2 -1
  86. package/services/swap-service/handler/hydradx-handler.js +8 -6
  87. package/services/swap-service/index.js +7 -1
  88. package/services/swap-service/utils.d.ts +2 -4
  89. package/services/swap-service/utils.js +7 -47
  90. package/services/transaction-service/index.d.ts +1 -1
  91. package/services/transaction-service/index.js +30 -119
  92. package/services/transaction-service/types.d.ts +1 -0
  93. package/types/balance/index.d.ts +6 -10
  94. package/types/yield/info/pallet.d.ts +0 -6
@@ -49,8 +49,8 @@ export default {
49
49
  '1.1.28-01': MigrateEarningVersion,
50
50
  '1.1.41-01': DeleteChainStaking,
51
51
  '1.1.46-01': AutoEnableSomeTokens,
52
- '1.1.62-01': MigrateAssetSetting,
53
- '1.1.62-02': MigrateTransactionHistoryBySymbol,
52
+ '1.1.69-03': MigrateAssetSetting,
53
+ '1.1.69-02': MigrateTransactionHistoryBySymbol,
54
54
  '1.2.69-01': MigrateRemoveGenesisHash
55
55
  // [`${EVERYTIME}-1.1.42-02`]: MigrateTransactionHistoryBySymbol
56
56
  // [`${EVERYTIME}-1`]: AutoEnableChainsTokens
@@ -3,8 +3,9 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/Tr
3
3
  import { BalanceService } from '@subwallet/extension-base/services/balance-service';
4
4
  import { ChainService } from '@subwallet/extension-base/services/chain-service';
5
5
  import { BaseStepDetail } from '@subwallet/extension-base/types/service-base';
6
- import { GenSwapStepFunc, OptimalSwapPath, OptimalSwapPathParams, SwapEarlyValidation, SwapFeeInfo, SwapProvider, SwapQuote, SwapRequest, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types/swap';
6
+ import { GenSwapStepFunc, OptimalSwapPath, OptimalSwapPathParams, SwapEarlyValidation, SwapFeeInfo, SwapProvider, SwapProviderId, SwapQuote, SwapRequest, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types/swap';
7
7
  export interface SwapBaseInterface {
8
+ providerSlug: SwapProviderId;
8
9
  getSwapQuote: (request: SwapRequest) => Promise<SwapQuote | SwapError>;
9
10
  generateOptimalProcess: (params: OptimalSwapPathParams) => Promise<OptimalSwapPath>;
10
11
  getSubmitStep: (params: OptimalSwapPathParams) => Promise<[BaseStepDetail, SwapFeeInfo] | undefined>;
@@ -16,7 +17,7 @@ export interface SwapBaseInterface {
16
17
  init?: () => Promise<void>;
17
18
  }
18
19
  export interface SwapBaseHandlerInitParams {
19
- providerSlug: string;
20
+ providerSlug: SwapProviderId;
20
21
  providerName: string;
21
22
  chainService: ChainService;
22
23
  balanceService: BalanceService;
@@ -3,13 +3,13 @@
3
3
 
4
4
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
5
  import { BasicTxErrorType } from '@subwallet/extension-base/background/KoniTypes';
6
- import { _getAssetDecimals, _getTokenMinAmount, _isChainEvmCompatible, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
6
+ import { _validateBalanceToSwap, _validateSwapRecipient } from '@subwallet/extension-base/core/logic-validation/swap';
7
+ import { _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
7
8
  import { DEFAULT_SWAP_FIRST_STEP, getSwapAlternativeAsset, MOCK_SWAP_FEE } from '@subwallet/extension-base/services/swap-service/utils';
8
9
  import { SwapErrorType, SwapFeeType } from '@subwallet/extension-base/types/swap';
9
10
  import { formatNumber } from '@subwallet/extension-base/utils';
10
11
  import BigNumber from 'bignumber.js';
11
12
  import { t } from 'i18next';
12
- import { isEthereumAddress } from '@polkadot/util-crypto';
13
13
  export class SwapBaseHandler {
14
14
  constructor({
15
15
  balanceService,
@@ -54,18 +54,19 @@ export class SwapBaseHandler {
54
54
  }
55
55
  const alternativeAsset = this.chainService.getAssetBySlug(alternativeAssetSlug);
56
56
  const fromAsset = this.chainService.getAssetBySlug(swapPair.from);
57
- const [alternativeAssetBalance, fromAssetBalance] = await Promise.all([this.balanceService.getTokenFreeBalance(params.address, alternativeAsset.originChain, alternativeAssetSlug), this.balanceService.getTokenFreeBalance(params.address, fromAsset.originChain, fromAsset.slug)]);
57
+ const [alternativeAssetBalance, fromAssetBalance] = await Promise.all([this.balanceService.getTransferableBalance(params.address, alternativeAsset.originChain, alternativeAssetSlug), this.balanceService.getTransferableBalance(params.address, fromAsset.originChain, fromAsset.slug)]);
58
58
  const bnAlternativeAssetBalance = new BigNumber(alternativeAssetBalance.value);
59
59
  const bnFromAssetBalance = new BigNumber(fromAssetBalance.value);
60
60
  const xcmFeeComponent = params.process.totalFee[stepIndex].feeComponent[0]; // todo: can do better than indexing
61
61
  const xcmFee = new BigNumber(xcmFeeComponent.amount || '0');
62
62
  let xcmAmount = bnAmount.minus(bnFromAssetBalance);
63
+ let editedXcmFee = new BigNumber(0);
63
64
  if (_isNativeToken(alternativeAsset)) {
64
65
  xcmAmount = xcmAmount.plus(xcmFee);
66
+ editedXcmFee = xcmFee.times(2);
65
67
  }
66
- const alternativeTokenMinAmount = new BigNumber(alternativeAsset.minAmount || '0');
67
- if (!bnAlternativeAssetBalance.minus(xcmAmount).gte(alternativeTokenMinAmount)) {
68
- const maxBn = bnFromAssetBalance.plus(new BigNumber(alternativeAssetBalance.value)).minus(xcmFee).minus(alternativeTokenMinAmount);
68
+ if (!bnAlternativeAssetBalance.minus(_isNativeToken(alternativeAsset) ? xcmAmount.plus(xcmFee) : xcmFee).gt(0)) {
69
+ const maxBn = bnFromAssetBalance.plus(new BigNumber(alternativeAssetBalance.value)).minus(_isNativeToken(alternativeAsset) ? editedXcmFee : xcmFee);
69
70
  const maxValue = formatNumber(maxBn.toString(), fromAsset.decimals || 0);
70
71
  const altInputTokenInfo = this.chainService.getAssetBySlug(alternativeAssetSlug);
71
72
  const symbol = altInputTokenInfo.symbol;
@@ -74,7 +75,7 @@ export class SwapBaseHandler {
74
75
  const inputNetworkName = chain.name;
75
76
  const altNetworkName = alternativeChain.name;
76
77
  const currentValue = formatNumber(bnFromAssetBalance.toString(), fromAsset.decimals || 0);
77
- const bnMaxXCM = new BigNumber(alternativeAssetBalance.value).minus(xcmFee).minus(alternativeTokenMinAmount);
78
+ const bnMaxXCM = new BigNumber(alternativeAssetBalance.value).minus(_isNativeToken(alternativeAsset) ? editedXcmFee : xcmFee);
78
79
  const maxXCMValue = formatNumber(bnMaxXCM.toString(), fromAsset.decimals || 0);
79
80
  if (maxBn.lte(0) || bnFromAssetBalance.lte(0) || bnMaxXCM.lte(0)) {
80
81
  return [new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE, t(`Insufficient balance. Deposit ${fromAsset.symbol} and try again.`))];
@@ -102,7 +103,7 @@ export class SwapBaseHandler {
102
103
  const feeInfo = params.process.totalFee[stepIndex];
103
104
  const feeAmount = feeInfo.feeComponent[0];
104
105
  const feeTokenInfo = this.chainService.getAssetBySlug(feeInfo.defaultFeeToken);
105
- const feeTokenBalance = await this.balanceService.getTokenFreeBalance(params.address, feeTokenInfo.originChain, feeTokenInfo.slug);
106
+ const feeTokenBalance = await this.balanceService.getTransferableBalance(params.address, feeTokenInfo.originChain, feeTokenInfo.slug);
106
107
  const bnFeeTokenBalance = new BigNumber(feeTokenBalance.value);
107
108
  const bnFeeAmount = new BigNumber(feeAmount.amount);
108
109
  if (bnFeeAmount.gte(bnFeeTokenBalance)) {
@@ -111,6 +112,9 @@ export class SwapBaseHandler {
111
112
  return [];
112
113
  }
113
114
  async validateSwapStep(params, isXcmOk, stepIndex) {
115
+ // check swap quote timestamp
116
+ // check balance to pay transaction fee
117
+ // check balance against spending amount
114
118
  if (!params.selectedQuote) {
115
119
  return Promise.resolve([new TransactionError(BasicTxErrorType.INTERNAL_ERROR)]);
116
120
  }
@@ -119,49 +123,31 @@ export class SwapBaseHandler {
119
123
  if (selectedQuote.aliveUntil <= currentTimestamp) {
120
124
  return Promise.resolve([new TransactionError(SwapErrorType.QUOTE_TIMEOUT)]);
121
125
  }
122
- const bnAmount = new BigNumber(params.selectedQuote.fromAmount);
123
- const fromAsset = this.chainService.getAssetBySlug(params.selectedQuote.pair.from);
124
126
  const stepFee = params.process.totalFee[stepIndex].feeComponent;
125
127
  const networkFee = stepFee.find(fee => fee.feeType === SwapFeeType.NETWORK_FEE);
126
128
  if (!networkFee) {
127
129
  return Promise.resolve([new TransactionError(BasicTxErrorType.INTERNAL_ERROR)]);
128
130
  }
131
+ const fromAsset = this.chainService.getAssetBySlug(params.selectedQuote.pair.from);
129
132
  const feeTokenInfo = this.chainService.getAssetBySlug(networkFee.tokenSlug);
130
133
  const feeTokenChain = this.chainService.getChainInfoByKey(feeTokenInfo.originChain);
131
- const [feeTokenBalance, fromAssetBalance] = await Promise.all([this.balanceService.getTokenFreeBalance(params.address, feeTokenInfo.originChain, feeTokenInfo.slug), this.balanceService.getTokenFreeBalance(params.address, fromAsset.originChain, fromAsset.slug)]);
132
- const bnFeeTokenBalance = new BigNumber(feeTokenBalance.value);
133
- const bnFromAssetBalance = new BigNumber(fromAssetBalance.value);
134
- const bnFeeAmount = new BigNumber(networkFee.amount);
135
- if (bnFeeTokenBalance.lte(bnFeeAmount)) {
136
- return Promise.resolve([new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE, `You don't have enough ${feeTokenInfo.symbol} (${feeTokenChain.name}) to pay transaction fee`)]);
134
+ const {
135
+ fromAmount,
136
+ minSwap
137
+ } = params.selectedQuote;
138
+ const [feeTokenBalance, fromAssetBalance] = await Promise.all([this.balanceService.getTransferableBalance(params.address, feeTokenInfo.originChain, feeTokenInfo.slug), this.balanceService.getTransferableBalance(params.address, fromAsset.originChain, fromAsset.slug)]);
139
+ const balanceError = _validateBalanceToSwap(fromAsset, feeTokenInfo, feeTokenChain, networkFee.amount, fromAssetBalance.value, feeTokenBalance.value, fromAmount, isXcmOk, minSwap);
140
+ if (balanceError) {
141
+ return Promise.resolve([balanceError]);
137
142
  }
138
- if (fromAsset.slug === feeTokenInfo.slug) {
139
- if (bnFromAssetBalance.lte(bnFeeAmount.plus(bnAmount))) {
140
- return Promise.resolve([new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE, `Insufficient balance. Deposit ${fromAsset.symbol} and try again.`)]);
141
- }
143
+ if (!params.recipient) {
144
+ return Promise.resolve([]);
142
145
  }
143
- if (params.selectedQuote.minSwap) {
144
- const minProtocolSwap = new BigNumber(params.selectedQuote.minSwap);
145
- if (!isXcmOk && bnFromAssetBalance.lte(minProtocolSwap)) {
146
- const parsedMinSwapValue = formatNumber(minProtocolSwap, _getAssetDecimals(fromAsset));
147
- return Promise.resolve([new TransactionError(SwapErrorType.SWAP_NOT_ENOUGH_BALANCE, `Insufficient balance. You need more than ${parsedMinSwapValue} ${fromAsset.symbol} to start swapping. Deposit ${fromAsset.symbol} and try again.`)]); // todo: min swap or amount?
148
- }
149
- }
150
-
151
- const bnSrcAssetMinAmount = new BigNumber(_getTokenMinAmount(fromAsset));
152
- const bnMaxBalanceSwap = bnFromAssetBalance.minus(bnSrcAssetMinAmount);
153
- if (!isXcmOk && bnAmount.gte(bnMaxBalanceSwap)) {
154
- const parsedMaxBalanceSwap = formatNumber(bnMaxBalanceSwap, _getAssetDecimals(fromAsset));
155
- return Promise.resolve([new TransactionError(SwapErrorType.SWAP_EXCEED_ALLOWANCE, `Amount too high. Lower your amount ${bnMaxBalanceSwap.gt(0) ? `below ${parsedMaxBalanceSwap} ${fromAsset.symbol}` : ''} and try again`)]);
156
- }
157
- if (params.recipient) {
158
- const toAsset = this.chainService.getAssetBySlug(params.selectedQuote.pair.to);
159
- const destChainInfo = this.chainService.getChainInfoByKey(toAsset.originChain);
160
- const isEvmAddress = isEthereumAddress(params.recipient);
161
- const isEvmDestChain = _isChainEvmCompatible(destChainInfo);
162
- if (isEvmAddress && !isEvmDestChain || !isEvmAddress && isEvmDestChain) {
163
- return Promise.resolve([new TransactionError(SwapErrorType.INVALID_RECIPIENT)]);
164
- }
146
+ const toAsset = this.chainService.getAssetBySlug(params.selectedQuote.pair.to);
147
+ const toAssetChain = this.chainService.getChainInfoByKey(toAsset.originChain);
148
+ const recipientError = _validateSwapRecipient(toAssetChain, params.recipient);
149
+ if (recipientError) {
150
+ return Promise.resolve([recipientError]);
165
151
  }
166
152
  return Promise.resolve([]);
167
153
  }
@@ -5,11 +5,12 @@ import { BalanceService } from '@subwallet/extension-base/services/balance-servi
5
5
  import { ChainService } from '@subwallet/extension-base/services/chain-service';
6
6
  import { SwapBaseInterface } from '@subwallet/extension-base/services/swap-service/handler/base-handler';
7
7
  import { BaseStepDetail } from '@subwallet/extension-base/types/service-base';
8
- import { OptimalSwapPath, OptimalSwapPathParams, SwapEarlyValidation, SwapFeeInfo, SwapQuote, SwapRequest, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types/swap';
8
+ import { OptimalSwapPath, OptimalSwapPathParams, SwapEarlyValidation, SwapFeeInfo, SwapProviderId, SwapQuote, SwapRequest, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types/swap';
9
9
  export declare class ChainflipSwapHandler implements SwapBaseInterface {
10
10
  private swapSdk;
11
11
  private readonly isTestnet;
12
12
  private swapBaseHandler;
13
+ providerSlug: SwapProviderId;
13
14
  constructor(chainService: ChainService, balanceService: BalanceService, isTestnet?: boolean);
14
15
  get chainService(): ChainService;
15
16
  get balanceService(): BalanceService;
@@ -6,11 +6,12 @@ import { COMMON_ASSETS } from '@subwallet/chain-list';
6
6
  import { SwapError } from '@subwallet/extension-base/background/errors/SwapError';
7
7
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
8
8
  import { BasicTxErrorType, ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
9
+ import { _getChainflipEarlyValidationError } from '@subwallet/extension-base/core/logic-validation/swap';
9
10
  import { createTransferExtrinsic } from '@subwallet/extension-base/koni/api/dotsama/transfer';
10
11
  import { getERC20TransactionObject, getEVMTransactionObject } from '@subwallet/extension-base/koni/api/tokens/evm/transfer';
11
12
  import { _getAssetDecimals, _getChainNativeTokenSlug, _getContractAddressOfToken, _isNativeToken, _isSubstrateChain } from '@subwallet/extension-base/services/chain-service/utils';
12
13
  import { SwapBaseHandler } from '@subwallet/extension-base/services/swap-service/handler/base-handler';
13
- import { calculateSwapRate, CHAIN_FLIP_SUPPORTED_MAINNET_ASSET_MAPPING, CHAIN_FLIP_SUPPORTED_MAINNET_MAPPING, CHAIN_FLIP_SUPPORTED_TESTNET_ASSET_MAPPING, CHAIN_FLIP_SUPPORTED_TESTNET_MAPPING, getChainflipEarlyValidationError, SWAP_QUOTE_TIMEOUT_MAP } from '@subwallet/extension-base/services/swap-service/utils';
14
+ import { calculateSwapRate, CHAIN_FLIP_SUPPORTED_MAINNET_ASSET_MAPPING, CHAIN_FLIP_SUPPORTED_MAINNET_MAPPING, CHAIN_FLIP_SUPPORTED_TESTNET_ASSET_MAPPING, CHAIN_FLIP_SUPPORTED_TESTNET_MAPPING, SWAP_QUOTE_TIMEOUT_MAP } from '@subwallet/extension-base/services/swap-service/utils';
14
15
  import { SwapErrorType, SwapFeeType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types/swap';
15
16
  import BigNumber from 'bignumber.js';
16
17
  var ChainflipFeeType;
@@ -37,6 +38,7 @@ export class ChainflipSwapHandler {
37
38
  providerSlug: isTestnet ? SwapProviderId.CHAIN_FLIP_TESTNET : SwapProviderId.CHAIN_FLIP_MAINNET
38
39
  });
39
40
  this.isTestnet = isTestnet;
41
+ this.providerSlug = isTestnet ? SwapProviderId.CHAIN_FLIP_TESTNET : SwapProviderId.CHAIN_FLIP_MAINNET;
40
42
  this.swapSdk = new SwapSDK({
41
43
  network: isTestnet ? 'perseverance' : 'mainnet'
42
44
  });
@@ -191,7 +193,7 @@ export class ChainflipSwapHandler {
191
193
  const earlyValidation = await this.validateSwapRequest(request);
192
194
  const metadata = earlyValidation.metadata;
193
195
  if (earlyValidation.error) {
194
- return getChainflipEarlyValidationError(earlyValidation.error, metadata);
196
+ return _getChainflipEarlyValidationError(earlyValidation.error, metadata);
195
197
  }
196
198
  const srcChainId = this.chainMapping[fromAsset.originChain];
197
199
  const destChainId = this.chainMapping[toAsset.originChain];
@@ -4,12 +4,13 @@ import { BalanceService } from '@subwallet/extension-base/services/balance-servi
4
4
  import { ChainService } from '@subwallet/extension-base/services/chain-service';
5
5
  import { SwapBaseInterface } from '@subwallet/extension-base/services/swap-service/handler/base-handler';
6
6
  import { BaseStepDetail } from '@subwallet/extension-base/types/service-base';
7
- import { OptimalSwapPath, OptimalSwapPathParams, SwapEarlyValidation, SwapFeeInfo, SwapQuote, SwapRequest, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types/swap';
7
+ import { OptimalSwapPath, OptimalSwapPathParams, SwapEarlyValidation, SwapFeeInfo, SwapProviderId, SwapQuote, SwapRequest, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types/swap';
8
8
  export declare class HydradxHandler implements SwapBaseInterface {
9
9
  private swapBaseHandler;
10
10
  private tradeRouter;
11
11
  private readonly isTestnet;
12
12
  isReady: boolean;
13
+ providerSlug: SwapProviderId;
13
14
  constructor(chainService: ChainService, balanceService: BalanceService, isTestnet?: boolean);
14
15
  init(): Promise<void>;
15
16
  chain: () => string;
@@ -7,10 +7,11 @@ import { _AssetType } from '@subwallet/chain-list/types';
7
7
  import { SwapError } from '@subwallet/extension-base/background/errors/SwapError';
8
8
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
9
9
  import { BasicTxErrorType, ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
10
+ import { _getEarlyHydradxValidationError } from '@subwallet/extension-base/core/logic-validation/swap';
10
11
  import { createXcmExtrinsic } from '@subwallet/extension-base/koni/api/xcm';
11
12
  import { _getAssetDecimals, _getChainNativeTokenSlug, _getTokenOnChainAssetId, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
12
13
  import { SwapBaseHandler } from '@subwallet/extension-base/services/swap-service/handler/base-handler';
13
- import { calculateSwapRate, getEarlyHydradxValidationError, getSwapAlternativeAsset, SWAP_QUOTE_TIMEOUT_MAP } from '@subwallet/extension-base/services/swap-service/utils';
14
+ import { calculateSwapRate, getSwapAlternativeAsset, SWAP_QUOTE_TIMEOUT_MAP } from '@subwallet/extension-base/services/swap-service/utils';
14
15
  import { SwapErrorType, SwapFeeType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types/swap';
15
16
  import BigNumber from 'bignumber.js';
16
17
  const HYDRADX_LOW_LIQUIDITY_THRESHOLD = 0.15;
@@ -25,9 +26,10 @@ export class HydradxHandler {
25
26
  this.swapBaseHandler = new SwapBaseHandler({
26
27
  balanceService,
27
28
  chainService,
28
- providerName: isTestnet ? 'HydraDX Testnet' : 'HydraDX',
29
+ providerName: isTestnet ? 'Hydration Testnet' : 'Hydration',
29
30
  providerSlug: isTestnet ? SwapProviderId.HYDRADX_TESTNET : SwapProviderId.HYDRADX_MAINNET
30
31
  });
32
+ this.providerSlug = isTestnet ? SwapProviderId.HYDRADX_TESTNET : SwapProviderId.HYDRADX_MAINNET;
31
33
  this.isTestnet = isTestnet;
32
34
  }
33
35
  async init() {
@@ -67,7 +69,7 @@ export class HydradxHandler {
67
69
  async getXcmStep(params) {
68
70
  const bnAmount = new BigNumber(params.request.fromAmount);
69
71
  const fromAsset = this.chainService.getAssetBySlug(params.request.pair.from);
70
- const fromAssetBalance = await this.balanceService.getTokenFreeBalance(params.request.address, fromAsset.originChain, fromAsset.slug);
72
+ const fromAssetBalance = await this.balanceService.getTransferableBalance(params.request.address, fromAsset.originChain, fromAsset.slug);
71
73
  const bnFromAssetBalance = new BigNumber(fromAssetBalance.value);
72
74
  if (bnFromAssetBalance.gte(bnAmount)) {
73
75
  return undefined; // enough balance, no need to xcm
@@ -78,7 +80,7 @@ export class HydradxHandler {
78
80
  return undefined;
79
81
  }
80
82
  const alternativeAsset = this.chainService.getAssetBySlug(alternativeAssetSlug);
81
- const alternativeAssetBalance = await this.balanceService.getTokenFreeBalance(params.request.address, alternativeAsset.originChain, alternativeAsset.slug);
83
+ const alternativeAssetBalance = await this.balanceService.getTransferableBalance(params.request.address, alternativeAsset.originChain, alternativeAsset.slug);
82
84
  const bnAlternativeAssetBalance = new BigNumber(alternativeAssetBalance.value);
83
85
  if (bnAlternativeAssetBalance.lte(0)) {
84
86
  return undefined;
@@ -214,7 +216,7 @@ export class HydradxHandler {
214
216
  const earlyValidation = await this.validateSwapRequest(request);
215
217
  if (earlyValidation.error) {
216
218
  const metadata = earlyValidation.metadata;
217
- return getEarlyHydradxValidationError(earlyValidation.error, metadata);
219
+ return _getEarlyHydradxValidationError(earlyValidation.error, metadata);
218
220
  }
219
221
  try {
220
222
  const fromAssetId = _getTokenOnChainAssetId(fromAsset);
@@ -295,7 +297,7 @@ export class HydradxHandler {
295
297
  const destinationAsset = this.chainService.getAssetBySlug(pair.from);
296
298
  const substrateApi = this.chainService.getSubstrateApi(originAsset.originChain);
297
299
  const chainApi = await substrateApi.isReady;
298
- const destinationAssetBalance = await this.balanceService.getTokenFreeBalance(params.address, destinationAsset.originChain, destinationAsset.slug);
300
+ const destinationAssetBalance = await this.balanceService.getTransferableBalance(params.address, destinationAsset.originChain, destinationAsset.slug);
299
301
  const xcmFee = params.process.totalFee[params.currentStep];
300
302
  const bnAmount = new BigNumber(params.quote.fromAmount);
301
303
  const bnDestinationAssetBalance = new BigNumber(destinationAssetBalance.value);
@@ -7,7 +7,7 @@ import { BasicTxErrorType } from '@subwallet/extension-base/background/KoniTypes
7
7
  import { ServiceStatus } from '@subwallet/extension-base/services/base/types';
8
8
  import { ChainflipSwapHandler } from '@subwallet/extension-base/services/swap-service/handler/chainflip-handler';
9
9
  import { HydradxHandler } from '@subwallet/extension-base/services/swap-service/handler/hydradx-handler';
10
- import { DEFAULT_SWAP_FIRST_STEP, getSwapAltToken, MOCK_SWAP_FEE, SWAP_QUOTE_TIMEOUT_MAP } from '@subwallet/extension-base/services/swap-service/utils';
10
+ import { _PROVIDER_TO_SUPPORTED_PAIR_MAP, DEFAULT_SWAP_FIRST_STEP, getSwapAltToken, MOCK_SWAP_FEE, SWAP_QUOTE_TIMEOUT_MAP } from '@subwallet/extension-base/services/swap-service/utils';
11
11
  import { _SUPPORTED_SWAP_PROVIDERS, SwapErrorType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types/swap';
12
12
  import { createPromiseHandler } from '@subwallet/extension-base/utils';
13
13
  import { BehaviorSubject } from 'rxjs';
@@ -24,12 +24,18 @@ export class SwapService {
24
24
  }
25
25
  async askProvidersForQuote(request) {
26
26
  const availableQuotes = [];
27
+ const swappingSrcChain = this.chainService.getAssetBySlug(request.pair.from).originChain;
27
28
  await Promise.all(Object.values(this.handlers).map(async handler => {
29
+ // temporary solution to reduce number of requests to providers, will work as long as there's only 1 provider for 1 chain
30
+ if (!_PROVIDER_TO_SUPPORTED_PAIR_MAP[handler.providerSlug].includes(swappingSrcChain)) {
31
+ return;
32
+ }
28
33
  if (handler.init && handler.isReady === false) {
29
34
  await handler.init();
30
35
  }
31
36
  const quote = await handler.getSwapQuote(request);
32
37
  if (!(quote instanceof SwapError)) {
38
+ // todo: can do better
33
39
  availableQuotes.push({
34
40
  quote
35
41
  });
@@ -1,7 +1,6 @@
1
1
  import { Asset, Chain } from '@chainflip/sdk/swap';
2
2
  import { _ChainAsset } from '@subwallet/chain-list/types';
3
- import { SwapError } from '@subwallet/extension-base/background/errors/SwapError';
4
- import { ChainflipPreValidationMetadata, HydradxPreValidationMetadata, SwapErrorType, SwapFeeInfo, SwapPair, SwapStepDetail } from '@subwallet/extension-base/types/swap';
3
+ import { SwapFeeInfo, SwapPair, SwapStepDetail } from '@subwallet/extension-base/types/swap';
5
4
  export declare const CHAIN_FLIP_TESTNET_EXPLORER = "https://blocks-perseverance.chainflip.io";
6
5
  export declare const CHAIN_FLIP_MAINNET_EXPLORER = "https://scan.chainflip.io";
7
6
  export declare const CHAIN_FLIP_SUPPORTED_MAINNET_MAPPING: Record<string, Chain>;
@@ -11,8 +10,7 @@ export declare const CHAIN_FLIP_SUPPORTED_TESTNET_ASSET_MAPPING: Record<string,
11
10
  export declare const SWAP_QUOTE_TIMEOUT_MAP: Record<string, number>;
12
11
  export declare const DEFAULT_SWAP_FIRST_STEP: SwapStepDetail;
13
12
  export declare const MOCK_SWAP_FEE: SwapFeeInfo;
13
+ export declare const _PROVIDER_TO_SUPPORTED_PAIR_MAP: Record<string, string[]>;
14
14
  export declare function getSwapAlternativeAsset(swapPair: SwapPair): string | undefined;
15
15
  export declare function getSwapAltToken(chainAsset: _ChainAsset): string | undefined;
16
16
  export declare function calculateSwapRate(fromAmount: string, toAmount: string, fromAsset: _ChainAsset, toAsset: _ChainAsset): number;
17
- export declare function getChainflipEarlyValidationError(error: SwapErrorType, metadata: ChainflipPreValidationMetadata): SwapError;
18
- export declare function getEarlyHydradxValidationError(error: SwapErrorType, metadata: HydradxPreValidationMetadata): SwapError;
@@ -3,10 +3,8 @@
3
3
 
4
4
  import { Assets, Chains } from '@chainflip/sdk/swap';
5
5
  import { COMMON_ASSETS, COMMON_CHAIN_SLUGS } from '@subwallet/chain-list';
6
- import { SwapError } from '@subwallet/extension-base/background/errors/SwapError';
7
6
  import { _getAssetDecimals } from '@subwallet/extension-base/services/chain-service/utils';
8
- import { SwapErrorType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types/swap';
9
- import { formatNumber } from '@subwallet/extension-base/utils';
7
+ import { SwapProviderId, SwapStepType } from '@subwallet/extension-base/types/swap';
10
8
  import BigN from 'bignumber.js';
11
9
  export const CHAIN_FLIP_TESTNET_EXPLORER = 'https://blocks-perseverance.chainflip.io';
12
10
  export const CHAIN_FLIP_MAINNET_EXPLORER = 'https://scan.chainflip.io';
@@ -44,6 +42,12 @@ export const MOCK_SWAP_FEE = {
44
42
  defaultFeeToken: '',
45
43
  feeOptions: []
46
44
  };
45
+ export const _PROVIDER_TO_SUPPORTED_PAIR_MAP = {
46
+ [SwapProviderId.HYDRADX_MAINNET]: [COMMON_CHAIN_SLUGS.HYDRADX],
47
+ [SwapProviderId.HYDRADX_TESTNET]: [COMMON_CHAIN_SLUGS.HYDRADX_TESTNET],
48
+ [SwapProviderId.CHAIN_FLIP_MAINNET]: [COMMON_CHAIN_SLUGS.POLKADOT, COMMON_CHAIN_SLUGS.ETHEREUM],
49
+ [SwapProviderId.CHAIN_FLIP_TESTNET]: [COMMON_CHAIN_SLUGS.CHAINFLIP_POLKADOT, COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA]
50
+ };
47
51
  export function getSwapAlternativeAsset(swapPair) {
48
52
  var _swapPair$metadata;
49
53
  return swapPair === null || swapPair === void 0 ? void 0 : (_swapPair$metadata = swapPair.metadata) === null || _swapPair$metadata === void 0 ? void 0 : _swapPair$metadata.alternativeAsset;
@@ -58,48 +62,4 @@ export function calculateSwapRate(fromAmount, toAmount, fromAsset, toAsset) {
58
62
  const decimalDiff = _getAssetDecimals(toAsset) - _getAssetDecimals(fromAsset);
59
63
  const bnRate = bnFromAmount.div(bnToAmount);
60
64
  return 1 / bnRate.times(10 ** decimalDiff).toNumber();
61
- }
62
- export function getChainflipEarlyValidationError(error, metadata) {
63
- // todo: support more providers
64
- switch (error) {
65
- case SwapErrorType.NOT_MEET_MIN_SWAP:
66
- {
67
- const parsedMinSwapValue = formatNumber(metadata.minSwap.value, metadata.minSwap.decimals);
68
- const message = `Amount too low. Increase your amount above ${parsedMinSwapValue} ${metadata.minSwap.symbol} and try again`;
69
- return new SwapError(error, message);
70
- }
71
- case SwapErrorType.SWAP_EXCEED_ALLOWANCE:
72
- {
73
- if (metadata.maxSwap) {
74
- const parsedMaxSwapValue = formatNumber(metadata.maxSwap.value, metadata.maxSwap.decimals);
75
- return new SwapError(error, `Amount too high. Lower your amount below ${parsedMaxSwapValue} ${metadata.maxSwap.symbol} and try again`);
76
- } else {
77
- return new SwapError(error, 'Amount too high. Lower your amount and try again');
78
- }
79
- }
80
- case SwapErrorType.ASSET_NOT_SUPPORTED:
81
- return new SwapError(error, 'This swap pair is not supported');
82
- case SwapErrorType.UNKNOWN:
83
- return new SwapError(error, `Undefined error. Check your Internet and ${metadata.chain.slug} connection or contact support`);
84
- case SwapErrorType.ERROR_FETCHING_QUOTE:
85
- return new SwapError(error, 'No swap quote found. Adjust your amount or try again later.');
86
- default:
87
- return new SwapError(error);
88
- }
89
- }
90
- export function getEarlyHydradxValidationError(error, metadata) {
91
- switch (error) {
92
- case SwapErrorType.AMOUNT_CANNOT_BE_ZERO:
93
- {
94
- return new SwapError(error, 'Amount too low. Increase your amount above 0 and try again');
95
- }
96
- case SwapErrorType.ASSET_NOT_SUPPORTED:
97
- return new SwapError(error, 'This swap pair is not supported');
98
- case SwapErrorType.UNKNOWN:
99
- return new SwapError(error, `Undefined error. Check your Internet and ${metadata.chain.slug} connection or contact support`);
100
- case SwapErrorType.ERROR_FETCHING_QUOTE:
101
- return new SwapError(error, 'No swap quote found. Adjust your amount or try again later.');
102
- default:
103
- return new SwapError(error);
104
- }
105
65
  }
@@ -18,7 +18,7 @@ export default class TransactionService {
18
18
  private get processingTransactions();
19
19
  getTransaction(id: string): SWTransaction;
20
20
  private checkDuplicate;
21
- generalValidate(validationInput: SWTransactionInput): Promise<SWTransactionResponse>;
21
+ validateTransaction(transactionInput: SWTransactionInput): Promise<SWTransactionResponse>;
22
22
  getTransactionSubject(): BehaviorSubject<Record<string, SWTransaction>>;
23
23
  private fillTransactionDefaultInfo;
24
24
  addTransaction(inputTransaction: SWTransactionInput): Promise<TransactionEmitter>;
@@ -3,11 +3,10 @@
3
3
 
4
4
  import { EvmProviderError } from '@subwallet/extension-base/background/errors/EvmProviderError';
5
5
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
6
- import { BasicTxErrorType, BasicTxWarningCode, ChainType, EvmProviderErrorType, ExtrinsicStatus, ExtrinsicType, NotificationType, TransactionDirection } from '@subwallet/extension-base/background/KoniTypes';
7
- import { TransactionWarning } from '@subwallet/extension-base/background/warnings/TransactionWarning';
6
+ import { BasicTxErrorType, ChainType, EvmProviderErrorType, ExtrinsicStatus, ExtrinsicType, NotificationType, TransactionDirection } from '@subwallet/extension-base/background/KoniTypes';
8
7
  import { ALL_ACCOUNT_KEY } from '@subwallet/extension-base/constants';
8
+ import { checkBalanceWithTransactionFee, checkSigningAccountForTransaction, checkSupportForTransaction, estimateFeeForTransaction } from '@subwallet/extension-base/core/logic-validation/transfer';
9
9
  import { _getAssetDecimals, _getAssetSymbol, _getChainNativeTokenBasicInfo, _getEvmChainId, _isChainEvmCompatible } from '@subwallet/extension-base/services/chain-service/utils';
10
- import { calculateGasFeeParams } from '@subwallet/extension-base/services/fee-service/utils';
11
10
  import { EXTENSION_REQUEST_URL } from '@subwallet/extension-base/services/request-service/constants';
12
11
  import { TRANSACTION_TIMEOUT } from '@subwallet/extension-base/services/transaction-service/constants';
13
12
  import { parseLiquidStakingEvents, parseLiquidStakingFastUnstakeEvents, parseTransferEventLogs, parseXcmEventLogs } from '@subwallet/extension-base/services/transaction-service/event-parser';
@@ -20,14 +19,12 @@ import { mergeTransactionAndSignature } from '@subwallet/extension-base/utils/et
20
19
  import { isContractAddress, parseContractInput } from '@subwallet/extension-base/utils/eth/parseTransaction';
21
20
  import { BN_ZERO } from '@subwallet/extension-base/utils/number';
22
21
  import keyring from '@subwallet/ui-keyring';
23
- import BigN from 'bignumber.js';
24
22
  import { addHexPrefix } from 'ethereumjs-util';
25
23
  import { ethers } from 'ethers';
26
24
  import EventEmitter from 'eventemitter3';
27
25
  import { t } from 'i18next';
28
26
  import { BehaviorSubject, interval as rxjsInterval } from 'rxjs';
29
27
  import { isHex } from '@polkadot/util';
30
- import { _TRANSFER_CHAIN_GROUP } from "../chain-service/constants.js";
31
28
  export default class TransactionService {
32
29
  transactionSubject = new BehaviorSubject({});
33
30
  watchTransactionSubscribes = {};
@@ -58,134 +55,48 @@ export default class TransactionService {
58
55
  }
59
56
  return [];
60
57
  }
61
- async generalValidate(validationInput) {
62
- const validation = {
63
- ...validationInput,
64
- errors: validationInput.errors || [],
65
- warnings: validationInput.warnings || []
58
+ async validateTransaction(transactionInput) {
59
+ const validationResponse = {
60
+ ...transactionInput,
61
+ status: undefined,
62
+ errors: transactionInput.errors || [],
63
+ warnings: transactionInput.warnings || []
66
64
  };
67
65
  const {
68
66
  additionalValidator,
69
67
  address,
70
68
  chain,
71
- edAsWarning,
72
- extrinsicType,
73
- isTransferAll,
74
- transaction
75
- } = validation;
76
-
77
- // Check duplicate transaction
78
- validation.errors.push(...this.checkDuplicate(validationInput));
69
+ extrinsicType
70
+ } = validationResponse;
71
+ const transaction = transactionInput.transaction;
79
72
 
80
- // Return unsupported error if not found transaction
81
- if (!transaction) {
82
- if (extrinsicType === ExtrinsicType.SEND_NFT) {
83
- validation.errors.push(new TransactionError(BasicTxErrorType.UNSUPPORTED, t('This feature is not yet available for this NFT')));
84
- } else {
85
- validation.errors.push(new TransactionError(BasicTxErrorType.UNSUPPORTED));
86
- }
87
- }
88
- const validationResponse = {
89
- status: undefined,
90
- ...validation
91
- };
73
+ // Check duplicated transaction
74
+ validationResponse.errors.push(...this.checkDuplicate(transactionInput));
92
75
 
93
- // Estimate fee
94
- const estimateFee = {
95
- symbol: '',
96
- decimals: 0,
97
- value: '',
98
- tooHigh: false
99
- };
76
+ // Check support for transaction
77
+ checkSupportForTransaction(validationResponse, transaction);
100
78
  const chainInfo = this.state.chainService.getChainInfoByKey(chain);
101
79
  if (!chainInfo) {
102
80
  validationResponse.errors.push(new TransactionError(BasicTxErrorType.INTERNAL_ERROR, t('Cannot find network')));
103
- } else {
104
- const {
105
- decimals,
106
- symbol
107
- } = _getChainNativeTokenBasicInfo(chainInfo);
108
- estimateFee.decimals = decimals;
109
- estimateFee.symbol = symbol;
110
- if (transaction) {
111
- try {
112
- if (isSubstrateTransaction(transaction)) {
113
- estimateFee.value = (await transaction.paymentInfo(address)).partialFee.toString();
114
- } else {
115
- const web3 = this.state.chainService.getEvmApi(chain);
116
- if (!web3) {
117
- validationResponse.errors.push(new TransactionError(BasicTxErrorType.CHAIN_DISCONNECTED, undefined));
118
- } else {
119
- const gasLimit = await web3.api.eth.estimateGas(transaction);
120
- const priority = await calculateGasFeeParams(web3, chainInfo.slug);
121
- if (priority.baseGasFee) {
122
- const maxFee = priority.maxFeePerGas; // TODO: Need review
123
-
124
- estimateFee.value = maxFee.multipliedBy(gasLimit).toFixed(0);
125
- } else {
126
- estimateFee.value = new BigN(priority.gasPrice).multipliedBy(gasLimit).toFixed(0);
127
- }
128
- estimateFee.tooHigh = priority.busyNetwork;
129
- }
130
- }
131
- } catch (e) {
132
- const error = e;
133
- if (error.message.includes('gas required exceeds allowance') && error.message.includes('insufficient funds')) {
134
- validationResponse.errors.push(new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE));
135
- }
136
- estimateFee.value = '0';
137
- }
138
- }
139
81
  }
140
- validationResponse.estimateFee = estimateFee;
141
-
142
- // Read-only account
143
- const pair = keyring.getPair(address);
144
- if (!pair) {
145
- validationResponse.errors.push(new TransactionError(BasicTxErrorType.INTERNAL_ERROR, t('Unable to find account')));
146
- } else {
147
- var _pair$meta;
148
- if ((_pair$meta = pair.meta) !== null && _pair$meta !== void 0 && _pair$meta.isReadOnly) {
149
- validationResponse.errors.push(new TransactionError(BasicTxErrorType.INTERNAL_ERROR, t('This account is watch-only')));
150
- }
82
+ const evmApi = this.state.chainService.getEvmApi(chainInfo.slug);
83
+ const isNeedEvmApi = transaction && !isSubstrateTransaction(transaction) && !evmApi;
84
+ if (isNeedEvmApi) {
85
+ validationResponse.errors.push(new TransactionError(BasicTxErrorType.CHAIN_DISCONNECTED, undefined));
151
86
  }
152
87
 
153
- // Balance
154
- const transferNative = validationResponse.transferNativeAmount || '0';
88
+ // Estimate fee for transaction
89
+ validationResponse.estimateFee = await estimateFeeForTransaction(validationResponse, transaction, chainInfo, evmApi);
90
+
91
+ // Check account signing transaction
92
+ checkSigningAccountForTransaction(validationResponse);
155
93
  const nativeTokenInfo = this.state.chainService.getNativeTokenInfo(chain);
156
- const balance = await this.state.balanceService.getTokenFreeBalance(address, chain, nativeTokenInfo.slug);
157
- const existentialDeposit = nativeTokenInfo.minAmount || '0';
158
- const feeNum = parseInt(estimateFee.value);
159
- const balanceNum = parseInt(balance.value);
160
- const edNum = parseInt(existentialDeposit);
161
- const transferNativeNum = parseInt(transferNative);
162
- if (!validationInput.skipFeeValidation) {
163
- // TODO
164
- if (!new BigN(balance.value).gt(0)) {
165
- validationResponse.errors.push(new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE));
166
- }
167
- if (transferNativeNum + feeNum > balanceNum) {
168
- if (!isTransferAll) {
169
- validationResponse.errors.push(new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE));
170
- } else {
171
- if ([..._TRANSFER_CHAIN_GROUP.acala, ..._TRANSFER_CHAIN_GROUP.genshiro, ..._TRANSFER_CHAIN_GROUP.bitcountry, ..._TRANSFER_CHAIN_GROUP.statemine].includes(chain)) {
172
- // Chain not have transfer all function
173
- validationResponse.errors.push(new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE));
174
- }
175
- }
176
- }
177
- if (!isTransferAll) {
178
- if (balanceNum - (transferNativeNum + feeNum) < edNum) {
179
- if (edAsWarning) {
180
- validationResponse.warnings.push(new TransactionWarning(BasicTxWarningCode.NOT_ENOUGH_EXISTENTIAL_DEPOSIT));
181
- } else {
182
- validationResponse.errors.push(new TransactionError(BasicTxErrorType.NOT_ENOUGH_EXISTENTIAL_DEPOSIT));
183
- }
184
- }
185
- }
186
- }
94
+ const nativeTokenAvailable = await this.state.balanceService.getTransferableBalance(address, chain, nativeTokenInfo.slug, extrinsicType);
95
+
96
+ // Check available balance against transaction fee
97
+ checkBalanceWithTransactionFee(validationResponse, transactionInput, nativeTokenInfo, nativeTokenAvailable);
187
98
 
188
- // Validate transaction with additionalValidator method
99
+ // Check additional validations
189
100
  additionalValidator && (await additionalValidator(validationResponse));
190
101
  return validationResponse;
191
102
  }
@@ -235,7 +146,7 @@ export default class TransactionService {
235
146
  };
236
147
  }
237
148
  async handleTransaction(transaction) {
238
- const validatedTransaction = await this.generalValidate(transaction);
149
+ const validatedTransaction = await this.validateTransaction(transaction);
239
150
  const stopByErrors = validatedTransaction.errors.length > 0;
240
151
  const stopByWarnings = validatedTransaction.warnings.length > 0 && !validatedTransaction.ignoreWarnings;
241
152
  if (stopByErrors || stopByWarnings) {
@@ -53,4 +53,5 @@ export interface TransactionEventMap {
53
53
  success: (response: TransactionEventResponse) => void;
54
54
  timeout: (response: TransactionEventResponse) => void;
55
55
  }
56
+ export declare type OptionalSWTransaction = SWTransaction['transaction'] | null | undefined;
56
57
  export {};