Skip to content

Commit

Permalink
Set up data migration
Browse files Browse the repository at this point in the history
  • Loading branch information
OKendigelyan committed Dec 18, 2024
1 parent 1f176ca commit bd10f39
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 48 deletions.
48 changes: 1 addition & 47 deletions apps/desktop/src/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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 ? <LoggedInRouterWithPolling /> : <LoggedOutRouter />;
};

Expand Down
8 changes: 8 additions & 0 deletions packages/state/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,12 @@ module.exports = {
parser: "@typescript-eslint/parser",
tsconfigRootDir: __dirname,
},
overrides: [
{
files: ["*.ts", "*.tsx"],
rules: {
"import/no-unused-modules": "off",
},
},
],
};
84 changes: 83 additions & 1 deletion packages/state/src/reducer.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -32,21 +38,97 @@ 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<any>): Promise<PersistedState> => {
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 }),
};

const accountsPersistConfig = {
key: "accounts",
version: VERSION,
storage,
getStoredState: customGetStoredState,
migrate: createAsyncMigrate(accountsMigrations, { debug: false }),
blacklist: ["password"],
};
Expand Down

0 comments on commit bd10f39

Please sign in to comment.