@@ -39,6 +39,7 @@ import store from 'state/store';
3939import { loadAndActivateSlip44Vault , saveMainState } from 'state/store' ;
4040import {
4141 createAccount ,
42+ initializeCleanVaultForSlip44 ,
4243 forgetWallet ,
4344 removeAccount ,
4445 setAccountLabel ,
@@ -72,6 +73,7 @@ import {
7273 setError as setStoreError ,
7374 setIsLoadingBalances ,
7475 setNetwork ,
76+ setNetworks ,
7577 removeNetwork ,
7678 setIsPollingUpdate ,
7779 startConnecting ,
@@ -96,7 +98,10 @@ import {
9698 accountSwitchMutex ,
9799} from 'utils/asyncMutex' ;
98100import { areBalancesDifferent } from 'utils/balance' ;
99- import { SYSCOIN_UTXO_MAINNET_NETWORK } from 'utils/constants' ;
101+ import {
102+ SYSCOIN_UTXO_MAINNET_NETWORK ,
103+ PALI_NETWORKS_STATE ,
104+ } from 'utils/constants' ;
100105import { decodeTransactionData } from 'utils/ethUtil' ;
101106import { logError } from 'utils/logger' ;
102107import { getNetworkChain } from 'utils/network' ;
@@ -197,6 +202,128 @@ class MainController {
197202 return this . getOrCreatePersistentProvider ( mainnet . url ) ;
198203 }
199204
205+ // Centralized reset routine used by both forgetWallet and createWallet(import)
206+ private async resetWalletState ( options ?: { resetNetworks ?: boolean } ) {
207+ const { resetNetworks = false } = options || { } ;
208+
209+ // Clear all timers first to prevent any background operations
210+ this . clearAllTimers ( ) ;
211+
212+ // Clean up notification manager to prevent memory leaks
213+ notificationManager . cleanup ( ) ;
214+
215+ // Properly dispose of all keyrings to prevent memory leaks
216+ this . disposeAllKeyrings ( ) ;
217+
218+ // Clear all keyring instances from memory
219+ this . keyrings . clear ( ) ;
220+
221+ // Clean up persistent providers
222+ this . cleanupPersistentProviders ( ) ;
223+
224+ // Cancel any pending async operations
225+ if ( this . cancellablePromises . transactionPromise ) {
226+ this . cancellablePromises . transactionPromise . cancel ( ) ;
227+ }
228+ if ( this . cancellablePromises . assetsPromise ) {
229+ this . cancellablePromises . assetsPromise . cancel ( ) ;
230+ }
231+ if ( this . cancellablePromises . balancePromise ) {
232+ this . cancellablePromises . balancePromise . cancel ( ) ;
233+ }
234+ if ( this . cancellablePromises . nftsPromise ) {
235+ this . cancellablePromises . nftsPromise . cancel ( ) ;
236+ }
237+ if ( this . currentPromise ) {
238+ this . currentPromise . cancel ( ) ;
239+ this . currentPromise = null ;
240+ }
241+
242+ // Stop auto-lock timer
243+ await this . stopAutoLockTimer ( ) ;
244+
245+ // Reset internal state flags
246+ this . justUnlocked = false ;
247+ this . isStartingUp = false ;
248+ this . isAccountSwitching = false ;
249+ this . isNetworkSwitching = false ;
250+
251+ // Clear vault cache
252+ vaultCache . clearCache ( ) ;
253+
254+ // Clear all in-memory caches and session data
255+ if ( this . transactionsManager ) {
256+ this . transactionsManager . utils . clearCache ( ) ;
257+ }
258+ clearProviderCache ( ) ;
259+ clearFetchBackendAccountCache ( ) ;
260+ clearRpcCaches ( ) ;
261+
262+ // Clear all vault-related storage completely
263+ try {
264+ await chromeStorage . removeItem ( 'sysweb3-vault' ) ;
265+ await chromeStorage . removeItem ( 'sysweb3-vault-keys' ) ;
266+ } catch ( error ) {
267+ console . error (
268+ '[MainController] Error clearing vault storage during reset:' ,
269+ error
270+ ) ;
271+ }
272+
273+ // Clear all slip44-specific vault states and persisted Redux state
274+ try {
275+ const allItems = await new Promise < { [ key : string ] : any } > (
276+ ( resolve , reject ) => {
277+ chrome . storage . local . get ( null , ( items ) => {
278+ if ( chrome . runtime . lastError ) {
279+ reject (
280+ new Error (
281+ `Failed to get all items: ${ chrome . runtime . lastError . message } `
282+ )
283+ ) ;
284+ return ;
285+ }
286+ resolve ( items ) ;
287+ } ) ;
288+ }
289+ ) ;
290+
291+ const keysToRemove = Object . keys ( allItems ) . filter (
292+ ( key ) =>
293+ key . match ( / ^ s t a t e - v a u l t - \d + $ / ) ||
294+ key . startsWith ( 'sysweb3-vault-' ) ||
295+ key === 'state' ||
296+ key . startsWith ( 'state-' )
297+ ) ;
298+
299+ if ( keysToRemove . length > 0 ) {
300+ await Promise . all (
301+ keysToRemove . map ( ( key ) => chromeStorage . removeItem ( key ) )
302+ ) ;
303+ }
304+ } catch ( error ) {
305+ console . error (
306+ '[MainController] Error clearing slip44 vault states during reset:' ,
307+ error
308+ ) ;
309+ }
310+
311+ // Clear global settings via Redux
312+ store . dispatch ( setHasEncryptedVault ( false ) ) ;
313+ store . dispatch (
314+ setAdvancedSettings ( {
315+ advancedProperty : 'refresh' ,
316+ value : false ,
317+ isFirstTime : true ,
318+ } )
319+ ) ;
320+
321+ // Optionally reset networks to defaults (used by import flow and forget wallet)
322+ if ( resetNetworks ) {
323+ store . dispatch ( setNetworks ( PALI_NETWORKS_STATE ) ) ;
324+ }
325+ }
326+
200327 /**
201328 * Batch resolve multiple ENS names to addresses using on-chain Multicall3 on Ethereum mainnet.
202329 * Falls back to per-name provider.resolveName for entries that fail (e.g., CCIP-read resolvers).
@@ -1480,121 +1607,10 @@ class MainController {
14801607 // FIRST: Validate password - throws if wrong password or wallet locked
14811608 // This prevents unnecessary cleanup if validation fails
14821609 await this . forgetMainWallet ( pwd ) ;
1483-
14841610 // Now proceed with cleanup since password is valid
1485- // Clear all timers first to prevent any background operations
1486- this . clearAllTimers ( ) ;
1487-
1488- // Clean up notification manager to prevent memory leaks
1489- notificationManager . cleanup ( ) ;
1490-
1491- // Properly dispose of all keyrings to prevent memory leaks
1492- this . disposeAllKeyrings ( ) ;
1493-
1494- // Clear all keyring instances from memory
1495- this . keyrings . clear ( ) ;
1496-
1497- // Clean up persistent providers
1498- this . cleanupPersistentProviders ( ) ;
1499-
1500- // Cancel any pending async operations
1501- if ( this . cancellablePromises . transactionPromise ) {
1502- this . cancellablePromises . transactionPromise . cancel ( ) ;
1503- }
1504- if ( this . cancellablePromises . assetsPromise ) {
1505- this . cancellablePromises . assetsPromise . cancel ( ) ;
1506- }
1507- if ( this . cancellablePromises . balancePromise ) {
1508- this . cancellablePromises . balancePromise . cancel ( ) ;
1509- }
1510- if ( this . cancellablePromises . nftsPromise ) {
1511- this . cancellablePromises . nftsPromise . cancel ( ) ;
1512- }
1513- if ( this . currentPromise ) {
1514- this . currentPromise . cancel ( ) ;
1515- this . currentPromise = null ;
1516- }
1517-
1518- // Stop auto-lock timer
1519- await this . stopAutoLockTimer ( ) ;
1520-
1521- // Reset internal state flags
1522- this . justUnlocked = false ;
1523- this . isStartingUp = false ;
1524- this . isAccountSwitching = false ;
1525- this . isNetworkSwitching = false ;
1526-
1527- // Clear vault cache (no emergency save - we're forgetting the wallet!)
1528- vaultCache . clearCache ( ) ;
1529-
1530- // Clear all in-memory caches and session data
1531- if ( this . transactionsManager ) {
1532- this . transactionsManager . utils . clearCache ( ) ;
1533- }
1534- clearProviderCache ( ) ;
1535- clearFetchBackendAccountCache ( ) ;
1536- clearRpcCaches ( ) ;
1537-
1538- // Clear all vault-related storage completely
1539- // Remove vault from Chrome storage (both legacy and current keys)
1540- try {
1541- await chromeStorage . removeItem ( 'sysweb3-vault' ) ;
1542- await chromeStorage . removeItem ( 'sysweb3-vault-keys' ) ;
1543- } catch ( error ) {
1544- console . error ( 'Error clearing vault storage:' , error ) ;
1545- }
1546-
1547- // Clear all slip44-specific vault states
1548- try {
1549- // Note: chromeStorage doesn't have a direct equivalent to chrome.storage.local.get(null)
1550- // so we'll keep this as direct chrome.storage.local for now as it's a specialized operation
1551- const allItems = await new Promise < { [ key : string ] : any } > (
1552- ( resolve , reject ) => {
1553- chrome . storage . local . get ( null , ( items ) => {
1554- if ( chrome . runtime . lastError ) {
1555- reject (
1556- new Error (
1557- `Failed to get all items: ${ chrome . runtime . lastError . message } `
1558- )
1559- ) ;
1560- return ;
1561- }
1562- resolve ( items ) ;
1563- } ) ;
1564- }
1565- ) ;
1566-
1567- const keysToRemove = Object . keys ( allItems ) . filter (
1568- ( key ) =>
1569- key . match ( / ^ s t a t e - v a u l t - \d + $ / ) ||
1570- key . startsWith ( 'sysweb3-vault-' ) ||
1571- key === 'state' ||
1572- key . startsWith ( 'state-' )
1573- ) ;
1574-
1575- if ( keysToRemove . length > 0 ) {
1576- // Remove keys individually using chromeStorage
1577- await Promise . all (
1578- keysToRemove . map ( ( key ) => chromeStorage . removeItem ( key ) )
1579- ) ;
1580- }
1581- } catch ( error ) {
1582- console . error ( 'Error clearing slip44 vault states:' , error ) ;
1583- }
1584-
1585- // Clear global settings via Redux
1586- store . dispatch ( setHasEncryptedVault ( false ) ) ;
1587- store . dispatch (
1588- setAdvancedSettings ( {
1589- advancedProperty : 'refresh' ,
1590- value : false ,
1591- isFirstTime : true ,
1592- } )
1593- ) ;
1594-
1595- // Reset activeSlip44 to default after forgetting wallet
1596- // This ensures clean state regardless of what the previous wallet supported
1611+ await this . resetWalletState ( { resetNetworks : true } ) ;
15971612
1613+ // Reset activeSlip44 to default after forgetting wallet to ensure clean state
15981614 store . dispatch ( setActiveSlip44 ( DEFAULT_UTXO_SLIP44 ) ) ;
15991615 console . log (
16001616 `[MainController] Reset activeSlip44 to default: ${ DEFAULT_UTXO_SLIP44 } `
@@ -2088,6 +2104,17 @@ class MainController {
20882104
20892105 public async createWallet ( password : string , phrase : string ) : Promise < void > {
20902106 try {
2107+ // Ensure a FULL reset before creating a new wallet (import/fresh create)
2108+ await this . resetWalletState ( { resetNetworks : true } ) ;
2109+
2110+ // Reset active slip44 and create a TRULY clean vault for default UTXO network
2111+ store . dispatch ( setActiveSlip44 ( DEFAULT_UTXO_SLIP44 ) ) ;
2112+ store . dispatch ( forgetWallet ( ) ) ;
2113+ store . dispatch (
2114+ // Clean slate: no accounts/assets/txs; sets activeNetwork to provided network
2115+ initializeCleanVaultForSlip44 ( SYSCOIN_UTXO_MAINNET_NETWORK )
2116+ ) ;
2117+
20912118 // CRITICAL FIX: Ensure vault state is properly initialized before keyring operations
20922119 // The keyring manager expects activeNetwork and activeAccount to exist
20932120 const currentVaultState = store . getState ( ) . vault ;
0 commit comments