@subwallet/extension-base 1.2.3-0 → 1.2.3-1

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 (72) hide show
  1. package/background/KoniTypes.d.ts +4 -0
  2. package/cjs/core/logic-validation/earning.js +47 -0
  3. package/cjs/core/logic-validation/swap.js +99 -0
  4. package/cjs/core/logic-validation/transfer.js +219 -0
  5. package/cjs/core/substrate/nominationpools-pallet.js +12 -0
  6. package/cjs/core/substrate/system-pallet.js +78 -0
  7. package/cjs/koni/api/dotsama/transfer.js +49 -4
  8. package/cjs/koni/api/staking/bonding/utils.js +1 -1
  9. package/cjs/koni/api/xcm/index.js +30 -2
  10. package/cjs/koni/background/handlers/Extension.js +135 -245
  11. package/cjs/packageInfo.js +1 -1
  12. package/cjs/services/balance-service/helpers/group.js +4 -27
  13. package/cjs/services/balance-service/helpers/subscribe/index.js +2 -30
  14. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +41 -80
  15. package/cjs/services/balance-service/index.js +11 -9
  16. package/cjs/services/chain-service/index.js +0 -1
  17. package/cjs/services/chain-service/utils/index.js +6 -0
  18. package/cjs/services/earning-service/handlers/base.js +1 -1
  19. package/cjs/services/earning-service/handlers/special.js +11 -12
  20. package/cjs/services/swap-service/handler/base-handler.js +28 -44
  21. package/cjs/services/swap-service/handler/chainflip-handler.js +23 -21
  22. package/cjs/services/swap-service/handler/hydradx-handler.js +40 -38
  23. package/cjs/services/swap-service/index.js +6 -0
  24. package/cjs/services/swap-service/utils.js +8 -49
  25. package/cjs/services/transaction-service/index.js +66 -155
  26. package/core/logic-validation/earning.d.ts +10 -0
  27. package/core/logic-validation/earning.js +37 -0
  28. package/core/logic-validation/swap.d.ts +8 -0
  29. package/core/logic-validation/swap.js +89 -0
  30. package/core/logic-validation/transfer.d.ts +16 -0
  31. package/core/logic-validation/transfer.js +206 -0
  32. package/core/substrate/nominationpools-pallet.d.ts +7 -0
  33. package/core/substrate/nominationpools-pallet.js +6 -0
  34. package/core/substrate/system-pallet.d.ts +27 -0
  35. package/core/substrate/system-pallet.js +71 -0
  36. package/koni/api/dotsama/transfer.d.ts +3 -1
  37. package/koni/api/dotsama/transfer.js +44 -1
  38. package/koni/api/staking/bonding/relayChain.d.ts +2 -1
  39. package/koni/api/staking/bonding/utils.js +1 -1
  40. package/koni/api/xcm/index.d.ts +2 -0
  41. package/koni/api/xcm/index.js +27 -1
  42. package/koni/background/handlers/Extension.d.ts +5 -5
  43. package/koni/background/handlers/Extension.js +111 -221
  44. package/package.json +34 -9
  45. package/packageInfo.js +1 -1
  46. package/services/balance-service/helpers/group.js +4 -27
  47. package/services/balance-service/helpers/subscribe/index.d.ts +2 -1
  48. package/services/balance-service/helpers/subscribe/index.js +2 -30
  49. package/services/balance-service/helpers/subscribe/substrate/index.d.ts +2 -1
  50. package/services/balance-service/helpers/subscribe/substrate/index.js +26 -64
  51. package/services/balance-service/index.d.ts +7 -6
  52. package/services/balance-service/index.js +12 -10
  53. package/services/chain-service/index.js +0 -1
  54. package/services/chain-service/utils/index.d.ts +1 -0
  55. package/services/chain-service/utils/index.js +4 -0
  56. package/services/earning-service/handlers/base.js +1 -1
  57. package/services/earning-service/handlers/nomination-pool/index.d.ts +2 -1
  58. package/services/earning-service/handlers/special.js +11 -12
  59. package/services/swap-service/handler/base-handler.d.ts +3 -2
  60. package/services/swap-service/handler/base-handler.js +26 -42
  61. package/services/swap-service/handler/chainflip-handler.d.ts +2 -1
  62. package/services/swap-service/handler/chainflip-handler.js +4 -2
  63. package/services/swap-service/handler/hydradx-handler.d.ts +2 -1
  64. package/services/swap-service/handler/hydradx-handler.js +7 -5
  65. package/services/swap-service/index.js +7 -1
  66. package/services/swap-service/utils.d.ts +2 -4
  67. package/services/swap-service/utils.js +7 -47
  68. package/services/transaction-service/index.d.ts +1 -1
  69. package/services/transaction-service/index.js +30 -119
  70. package/services/transaction-service/types.d.ts +1 -0
  71. package/types/balance/index.d.ts +6 -10
  72. package/types/yield/info/pallet.d.ts +0 -6
@@ -67,18 +67,8 @@ const filterAddress = (addresses, chainInfo) => {
67
67
  }
68
68
  };
69
69
 
70
- // interface SubscribeBlanceOptions {
71
- // addresses: string[];
72
- // chains: string[];
73
- // tokens: string[];
74
- // chainInfoMap: Record<string, _ChainInfo>;
75
- // substrateApiMap: Record<string, _SubstrateApi>;
76
- // evmApiMap: Record<string, _EvmApi>;
77
- // callback: (rs: BalanceItem[]) => void;
78
- // }
79
-
80
70
  // main subscription, use for multiple chains, multiple addresses and multiple tokens
