diff --git a/apps/desktop/src/Router.tsx b/apps/desktop/src/Router.tsx
index 3662d56e5..72d9d64d4 100644
--- a/apps/desktop/src/Router.tsx
+++ b/apps/desktop/src/Router.tsx
@@ -8,13 +8,12 @@ import {
useResetBeaconConnections,
} from "@umami/state";
import { noop } from "lodash";
-import { useEffect, useState } from "react";
+import { useEffect } from "react";
import { HashRouter, Navigate, Route, Routes } from "react-router-dom";
import { AnnouncementBanner } from "./components/AnnouncementBanner";
import { SocialLoginWarningModal } from "./components/SocialLoginWarningModal/SocialLoginWarningModal";
import { BeaconProvider } from "./utils/beacon/BeaconProvider";
-import { persistor } from "./utils/persistor";
import { useDeeplinkHandler } from "./utils/useDeeplinkHandler";
import { AddressBookView } from "./views/addressBook/AddressBookView";
import { BatchPage } from "./views/batch/BatchPage";
@@ -34,51 +33,6 @@ export const Router = () => {
useDeeplinkHandler();
const isLoggedIn = useImplicitAccounts().length > 0;
- const [backupData, setBackupData] = useState({});
-
- useEffect(() => {
- // @ts-ignore
- window.electronAPI.onBackupData((_, backupData) => {
- console.log(backupData);
- setBackupData(backupData);
- });
- }, []);
-
- useEffect(() => {
- if (Object.keys(backupData).length > 0) {
- try {
- const accountsValue = backupData["persist:accounts"].accountsValue.slice(1); // Remove the \u0001 prefix
- const rootValue = backupData["persist:root"].rootValue.slice(1); // Remove the \u0001 prefix
- // Step 2: Parse the outer JSON string
- const parsedAccounts = JSON.parse(accountsValue);
- const sanitizedRootValue = backupData["persist:root"].rootValue.replaceAll(
- /[\u0000-\u001F\u007F-\u009F]/g,
- ""
- );
- const parsedRootValue = JSON.parse(sanitizedRootValue);
-
- // Step 3: Parse the inner strings as needed
- parsedAccounts.items = JSON.parse(parsedAccounts.items);
- parsedAccounts.seedPhrases = JSON.parse(parsedAccounts.seedPhrases);
- parsedAccounts.secretKeys = JSON.parse(parsedAccounts.secretKeys);
- parsedAccounts._persist = JSON.parse(parsedAccounts._persist);
- parsedAccounts.current = JSON.parse(parsedAccounts.current);
-
-
- console.log(parsedAccounts, "parsedAccounts");
- console.log(parsedRootValue, "parsedRootValue");
-
- persistor.pause();
- // localStorage.clear();
- localStorage.setItem("persist:accounts", JSON.stringify(parsedAccounts));
- localStorage.setItem("persist:root", JSON.stringify(parsedRootValue));
- // window.location.reload();
- } catch (error) {
- console.error("Error during backup restoration", error);
- }
- }
- }, [backupData]);
-
return isLoggedIn ? : ;
};
diff --git a/packages/state/.eslintrc.cjs b/packages/state/.eslintrc.cjs
index 9235a456a..bec5bb76c 100644
--- a/packages/state/.eslintrc.cjs
+++ b/packages/state/.eslintrc.cjs
@@ -5,4 +5,12 @@ module.exports = {
parser: "@typescript-eslint/parser",
tsconfigRootDir: __dirname,
},
+ overrides: [
+ {
+ files: ["*.ts", "*.tsx"],
+ rules: {
+ "import/no-unused-modules": "off",
+ },
+ },
+ ],
};
diff --git a/packages/state/src/reducer.ts b/packages/state/src/reducer.ts
index f516ea652..cb5416c42 100644
--- a/packages/state/src/reducer.ts
+++ b/packages/state/src/reducer.ts
@@ -1,5 +1,11 @@
import { combineReducers } from "@reduxjs/toolkit";
-import { type Storage, persistReducer } from "redux-persist";
+import {
+ type PersistConfig,
+ type PersistedState,
+ type Storage,
+ getStoredState,
+ persistReducer,
+} from "redux-persist";
import createWebStorage from "redux-persist/lib/storage/createWebStorage";
import { createAsyncMigrate } from "./createAsyncMigrate";
@@ -32,14 +38,89 @@ const getTestStorage = () => {
: TEST_STORAGE;
};
+export const processMigrationData = (backupData: any) => {
+ try {
+ const processedData: { accounts: any; root: any } = {
+ accounts: null,
+ root: null,
+ };
+
+ console.log(backupData, "backupData");
+
+ if (backupData["persist:accounts"]?.accountsValue) {
+ const accountsValue = backupData["persist:accounts"].accountsValue.slice(1);
+ processedData.accounts = JSON.parse(accountsValue);
+
+ for (const item in processedData.accounts) {
+ processedData.accounts[item] = JSON.parse(processedData.accounts[item]);
+ }
+ }
+
+ if (backupData["persist:root"]?.rootValue) {
+ const sanitizedRootValue = backupData["persist:root"].rootValue.replaceAll(
+ // eslint-disable-next-line no-control-regex
+ /[\u0000-\u001F\u007F-\u009F]/g,
+ ""
+ );
+
+ processedData.root = JSON.parse(sanitizedRootValue);
+
+ for (const item in processedData.root) {
+ processedData.root[item] = JSON.parse(processedData.root[item]);
+ }
+ }
+
+ return processedData;
+ } catch (error) {
+ console.error("Error processing backup data:", error);
+ return null;
+ }
+};
+
export const makeReducer = (storage_: Storage | undefined) => {
const storage = storage_ || getTestStorage() || createWebStorage("local");
+ // Custom getStoredState function to handle migration
+ const customGetStoredState = async (config: PersistConfig): Promise => {
+ try {
+ // First try to get state from current storage
+ const state = (await getStoredState(config)) as PersistedState;
+ console.log(state, "state");
+ if (state) {
+ return state;
+ }
+
+ // If no state, check if we have backup data
+ // @ts-ignore
+ if (window.electronAPI) {
+ return new Promise(resolve => {
+ // @ts-ignore
+ window.electronAPI.onBackupData((_, data) => {
+ if (data) {
+ const processed = processMigrationData(data);
+ console.log(processed, "processed");
+ if (processed) {
+ // Return the processed state based on config key
+ // @ts-ignore
+ return resolve(config.key === "root" ? processed.root : processed.accounts);
+ }
+ }
+ resolve(undefined);
+ });
+ });
+ }
+ } catch (err) {
+ console.error("Error getting stored state:", err);
+ return undefined;
+ }
+ };
+
const rootPersistConfig = {
key: "root",
version: VERSION,
storage,
blacklist: ["accounts"],
+ getStoredState: customGetStoredState,
migrate: createAsyncMigrate(mainStoreMigrations, { debug: false }),
};
@@ -47,6 +128,7 @@ export const makeReducer = (storage_: Storage | undefined) => {
key: "accounts",
version: VERSION,
storage,
+ getStoredState: customGetStoredState,
migrate: createAsyncMigrate(accountsMigrations, { debug: false }),
blacklist: ["password"],
};