@subwallet/extension-base 1.3.30-0 → 1.3.31-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 (75) hide show
  1. package/background/KoniTypes.d.ts +12 -0
  2. package/cjs/constants/paraspell-chain-map.js +13 -0
  3. package/cjs/core/logic-validation/transfer.js +13 -1
  4. package/cjs/core/substrate/xcm-parser.js +5 -1
  5. package/cjs/core/utils.js +36 -15
  6. package/cjs/koni/background/handlers/Extension.js +136 -90
  7. package/cjs/koni/background/handlers/State.js +8 -1
  8. package/cjs/packageInfo.js +1 -1
  9. package/cjs/services/balance-service/helpers/process.js +27 -0
  10. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +33 -1
  11. package/cjs/services/balance-service/index.js +9 -0
  12. package/cjs/services/balance-service/transfer/xcm/acrossBridge/index.js +229 -0
  13. package/cjs/services/balance-service/transfer/xcm/index.js +96 -7
  14. package/cjs/services/balance-service/transfer/xcm/utils.js +213 -0
  15. package/cjs/services/chain-service/constants.js +2 -4
  16. package/cjs/services/chain-service/index.js +71 -17
  17. package/cjs/services/chain-service/utils/patch.js +1 -1
  18. package/cjs/services/earning-service/handlers/special.js +18 -9
  19. package/cjs/services/keyring-service/context/handlers/Ledger.js +1 -1
  20. package/cjs/services/keyring-service/context/state.js +3 -0
  21. package/cjs/services/migration-service/scripts/DisableZeroBalanceTokens.js +60 -0
  22. package/cjs/services/migration-service/scripts/EnableChain.js +1 -1
  23. package/cjs/services/migration-service/scripts/index.js +3 -2
  24. package/cjs/services/swap-service/handler/base-handler.js +24 -11
  25. package/cjs/services/transaction-service/utils.js +38 -14
  26. package/cjs/utils/fee/transfer.js +52 -28
  27. package/cjs/utils/staticData/index.js +7 -2
  28. package/constants/paraspell-chain-map.d.ts +1 -0
  29. package/constants/paraspell-chain-map.js +7 -0
  30. package/core/logic-validation/transfer.d.ts +1 -0
  31. package/core/logic-validation/transfer.js +12 -1
  32. package/core/substrate/xcm-parser.d.ts +1 -0
  33. package/core/substrate/xcm-parser.js +4 -1
  34. package/core/utils.d.ts +2 -2
  35. package/core/utils.js +36 -15
  36. package/koni/background/handlers/Extension.d.ts +1 -0
  37. package/koni/background/handlers/Extension.js +60 -15
  38. package/koni/background/handlers/State.d.ts +1 -0
  39. package/koni/background/handlers/State.js +7 -1
  40. package/package.json +23 -7
  41. package/packageInfo.js +1 -1
  42. package/services/balance-service/helpers/process.d.ts +2 -1
  43. package/services/balance-service/helpers/process.js +26 -0
  44. package/services/balance-service/helpers/subscribe/substrate/index.js +34 -2
  45. package/services/balance-service/index.js +11 -2
  46. package/services/balance-service/transfer/xcm/acrossBridge/index.d.ts +15 -0
  47. package/services/balance-service/transfer/xcm/acrossBridge/index.js +216 -0
  48. package/services/balance-service/transfer/xcm/index.d.ts +5 -1
  49. package/services/balance-service/transfer/xcm/index.js +85 -1
  50. package/services/balance-service/transfer/xcm/utils.d.ts +11 -0
  51. package/services/balance-service/transfer/xcm/utils.js +208 -0
  52. package/services/chain-service/constants.d.ts +0 -1
  53. package/services/chain-service/constants.js +1 -2
  54. package/services/chain-service/index.d.ts +9 -2
  55. package/services/chain-service/index.js +72 -18
  56. package/services/chain-service/utils/patch.js +1 -1
  57. package/services/earning-service/handlers/special.js +19 -10
  58. package/services/keyring-service/context/handlers/Ledger.js +1 -1
  59. package/services/keyring-service/context/state.d.ts +1 -0
  60. package/services/keyring-service/context/state.js +3 -0
  61. package/services/migration-service/scripts/DisableZeroBalanceTokens.d.ts +4 -0
  62. package/services/migration-service/scripts/DisableZeroBalanceTokens.js +51 -0
  63. package/services/migration-service/scripts/EnableChain.js +1 -1
  64. package/services/migration-service/scripts/index.js +3 -2
  65. package/services/swap-service/handler/base-handler.js +25 -12
  66. package/services/transaction-service/types.d.ts +3 -2
  67. package/services/transaction-service/utils.d.ts +1 -0
  68. package/services/transaction-service/utils.js +38 -15
  69. package/types/balance/transfer.d.ts +1 -0
  70. package/types/transaction/request.d.ts +7 -0
  71. package/utils/fee/transfer.d.ts +1 -0
  72. package/utils/fee/transfer.js +54 -30
  73. package/utils/staticData/index.d.ts +4 -1
  74. package/utils/staticData/index.js +5 -1
  75. package/utils/staticData/paraSpellChainMap.json +1 -0
@@ -11,7 +11,7 @@ import { SubstrateChainHandler } from '@subwallet/extension-base/services/chain-
11
11
  import { TonChainHandler } from '@subwallet/extension-base/services/chain-service/handler/TonChainHandler';
12
12
  import { _CHAIN_VALIDATION_ERROR } from '@subwallet/extension-base/services/chain-service/handler/types';
13
13
  import { _ChainConnectionStatus, _CUSTOM_PREFIX, _NFT_CONTRACT_STANDARDS, _SMART_CONTRACT_STANDARDS } from '@subwallet/extension-base/services/chain-service/types';