81
- export function subscribeBalance(addresses, chains, tokens, _chainAssetMap, _chainInfoMap, substrateApiMap, evmApiMap, callback) {
71
+ export function subscribeBalance(addresses, chains, tokens, _chainAssetMap, _chainInfoMap, substrateApiMap, evmApiMap, callback, extrinsicType) {
82
72
  // Filter chain and token
83
73
  const chainAssetMap = Object.fromEntries(Object.entries(_chainAssetMap).filter(([token]) => tokens.includes(token)));
84
74
  const chainInfoMap = Object.fromEntries(Object.entries(_chainInfoMap).filter(([chain]) => chains.includes(chain)));
@@ -112,26 +102,8 @@ export function subscribeBalance(addresses, chains, tokens, _chainAssetMap, _cha
112
102
  evmApi
113
103
  });
114
104
  }
115
-
116
- // if (!useAddresses || useAddresses.length === 0 || _PURE_EVM_CHAINS.indexOf(chainSlug) > -1) {
117
- // const fungibleTokensByChain = state.chainService.getFungibleTokensByChain(chainSlug, true);
118
- // const now = new Date().getTime();
119
- //
120
- // Object.values(fungibleTokensByChain).map((token) => {
121
- // return {
122
- // tokenSlug: token.slug,
123
- // free: '0',
124
- // locked: '0',
125
- // state: APIItemState.READY,
126
- // timestamp: now
127
- // } as BalanceItem;
128
- // }).forEach(callback);
129
- //
130
- // return undefined;
131
- // }
132
-
133
105
  const substrateApi = await substrateApiMap[chainSlug].isReady;
134
- return subscribeSubstrateBalance(useAddresses, chainInfo, chainAssetMap, substrateApi, evmApi, callback);
106
+ return subscribeSubstrateBalance(useAddresses, chainInfo, chainAssetMap, substrateApi, evmApi, callback, extrinsicType);
135
107
  });
