@subwallet/extension-base 1.3.28-1 → 1.3.29-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.
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.additionalValidateTransferForRecipient = additionalValidateTransferForRecipient;
8
- exports.additionalValidateXcmTransfer = additionalValidateXcmTransfer;
9
8
  exports.checkBalanceWithTransactionFee = checkBalanceWithTransactionFee;
10
9
  exports.checkSigningAccountForTransaction = checkSigningAccountForTransaction;
11
10
  exports.checkSupportForAction = checkSupportForAction;
@@ -60,13 +59,27 @@ function validateTransferRequest(tokenInfo, from, to, value, transferAll) {
60
59
  }
61
60
  function additionalValidateTransferForRecipient(sendingTokenInfo, nativeTokenInfo, extrinsicType, receiverSendingTokenKeepAliveBalance, transferAmount, senderSendingTokenTransferable, receiverSystemAccountInfo, isSendingTokenSufficient) {
62
61
  const sendingTokenMinAmount = BigInt((0, _utils3._getTokenMinAmount)(sendingTokenInfo));
62
+ const sendingTokenMinAmountXCM = new _bignumber.default((0, _utils3._getTokenMinAmount)(sendingTokenInfo)).multipliedBy(_constants.XCM_MIN_AMOUNT_RATIO);
63
63
  const nativeTokenMinAmount = (0, _utils3._getTokenMinAmount)(nativeTokenInfo);
64
64
  const warnings = [];
65
65
  const errors = [];
66
66
  const remainingSendingTokenOfSenderEnoughED = senderSendingTokenTransferable ? senderSendingTokenTransferable - transferAmount >= sendingTokenMinAmount : false;
67
67
  const isReceiverAliveByNativeToken = receiverSystemAccountInfo ? (0, _systemPallet._isAccountActive)(receiverSystemAccountInfo) : false;
68
68
  const isReceivingAmountPassED = receiverSendingTokenKeepAliveBalance + transferAmount >= sendingTokenMinAmount;
69
- if (extrinsicType === _KoniTypes.ExtrinsicType.TRANSFER_TOKEN) {
69
+ const enoughAmountForXCM = extrinsicType === _KoniTypes.ExtrinsicType.TRANSFER_XCM ? new _bignumber.default(transferAmount.toString()).gte(sendingTokenMinAmountXCM) : true;
70
+ if (!enoughAmountForXCM) {
71
+ const minXCMStr = (0, _utils5.formatNumber)(sendingTokenMinAmountXCM.toString(), (0, _utils3._getAssetDecimals)(sendingTokenInfo), _utils5.balanceFormatter, {
72
+ maxNumberFormat: (0, _utils3._getAssetDecimals)(sendingTokenInfo) || 6
73
+ });
74
+ const error = new _TransactionError.TransactionError(_types.TransferTxErrorType.NOT_ENOUGH_VALUE, (0, _i18next.t)('You must transfer at least {{amount}} {{symbol}} to keep the recipient account alive. Increase amount and try again', {
75
+ replace: {
76
+ amount: minXCMStr,
77
+ symbol: sendingTokenInfo.symbol
78
+ }
79
+ }));
80
+ errors.push(error);
81
+ }
82
+ if (!(0, _utils3._isNativeToken)(sendingTokenInfo)) {
70
83
  if (!remainingSendingTokenOfSenderEnoughED) {
71
84
  const warning = new _TransactionWarning.TransactionWarning(_types.BasicTxWarningCode.NOT_ENOUGH_EXISTENTIAL_DEPOSIT);
72
85
  warnings.push(warning);
@@ -123,53 +136,6 @@ function validateXcmTransferRequest(destTokenInfo, sender, sendingValue) {
123
136
  }
124
137
  return [errors, keypair];
125
138
  }
126
- function additionalValidateXcmTransfer(originTokenInfo, destinationTokenInfo, sendingAmount, senderTransferable, receiverNativeBalance, destChainInfo) {
127
- let isSnowBridge = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;
128
- const destMinAmount = (0, _utils3._getTokenMinAmount)(destinationTokenInfo);
129
- const minSendingRequired = new _bignumber.default(destMinAmount).multipliedBy(_constants.XCM_MIN_AMOUNT_RATIO);
130
- let error;
131
- let warning;
132
-
133
- // Check sending token ED for receiver
134
- if (new _bignumber.default(sendingAmount).lt(minSendingRequired)) {
135
- const atLeastStr = (0, _utils5.formatNumber)(minSendingRequired, destinationTokenInfo.decimals || 0, _utils5.balanceFormatter, {
136
- maxNumberFormat: destinationTokenInfo.decimals || 6
137
- });
138
- error = new _TransactionError.TransactionError(_types.TransferTxErrorType.RECEIVER_NOT_ENOUGH_EXISTENTIAL_DEPOSIT, (0, _i18next.t)('You must transfer at least {{amount}} {{symbol}} to keep the destination account alive', {
139
- replace: {
140
- amount: atLeastStr,
141
- symbol: originTokenInfo.symbol
142
- }
143
- }));
144
- }
145
-
146
- // check native token ED on dest chain for receiver
147
- const bnKeepAliveBalance = (0, _utils3._isNativeToken)(destinationTokenInfo) ? new _bignumber.default(receiverNativeBalance).plus(sendingAmount) : new _bignumber.default(receiverNativeBalance);
148
- if (isSnowBridge && bnKeepAliveBalance.lt((0, _utils3._getChainExistentialDeposit)(destChainInfo))) {
149
- const {
150
- decimals,
151
- symbol
152
- } = (0, _utils3._getChainNativeTokenBasicInfo)(destChainInfo);
153
- const atLeastStr = (0, _utils5.formatNumber)((0, _utils3._getChainExistentialDeposit)(destChainInfo), decimals || 0, _utils5.balanceFormatter, {
154
- maxNumberFormat: 6
155
- });
156
- error = new _TransactionError.TransactionError(_types.TransferTxErrorType.RECEIVER_NOT_ENOUGH_EXISTENTIAL_DEPOSIT, (0, _i18next.t)(' Insufficient {{symbol}} on {{chain}} to cover min balance ({{amount}} {{symbol}})', {
157
- replace: {
158
- amount: atLeastStr,
159
- symbol,
160
- chain: destChainInfo.name
161
- }
162
- }));
163
- }
164
-
165
- // Check ed for sender
166
- if (!(0, _utils3._isNativeToken)(originTokenInfo)) {
167
- if (new _bignumber.default(senderTransferable).minus(sendingAmount).lt((0, _utils3._getTokenMinAmount)(originTokenInfo))) {
168
- warning = new _TransactionWarning.TransactionWarning(_types.BasicTxWarningCode.NOT_ENOUGH_EXISTENTIAL_DEPOSIT);
169
- }
170
- }
171
- return [warning, error];
172
- }
173
139
  function checkSupportForFeature(validationResponse, blockedFeaturesList, chainInfo) {
174
140
  const extrinsicType = validationResponse.extrinsicType;
175
141
  const chain = validationResponse.chain;
@@ -1185,7 +1185,6 @@ class KoniExtension {
1185
1185
  const transferTokenInfo = this.#koniState.chainService.getAssetBySlug(tokenSlug);
1186
1186
  const errors = (0, _transfer.validateTransferRequest)(transferTokenInfo, from, to, value, transferAll);
1187
1187
  const warnings = [];
1188
- const chainInfo = this.#koniState.getChainInfo(chain);
1189
1188
  const nativeTokenInfo = this.#koniState.getNativeTokenInfo(chain);
1190
1189
  const nativeTokenSlug = nativeTokenInfo.slug;
1191
1190
  const isTransferNativeToken = nativeTokenSlug === tokenSlug;
@@ -1301,7 +1300,7 @@ class KoniExtension {
1301
1300
  const additionalValidator = async inputTransaction => {
1302
1301
  let senderSendingTokenTransferable;
1303
1302
  let receiverSystemAccountInfo;
1304
- if (!(0, _utils5._isChainSubstrateCompatible)(chainInfo)) {
1303
+ if (chainType !== _KoniTypes.ChainType.SUBSTRATE) {
1305
1304
  return undefined;
1306
1305
  }
1307
1306
 
@@ -1392,6 +1391,8 @@ class KoniExtension {
1392
1391
  } = inputData;
1393
1392
  const originTokenInfo = this.#koniState.getAssetBySlug(tokenSlug);
1394
1393
  const destinationTokenInfo = this.#koniState.getXcmEqualAssetByChain(destinationNetworkKey, tokenSlug);
1394
+ const destinationNativeTokenInfo = this.#koniState.getNativeTokenInfo(destinationNetworkKey);
1395
+ const destinationNativeTokenSlug = destinationNativeTokenInfo.slug;
1395
1396
  const [errors, fromKeyPair] = (0, _transfer.validateXcmTransferRequest)(destinationTokenInfo, from, value);
1396
1397
  let extrinsic = null;
1397
1398
  if (errors.length > 0) {
@@ -1403,6 +1404,7 @@ class KoniExtension {
1403
1404
  const isSnowBridgeEvmTransfer = (0, _utils5._isPureEvmChain)(chainInfoMap[originNetworkKey]) && (0, _xcmParser._isSnowBridgeXcm)(chainInfoMap[originNetworkKey], chainInfoMap[destinationNetworkKey]) && !isAvailBridgeFromEvm;
1404
1405
  const isPolygonBridgeTransfer = (0, _polygonBridge._isPolygonChainBridge)(originNetworkKey, destinationNetworkKey);
1405
1406
  const isPosBridgeTransfer = (0, _posBridge._isPosChainBridge)(originNetworkKey, destinationNetworkKey);
1407
+ const extrinsicType = _KoniTypes.ExtrinsicType.TRANSFER_XCM;
1406
1408
  const isTransferNative = this.#koniState.getNativeTokenInfo(originNetworkKey).slug === tokenSlug;
1407
1409
  const isTransferLocalTokenAndPayThatTokenAsFee = !isTransferNative && tokenSlug === tokenPayFeeSlug;
1408
1410
  let additionalValidator;
@@ -1453,28 +1455,47 @@ class KoniExtension {
1453
1455
  extrinsic = (0, _tokenPayFee.batchExtrinsicSetFeeHydration)(substrateApi, _extrinsic, feeSetting, hydrationFeeAssetId);
1454
1456
  }
1455
1457
  additionalValidator = async inputTransaction => {
1458
+ let isSendingTokenSufficient = false;
1459
+ let receiverSystemAccountInfo;
1460
+ if (!(0, _utils5._isChainSubstrateCompatible)(chainInfoMap[destinationNetworkKey])) {
1461
+ return undefined;
1462
+ }
1456
1463
  const {
1457
- value: senderTransferable
1464
+ value: _senderTransferable
1458
1465
  } = await this.getAddressTransferableBalance({
1459
1466
  address: from,
1460
1467
  networkKey: originNetworkKey,
1461
1468
  token: originTokenInfo.slug
1462
1469
  });
1463
- const isSnowBridge = (0, _xcmParser._isSnowBridgeXcm)(chainInfoMap[originNetworkKey], chainInfoMap[destinationNetworkKey]);
1464
- let recipientNativeBalance = '0';
1465
- if (isSnowBridge) {
1466
- const {
1467
- value
1468
- } = await this.getAddressTransferableBalance({
1470
+ const senderTransferable = BigInt(_senderTransferable);
1471
+ const sendingAmount = BigInt(value);
1472
+ const {
1473
+ value: _receiverDestinationTokenKeepAliveBalance
1474
+ } = await this.getAddressTotalBalance({
1475
+ address: to,
1476
+ networkKey: destinationNetworkKey,
1477
+ token: destinationTokenInfo.slug,
1478
+ extrinsicType
1479
+ });
1480
+ const receiverDestinationTokenKeepAliveBalance = BigInt(_receiverDestinationTokenKeepAliveBalance);
1481
+ if (!(0, _utils5._isNativeToken)(destinationTokenInfo)) {
1482
+ const _receiverNativeTotal = await this.getAddressTotalBalance({
1469
1483
  address: to,
1470
1484
  networkKey: destinationNetworkKey,
1471
- extrinsicType: _KoniTypes.ExtrinsicType.TRANSFER_BALANCE
1485
+ token: destinationNativeTokenSlug,
1486
+ extrinsicType
1472
1487
  });
1473
- recipientNativeBalance = value;
1488
+ receiverSystemAccountInfo = _receiverNativeTotal.metadata;
1474
1489
  }
1475
- const [warning, error] = (0, _transfer.additionalValidateXcmTransfer)(originTokenInfo, destinationTokenInfo, value, senderTransferable, recipientNativeBalance, chainInfoMap[destinationNetworkKey], isSnowBridge);
1476
- error && inputTransaction.errors.push(error);
1477
- warning && inputTransaction.warnings.push(warning);
1490
+ if ((0, _utils5._isChainSubstrateCompatible)(chainInfoMap[destinationNetworkKey])) {
1491
+ const substrateApi = this.#koniState.getSubstrateApi(destinationNetworkKey);
1492
+ isSendingTokenSufficient = await (0, _utils._isSufficientToken)(destinationTokenInfo, substrateApi);
1493
+ }
1494
+ const [warning, error] = (0, _transfer.additionalValidateTransferForRecipient)(destinationTokenInfo, destinationNativeTokenInfo, extrinsicType, receiverDestinationTokenKeepAliveBalance, sendingAmount, senderTransferable,
1495
+ // different from sendingTokenInfo being passed in
1496
+ receiverSystemAccountInfo, isSendingTokenSufficient);
1497
+ warning.length && inputTransaction.warnings.push(...warning);
1498
+ error.length && inputTransaction.errors.push(...error);
1478
1499
  };
1479
1500
  eventsHandler = eventEmitter => {
1480
1501
  eventEmitter.on('send', () => {
@@ -1506,7 +1527,7 @@ class KoniExtension {
1506
1527
  chain: originNetworkKey,
1507
1528
  transaction: extrinsic,
1508
1529
  data: inputData,
1509
- extrinsicType: _KoniTypes.ExtrinsicType.TRANSFER_XCM,
1530
+ extrinsicType,
1510
1531
  chainType: !isSnowBridgeEvmTransfer && !isAvailBridgeFromEvm && !isPolygonBridgeTransfer && !isPosBridgeTransfer ? _KoniTypes.ChainType.SUBSTRATE : _KoniTypes.ChainType.EVM,
1511
1532
  transferNativeAmount: (0, _utils5._isNativeToken)(originTokenInfo) ? value : '0',
1512
1533
  ignoreWarnings,
@@ -1285,9 +1285,14 @@ class KoniState {
1285
1285
  }
1286
1286
  return result;
1287
1287
  }
1288
+ scanAddressOnAdd = [];
1288
1289
  onAccountAdd() {
1289
1290
  this.eventService.on('account.add', address => {
1290
- this.balanceService.autoEnableChains([address]).catch(this.logger.error);
1291
+ this.scanAddressOnAdd.push(address);
1292
+ (0, _utils3.addLazy)('autoScanBalanceOnAdd', () => {
1293
+ this.balanceService.autoEnableChains(this.scanAddressOnAdd).catch(this.logger.error);
1294
+ this.scanAddressOnAdd = [];
1295
+ }, 500, 5000, false);
1291
1296
  });
1292
1297
  }
1293
1298
  onAccountRemove() {
@@ -13,6 +13,6 @@ const packageInfo = {
13
13
  name: '@subwallet/extension-base',
14
14
  path: typeof __dirname === 'string' ? __dirname : 'auto',
15
15
  type: 'cjs',
16
- version: '1.3.28-1'
16
+ version: '1.3.29-0'
17
17
  };
18
18
  exports.packageInfo = packageInfo;
@@ -16,6 +16,7 @@ var _DetectAccountBalance = _interopRequireDefault(require("@subwallet/extension
16
16
  var _utils2 = require("@subwallet/extension-base/utils");
17
17
  var _keyring = require("@subwallet/keyring");
18
18
  var _types2 = require("@subwallet/keyring/types");
19
+ var _subwalletApiSdk = _interopRequireDefault(require("@subwallet/subwallet-api-sdk"));
19
20
  var _uiKeyring = _interopRequireDefault(require("@subwallet/ui-keyring"));
20
21
  var _bignumber = _interopRequireDefault(require("bignumber.js"));
21
22
  var _i18next = require("i18next");
@@ -422,9 +423,29 @@ class BalanceService {
422
423
  return null;
423
424
  }
424
425
  });
426
+ const evmPromiseList = addresses.map(address => {
427
+ const type = (0, _keyring.getKeypairTypeByAddress)(address);
428
+ const typeValid = [..._types2.EthereumKeypairTypes].includes(type);
429
+ if (typeValid) {
430
+ return new Promise(resolve => {
431
+ var _subwalletApiSdk$bala;
432
+ const timeOutPromise = new Promise(_resolve => {
433
+ setTimeout(() => _resolve([]), 30000);
434
+ });
435
+ const apiPromise = ((_subwalletApiSdk$bala = _subwalletApiSdk.default.balanceDetectionApi) === null || _subwalletApiSdk$bala === void 0 ? void 0 : _subwalletApiSdk$bala.getEvmTokenBalanceSlug(address)) || Promise.resolve([]);
436
+ Promise.race([timeOutPromise, apiPromise]).then(result => resolve(result)).catch(error => {
437
+ console.error(error);
438
+ resolve(null);
439
+ });
440
+ });
441
+ } else {
442
+ return Promise.resolve(null);
443
+ }
444
+ });
425
445
  const needEnableChains = [];
426
446
  const needActiveTokens = [];
427
447
  const balanceDataList = await Promise.all(promiseList);
448
+ const evmBalanceDataList = await Promise.all(evmPromiseList);
428
449
  const currentAssetSettings = await this.state.chainService.getAssetSettings();
429
450
  const chainInfoMap = this.state.chainService.getChainInfoMap();
430
451
  const detectBalanceChainSlugMap = this.state.chainService.detectBalanceChainSlugMap;
@@ -474,6 +495,28 @@ class BalanceService {
474
495
  }
475
496
  }
476
497
  }
498
+ for (const balanceData of evmBalanceDataList) {
499
+ if (balanceData) {
500
+ for (const slug of balanceData) {
501
+ var _currentAssetSettings2;
502
+ const chainSlug = slug.split('-')[0];
503
+ const chainState = this.state.chainService.getChainStateByKey(chainSlug);
504
+ const existedKey = Object.keys(assetMap).find(v => v.toLowerCase() === slug.toLowerCase());
505
+
506
+ // Cancel is chain is turned off by user
507
+ if (chainState && chainState.manualTurnOff) {
508
+ continue;
509
+ }
510
+ if (existedKey && !((_currentAssetSettings2 = currentAssetSettings[existedKey]) !== null && _currentAssetSettings2 !== void 0 && _currentAssetSettings2.visible)) {
511
+ needEnableChains.push(chainSlug);
512
+ needActiveTokens.push(existedKey);
513
+ currentAssetSettings[existedKey] = {
514
+ visible: true
515
+ };
516
+ }
517
+ }
518
+ }
519
+ }
477
520
  if (needActiveTokens.length) {
478
521
  await this.state.chainService.enableChains(needEnableChains);
479
522
  this.state.chainService.setAssetSettings({
@@ -300,7 +300,7 @@ const _XCM_CHAIN_GROUP = {
300
300
  // default is xTokens pallet
301
301
  };
302
302
  exports._XCM_CHAIN_GROUP = _XCM_CHAIN_GROUP;
303
- const SUFFICIENT_CHAIN = ['astar', 'calamari', 'parallel', 'darwinia2', 'crabParachain', 'pangolin', 'statemint', 'moonriver', 'shiden', 'moonbeam', 'statemine', 'liberland', 'dentnet', 'phala', 'crust', 'dbcchain', 'rococo_assethub'];
303
+ const SUFFICIENT_CHAIN = ['astar', 'calamari', 'parallel', 'darwinia2', 'crabParachain', 'pangolin', 'statemint', 'moonriver', 'shiden', 'moonbeam', 'statemine', 'liberland', 'dentnet', 'phala', 'crust', 'dbcchain', 'rococo_assethub', 'hydradx_main'];
304
304
  exports.SUFFICIENT_CHAIN = SUFFICIENT_CHAIN;
305
305
  const _XCM_TYPE = {
306
306
  RP: `${_types._SubstrateChainType.RELAYCHAIN}-${_types._SubstrateChainType.PARACHAIN}`,
@@ -849,6 +849,7 @@ class ChainService {
849
849
  return true;
850
850
  }
851
851
  disableChain(chainSlug) {
852
+ let preventManualTurnOff = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
852
853
  const chainInfo = this.getChainInfoByKey(chainSlug);
853
854
  const chainStateMap = this.getChainStateMap();
854
855
  if (!chainStateMap[chainSlug].active || this.lockChainInfoMap) {
@@ -856,7 +857,7 @@ class ChainService {
856
857
  }
857
858
  this.lockChainInfoMap = true;
858
859
  chainStateMap[chainSlug].active = false;
859
- chainStateMap[chainSlug].manualTurnOff = true;
860
+ chainStateMap[chainSlug].manualTurnOff = !preventManualTurnOff;
860
861
  // Set disconnect state for inactive chain
861
862
  this.updateChainConnectionStatus(chainSlug, _types3._ChainConnectionStatus.DISCONNECTED);
862
863
  this.destroyApiForChain(chainInfo);
@@ -864,7 +865,7 @@ class ChainService {
864
865
  ...chainInfo,
865
866
  active: false,
866
867
  currentProvider: chainStateMap[chainSlug].currentProvider,
867
- manualTurnOff: true
868
+ manualTurnOff: !preventManualTurnOff
868
869
  }).catch(console.error);
869
870
  this.updateChainStateMapSubscription();
870
871
  this.lockChainInfoMap = false;
@@ -1772,7 +1773,7 @@ class ChainService {
1772
1773
  const activeChains = this.getActiveChainInfos();
1773
1774
  for (const chain of Object.keys(activeChains)) {
1774
1775
  if (!_constants._DEFAULT_ACTIVE_CHAINS.includes(chain)) {
1775
- this.disableChain(chain);
1776
+ this.disableChain(chain, true);
1776
1777
  }
1777
1778
  }
1778
1779
 
@@ -10,7 +10,6 @@ import { KeyringPair } from '@subwallet/keyring/types';
10
10
  export declare function validateTransferRequest(tokenInfo: _ChainAsset, from: _Address, to: _Address, value: string | undefined, transferAll: boolean | undefined): TransactionError[];
11
11
  export declare function additionalValidateTransferForRecipient(sendingTokenInfo: _ChainAsset, nativeTokenInfo: _ChainAsset, extrinsicType: ExtrinsicType, receiverSendingTokenKeepAliveBalance: bigint, transferAmount: bigint, senderSendingTokenTransferable?: bigint, receiverSystemAccountInfo?: FrameSystemAccountInfo, isSendingTokenSufficient?: boolean): [TransactionWarning[], TransactionError[]];
12
12
  export declare function validateXcmTransferRequest(destTokenInfo: _ChainAsset | undefined, sender: _Address, sendingValue: string): [TransactionError[], KeyringPair | undefined];
13
- export declare function additionalValidateXcmTransfer(originTokenInfo: _ChainAsset, destinationTokenInfo: _ChainAsset, sendingAmount: string, senderTransferable: string, receiverNativeBalance: string, destChainInfo: _ChainInfo, isSnowBridge?: boolean): [TransactionWarning | undefined, TransactionError | undefined];
14
13
  export declare function checkSupportForFeature(validationResponse: SWTransactionResponse, blockedFeaturesList: string[], chainInfo: _ChainInfo): void;
15
14
  export declare function checkSupportForAction(validationResponse: SWTransactionResponse, blockedActionsMap: Record<ExtrinsicType, string[]>): void;
16
15
  export declare function checkSupportForTransaction(validationResponse: SWTransactionResponse, transaction: OptionalSWTransaction): void;
@@ -9,7 +9,7 @@ import { _canAccountBeReaped, _isAccountActive } from '@subwallet/extension-base
9
9
  import { getCardanoAssetId } from '@subwallet/extension-base/services/balance-service/helpers/subscribe/cardano/utils';
10
10
  import { isBounceableAddress } from '@subwallet/extension-base/services/balance-service/helpers/subscribe/ton/utils';
11
11
  import { _TRANSFER_CHAIN_GROUP } from '@subwallet/extension-base/services/chain-service/constants';
12
- import { _getAssetDecimals, _getAssetPriceId, _getAssetSymbol, _getChainExistentialDeposit, _getChainNativeTokenBasicInfo, _getContractAddressOfToken, _getTokenMinAmount, _isCIP26Token, _isNativeToken, _isNativeTokenBySlug, _isTokenEvmSmartContract, _isTokenTonSmartContract } from '@subwallet/extension-base/services/chain-service/utils';
12
+ import { _getAssetDecimals, _getAssetPriceId, _getAssetSymbol, _getChainNativeTokenBasicInfo, _getContractAddressOfToken, _getTokenMinAmount, _isCIP26Token, _isNativeToken, _isNativeTokenBySlug, _isTokenEvmSmartContract, _isTokenTonSmartContract } from '@subwallet/extension-base/services/chain-service/utils';
13
13
  import { calculateToAmountByReservePool, FEE_COVERAGE_PERCENTAGE_SPECIAL_CASE } from '@subwallet/extension-base/services/fee-service/utils';
14
14
  import { isCardanoTransaction, isSubstrateTransaction, isTonTransaction } from '@subwallet/extension-base/services/transaction-service/helpers';
15
15
  import { AccountSignMode, BasicTxErrorType, BasicTxWarningCode, TransferTxErrorType } from '@subwallet/extension-base/types';
@@ -44,13 +44,27 @@ export function validateTransferRequest(tokenInfo, from, to, value, transferAll)
44
44
  }
45
45
  export function additionalValidateTransferForRecipient(sendingTokenInfo, nativeTokenInfo, extrinsicType, receiverSendingTokenKeepAliveBalance, transferAmount, senderSendingTokenTransferable, receiverSystemAccountInfo, isSendingTokenSufficient) {
46
46
  const sendingTokenMinAmount = BigInt(_getTokenMinAmount(sendingTokenInfo));
47
+ const sendingTokenMinAmountXCM = new BigN(_getTokenMinAmount(sendingTokenInfo)).multipliedBy(XCM_MIN_AMOUNT_RATIO);
47
48
  const nativeTokenMinAmount = _getTokenMinAmount(nativeTokenInfo);
48
49
  const warnings = [];
49
50
  const errors = [];
50
51
  const remainingSendingTokenOfSenderEnoughED = senderSendingTokenTransferable ? senderSendingTokenTransferable - transferAmount >= sendingTokenMinAmount : false;
51
52
  const isReceiverAliveByNativeToken = receiverSystemAccountInfo ? _isAccountActive(receiverSystemAccountInfo) : false;
52
53
  const isReceivingAmountPassED = receiverSendingTokenKeepAliveBalance + transferAmount >= sendingTokenMinAmount;
53
- if (extrinsicType === ExtrinsicType.TRANSFER_TOKEN) {
54
+ const enoughAmountForXCM = extrinsicType === ExtrinsicType.TRANSFER_XCM ? new BigN(transferAmount.toString()).gte(sendingTokenMinAmountXCM) : true;
55
+ if (!enoughAmountForXCM) {
56
+ const minXCMStr = formatNumber(sendingTokenMinAmountXCM.toString(), _getAssetDecimals(sendingTokenInfo), balanceFormatter, {
57
+ maxNumberFormat: _getAssetDecimals(sendingTokenInfo) || 6
58
+ });
59
+ const error = new TransactionError(TransferTxErrorType.NOT_ENOUGH_VALUE, t('You must transfer at least {{amount}} {{symbol}} to keep the recipient account alive. Increase amount and try again', {
60
+ replace: {
61
+ amount: minXCMStr,
62
+ symbol: sendingTokenInfo.symbol
63
+ }
64
+ }));
65
+ errors.push(error);
66
+ }
67
+ if (!_isNativeToken(sendingTokenInfo)) {
54
68
  if (!remainingSendingTokenOfSenderEnoughED) {
55
69
  const warning = new TransactionWarning(BasicTxWarningCode.NOT_ENOUGH_EXISTENTIAL_DEPOSIT);
56
70
  warnings.push(warning);
@@ -107,52 +121,6 @@ export function validateXcmTransferRequest(destTokenInfo, sender, sendingValue)
107
121
  }
108
122
  return [errors, keypair];
109
123
  }
110
- export function additionalValidateXcmTransfer(originTokenInfo, destinationTokenInfo, sendingAmount, senderTransferable, receiverNativeBalance, destChainInfo, isSnowBridge = false) {
111
- const destMinAmount = _getTokenMinAmount(destinationTokenInfo);
112
- const minSendingRequired = new BigN(destMinAmount).multipliedBy(XCM_MIN_AMOUNT_RATIO);
113
- let error;
114
- let warning;
115
-
116
- // Check sending token ED for receiver
117
- if (new BigN(sendingAmount).lt(minSendingRequired)) {
118
- const atLeastStr = formatNumber(minSendingRequired, destinationTokenInfo.decimals || 0, balanceFormatter, {
119
- maxNumberFormat: destinationTokenInfo.decimals || 6
120
- });
121
- error = new TransactionError(TransferTxErrorType.RECEIVER_NOT_ENOUGH_EXISTENTIAL_DEPOSIT, t('You must transfer at least {{amount}} {{symbol}} to keep the destination account alive', {
122
- replace: {
123
- amount: atLeastStr,
124
- symbol: originTokenInfo.symbol
125
- }
126
- }));
127
- }
128
-
129
- // check native token ED on dest chain for receiver
130
- const bnKeepAliveBalance = _isNativeToken(destinationTokenInfo) ? new BigN(receiverNativeBalance).plus(sendingAmount) : new BigN(receiverNativeBalance);
131
- if (isSnowBridge && bnKeepAliveBalance.lt(_getChainExistentialDeposit(destChainInfo))) {
132
- const {
133
- decimals,
134
- symbol
135
- } = _getChainNativeTokenBasicInfo(destChainInfo);
136
- const atLeastStr = formatNumber(_getChainExistentialDeposit(destChainInfo), decimals || 0, balanceFormatter, {
137
- maxNumberFormat: 6
138
- });
139
- error = new TransactionError(TransferTxErrorType.RECEIVER_NOT_ENOUGH_EXISTENTIAL_DEPOSIT, t(' Insufficient {{symbol}} on {{chain}} to cover min balance ({{amount}} {{symbol}})', {
140
- replace: {
141
- amount: atLeastStr,
142
- symbol,
143
- chain: destChainInfo.name
144
- }
145
- }));
146
- }
147
-
148
- // Check ed for sender
149
- if (!_isNativeToken(originTokenInfo)) {
150
- if (new BigN(senderTransferable).minus(sendingAmount).lt(_getTokenMinAmount(originTokenInfo))) {
151
- warning = new TransactionWarning(BasicTxWarningCode.NOT_ENOUGH_EXISTENTIAL_DEPOSIT);
152
- }
153
- }
154
- return [warning, error];
155
- }
156
124
  export function checkSupportForFeature(validationResponse, blockedFeaturesList, chainInfo) {
157
125
  const extrinsicType = validationResponse.extrinsicType;
158
126
  const chain = validationResponse.chain;
@@ -9,7 +9,7 @@ import { withErrorLog } from '@subwallet/extension-base/background/handlers/help
9
9
  import { createSubscription } from '@subwallet/extension-base/background/handlers/subscriptions';
10
10
  import { CampaignDataType, ChainType, ExternalRequestPromiseStatus, ExtrinsicType, MantaPayEnableMessage, StakingType } from '@subwallet/extension-base/background/KoniTypes';
11
11
  import { _SUPPORT_TOKEN_PAY_FEE_GROUP, ALL_ACCOUNT_KEY, LATEST_SESSION } from '@subwallet/extension-base/constants';
12
- import { additionalValidateTransferForRecipient, additionalValidateXcmTransfer, validateTransferRequest, validateXcmTransferRequest } from '@subwallet/extension-base/core/logic-validation/transfer';
12
+ import { additionalValidateTransferForRecipient, validateTransferRequest, validateXcmTransferRequest } from '@subwallet/extension-base/core/logic-validation/transfer';
13
13
  import { _isSnowBridgeXcm } from '@subwallet/extension-base/core/substrate/xcm-parser';
14
14
  import { _isSufficientToken } from '@subwallet/extension-base/core/utils';
15
15
  import { ALLOWED_PATH } from '@subwallet/extension-base/defaults';
@@ -1142,7 +1142,6 @@ export default class KoniExtension {
1142
1142
  const transferTokenInfo = this.#koniState.chainService.getAssetBySlug(tokenSlug);
1143
1143
  const errors = validateTransferRequest(transferTokenInfo, from, to, value, transferAll);
1144
1144
  const warnings = [];
1145
- const chainInfo = this.#koniState.getChainInfo(chain);
1146
1145
  const nativeTokenInfo = this.#koniState.getNativeTokenInfo(chain);
1147
1146
  const nativeTokenSlug = nativeTokenInfo.slug;
1148
1147
  const isTransferNativeToken = nativeTokenSlug === tokenSlug;
@@ -1258,7 +1257,7 @@ export default class KoniExtension {
1258
1257
  const additionalValidator = async inputTransaction => {
1259
1258
  let senderSendingTokenTransferable;
1260
1259
  let receiverSystemAccountInfo;
1261
- if (!_isChainSubstrateCompatible(chainInfo)) {
1260
+ if (chainType !== ChainType.SUBSTRATE) {
1262
1261
  return undefined;
1263
1262
  }
1264
1263
 
@@ -1349,6 +1348,8 @@ export default class KoniExtension {
1349
1348
  } = inputData;
1350
1349
  const originTokenInfo = this.#koniState.getAssetBySlug(tokenSlug);
1351
1350
  const destinationTokenInfo = this.#koniState.getXcmEqualAssetByChain(destinationNetworkKey, tokenSlug);
1351
+ const destinationNativeTokenInfo = this.#koniState.getNativeTokenInfo(destinationNetworkKey);
1352
+ const destinationNativeTokenSlug = destinationNativeTokenInfo.slug;
1352
1353
  const [errors, fromKeyPair] = validateXcmTransferRequest(destinationTokenInfo, from, value);
1353
1354
  let extrinsic = null;
1354
1355
  if (errors.length > 0) {
@@ -1360,6 +1361,7 @@ export default class KoniExtension {
1360
1361
  const isSnowBridgeEvmTransfer = _isPureEvmChain(chainInfoMap[originNetworkKey]) && _isSnowBridgeXcm(chainInfoMap[originNetworkKey], chainInfoMap[destinationNetworkKey]) && !isAvailBridgeFromEvm;
1361
1362
  const isPolygonBridgeTransfer = _isPolygonChainBridge(originNetworkKey, destinationNetworkKey);
1362
1363
  const isPosBridgeTransfer = _isPosChainBridge(originNetworkKey, destinationNetworkKey);
1364
+ const extrinsicType = ExtrinsicType.TRANSFER_XCM;
1363
1365
  const isTransferNative = this.#koniState.getNativeTokenInfo(originNetworkKey).slug === tokenSlug;
1364
1366
  const isTransferLocalTokenAndPayThatTokenAsFee = !isTransferNative && tokenSlug === tokenPayFeeSlug;
1365
1367
  let additionalValidator;
@@ -1410,28 +1412,47 @@ export default class KoniExtension {
1410
1412
  extrinsic = batchExtrinsicSetFeeHydration(substrateApi, _extrinsic, feeSetting, hydrationFeeAssetId);
1411
1413
  }
1412
1414
  additionalValidator = async inputTransaction => {
1415
+ let isSendingTokenSufficient = false;
1416
+ let receiverSystemAccountInfo;
1417
+ if (!_isChainSubstrateCompatible(chainInfoMap[destinationNetworkKey])) {
1418
+ return undefined;
1419
+ }
1413
1420
  const {
1414
- value: senderTransferable
1421
+ value: _senderTransferable
1415
1422
  } = await this.getAddressTransferableBalance({
1416
1423
  address: from,
1417
1424
  networkKey: originNetworkKey,
1418
1425
  token: originTokenInfo.slug
1419
1426
  });
1420
- const isSnowBridge = _isSnowBridgeXcm(chainInfoMap[originNetworkKey], chainInfoMap[destinationNetworkKey]);
1421
- let recipientNativeBalance = '0';
1422
- if (isSnowBridge) {
1423
- const {
1424
- value
1425
- } = await this.getAddressTransferableBalance({
1427
+ const senderTransferable = BigInt(_senderTransferable);
1428
+ const sendingAmount = BigInt(value);
1429
+ const {
1430
+ value: _receiverDestinationTokenKeepAliveBalance
1431
+ } = await this.getAddressTotalBalance({
1432
+ address: to,
1433
+ networkKey: destinationNetworkKey,
1434
+ token: destinationTokenInfo.slug,
1435
+ extrinsicType
1436
+ });
1437
+ const receiverDestinationTokenKeepAliveBalance = BigInt(_receiverDestinationTokenKeepAliveBalance);
1438
+ if (!_isNativeToken(destinationTokenInfo)) {
1439
+ const _receiverNativeTotal = await this.getAddressTotalBalance({
1426
1440
  address: to,
1427
1441
  networkKey: destinationNetworkKey,
1428
- extrinsicType: ExtrinsicType.TRANSFER_BALANCE
1442
+ token: destinationNativeTokenSlug,
1443
+ extrinsicType
1429
1444
  });
1430
- recipientNativeBalance = value;
1445
+ receiverSystemAccountInfo = _receiverNativeTotal.metadata;
1431
1446
  }
1432
- const [warning, error] = additionalValidateXcmTransfer(originTokenInfo, destinationTokenInfo, value, senderTransferable, recipientNativeBalance, chainInfoMap[destinationNetworkKey], isSnowBridge);
1433
- error && inputTransaction.errors.push(error);
1434
- warning && inputTransaction.warnings.push(warning);
1447
+ if (_isChainSubstrateCompatible(chainInfoMap[destinationNetworkKey])) {
1448
+ const substrateApi = this.#koniState.getSubstrateApi(destinationNetworkKey);
1449
+ isSendingTokenSufficient = await _isSufficientToken(destinationTokenInfo, substrateApi);
1450
+ }
1451
+ const [warning, error] = additionalValidateTransferForRecipient(destinationTokenInfo, destinationNativeTokenInfo, extrinsicType, receiverDestinationTokenKeepAliveBalance, sendingAmount, senderTransferable,
1452
+ // different from sendingTokenInfo being passed in
1453
+ receiverSystemAccountInfo, isSendingTokenSufficient);
1454
+ warning.length && inputTransaction.warnings.push(...warning);
1455
+ error.length && inputTransaction.errors.push(...error);
1435
1456
  };
1436
1457
  eventsHandler = eventEmitter => {
1437
1458
  eventEmitter.on('send', () => {
@@ -1463,7 +1484,7 @@ export default class KoniExtension {
1463
1484
  chain: originNetworkKey,
1464
1485
  transaction: extrinsic,
1465
1486
  data: inputData,
1466
- extrinsicType: ExtrinsicType.TRANSFER_XCM,
1487
+ extrinsicType,
1467
1488
  chainType: !isSnowBridgeEvmTransfer && !isAvailBridgeFromEvm && !isPolygonBridgeTransfer && !isPosBridgeTransfer ? ChainType.SUBSTRATE : ChainType.EVM,
1468
1489
  transferNativeAmount: _isNativeToken(originTokenInfo) ? value : '0',
1469
1490
  ignoreWarnings,
@@ -239,6 +239,7 @@ export default class KoniState {
239
239
  cancelSubscription(id: string): boolean;
240
240
  createUnsubscriptionHandle(id: string, unsubscribe: () => void): void;
241
241
  get detectBalanceChainSlugMap(): Record<string, string>;
242
+ scanAddressOnAdd: string[];
242
243
  onAccountAdd(): void;
243
244
  onAccountRemove(): void;
244
245
  reloadNft(): Promise<boolean>;
@@ -37,7 +37,7 @@ import TransactionService from '@subwallet/extension-base/services/transaction-s
37
37
  import WalletConnectService from '@subwallet/extension-base/services/wallet-connect-service';
38
38
  import { SWStorage } from '@subwallet/extension-base/storage';
39
39
  import { BasicTxErrorType } from '@subwallet/extension-base/types';
40
- import { isManifestV3, stripUrl, targetIsWeb } from '@subwallet/extension-base/utils';
40
+ import { addLazy, isManifestV3, stripUrl, targetIsWeb } from '@subwallet/extension-base/utils';
41
41
  import { createPromiseHandler } from '@subwallet/extension-base/utils/promise';
42
42
  import subwalletApiSdk from '@subwallet/subwallet-api-sdk';
43
43
  import { keyring } from '@subwallet/ui-keyring';
@@ -1265,9 +1265,14 @@ export default class KoniState {
1265
1265
  }
1266
1266
  return result;
1267
1267
  }
1268
+ scanAddressOnAdd = [];
1268
1269
  onAccountAdd() {
1269
1270
  this.eventService.on('account.add', address => {
1270
- this.balanceService.autoEnableChains([address]).catch(this.logger.error);
1271
+ this.scanAddressOnAdd.push(address);
1272
+ addLazy('autoScanBalanceOnAdd', () => {
1273
+ this.balanceService.autoEnableChains(this.scanAddressOnAdd).catch(this.logger.error);
1274
+ this.scanAddressOnAdd = [];
1275
+ }, 500, 5000, false);
1271
1276
  });
1272
1277
  }
1273
1278
  onAccountRemove() {
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "./cjs/detectPackage.js"
18
18
  ],
19
19
  "type": "module",
20
- "version": "1.3.28-1",
20
+ "version": "1.3.29-0",
21
21
  "main": "./cjs/index.js",
22
22
  "module": "./index.js",
23
23
  "types": "./index.d.ts",
@@ -2670,12 +2670,12 @@
2670
2670
  "@sora-substrate/type-definitions": "^1.17.7",
2671
2671
  "@substrate/connect": "^0.8.9",
2672
2672
  "@subwallet/chain-list": "0.2.102",
2673
- "@subwallet/extension-base": "^1.3.28-1",
2674
- "@subwallet/extension-chains": "^1.3.28-1",
2675
- "@subwallet/extension-dapp": "^1.3.28-1",
2676
- "@subwallet/extension-inject": "^1.3.28-1",
2673
+ "@subwallet/extension-base": "^1.3.29-0",
2674
+ "@subwallet/extension-chains": "^1.3.29-0",
2675
+ "@subwallet/extension-dapp": "^1.3.29-0",
2676
+ "@subwallet/extension-inject": "^1.3.29-0",
2677
2677
  "@subwallet/keyring": "^0.1.9",
2678
- "@subwallet/subwallet-api-sdk": "^1.3.28-1",
2678
+ "@subwallet/subwallet-api-sdk": "^1.3.29-0",
2679
2679
  "@subwallet/ui-keyring": "^0.1.9",
2680
2680
  "@ton/core": "^0.56.3",
2681
2681
  "@ton/crypto": "^3.2.0",
package/packageInfo.js CHANGED
@@ -7,5 +7,5 @@ export const packageInfo = {
7
7
  name: '@subwallet/extension-base',
8
8
  path: (import.meta && import.meta.url) ? new URL(import.meta.url).pathname.substring(0, new URL(import.meta.url).pathname.lastIndexOf('/') + 1) : 'auto',
9
9
  type: 'esm',
10
- version: '1.3.28-1'
10
+ version: '1.3.29-0'
11
11
  };
@@ -12,6 +12,7 @@ import DetectAccountBalanceStore from '@subwallet/extension-base/stores/DetectAc
12
12
  import { addLazy, createPromiseHandler, isAccountAll, waitTimeout } from '@subwallet/extension-base/utils';
13
13
  import { getKeypairTypeByAddress } from '@subwallet/keyring';
14
14
  import { EthereumKeypairTypes, SubstrateKeypairTypes } from '@subwallet/keyring/types';
15
+ import subwalletApiSdk from '@subwallet/subwallet-api-sdk';
15
16
  import keyring from '@subwallet/ui-keyring';
16
17
  import BigN from 'bignumber.js';
17
18
  import { t } from 'i18next';
@@ -413,9 +414,29 @@ export class BalanceService {
413
414
  return null;
414
415
  }
415
416
  });
417
+ const evmPromiseList = addresses.map(address => {
418
+ const type = getKeypairTypeByAddress(address);
419
+ const typeValid = [...EthereumKeypairTypes].includes(type);
420
+ if (typeValid) {
421
+ return new Promise(resolve => {
422
+ var _subwalletApiSdk$bala;
423
+ const timeOutPromise = new Promise(_resolve => {
424
+ setTimeout(() => _resolve([]), 30000);
425
+ });
426
+ const apiPromise = ((_subwalletApiSdk$bala = subwalletApiSdk.balanceDetectionApi) === null || _subwalletApiSdk$bala === void 0 ? void 0 : _subwalletApiSdk$bala.getEvmTokenBalanceSlug(address)) || Promise.resolve([]);
427
+ Promise.race([timeOutPromise, apiPromise]).then(result => resolve(result)).catch(error => {
428
+ console.error(error);
429
+ resolve(null);
430
+ });
431
+ });
432
+ } else {
433
+ return Promise.resolve(null);
434
+ }
435
+ });
416
436
  const needEnableChains = [];
417
437
  const needActiveTokens = [];
418
438
  const balanceDataList = await Promise.all(promiseList);
439
+ const evmBalanceDataList = await Promise.all(evmPromiseList);
419
440
  const currentAssetSettings = await this.state.chainService.getAssetSettings();
420
441
  const chainInfoMap = this.state.chainService.getChainInfoMap();
421
442
  const detectBalanceChainSlugMap = this.state.chainService.detectBalanceChainSlugMap;
@@ -465,6 +486,28 @@ export class BalanceService {
465
486
  }
466
487
  }
467
488
  }
489
+ for (const balanceData of evmBalanceDataList) {
490
+ if (balanceData) {
491
+ for (const slug of balanceData) {
492
+ var _currentAssetSettings2;
493
+ const chainSlug = slug.split('-')[0];
494
+ const chainState = this.state.chainService.getChainStateByKey(chainSlug);
495
+ const existedKey = Object.keys(assetMap).find(v => v.toLowerCase() === slug.toLowerCase());
496
+
497
+ // Cancel is chain is turned off by user
498
+ if (chainState && chainState.manualTurnOff) {
499
+ continue;
500
+ }
501
+ if (existedKey && !((_currentAssetSettings2 = currentAssetSettings[existedKey]) !== null && _currentAssetSettings2 !== void 0 && _currentAssetSettings2.visible)) {
502
+ needEnableChains.push(chainSlug);
503
+ needActiveTokens.push(existedKey);
504
+ currentAssetSettings[existedKey] = {
505
+ visible: true
506
+ };
507
+ }
508
+ }
509
+ }
510
+ }
468
511
  if (needActiveTokens.length) {
469
512
  await this.state.chainService.enableChains(needEnableChains);
470
513
  this.state.chainService.setAssetSettings({
@@ -278,7 +278,7 @@ export const _XCM_CHAIN_GROUP = {
278
278
  // default is xTokens pallet
279
279
  };
280
280
 
281
- export const SUFFICIENT_CHAIN = ['astar', 'calamari', 'parallel', 'darwinia2', 'crabParachain', 'pangolin', 'statemint', 'moonriver', 'shiden', 'moonbeam', 'statemine', 'liberland', 'dentnet', 'phala', 'crust', 'dbcchain', 'rococo_assethub'];
281
+ export const SUFFICIENT_CHAIN = ['astar', 'calamari', 'parallel', 'darwinia2', 'crabParachain', 'pangolin', 'statemint', 'moonriver', 'shiden', 'moonbeam', 'statemine', 'liberland', 'dentnet', 'phala', 'crust', 'dbcchain', 'rococo_assethub', 'hydradx_main'];
282
282
  export const _XCM_TYPE = {
283
283
  RP: `${_SubstrateChainType.RELAYCHAIN}-${_SubstrateChainType.PARACHAIN}`,
284
284
  // DMP
@@ -121,7 +121,7 @@ export declare class ChainService {
121
121
  enableChain(chainSlug: string): Promise<boolean>;
122
122
  enableChains(chainSlugs: string[]): Promise<boolean>;
123
123
  reconnectChain(chain: string): Promise<boolean>;
124
- disableChain(chainSlug: string): boolean;
124
+ disableChain(chainSlug: string, preventManualTurnOff?: boolean): boolean;
125
125
  private checkExistedPredefinedChain;
126
126
  private fetchLatestChainData;
127
127
  private fetchLatestPriceIdsData;
@@ -822,7 +822,7 @@ export class ChainService {
822
822
  await ((_this$getEvmApi = this.getEvmApi(chain)) === null || _this$getEvmApi === void 0 ? void 0 : _this$getEvmApi.recoverConnect());
823
823
  return true;
824
824
  }
825
- disableChain(chainSlug) {
825
+ disableChain(chainSlug, preventManualTurnOff = false) {
826
826
  const chainInfo = this.getChainInfoByKey(chainSlug);
827
827
  const chainStateMap = this.getChainStateMap();
828
828
  if (!chainStateMap[chainSlug].active || this.lockChainInfoMap) {
@@ -830,7 +830,7 @@ export class ChainService {
830
830
  }
831
831
  this.lockChainInfoMap = true;
832
832
  chainStateMap[chainSlug].active = false;
833
- chainStateMap[chainSlug].manualTurnOff = true;
833
+ chainStateMap[chainSlug].manualTurnOff = !preventManualTurnOff;
834
834
  // Set disconnect state for inactive chain
835
835
  this.updateChainConnectionStatus(chainSlug, _ChainConnectionStatus.DISCONNECTED);
836
836
  this.destroyApiForChain(chainInfo);
@@ -838,7 +838,7 @@ export class ChainService {
838
838
  ...chainInfo,
839
839
  active: false,
840
840
  currentProvider: chainStateMap[chainSlug].currentProvider,
841
- manualTurnOff: true
841
+ manualTurnOff: !preventManualTurnOff
842
842
  }).catch(console.error);
843
843
  this.updateChainStateMapSubscription();
844
844
  this.lockChainInfoMap = false;
@@ -1742,7 +1742,7 @@ export class ChainService {
1742
1742
  const activeChains = this.getActiveChainInfos();
1743
1743
  for (const chain of Object.keys(activeChains)) {
1744
1744
  if (!_DEFAULT_ACTIVE_CHAINS.includes(chain)) {
1745
- this.disableChain(chain);
1745
+ this.disableChain(chain, true);
1746
1746
  }
1747
1747
  }
1748
1748