14
- import { _getAssetOriginChain, _getTokenOnChainAssetId, _isAssetAutoEnable, _isAssetCanPayTxFee, _isAssetFungibleToken, _isChainEnabled, _isCustomAsset, _isCustomChain, _isCustomProvider, _isEqualContractAddress, _isEqualSmartContractAsset, _isLocalToken, _isMantaZkAsset, _isPureEvmChain, _isPureSubstrateChain, _parseAssetRefKey, randomizeProvider, updateLatestChainInfo } from '@subwallet/extension-base/services/chain-service/utils';
14
+ import { _getAssetOriginChain, _getTokenOnChainAssetId, _isAssetAutoEnable, _isAssetCanPayTxFee, _isAssetFungibleToken, _isChainEnabled, _isCustomAsset, _isCustomChain, _isCustomProvider, _isEqualContractAddress, _isEqualSmartContractAsset, _isLocalToken, _isMantaZkAsset, _isNativeToken, _isPureEvmChain, _isPureSubstrateChain, _parseAssetRefKey, randomizeProvider, updateLatestChainInfo } from '@subwallet/extension-base/services/chain-service/utils';
15
15
  import { MYTHOS_MIGRATION_KEY } from '@subwallet/extension-base/services/migration-service/scripts';
16
16
  import AssetSettingStore from '@subwallet/extension-base/stores/AssetSetting';
17
17
  import { addLazy, calculateMetadataHash, fetchStaticData, filterAssetsByChainAndType, getShortMetadata, MODULE_SUPPORT } from '@subwallet/extension-base/utils';