136
108
  return () => {
137
109
  unsubList.forEach(subProm => {
@@ -1,4 +1,5 @@
1
1
  import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types';
2
+ import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
2
3
  import { _EvmApi, _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
3
4
  import { BalanceItem } from '@subwallet/extension-base/types';
4
- export declare const subscribeSubstrateBalance: (addresses: string[], chainInfo: _ChainInfo, assetMap: Record<string, _ChainAsset>, substrateApi: _SubstrateApi, evmApi: _EvmApi, callback: (rs: BalanceItem[]) => void) => Promise<() => void>;
5
+ export declare const subscribeSubstrateBalance: (addresses: string[], chainInfo: _ChainInfo, assetMap: Record<string, _ChainAsset>, substrateApi: _SubstrateApi, evmApi: _EvmApi, callback: (rs: BalanceItem[]) => void, extrinsicType?: ExtrinsicType) => Promise<() => void>;
@@ -5,10 +5,12 @@ import { GearApi } from '@gear-js/api';
5
5
  import { _AssetType } from '@subwallet/chain-list/types';
6
6
  import { APIItemState } from '@subwallet/extension-base/background/KoniTypes';
7
7
  import { SUB_TOKEN_REFRESH_BALANCE_INTERVAL } from '@subwallet/extension-base/constants';
8
+ import { _getActiveStakeInNominationPool } from '@subwallet/extension-base/core/substrate/nominationpools-pallet';
9
+ import { _getSystemPalletTotalBalance, _getSystemPalletTransferable } from '@subwallet/extension-base/core/substrate/system-pallet';
8
10
  import { getPSP22ContractPromise } from '@subwallet/extension-base/koni/api/tokens/wasm';
9
11
  import { getDefaultWeightV2 } from '@subwallet/extension-base/koni/api/tokens/wasm/utils';
10
12
  import { _BALANCE_CHAIN_GROUP, _MANTA_ZK_CHAIN_GROUP, _ZK_ASSET_PREFIX } from '@subwallet/extension-base/services/chain-service/constants';
11
- import { _checkSmartContractSupportByChain, _getChainNativeTokenSlug, _getContractAddressOfToken, _getTokenOnChainAssetId, _getTokenOnChainInfo, _getTokenTypesSupportedByChain, _getXcmAssetMultilocation, _isBridgedToken, _isChainEvmCompatible, _isSubstrateRelayChain } from '@subwallet/extension-base/services/chain-service/utils';
13
+ import { _checkSmartContractSupportByChain, _getChainExistentialDeposit, _getChainNativeTokenSlug, _getContractAddressOfToken, _getTokenOnChainAssetId, _getTokenOnChainInfo, _getTokenTypesSupportedByChain, _getXcmAssetMultilocation, _isBridgedToken, _isChainEvmCompatible, _isSubstrateRelayChain } from '@subwallet/extension-base/services/chain-service/utils';
12
14
  import { filterAssetsByChainAndType, getGRC20ContractPromise } from '@subwallet/extension-base/utils';
13
15
  import BigN from 'bignumber.js';
14
16
  import { combineLatest, Observable } from 'rxjs';
@@ -16,7 +18,7 @@ import { BN, BN_ZERO, noop, u8aToHex } from '@polkadot/util';
16
18
  import { decodeAddress } from '@polkadot/util-crypto';
17
19
  import { subscribeERC20Interval } from "../evm.js";
18
20
  import { subscribeEquilibriumTokenBalance } from "./equilibrium.js";
19
- export const subscribeSubstrateBalance = async (addresses, chainInfo, assetMap, substrateApi, evmApi, callback) => {
21
+ export const subscribeSubstrateBalance = async (addresses, chainInfo, assetMap, substrateApi, evmApi, callback, extrinsicType) => {
20
22
  let unsubNativeToken;
21
23
  let unsubLocalToken;
22
24
  let unsubEvmContractToken;
@@ -28,7 +30,8 @@ export const subscribeSubstrateBalance = async (addresses, chainInfo, assetMap,
28
30
  addresses,
29
31
  chainInfo,
30
32
  assetMap,
31
- callback
33
+ callback,
34
+ extrinsicType
32
35
  };
33
36
  const substrateParams = {
34
37
  ...baseParams,
@@ -98,11 +101,13 @@ const subscribeWithSystemAccountPallet = async ({
98
101
  addresses,
99
102
  callback,
100
103
  chainInfo,
104
+ extrinsicType,
101
105
  substrateApi
102
106
  }) => {
103
107
  const chainNativeTokenSlug = _getChainNativeTokenSlug(chainInfo);
104
108
  const balanceSubscribe = substrateApi.rx.query.system.account.multi(addresses);
105
- let poolSubscribe;
109
+ let poolSubscribe; // add points in nomination pool back to user's balance
110
+
106
111
  if (_isSubstrateRelayChain(chainInfo) && substrateApi.query.nominationPools) {
107
112
  var _substrateApi$rx$quer;
108
113
  poolSubscribe = (_substrateApi$rx$quer = substrateApi.rx.query.nominationPools.poolMembers) === null || _substrateApi$rx$quer === void 0 ? void 0 : _substrateApi$rx$quer.multi(addresses);
@@ -118,52 +123,25 @@ const subscribeWithSystemAccountPallet = async ({
118
123
  }
119
124
  const subscription = combineLatest({
120
125
  balances: balanceSubscribe,
121
- pools: poolSubscribe
126
+ poolMemberInfos: poolSubscribe
122
127
  }).subscribe(({
123
- balances: _balances,
124
- pools: poolMemberDatas
128
+ balances,
129
+ poolMemberInfos
125
130
  }) => {
126
- const balances = _balances;
127
- const pooledStakingBalances = [];
128
- for (const _poolMemberData of poolMemberDatas) {
129
- const poolMemberData = _poolMemberData.toPrimitive();
130
- if (poolMemberData) {
131
- let pooled = new BN(poolMemberData.points.toString());
132
- Object.entries(poolMemberData.unbondingEras).forEach(([, amount]) => {
133
- pooled = pooled.add(new BN(amount));
134
- });
135
- pooledStakingBalances.push(pooled);
136
- } else {
137
- pooledStakingBalances.push(BN_ZERO);
138
- }
139
- }
140
- const items = balances.map((balance, index) => {
141
- var _balance$data, _balance$data$free, _balance$data2, _balance$data2$reserv, _balance$data3, _balance$data3$miscFr, _balance$data4, _balance$data4$frozen, _balance$data5, _balance$data5$feeFro;
142
- let total = ((_balance$data = balance.data) === null || _balance$data === void 0 ? void 0 : (_balance$data$free = _balance$data.free) === null || _balance$data$free === void 0 ? void 0 : _balance$data$free.toBn()) || new BN(0);
143
- const reserved = ((_balance$data2 = balance.data) === null || _balance$data2 === void 0 ? void 0 : (_balance$data2$reserv = _balance$data2.reserved) === null || _balance$data2$reserv === void 0 ? void 0 : _balance$data2$reserv.toBn()) || new BN(0);
144
- // @ts-ignore
145
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
146
- const miscFrozen = ((_balance$data3 = balance.data) === null || _balance$data3 === void 0 ? void 0 : (_balance$data3$miscFr = _balance$data3.miscFrozen) === null || _balance$data3$miscFr === void 0 ? void 0 : _balance$data3$miscFr.toBn()) || (balance === null || balance === void 0 ? void 0 : (_balance$data4 = balance.data) === null || _balance$data4 === void 0 ? void 0 : (_balance$data4$frozen = _balance$data4.frozen) === null || _balance$data4$frozen === void 0 ? void 0 : _balance$data4$frozen.toBn()) || new BN(0);
147
- const feeFrozen = ((_balance$data5 = balance.data) === null || _balance$data5 === void 0 ? void 0 : (_balance$data5$feeFro = _balance$data5.feeFrozen) === null || _balance$data5$feeFro === void 0 ? void 0 : _balance$data5$feeFro.toBn()) || new BN(0);
148
- let locked = reserved.add(miscFrozen);
149
- total = total.add(reserved);
150
- const pooledStakingBalance = pooledStakingBalances[index] || BN_ZERO;
151
- if (pooledStakingBalance.gt(BN_ZERO)) {
152
- total = total.add(pooledStakingBalance);
153
- locked = locked.add(pooledStakingBalance);
154
- }
155
- const free = total.sub(locked);
131
+ const items = balances.map((_balance, index) => {
132
+ const balanceInfo = _balance.toPrimitive();
133
+ const poolMemberInfo = poolMemberInfos[index].toPrimitive();
134
+ const nominationPoolBalance = poolMemberInfo ? _getActiveStakeInNominationPool(poolMemberInfo) : '0';
135
+ const transferableBalance = _getSystemPalletTransferable(balanceInfo, _getChainExistentialDeposit(chainInfo), extrinsicType);
136
+ const totalBalance = _getSystemPalletTotalBalance(balanceInfo);
137
+ const totalLockedFromTransfer = new BigN(totalBalance).minus(transferableBalance).plus(nominationPoolBalance);
156
138
  return {
157
139
  address: addresses[index],
158
140
  tokenSlug: chainNativeTokenSlug,
159
- free: free.gte(BN_ZERO) ? free.toString() : '0',
160
- locked: locked.toString(),
141
+ free: transferableBalance,
142
+ locked: totalLockedFromTransfer.toFixed(),
161
143
  state: APIItemState.READY,
162
- substrateInfo: {
163
- miscFrozen: miscFrozen.toString(),
164
- reserved: reserved.toString(),
165
- feeFrozen: feeFrozen.toString()
166
- }
144
+ metadata: balanceInfo
167
145
  };
168
146
  });
169
147
  callback(items);
@@ -211,11 +189,7 @@ const subscribeBridgedBalance = async ({
211
189
  tokenSlug: tokenInfo.slug,
212
190
  free: free.toString(),
213
191
  locked: frozen.toString(),
214
- state: APIItemState.READY,
215
- substrateInfo: {
216
- miscFrozen: frozen.toString(),
217
- reserved: '0'
218
- }
192
+ state: APIItemState.READY
219
193
  };
220
194
  });
221
195
  callback(items);
@@ -331,11 +305,7 @@ const subscribeTokensAccountsPallet = async ({
331
305
  tokenSlug: tokenInfo.slug,
332
306
  state: APIItemState.READY,
333
307
  free: freeBalance.toString(),
334
- locked: lockedBalance.toString(),
335
- substrateInfo: {
336
- reserved: tokenBalance.reserved.toString(),
337
- miscFrozen: tokenBalance.frozen.toString()
338
- }
308
+ locked: lockedBalance.toString()
339
309
  };
340
310
  });
341
311
  callback(items);
@@ -393,11 +363,7 @@ const subscribeAssetsAccountPallet = async ({
393
363
  tokenSlug: tokenInfo.slug,
394
364
  free: free.toString(),
395
365
  locked: frozen.toString(),
396
- state: APIItemState.READY,
397
- substrateInfo: {
398
- miscFrozen: frozen.toString(),
399
- reserved: '0'
400
- }
366
+ state: APIItemState.READY
401
367
  };
402
368
  });
403
369
  callback(items);
@@ -448,11 +414,7 @@ const subscribeOrmlTokensPallet = async ({
448
414
  tokenSlug: tokenInfo.slug,
449
415
  state: APIItemState.READY,
450
416
  free: freeBalance.toString(),
451
- locked: lockedBalance.toString(),
452
- substrateInfo: {
453
- reserved: tokenBalance.reserved.toString(),
454
- miscFrozen: tokenBalance.frozen.toString()
455
- }
417
+ locked: lockedBalance.toString()
456
418
  };
457
419
  });
458
420
  callback(items);
@@ -1,4 +1,4 @@
1
- import { AmountData, DetectBalanceCache } from '@subwallet/extension-base/background/KoniTypes';
1
+ import { AmountData, DetectBalanceCache, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
2
2
  import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
3
3
  import { ServiceStatus, StoppableServiceInterface } from '@subwallet/extension-base/services/base/types';
4
4
  import { EventItem, EventType } from '@subwallet/extension-base/services/event-service/types';
@@ -44,19 +44,20 @@ export declare class BalanceService implements StoppableServiceInterface {
44
44
  handleEvents(events: EventItem<EventType>[], eventTypes: EventType[]): void;
45
45
  getBalanceDetectCache(update: (value: DetectBalanceCache) => void): void;
46
46
  setBalanceDetectCache(addresses: string[]): void;
47
- /** Subscribe token free balance of a address on chain */
48
- subscribeTokenFreeBalance(address: string, chain: string, tokenSlug: string | undefined, callback?: (rs: AmountData) => void): Promise<[() => void, AmountData]>;
47
+ /** Subscribe token free balance of an address on chain */
48
+ subscribeTransferableBalance(address: string, chain: string, tokenSlug: string | undefined, extrinsicType?: ExtrinsicType, callback?: (rs: AmountData) => void): Promise<[() => void, AmountData]>;
49
49
  /**
50
50
  * @public
51
51
  * @async
52
- * @function getTokenFreeBalance
52
+ * @function getTransferableBalance
53
53
  * @desc Fetch free balance on chain
54
54
  * @param {string} address - Address
55
55
  * @param {string} chain - Slug of chain
56
56
  * @param {string} [tokenSlug] - Slug of token
57
+ * @param extrinsicType - Customize transferable based on context
57
58
  * @return {Promise<AmountData>} - Free token balance of address on chain
58
- */
59
- getTokenFreeBalance(address: string, chain: string, tokenSlug?: string): Promise<AmountData>;
59
+ */
60
+ getTransferableBalance(address: string, chain: string, tokenSlug?: string, extrinsicType?: ExtrinsicType): Promise<AmountData>;
60
61
  /** Remove balance from the subject object by addresses */
61
62
  removeBalanceByAddresses(addresses: string[]): void;
62
63
  /** Remove inactive asset from the balance map */
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { BalanceError } from '@subwallet/extension-base/background/errors/BalanceError';
5
- import { BalanceErrorType } from '@subwallet/extension-base/background/KoniTypes';
5
+ import { BalanceErrorType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
6
6
  import { ALL_ACCOUNT_KEY } from '@subwallet/extension-base/constants';
7
7
  import { ServiceStatus } from '@subwallet/extension-base/services/base/types';
8
8
  import { _getChainNativeTokenSlug } from '@subwallet/extension-base/services/chain-service/utils';
@@ -159,8 +159,8 @@ export class BalanceService {
159
159
  });
160
160
  }
161
161
 
162
- /** Subscribe token free balance of a address on chain */
163
- async subscribeTokenFreeBalance(address, chain, tokenSlug, callback) {
162
+ /** Subscribe token free balance of an address on chain */
163
+ async subscribeTransferableBalance(address, chain, tokenSlug, extrinsicType, callback) {
164
164
  const chainInfo = this.state.chainService.getChainInfoByKey(chain);
165
165
  const chainState = this.state.chainService.getChainStateByKey(chain);
166
166
  if (!chainInfo || !chainState || !chainState.active) {
@@ -193,7 +193,8 @@ export class BalanceService {
193
193
  const balance = {
194
194
  value: rs.free,
195
195
  decimals: tokenInfo.decimals || 0,
196
- symbol: tokenInfo.symbol
196
+ symbol: tokenInfo.symbol,
197
+ metadata: rs.metadata
197
198
  };
198
199
  if (callback) {
199
200
  callback(balance);
@@ -204,7 +205,7 @@ export class BalanceService {
204
205
  }
205
206
  resolve([unsub, balance]);
206
207
  }
207
- });
208
+ }, extrinsicType);
208
209
  setTimeout(() => {
209
210
  if (hasError) {
210
211
  var _unsub2;
@@ -218,15 +219,16 @@ export class BalanceService {
218
219
  /**
219
220
  * @public
220
221
  * @async
221
- * @function getTokenFreeBalance
222
+ * @function getTransferableBalance
222
223
  * @desc Fetch free balance on chain
223
224
  * @param {string} address - Address
224
225
  * @param {string} chain - Slug of chain
225
226
  * @param {string} [tokenSlug] - Slug of token
227
+ * @param extrinsicType - Customize transferable based on context
226
228
  * @return {Promise<AmountData>} - Free token balance of address on chain
227
- */
228
- async getTokenFreeBalance(address, chain, tokenSlug) {
229
- const [, balance] = await this.subscribeTokenFreeBalance(address, chain, tokenSlug);
229
+ */
230
+ async getTransferableBalance(address, chain, tokenSlug, extrinsicType) {
231
+ const [, balance] = await this.subscribeTransferableBalance(address, chain, tokenSlug, extrinsicType);
230
232
  return balance;
231
233
  }
232
234
 
@@ -328,7 +330,7 @@ export class BalanceService {
328
330
  }).map(asset => asset.slug);
329
331
  const unsub = subscribeBalance(addresses, activeChainSlugs, assets, assetMap, chainInfoMap, substrateApiMap, evmApiMap, result => {
330
332
  !cancel && this.setBalanceItem(result);
331
- });
333
+ }, ExtrinsicType.TRANSFER_BALANCE);
332
334
  const unsub2 = this.state.subscribeMantaPayBalance();
333
335
  this._unsubscribeBalance = () => {
334
336
  cancel = true;
@@ -474,7 +474,6 @@ export class ChainService {
474
474
  needUpdateChainApiList,
475
475
  storedChainInfoList
476
476
  } = updateLatestChainInfo(this.dataMap, latestChainInfo);
477
- console.log('here', needUpdateChainApiList, storedChainInfoList);
478
477
  this.dbService.bulkUpdateChainStore(storedChainInfoList).catch(console.error);
479
478
  this.updateChainSubscription();
480
479
  needUpdateChainApiList.forEach(chainInfo => {
@@ -88,6 +88,7 @@ export declare function _generateCustomProviderKey(index: number): string;
88
88
  export declare const findChainInfoByHalfGenesisHash: (chainMap: Record<string, _ChainInfo>, halfGenesisHash?: string) => _ChainInfo | null;
89
89
  export declare const findChainInfoByChainId: (chainMap: Record<string, _ChainInfo>, chainId?: number) => _ChainInfo | null;
90
90
  export declare function _isMantaZkAsset(chainAsset: _ChainAsset): boolean;
91
+ export declare function _getChainExistentialDeposit(chainInfo: _ChainInfo): string;
91
92
  export declare function randomizeProvider(providers: Record<string, string>, excludedKeys?: string[]): {
92
93
  providerKey: string;
93
94
  providerValue: string;
@@ -406,6 +406,10 @@ export const findChainInfoByChainId = (chainMap, chainId) => {
406
406
  export function _isMantaZkAsset(chainAsset) {
407
407
  return _MANTA_ZK_CHAIN_GROUP.includes(chainAsset.originChain) && chainAsset.symbol.startsWith(_ZK_ASSET_PREFIX);
408
408
  }
409
+ export function _getChainExistentialDeposit(chainInfo) {
410
+ var _chainInfo$substrateI18;
411
+ return (chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$substrateI18 = chainInfo.substrateInfo) === null || _chainInfo$substrateI18 === void 0 ? void 0 : _chainInfo$substrateI18.existentialDeposit) || '0';
412
+ }
409
413
  export function randomizeProvider(providers, excludedKeys) {
410
414
  if (Object.keys(providers).length === 0) {
411
415
  return {
@@ -129,7 +129,7 @@ export default class BasePoolHandler {
129
129
  };
130
130
  }
131
131
  const nativeTokenInfo = this.state.chainService.getNativeTokenInfo(this.chain);
132
- const nativeTokenBalance = await this.state.balanceService.getTokenFreeBalance(request.address, this.chain);
132
+ const nativeTokenBalance = await this.state.balanceService.getTransferableBalance(request.address, this.chain);
133
133
  const bnNativeTokenBalance = new BN(nativeTokenBalance.value);
134
134
  const bnMinBalanceToJoin = new BN(((_poolInfo$statistic2 = poolInfo.statistic) === null || _poolInfo$statistic2 === void 0 ? void 0 : (_poolInfo$statistic2$ = _poolInfo$statistic2.earningThreshold) === null || _poolInfo$statistic2$ === void 0 ? void 0 : _poolInfo$statistic2$.join) || '0').add(new BN(poolInfo.metadata.maintainBalance));
135
135
  if (bnNativeTokenBalance.lte(bnMinBalanceToJoin)) {
@@ -1,8 +1,9 @@
1
1
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
2
2
  import { ExtrinsicType, UnstakingInfo } from '@subwallet/extension-base/background/KoniTypes';
3
+ import { PalletNominationPoolsPoolMember } from '@subwallet/extension-base/core/substrate/nominationpools-pallet';
3
4
  import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
4
5
  import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
5
- import { BaseYieldPositionInfo, EarningRewardHistoryItem, EarningRewardItem, HandleYieldStepData, NominationPoolInfo, OptimalYieldPath, OptimalYieldPathParams, PalletNominationPoolsPoolMember, StakeCancelWithdrawalParams, SubmitJoinNominationPool, SubmitYieldJoinData, TransactionData, YieldPoolInfo, YieldPoolMethodInfo, YieldPoolType, YieldPositionInfo, YieldStepBaseInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types';
6
+ import { BaseYieldPositionInfo, EarningRewardHistoryItem, EarningRewardItem, HandleYieldStepData, NominationPoolInfo, OptimalYieldPath, OptimalYieldPathParams, StakeCancelWithdrawalParams, SubmitJoinNominationPool, SubmitYieldJoinData, TransactionData, YieldPoolInfo, YieldPoolMethodInfo, YieldPoolType, YieldPositionInfo, YieldStepBaseInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types';
6
7
  import { DeriveSessionProgress } from '@polkadot/api-derive/types';
7
8
  import BasePoolHandler from '../base';
8
9
  export default class NominationPoolHandler extends BasePoolHandler {
@@ -67,11 +67,11 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
67
67
  const feeAssetInfo = this.state.chainService.getAssetBySlug(this.feeAssets[0]);
68
68
  const altInputAssetInfo = this.state.chainService.getAssetBySlug(this.altInputAsset);
69
69
  const inputAssetInfo = this.state.chainService.getAssetBySlug(this.inputAsset);
70
- const [inputAssetBalance, altInputAssetBalance, feeAssetBalance] = await Promise.all([this.state.balanceService.getTokenFreeBalance(request.address, inputAssetInfo.originChain, inputAssetInfo.slug), altInputAssetInfo ? this.state.balanceService.getTokenFreeBalance(request.address, altInputAssetInfo.originChain, altInputAssetInfo.slug) : Promise.resolve({
70
+ const [inputAssetBalance, altInputAssetBalance, feeAssetBalance] = await Promise.all([this.state.balanceService.getTransferableBalance(request.address, inputAssetInfo.originChain, inputAssetInfo.slug), altInputAssetInfo ? this.state.balanceService.getTransferableBalance(request.address, altInputAssetInfo.originChain, altInputAssetInfo.slug) : Promise.resolve({
71
71
  symbol: '',
72
72
  decimals: 0,
73
73
  value: '0'
74
- }), this.state.balanceService.getTokenFreeBalance(request.address, feeAssetInfo.originChain, feeAssetInfo.slug)]);
74
+ }), this.state.balanceService.getTransferableBalance(request.address, feeAssetInfo.originChain, feeAssetInfo.slug)]);
75
75
  const bnInputAssetBalance = new BN(inputAssetBalance.value);
76
76
  const bnAltInputAssetBalance = new BN(altInputAssetBalance.value);
77
77
  const bnMinJoinPool = new BN(poolInfo.statistic.earningThreshold.join);
@@ -193,13 +193,13 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
193
193
  const bnAmount = new BN(amount);
194
194
  const inputTokenSlug = this.inputAsset; // assume that the pool only has 1 input token, will update later
195
195
  const inputTokenInfo = this.state.getAssetBySlug(inputTokenSlug);
196
- const inputTokenBalance = await this.state.balanceService.getTokenFreeBalance(address, inputTokenInfo.originChain, inputTokenSlug);
196
+ const inputTokenBalance = await this.state.balanceService.getTransferableBalance(address, inputTokenInfo.originChain, inputTokenSlug);
197
197
  const bnInputTokenBalance = new BN(inputTokenBalance.value);
198
198
  if (!bnInputTokenBalance.gte(bnAmount)) {
199
199
  if (this.altInputAsset) {
200
200
  const altInputTokenSlug = this.altInputAsset;
201
201
  const altInputTokenInfo = this.state.getAssetBySlug(altInputTokenSlug);
202
- const altInputTokenBalance = await this.state.balanceService.getTokenFreeBalance(address, altInputTokenInfo.originChain, altInputTokenSlug);
202
+ const altInputTokenBalance = await this.state.balanceService.getTransferableBalance(address, altInputTokenInfo.originChain, altInputTokenSlug);
203
203
  const bnAltInputTokenBalance = new BN(altInputTokenBalance.value || '0');
204
204
  if (bnAltInputTokenBalance.gt(BN_ZERO)) {
205
205
  const altChainInfo = this.state.getChainInfo(altInputTokenInfo.originChain);
@@ -272,17 +272,16 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
272
272
  const altInputTokenSlug = this.altInputAsset || '';
273
273
  const altInputTokenInfo = this.state.getAssetBySlug(altInputTokenSlug);
274
274
  const inputTokenInfo = this.state.getAssetBySlug(this.inputAsset);
275
- const altInputTokenBalance = await this.state.balanceService.getTokenFreeBalance(params.address, altInputTokenInfo.originChain, altInputTokenSlug);
275
+ const altInputTokenBalance = await this.state.balanceService.getTransferableBalance(params.address, altInputTokenInfo.originChain, altInputTokenSlug);
276
276
  const missingAmount = bnAmount.sub(bnInputTokenBalance); // TODO: what if input token is not LOCAL ??
277
277
  const xcmFee = new BN(path.totalFee[1].amount || '0');
278
278
  const xcmAmount = missingAmount.add(xcmFee);
279
279
  const bnAltInputTokenBalance = new BN(altInputTokenBalance.value || '0');
280
- const altInputTokenMinAmount = new BN(altInputTokenInfo.minAmount || '0');
281
- if (!bnAltInputTokenBalance.sub(xcmAmount).gte(altInputTokenMinAmount)) {
280
+ if (!bnAltInputTokenBalance.sub(xcmAmount).gt(BN_ZERO)) {
282
281
  processValidation.failedStep = path.steps[1];
283
282
  processValidation.ok = false;
284
283
  processValidation.status = YieldValidationStatus.NOT_ENOUGH_BALANCE;
285
- const maxBn = bnInputTokenBalance.add(new BN(altInputTokenBalance.value)).sub(xcmFee).sub(altInputTokenMinAmount);
284
+ const maxBn = bnInputTokenBalance.add(new BN(altInputTokenBalance.value)).sub(xcmFee);
286
285
  const maxValue = formatNumber(maxBn.toString(), inputTokenInfo.decimals || 0);
287
286
  const altInputTokenInfo = this.state.getAssetBySlug(altInputTokenSlug);
288
287
  const symbol = altInputTokenInfo.symbol;
@@ -290,7 +289,7 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
290
289
  const inputNetworkName = this.chainInfo.name;
291
290
  const altNetworkName = altNetwork.name;
292
291
  const currentValue = formatNumber(bnInputTokenBalance.toString(), inputTokenInfo.decimals || 0);
293
- const bnMaxXCM = new BN(altInputTokenBalance.value).sub(xcmFee).sub(altInputTokenMinAmount);
292
+ const bnMaxXCM = new BN(altInputTokenBalance.value).sub(xcmFee);
294
293
  const maxXCMValue = formatNumber(bnMaxXCM.toString(), inputTokenInfo.decimals || 0);
295
294
  processValidation.message = t('You can only enter a maximum of {{maxValue}} {{symbol}}, which is {{currentValue}} {{symbol}} ({{inputNetworkName}}) and {{maxXCMValue}} {{symbol}} ({{altNetworkName}}). Lower your amount and try again.', {
296
295
  replace: {
@@ -327,7 +326,7 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
327
326
  if (this.feeAssets.length === 1 && feeTokenSlug === defaultFeeTokenSlug) {
328
327
  var _path$totalFee$id;
329
328
  const bnFeeAmount = new BN(((_path$totalFee$id = path.totalFee[id]) === null || _path$totalFee$id === void 0 ? void 0 : _path$totalFee$id.amount) || '0');
330
- const feeTokenBalance = await this.state.balanceService.getTokenFreeBalance(params.address, feeTokenInfo.originChain, feeTokenSlug);
329
+ const feeTokenBalance = await this.state.balanceService.getTransferableBalance(params.address, feeTokenInfo.originChain, feeTokenSlug);
331
330
  const bnFeeTokenBalance = new BN(feeTokenBalance.value || '0');
332
331
  const bnFeeTokenMinAmount = new BN((feeTokenInfo === null || feeTokenInfo === void 0 ? void 0 : feeTokenInfo.minAmount) || '0');
333
332
  if (!bnFeeTokenBalance.sub(bnFeeAmount).gte(bnFeeTokenMinAmount)) {
@@ -365,7 +364,7 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
365
364
  const inputTokenSlug = this.inputAsset;
366
365
  const inputTokenInfo = this.state.getAssetBySlug(inputTokenSlug);
367
366
  const balanceService = this.state.balanceService;
368
- const inputTokenBalance = await balanceService.getTokenFreeBalance(params.address, inputTokenInfo.originChain, inputTokenSlug);
367
+ const inputTokenBalance = await balanceService.getTransferableBalance(params.address, inputTokenInfo.originChain, inputTokenSlug);
369
368
  const bnInputTokenBalance = new BN(inputTokenBalance.value || '0');
370
369
  const bnAmount = new BN(params.amount);
371
370
  if (bnAmount.lte(BN_ZERO)) {
@@ -415,7 +414,7 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
415
414
  const originTokenInfo = this.state.getAssetBySlug(originTokenSlug);
416
415
  const destinationTokenInfo = this.state.getAssetBySlug(destinationTokenSlug);
417
416
  const substrateApi = this.state.getSubstrateApi(originChainInfo.slug);
418
- const inputTokenBalance = await this.state.balanceService.getTokenFreeBalance(address, destinationTokenInfo.originChain, destinationTokenSlug);
417
+ const inputTokenBalance = await this.state.balanceService.getTransferableBalance(address, destinationTokenInfo.originChain, destinationTokenSlug);
419
418
  const bnInputTokenBalance = new BN(inputTokenBalance.value);
420
419
  const bnXcmFee = new BN(xcmFee);
421
420
  const bnAmount = new BN(amount);
@@ -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,7 +54,7 @@ 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
@@ -63,9 +63,8 @@ export class SwapBaseHandler {
63
63
  if (_isNativeToken(alternativeAsset)) {
64
64
  xcmAmount = xcmAmount.plus(xcmFee);
65
65
  }
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);
66
+ if (!bnAlternativeAssetBalance.minus(xcmAmount).gt(0)) {
67
+ const maxBn = bnFromAssetBalance.plus(new BigNumber(alternativeAssetBalance.value)).minus(xcmFee);
69
68
  const maxValue = formatNumber(maxBn.toString(), fromAsset.decimals || 0);
70
69
  const altInputTokenInfo = this.chainService.getAssetBySlug(alternativeAssetSlug);
71
70
  const symbol = altInputTokenInfo.symbol;
@@ -74,7 +73,7 @@ export class SwapBaseHandler {
74
73
  const inputNetworkName = chain.name;
75
74
  const altNetworkName = alternativeChain.name;
76
75
  const currentValue = formatNumber(bnFromAssetBalance.toString(), fromAsset.decimals || 0);
77
- const bnMaxXCM = new BigNumber(alternativeAssetBalance.value).minus(xcmFee).minus(alternativeTokenMinAmount);
76
+ const bnMaxXCM = new BigNumber(alternativeAssetBalance.value).minus(xcmFee);
78
77
  const maxXCMValue = formatNumber(bnMaxXCM.toString(), fromAsset.decimals || 0);
79
78
  if (maxBn.lte(0) || bnFromAssetBalance.lte(0) || bnMaxXCM.lte(0)) {
80
79
  return [new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE, t(`Insufficient balance. Deposit ${fromAsset.symbol} and try again.`))];
@@ -102,7 +101,7 @@ export class SwapBaseHandler {
102
101
  const feeInfo = params.process.totalFee[stepIndex];
103
102
  const feeAmount = feeInfo.feeComponent[0];
104
103
  const feeTokenInfo = this.chainService.getAssetBySlug(feeInfo.defaultFeeToken);
105
- const feeTokenBalance = await this.balanceService.getTokenFreeBalance(params.address, feeTokenInfo.originChain, feeTokenInfo.slug);
104
+ const feeTokenBalance = await this.balanceService.getTransferableBalance(params.address, feeTokenInfo.originChain, feeTokenInfo.slug);
106
105
  const bnFeeTokenBalance = new BigNumber(feeTokenBalance.value);
107
106
  const bnFeeAmount = new BigNumber(feeAmount.amount);
108
107
  if (bnFeeAmount.gte(bnFeeTokenBalance)) {
@@ -111,6 +110,9 @@ export class SwapBaseHandler {
111
110
  return [];
112
111
  }
113
112
  async validateSwapStep(params, isXcmOk, stepIndex) {
113
+ // check swap quote timestamp
114
+ // check balance to pay transaction fee
115
+ // check balance against spending amount
114
116
  if (!params.selectedQuote) {
115
117
  return Promise.resolve([new TransactionError(BasicTxErrorType.INTERNAL_ERROR)]);
116
118
  }
@@ -119,49 +121,31 @@ export class SwapBaseHandler {
119
121
  if (selectedQuote.aliveUntil <= currentTimestamp) {
120
122
  return Promise.resolve([new TransactionError(SwapErrorType.QUOTE_TIMEOUT)]);
121
123
  }
122
- const bnAmount = new BigNumber(params.selectedQuote.fromAmount);
123
- const fromAsset = this.chainService.getAssetBySlug(params.selectedQuote.pair.from);
124
124
  const stepFee = params.process.totalFee[stepIndex].feeComponent;
125
125
  const networkFee = stepFee.find(fee => fee.feeType === SwapFeeType.NETWORK_FEE);
126
126
  if (!networkFee) {
127
127
  return Promise.resolve([new TransactionError(BasicTxErrorType.INTERNAL_ERROR)]);
128
128
  }
129
+ const fromAsset = this.chainService.getAssetBySlug(params.selectedQuote.pair.from);
129
130
  const feeTokenInfo = this.chainService.getAssetBySlug(networkFee.tokenSlug);
130
131
  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`)]);
132
+ const {
133
+ fromAmount,
134
+ minSwap
135
+ } = params.selectedQuote;
136
+ const [feeTokenBalance, fromAssetBalance] = await Promise.all([this.balanceService.getTransferableBalance(params.address, feeTokenInfo.originChain, feeTokenInfo.slug), this.balanceService.getTransferableBalance(params.address, fromAsset.originChain, fromAsset.slug)]);
137
+ const balanceError = _validateBalanceToSwap(fromAsset, feeTokenInfo, feeTokenChain, networkFee.amount, fromAssetBalance.value, feeTokenBalance.value, fromAmount, isXcmOk, minSwap);
138
+ if (balanceError) {
139
+ return Promise.resolve([balanceError]);
137
140
  }
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
- }
141
+ if (!params.recipient) {
142
+ return Promise.resolve([]);
142
143
  }
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
- }
144
+ const toAsset = this.chainService.getAssetBySlug(params.selectedQuote.pair.to);
145
+ const toAssetChain = this.chainService.getChainInfoByKey(toAsset.originChain);
146
+ const recipientError = _validateSwapRecipient(toAssetChain, params.recipient);
147
+ if (recipientError) {
148
+ return Promise.resolve([recipientError]);
165
149
  }
166
150
  return Promise.resolve([]);
167
151
  }