@@ -50,6 +50,7 @@ export class ChainService {
50
50
  chainLogoMapSubject = new BehaviorSubject(ChainLogoMap);
51
51
  ledgerGenericAllowChainsSubject = new BehaviorSubject([]);
52
52
  priorityTokensSubject = new BehaviorSubject({});
53
+ sufficientChainsSubject = new BehaviorSubject({});
53
54
 
54
55
  // Todo: Update to new store indexed DB
55
56
  store = new AssetSettingStore();
@@ -75,24 +76,32 @@ export class ChainService {
75
76
  get value() {
76
77
  const ledgerGenericAllowChains = this.ledgerGenericAllowChainsSubject;
77
78
  const priorityTokens = this.priorityTokensSubject;
79
+ const sufficientChains = this.sufficientChainsSubject;
78
80
  return {
79
81
  get ledgerGenericAllowChains() {
80
82
  return ledgerGenericAllowChains.value;
81
83
  },
82
84
  get priorityTokens() {
83
85
  return priorityTokens.value;
86
+ },
87
+ get sufficientChains() {
88
+ return sufficientChains.value;
84
89
  }
85
90
  };
86
91
  }
87
92
  get observable() {
88
93
  const ledgerGenericAllowChains = this.ledgerGenericAllowChainsSubject;
89
94
  const priorityTokens = this.priorityTokensSubject;
95
+ const sufficientChains = this.sufficientChainsSubject;
90
96
  return {
91
97
  get ledgerGenericAllowChains() {
92
98
  return ledgerGenericAllowChains.asObservable();
93
99
  },
94
100
  get priorityTokens() {
95
101
  return priorityTokens.asObservable();
102
+ },
103
+ get sufficientChains() {
104
+ return sufficientChains.asObservable();
96
105
  }
97
106
  };
98
107
  }
@@ -526,7 +535,7 @@ export class ChainService {
526
535
  this.initAssetRefMap();
527
536
  this.xcmRefMapSubject.next(this.xcmRefMap);
528
537
  await this.initApis();
529
- await this.initAssetSettings();
538
+ this.initAssetSettings();
530
539
  await this.autoEnableTokens();
531
540
  }
532
541
  initAssetRefMap() {
@@ -605,14 +614,47 @@ export class ChainService {
605
614
  }
606
615
  }
607
616
  }
617
+ async enablePopularTokens() {
618
+ const assetSettings = this.assetSettingSubject.value;
619
+ const chainStateMap = this.getChainStateMap();
620
+ const priorityTokensMap = this.priorityTokensSubject.value || {};
621
+ const priorityTokensList = priorityTokensMap.token && typeof priorityTokensMap.token === 'object' ? Object.keys(priorityTokensMap.token) : [];
622
+ for (const assetSlug of priorityTokensList) {
623
+ const assetState = assetSettings[assetSlug];
624
+ const assetInfo = this.getAssetBySlug(assetSlug);
625
+ const chainState = chainStateMap[assetInfo.originChain];
626
+ if (!assetState) {
627
+ // If this asset not has asset setting, this token is not enabled before (not turned off before)
628
+ if (!chainState || !chainState.manualTurnOff) {
629
+ await this.updateAssetSetting(assetSlug, {
630
+ visible: true
631
+ }, true);
632
+ }
633
+ }
634
+ }
635
+ }
608
636
  handleLatestLedgerGenericAllowChains(latestledgerGenericAllowChains) {
609
637
  this.ledgerGenericAllowChainsSubject.next(latestledgerGenericAllowChains);
610
638
  this.eventService.emit('ledger.ready', true);
611
639
  this.logger.log('Finished updating latest ledger generic allow chains');
612
640
  }
613
641
  handleLatestPriorityTokens(latestPriorityTokens) {
642
+ const currentTokens = this.priorityTokensSubject.value || {};
614
643
  this.priorityTokensSubject.next(latestPriorityTokens);
615
644
  this.logger.log('Finished updating latest popular tokens');
645
+ const currentTokenKeys = Object.keys(currentTokens.token || {}); // Extract keys from current tokens
646
+ const newTokenKeys = Object.keys(latestPriorityTokens.token || {}); // Extract keys from new tokens
647
+
648
+ if (JSON.stringify(currentTokenKeys) !== JSON.stringify(newTokenKeys)) {
649
+ // Check if token keys have changed
650
+ this.enablePopularTokens().then(() => this.logger.log('Popular tokens enabled due to priority tokens change')) // Log success after enabling tokens
651
+ .catch(e => console.error('Error enabling popular tokens:', e)); // Log error if enabling fails
652
+ }
653
+ }
654
+
655
+ handleLatestSufficientChains(latestSufficientChains) {
656
+ this.sufficientChainsSubject.next(latestSufficientChains);
657
+ this.logger.log('Finished updating latest supported sufficient chains');
616
658
  }
617
659
  handleLatestData() {
618
660
  this.fetchLatestChainData().then(latestChainInfo => {
@@ -634,6 +676,9 @@ export class ChainService {
634
676
  this.fetchLatestPriorityTokens().then(latestPriorityTokens => {
635
677
  this.handleLatestPriorityTokens(latestPriorityTokens);
636
678
  }).catch(console.error);
679
+ this.fetchLatestSufficientChains().then(latestSufficientChains => {
680
+ this.handleLatestSufficientChains(latestSufficientChains);
681
+ }).catch(console.error);
637
682
  }
638
683
  async initApis() {
639
684
  const chainInfoMap = this.getChainInfoMap();
@@ -913,6 +958,9 @@ export class ChainService {
913
958
  token: {}
914
959
  };
915
960
  }
961
+ async fetchLatestSufficientChains() {
962
+ return (await fetchStaticData('chains/supported-sufficient-chains')) || [];
963
+ }
916
964
  async initChains() {
917
965
  const storedChainSettings = await this.dbService.getAllChainStore();
918
966
  const defaultChainInfoMap = filterChainInfoMap(ChainInfoMap, ignoredList);
@@ -1616,22 +1664,7 @@ export class ChainService {
1616
1664
  await Promise.all([this.substrateChainHandler.wakeUp(), this.evmChainHandler.wakeUp(), this.tonChainHandler.wakeUp(), this.cardanoChainHandler.wakeUp()]);
1617
1665
  this.checkLatestData();
1618
1666
  }
1619
- async initAssetSettings() {
1620
- const assetSettings = await this.getAssetSettings();
1621
- const activeChainSlugs = this.getActiveChainSlugs();
1622
- const assetRegistry = this.getAssetRegistry();
1623
- Object.values(assetRegistry).forEach(assetInfo => {
1624
- const isSettingExisted = (assetInfo.slug in assetSettings);
1625
-
1626
- // Set visible for every enabled chains
1627
- if (activeChainSlugs.includes(assetInfo.originChain) && !isSettingExisted) {
1628
- // Setting only exist when set either by chain settings or user
1629
- assetSettings[assetInfo.slug] = {
1630
- visible: true
1631
- };
1632
- }
1633
- });
1634
- this.setAssetSettings(assetSettings, false);
1667
+ initAssetSettings() {
1635
1668
  this.eventService.emit('asset.ready', true);
1636
1669
  }
1637
1670
  setAssetSettings(assetSettings, emitEvent = true) {
@@ -1719,6 +1752,27 @@ export class ChainService {
1719
1752
  });
1720
1753
  this.setAssetSettings(assetSettings);
1721
1754
  }
1755
+ async updatePriorityAssetsByChain(chainSlug, visible) {
1756
+ const currentAssetSettings = await this.getAssetSettings();
1757
+ const assetsByChain = this.getFungibleTokensByChain(chainSlug);
1758
+ const priorityTokensMap = this.priorityTokensSubject.value || {};
1759
+ const priorityTokensList = priorityTokensMap.token && typeof priorityTokensMap.token === 'object' ? Object.keys(priorityTokensMap.token) : [];
1760
+ for (const asset of Object.values(assetsByChain)) {
1761
+ if (visible) {
1762
+ const isPriorityToken = priorityTokensList.includes(asset.slug);
1763
+ if (isPriorityToken || _isNativeToken(asset)) {
1764
+ currentAssetSettings[asset.slug] = {
1765
+ visible: true
1766
+ };
1767
+ }
1768
+ } else {
1769
+ currentAssetSettings[asset.slug] = {
1770
+ visible: false
1771
+ };
1772
+ }
1773
+ }
1774
+ this.setAssetSettings(currentAssetSettings);
1775
+ }
1722
1776
  subscribeAssetSettings() {
1723
1777
  return this.assetSettingSubject;
1724
1778
  }
@@ -5,7 +5,7 @@ const PRODUCTION_BRANCHES = ['master', 'webapp', 'webapp-dev'];
5
5
  const branchName = process.env.BRANCH_NAME || 'subwallet-dev';
6
6
  const fetchDomain = PRODUCTION_BRANCHES.indexOf(branchName) > -1 ? 'https://chain-list-assets.subwallet.app' : 'https://dev.sw-chain-list-assets.pages.dev';
7
7
  const fetchFile = PRODUCTION_BRANCHES.indexOf(branchName) > -1 ? 'list.json' : 'preview.json';
8
- const ChainListVersion = '0.2.102'; // update this when build chainlist
8
+ const ChainListVersion = '0.2.103'; // update this when build chainlist
9
9
 
10
10
  // todo: move this interface to chainlist
11
11
 
@@ -5,11 +5,12 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/Tr
5
5
  import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
6
6
  import { ALL_ACCOUNT_KEY, XCM_FEE_RATIO, XCM_MIN_AMOUNT_RATIO } from '@subwallet/extension-base/constants';
7
7
  import { YIELD_POOL_STAT_REFRESH_INTERVAL } from '@subwallet/extension-base/koni/api/yield/helper/utils';
8
- import { createXcmExtrinsic } from '@subwallet/extension-base/services/balance-service/transfer/xcm';
8
+ import { createXcmExtrinsicV2, dryRunXcmExtrinsicV2 } from '@subwallet/extension-base/services/balance-service/transfer/xcm';
9
9
  import { _getAssetDecimals, _getAssetExistentialDeposit, _getAssetName, _getAssetSymbol, _getChainNativeTokenSlug, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
10
10
  import { BasicTxErrorType, YieldStepType, YieldValidationStatus } from '@subwallet/extension-base/types';
11
11
  import { createPromiseHandler, formatNumber } from '@subwallet/extension-base/utils';
12
12
  import { getId } from '@subwallet/extension-base/utils/getId';
13
+ import BigN from 'bignumber.js';
13
14
  import { t } from 'i18next';
14
15
  import { BN, BN_TEN, BN_ZERO, noop } from '@polkadot/util';
15
16
  import BasePoolHandler from "./base.js";
@@ -219,7 +220,7 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
219
220
  const xcmOriginSubstrateApi = await this.state.getSubstrateApi(altInputTokenInfo.originChain).isReady;
220
221
  const id = getId();
221
222
  const feeInfo = await this.state.feeService.subscribeChainFee(id, altChainInfo.slug, 'substrate');
222
- const xcmTransfer = await createXcmExtrinsic({
223
+ const xcmRequest = {
223
224
  sender: address,
224
225
  originTokenInfo: altInputTokenInfo,
225
226
  destinationTokenInfo: inputTokenInfo,
@@ -229,16 +230,20 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
229
230
  originChain: altChainInfo,
230
231
  substrateApi: xcmOriginSubstrateApi,
231
232
  feeInfo
232
- });
233
- const _xcmFeeInfo = await xcmTransfer.paymentInfo(address);
234
- const xcmFeeInfo = _xcmFeeInfo.toPrimitive();
235
- // TODO: calculate fee for destination chain
233
+ };
236
234
 
235
+ // TODO: calculate fee for destination chain
236
+ let xcmFee;
237
+ const xcmFeeByDryRun = await dryRunXcmExtrinsicV2(xcmRequest);
238
+ if (xcmFeeByDryRun.fee) {
239
+ xcmFee = BigN(xcmFeeByDryRun.fee).multipliedBy(XCM_MIN_AMOUNT_RATIO).toFixed(0, 1);
240
+ } else {
241
+ throw new Error('Error estimating XCM fee');
242
+ }
237
243
  const fee = {
238
244
  slug: altInputTokenSlug,
239
- amount: Math.round(xcmFeeInfo.partialFee * XCM_MIN_AMOUNT_RATIO).toString() // TODO
245
+ amount: xcmFee
240
246
  };
241
-
242
247
  let bnTransferAmount = bnAmount.sub(bnInputTokenBalance);
243
248
  if (_isNativeToken(altInputTokenInfo)) {
244
249
  const bnXcmFee = new BN(fee.amount || 0); // xcm fee is paid in native token but swap token is not always native token
@@ -442,7 +447,7 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
442
447
  const bnTotalAmount = bnAmount.sub(bnInputTokenBalance).add(bnXcmFee);
443
448
  const id = getId();
444
449
  const feeInfo = await this.state.feeService.subscribeChainFee(id, originChainInfo.slug, 'substrate');
445
- const extrinsic = await createXcmExtrinsic({
450
+ const xcmRequest = {
446
451
  destinationTokenInfo,
447
452
  originTokenInfo,
448
453
  recipient: address,
@@ -452,7 +457,11 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
452
457
  originChain: originChainInfo,
453
458
  destinationChain: this.chainInfo,
454
459
  feeInfo
455
- });
460
+ };
461
+ const extrinsic = await createXcmExtrinsicV2(xcmRequest);
462
+ if (!extrinsic) {
463
+ throw new Error('Error handling XCM extrinsic');
464
+ }
456
465
  const xcmData = {
457
466
  originNetworkKey: originChainInfo.slug,
458
467
  destinationNetworkKey: destinationTokenInfo.originChain,
@@ -150,7 +150,7 @@ export class AccountLedgerHandler extends AccountBaseHandler {
150
150
  }
151
151
  if (Object.keys(slugMap).length) {
152
152
  for (const chainSlug of Object.keys(slugMap)) {
153
- this.state.enableChain(chainSlug);
153
+ this.state.enableChainWithPriorityAssets(chainSlug);
154
154
  }
155
155
  }
156
156
  return true;
@@ -88,6 +88,7 @@ export declare class AccountState {
88
88
  updateMetadataForProxy(): void;
89
89
  findNetworkKeyByGenesisHash(genesisHash?: string): string | undefined;
90
90
  enableChain(slug: string): void;
91
+ enableChainWithPriorityAssets(slug: string): void;
91
92
  resetWallet(): void;
92
93
  }
93
94
  export {};
@@ -619,6 +619,9 @@ export class AccountState {
619
619
  enableChain(slug) {
620
620
  this.koniState.enableChain(slug, true).catch(console.error);
621
621
  }
622
+ enableChainWithPriorityAssets(slug) {
623
+ this.koniState.enableChainWithPriorityAssets(slug, true).catch(console.error);
624
+ }
622
625
 
623
626
  /* Others */
624
627
 
@@ -0,0 +1,4 @@
1
+ import BaseMigrationJob from '@subwallet/extension-base/services/migration-service/Base';
2
+ export default class DisableZeroBalanceTokens extends BaseMigrationJob {
3
+ run(): Promise<void>;
4
+ }
@@ -0,0 +1,51 @@
1
+ // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { _isAssetAutoEnable } from '@subwallet/extension-base/services/chain-service/utils';
5
+ import BaseMigrationJob from '@subwallet/extension-base/services/migration-service/Base';
6
+ import { fetchStaticData } from '@subwallet/extension-base/utils';
7
+ // Usage:
8
+ // 1. Disable tokens with a balance of 0
9
+ // 2. Exclude tokens that belong to the popular list
10
+ // 3. Exclude tokens with the "auto enable" attribute
11
+
12
+ export default class DisableZeroBalanceTokens extends BaseMigrationJob {
13
+ async run() {
14
+ const state = this.state;
15
+ try {
16
+ const rawBalanceMap = await state.dbService.getStoredBalance();
17
+ const tokensList = await state.chainService.getAssetSettings();
18
+ const filteredEnabledTokens = Object.entries(tokensList).reduce((acc, [key, value]) => {
19
+ if (value.visible) {
20
+ acc[key] = value;
21
+ }
22
+ return acc;
23
+ }, {});
24
+ const balanceNonZero = rawBalanceMap.filter(item => {
25
+ return BigInt(item.free) + BigInt(item.locked) > 0;
26
+ });
27
+ const priorityTokensMap = (await fetchStaticData('chain-assets/priority-tokens')) || {
28
+ tokenGroup: {},
29
+ token: {}
30
+ };
31
+ const priorityTokensList = priorityTokensMap.token && typeof priorityTokensMap.token === 'object' ? Object.keys(priorityTokensMap.token) : [];
32
+ const autoEnableTokenSlugs = Object.values(this.state.chainService.getAssetRegistry()).filter(asset => _isAssetAutoEnable(asset)).map(asset => asset.slug);
33
+ // Extract the slugs of tokens with balance > 0
34
+ const nonZeroBalanceSlugs = new Set(balanceNonZero.map(item => item.tokenSlug));
35
+ const updatedSettings = structuredClone(tokensList);
36
+ Object.keys(filteredEnabledTokens).forEach(slug => {
37
+ const hasBalance = nonZeroBalanceSlugs.has(slug);
38
+ const isPopularToken = priorityTokensList.includes(slug);
39
+ const isAutoEnableToken = autoEnableTokenSlugs.includes(slug);
40
+ if (!hasBalance && !isPopularToken && !isAutoEnableToken) {
41
+ updatedSettings[slug] = {
42
+ visible: false
43
+ };
44
+ }
45
+ });
46
+ state.chainService.setAssetSettings(updatedSettings);
47
+ } catch (error) {
48
+ console.error(error);
49
+ }
50
+ }
51
+ }
@@ -5,6 +5,6 @@ import BaseMigrationJob from '@subwallet/extension-base/services/migration-servi
5
5
  export default class EnableChain extends BaseMigrationJob {
6
6
  async run() {
7
7
  const state = this.state;
8
- await state.enableChain(this.slug, true);
8
+ await state.enableChainWithPriorityAssets(this.slug, true);
9
9
  }
10
10
  }
@@ -1,7 +1,6 @@
1
1
  // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
- import AutoEnableSomeTokens from "./databases/AutoEnableSomeTokens.js";
5
4
  import ClearMetadataDatabase from "./databases/ClearMetadataDatabase.js";
6
5
  import ClearMetadataForMythos from "./databases/ClearMetadataForMythos.js";
7
6
  import MigrateAssetSetting from "./databases/MigrateAssetSetting.js";
@@ -18,6 +17,7 @@ import MigratePolygonUSDCProvider from "./tokens/MigratePolygonUSDCProvider.js";
18
17
  import DeleteChain from "./DeleteChain.js";
19
18
  import DeleteChainStaking from "./DeleteChainStaking.js";
20
19
  import DeleteEarningData from "./DeleteEarningData.js";
20
+ import DisableZeroBalanceTokens from "./DisableZeroBalanceTokens.js";
21
21
  import EnableVaraChain from "./EnableVaraChain.js";
22
22
  import MigrateAuthUrls from "./MigrateAuthUrls.js";
23
23
  import MigrateImportedToken from "./MigrateImportedToken.js";
@@ -52,7 +52,7 @@ export default {
52
52
  '1.1.28-01': MigrateEarningVersion,
53
53
  '1.1.33-01': MigrateLedgerAccountV2,
54
54
  '1.1.41-01': DeleteChainStaking,
55
- '1.1.46-01': AutoEnableSomeTokens,
55
+ // '1.1.46-01': AutoEnableSomeTokens,
56
56
  '1.2.28-01': MigrateAssetSetting,
57
57
  '1.2.28-02': MigrateTransactionHistoryBySymbol,
58
58
  '1.2.69-01': MigrateRemoveGenesisHash,
@@ -60,6 +60,7 @@ export default {
60
60
  '1.2.32-01': MigratePairData,
61
61
  '1.3.6-01': MigrateTransactionHistoryBridge,
62
62
  '1.3.10-01': ClearMetadataDatabase,
63
+ '1.3.26-01': DisableZeroBalanceTokens,
63
64
  [MYTHOS_MIGRATION_KEY]: ClearMetadataForMythos
64
65
  // [`${EVERYTIME}-1.1.42-02`]: MigrateTransactionHistoryBySymbol
65
66
  // [`${EVERYTIME}-1`]: AutoEnableChainsTokens
@@ -5,8 +5,9 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/Tr
5
5
  import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
6
6
  import { validateSpendingAndFeePayment } from '@subwallet/extension-base/core/logic-validation';
7
7
  import { _isAccountActive } from '@subwallet/extension-base/core/substrate/system-pallet';
8
- import { _isSnowBridgeXcm } from '@subwallet/extension-base/core/substrate/xcm-parser';
8
+ import { _isAcrossBridgeXcm, _isSnowBridgeXcm, _isXcmWithinSameConsensus } from '@subwallet/extension-base/core/substrate/xcm-parser';
9
9
  import { _isSufficientToken } from '@subwallet/extension-base/core/utils';
10
+ import { createXcmExtrinsicV2, dryRunXcmExtrinsicV2 } from '@subwallet/extension-base/services/balance-service/transfer/xcm';
10
11
  import { _getAssetDecimals, _getAssetSymbol, _getChainNativeTokenSlug, _getTokenMinAmount, _isChainEvmCompatible, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
11
12
  import { DEFAULT_EXCESS_AMOUNT_WEIGHT, FEE_RATE_MULTIPLIER } from '@subwallet/extension-base/services/swap-service/utils';
12
13
  import { BasicTxErrorType, SwapStepType, TransferTxErrorType } from '@subwallet/extension-base/types';
@@ -17,7 +18,6 @@ import { getId } from '@subwallet/extension-base/utils/getId';
17
18
  import BigN from 'bignumber.js';
18
19
  import { t } from 'i18next';
19
20
  import { isEthereumAddress } from '@polkadot/util-crypto';
20
- import { createXcmExtrinsic } from "../../balance-service/transfer/xcm/index.js";
21
21
  export class SwapBaseHandler {
22
22
  constructor({
23
23
  balanceService,
@@ -90,6 +90,9 @@ export class SwapBaseHandler {
90
90
  // bridge after swap
91
91
  recipientAddress = _reformatAddressWithChain(recipient || address, toChainInfo);
92
92
  }
93
+ if (!_isXcmWithinSameConsensus(fromChainInfo, toChainInfo) || _isSnowBridgeXcm(fromChainInfo, toChainInfo) || _isAcrossBridgeXcm(fromChainInfo, toChainInfo)) {
94
+ return undefined;
95
+ }
93
96
  try {
94
97
  if (!this.chainService.getChainStateByKey(toTokenInfo.originChain).active) {
95
98
  await this.chainService.enableChain(toTokenInfo.originChain);
@@ -97,7 +100,8 @@ export class SwapBaseHandler {
97
100
  const substrateApi = await this.chainService.getSubstrateApi(fromTokenInfo.originChain).isReady;
98
101
  const id = getId();
99
102
  const [feeInfo, toTokenBalance] = await Promise.all([this.feeService.subscribeChainFee(id, fromTokenInfo.originChain, 'substrate'), this.balanceService.getTotalBalance(senderAddress, toTokenInfo.originChain, toTokenInfo.slug, ExtrinsicType.TRANSFER_BALANCE)]);
100
- const xcmTransfer = await createXcmExtrinsic({
103
+ const mockSendingValue = stepIndex === 0 ? fromAmount : (selectedQuote === null || selectedQuote === void 0 ? void 0 : selectedQuote.toAmount) || '0';
104
+ const xcmRequest = {
101
105
  originTokenInfo: fromTokenInfo,
102
106
  destinationTokenInfo: toTokenInfo,
103
107
  originChain: fromChainInfo,
@@ -105,13 +109,17 @@ export class SwapBaseHandler {
105
109
  substrateApi: substrateApi,
106
110
  feeInfo,
107
111
  // Mock sending value to get payment info
108
- sendingValue: fromAmount,
112
+ sendingValue: mockSendingValue,
109
113
  sender: senderAddress,
110
114
  recipient: recipientAddress
111
- });
112
- const _xcmFeeInfo = await xcmTransfer.paymentInfo(senderAddress);
113
- const xcmFeeInfo = _xcmFeeInfo.toPrimitive();
114
- const estimatedBridgeFee = Math.ceil(xcmFeeInfo.partialFee * FEE_RATE_MULTIPLIER.medium).toString();
115
+ };
116
+
117
+ // TODO: calculate fee for destination chain
118
+ const bridgeFeeByDryRun = await dryRunXcmExtrinsicV2(xcmRequest);
119
+ if (!bridgeFeeByDryRun.fee) {
120
+ return undefined;
121
+ }
122
+ const estimatedBridgeFee = BigN(bridgeFeeByDryRun.fee).multipliedBy(FEE_RATE_MULTIPLIER.medium).toFixed(0, 1);
115
123
  const fee = {
116
124
  feeComponent: [{
117
125
  feeType: SwapFeeType.NETWORK_FEE,
@@ -188,7 +196,7 @@ export class SwapBaseHandler {
188
196
  const substrateApi = this.chainService.getSubstrateApi(originAsset.originChain);
189
197
  const chainApi = await substrateApi.isReady;
190
198
  const feeInfo = await this.feeService.subscribeChainFee(getId(), originAsset.originChain, 'substrate');
191
- const xcmTransfer = await createXcmExtrinsic({
199
+ const xcmRequest = {
192
200
  originTokenInfo: originAsset,
193
201
  destinationTokenInfo: destinationAsset,
194
202
  sendingValue: briefXcmStep.sendingValue,
@@ -198,7 +206,11 @@ export class SwapBaseHandler {
198
206
  destinationChain,
199
207
  originChain,
200
208
  feeInfo
201
- });
209
+ };
210
+ const extrinsic = await createXcmExtrinsicV2(xcmRequest);
211
+ if (!extrinsic) {
212
+ throw new Error('XCM extrinsic error');
213
+ }
202
214
  const xcmData = {
203
215
  originNetworkKey: originAsset.originChain,
204
216
  destinationNetworkKey: destinationAsset.originChain,
@@ -210,7 +222,7 @@ export class SwapBaseHandler {
210
222
  };
211
223
  return {
212
224
  txChain: originAsset.originChain,
213
- extrinsic: xcmTransfer,
225
+ extrinsic,
214
226
  transferNativeAmount: _isNativeToken(originAsset) ? briefXcmStep.sendingValue : '0',
215
227
  extrinsicType: ExtrinsicType.TRANSFER_XCM,
216
228
  chainType: ChainType.SUBSTRATE,
@@ -252,12 +264,13 @@ export class SwapBaseHandler {
252
264
 
253
265
  // By here, we know that the user is receiving a valid amount of toToken
254
266
  const toChainApi = this.chainService.getSubstrateApi(toToken.originChain);
267
+ const sufficientChain = this.chainService.value.sufficientChains;
255
268
  if (!toChainApi) {
256
269
  return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
257
270
  }
258
271
 
259
272
  // Only need to check if account is alive with the receiving toToken
260
- const isToTokenSufficient = await _isSufficientToken(toToken, toChainApi);
273
+ const isToTokenSufficient = await _isSufficientToken(toToken, toChainApi, sufficientChain);
261
274
  if (!isToTokenSufficient && !_isNativeToken(toToken)) {
262
275
  // sending token cannot keep account alive, must check with native token
263
276
  const toChainNativeTokenBalance = await this.balanceService.getTotalBalance(receiver, toToken.originChain, toChainNativeToken.slug, ExtrinsicType.TRANSFER_BALANCE);
@@ -20,6 +20,7 @@ export interface SWTransaction extends ValidateTransactionResponse, Partial<Pick
20
20
  createdAt: number;
21
21
  updatedAt: number;
22
22
  estimateFee?: FeeData;
23
+ xcmFeeDryRun?: string;
23
24
  transaction: SubmittableExtrinsic | TransactionConfig | TonTransactionConfig;
24
25
  additionalValidator?: (inputTransaction: SWTransactionResponse) => Promise<void>;
25
26
  eventsHandler?: (eventEmitter: TransactionEmitter) => void;
@@ -35,7 +36,7 @@ export interface SWTransactionResult extends Omit<SWTransaction, 'transaction' |
35
36
  process?: ProcessTransactionData;
36
37
  }
37
38
  declare type SwInputBase = Pick<SWTransaction, 'address' | 'url' | 'data' | 'extrinsicType' | 'chain' | 'chainType' | 'ignoreWarnings' | 'transferNativeAmount'> & Partial<Pick<SWTransaction, 'additionalValidator' | 'eventsHandler'>>;
38
- export interface SWTransactionInput extends SwInputBase, Partial<Pick<SWTransaction, 'estimateFee' | 'signAfterCreate' | 'isPassConfirmation' | 'step' | 'errorOnTimeOut'>>, TransactionFee {
39
+ export interface SWTransactionInput extends SwInputBase, Partial<Pick<SWTransaction, 'estimateFee' | 'signAfterCreate' | 'isPassConfirmation' | 'step' | 'errorOnTimeOut' | 'xcmFeeDryRun'>>, TransactionFee {
39
40
  id?: string;
40
41
  transaction?: SWTransaction['transaction'] | null;
41
42
  warnings?: SWTransaction['warnings'];
@@ -49,7 +50,7 @@ export interface SWTransactionInput extends SwInputBase, Partial<Pick<SWTransact
49
50
  export interface SWPermitTransactionInput extends Omit<SWTransactionInput, 'transaction'> {
50
51
  transaction?: SWPermitTransaction['transaction'] | null;
51
52
  }
52
- export declare type SWTransactionResponse = SwInputBase & Pick<SWTransaction, 'warnings' | 'errors'> & Partial<Pick<SWTransaction, 'id' | 'extrinsicHash' | 'status' | 'estimateFee'>> & TransactionFee & {
53
+ export declare type SWTransactionResponse = SwInputBase & Pick<SWTransaction, 'warnings' | 'errors'> & Partial<Pick<SWTransaction, 'id' | 'extrinsicHash' | 'status' | 'estimateFee' | 'xcmFeeDryRun'>> & TransactionFee & {
53
54
  processId?: string;
54
55
  };
55
56
  export declare type ValidateTransactionResponseInput = SWTransactionInput;
@@ -2,6 +2,7 @@ import { _ChainInfo } from '@subwallet/chain-list/types';
2
2
  import { ExtrinsicDataTypeMap, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
3
3
  import { ChainflipSwapTxData, SimpleSwapTxData } from '@subwallet/extension-base/types/swap';
4
4
  export declare function parseTransactionData<T extends ExtrinsicType>(data: unknown): ExtrinsicDataTypeMap[T];
5
+ export declare function getTransactionId(value: string): Promise<string>;
5
6
  export declare function getExplorerLink(chainInfo: _ChainInfo, value: string, type: 'account' | 'tx'): string | undefined;
6
7
  export declare function getChainflipExplorerLink(data: ChainflipSwapTxData, chainInfo: _ChainInfo): string;
7
8
  export declare function getSimpleSwapExplorerLink(data: SimpleSwapTxData): string;
@@ -3,7 +3,8 @@
3
3
 
4
4
  import { _getBlockExplorerFromChain, _isChainTestNet, _isPureCardanoChain, _isPureEvmChain } from '@subwallet/extension-base/services/chain-service/utils';
5
5
  import { CHAIN_FLIP_MAINNET_EXPLORER, CHAIN_FLIP_TESTNET_EXPLORER, SIMPLE_SWAP_EXPLORER } from '@subwallet/extension-base/services/swap-service/utils';
6
- import { hexAddPrefix, isHex } from '@polkadot/util';
6
+ import { hexAddPrefix, isHex, u8aToHex } from '@polkadot/util';
7
+ import { decodeAddress } from '@polkadot/util-crypto';
7
8
 
8
9
  // @ts-ignore
9
10
  export function parseTransactionData(data) {
@@ -24,19 +25,7 @@ function getBlockExplorerAccountRoute(explorerLink) {
24
25
  if (explorerLink.includes('3dpscan.io')) {
25
26
  return 'account';
26
27
  }
27
- if (explorerLink.includes('explorer.polimec.org')) {
28
- return 'account';
29
- }
30
- if (explorerLink.includes('invarch.statescan.io')) {
31
- return '#/accounts';
32
- }
33
- if (explorerLink.includes('tangle.statescan.io')) {
34
- return '#/accounts';
35
- }
36
- if (explorerLink.includes('laos.statescan.io')) {
37
- return '#/accounts';
38
- }
39
- if (explorerLink.includes('polimec.statescan.io')) {
28
+ if (explorerLink.includes('statescan.io')) {
40
29
  return '#/accounts';
41
30
  }
42
31
  if (explorerLink.includes('explorer.zkverify.io')) {
@@ -60,15 +49,38 @@ function getBlockExplorerTxRoute(chainInfo) {
60
49
  if (['aventus', 'deeper_network'].includes(chainInfo.slug)) {
61
50
  return 'transaction';
62
51
  }
63
- if (['invarch', 'tangle', 'polimec'].includes(chainInfo.slug)) {
52
+ const explorerLink = _getBlockExplorerFromChain(chainInfo);
53
+ if (explorerLink && explorerLink.includes('statescan.io')) {
64
54
  return '#/extrinsics';
65
55
  }
66
56
  return 'extrinsic';
67
57
  }
58
+ export function getTransactionId(value) {
59
+ const query = `
60
+ query ExtrinsicQuery {
61
+ extrinsics(where: {hash_eq: ${value}}, limit: 1) {
62
+ id
63
+ }
64
+ }`;
65
+ const apiUrl = 'https://archive-explorer.truth-network.io/graphql';
66
+ return fetch(apiUrl, {
67
+ method: 'POST',
68
+ headers: {
69
+ 'Content-Type': 'application/json'
70
+ },
71
+ body: JSON.stringify({
72
+ query
73
+ })
74
+ }).then(response => response.json()).then(result => result.data.extrinsics[0].id);
75
+ }
68
76
  export function getExplorerLink(chainInfo, value, type) {
69
77
  const explorerLink = _getBlockExplorerFromChain(chainInfo);
70
78
  if (explorerLink && type === 'account') {
71
79
  const route = getBlockExplorerAccountRoute(explorerLink);
80
+ if (chainInfo.slug === 'truth_network') {
81
+ const address = u8aToHex(decodeAddress(value));
82
+ return `${explorerLink}${explorerLink.endsWith('/') ? '' : '/'}${route}/${address}`;
83
+ }
72
84
  return `${explorerLink}${explorerLink.endsWith('/') ? '' : '/'}${route}/${value}`;
73
85
  }
74
86
  if (explorerLink && isHex(hexAddPrefix(value))) {
@@ -76,6 +88,17 @@ export function getExplorerLink(chainInfo, value, type) {
76
88
  if (chainInfo.slug === 'tangle') {
77
89
  return `${explorerLink}${explorerLink.endsWith('/') ? '' : '/'}extrinsic/${value}${route}/${value}`;
78
90
  }
91
+ if (chainInfo.slug === 'truth_network') {
92
+ // getTransactionId(value)
93
+ // .then((transactionId) => {
94
+ // return (`${explorerLink}${explorerLink.endsWith('/') ? '' : '/'}${route}/${transactionId}`);
95
+ // })
96
+ // .catch((err) => {
97
+ // console.error(err);
98
+ // });
99
+
100
+ return undefined;
101
+ }
79
102
  return `${explorerLink}${explorerLink.endsWith('/') ? '' : '/'}${route}/${value}`;
80
103
  }
81
104
  return undefined;
@@ -3,6 +3,7 @@ import { FeeChainType, FeeDetail, TransactionFee } from '../fee';
3
3
  export interface RequestSubscribeTransfer extends TransactionFee {
4
4
  address: string;
5
5
  chain: string;
6
+ value: string;
6
7
  token: string;
7
8
  destChain: string;
8
9
  }
@@ -22,6 +22,12 @@ export interface RequestCheckCrossChainTransfer extends RequestBaseTransfer, Tra
22
22
  originNetworkKey: string;
23
23
  destinationNetworkKey: string;
24
24
  showExtraWarning?: boolean;
25
+ metadata?: AcrossMetadata;
26
+ }
27
+ interface AcrossMetadata {
28
+ amountOut: string;
29
+ destChainSlug: string;
30
+ rate: string;
25
31
  }
26
32
  export declare type RequestCrossChainTransfer = InternalRequestSign<RequestCheckCrossChainTransfer>;
27
33
  export interface RequestGetTokensCanPayFee {
@@ -34,3 +40,4 @@ export interface RequestGetAmountForPair {
34
40
  nativeTokenSlug: string;
35
41
  toTokenSlug: string;
36
42
  }
43
+ export {};
@@ -5,6 +5,7 @@ import { FeeChainType, FeeInfo, TransactionFee } from '@subwallet/extension-base
5
5
  import { ResponseSubscribeTransfer } from '@subwallet/extension-base/types/balance/transfer';
6
6
  export interface CalculateMaxTransferable extends TransactionFee {
7
7
  address: string;
8
+ value: string;
8
9
  srcToken: _ChainAsset;
9
10
  destToken?: _ChainAsset;
10
11
  srcChain: _ChainInfo;