diff --git a/package-lock.json b/package-lock.json index d1cbe9c2..887ab51b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "react-redux": "^8.1.3", "redux": "^4.2.1", "redux-persist": "^6.0.0", + "redux-persist-expire": "^1.1.1", "ts-unused-exports": "^10.0.1", "vitest": "^0.34.6" }, @@ -6040,6 +6041,15 @@ "redux": ">4.0.0" } }, + "node_modules/redux-persist-expire": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/redux-persist-expire/-/redux-persist-expire-1.1.1.tgz", + "integrity": "sha512-CoVGJrIHpg7H1++PFRivY61hC9weN1SsK80YV6axr7SxIcZzlYvnXitlxIbByFfKDTujInw40abEPIzW1Hbp/g==", + "dependencies": { + "redux": "^4.0.5", + "redux-persist": "^6.0.0" + } + }, "node_modules/redux-thunk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", @@ -11541,6 +11551,15 @@ "integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==", "requires": {} }, + "redux-persist-expire": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/redux-persist-expire/-/redux-persist-expire-1.1.1.tgz", + "integrity": "sha512-CoVGJrIHpg7H1++PFRivY61hC9weN1SsK80YV6axr7SxIcZzlYvnXitlxIbByFfKDTujInw40abEPIzW1Hbp/g==", + "requires": { + "redux": "^4.0.5", + "redux-persist": "^6.0.0" + } + }, "redux-thunk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", diff --git a/package.json b/package.json index 1a745c9b..d3b835c3 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "react-redux": "^8.1.3", "redux": "^4.2.1", "redux-persist": "^6.0.0", + "redux-persist-expire": "^1.1.1", "ts-unused-exports": "^10.0.1", "vitest": "^0.34.6" }, diff --git a/src/app/store/index.ts b/src/app/store/index.ts index 3e647d15..1246b781 100644 --- a/src/app/store/index.ts +++ b/src/app/store/index.ts @@ -1,5 +1,8 @@ import { combineReducers, configureStore } from "@reduxjs/toolkit"; -import { accountSlice } from "@store/slices/account/account.slice"; +import { + accountSlice, + initialAccountState, +} from "@store/slices/account/account.slice"; import { modalSlice } from "@store/slices/modal/modal.slice"; import { vaultSlice } from "@store/slices/vault/vault.slice"; import { @@ -11,7 +14,9 @@ import { REGISTER, REHYDRATE, persistReducer, + persistStore, } from "redux-persist"; +import expireReducer from "redux-persist-expire"; import storage from "redux-persist/lib/storage"; export interface RootState { @@ -28,9 +33,15 @@ const rootReducer = combineReducers({ const persistConfig: PersistConfig = { key: "root", - version: 1, - storage, + storage: storage, whitelist: ["account", "vault"], + transforms: [ + expireReducer("account", { + persistedAtKey: "loadedAt", + expireSeconds: 3600, + expiredState: initialAccountState, + }), + ], }; const persistedReducer = persistReducer(persistConfig, rootReducer); @@ -44,3 +55,5 @@ export const store = configureStore({ }, }), }); + +export const persistor = persistStore(store); diff --git a/src/app/store/slices/account/account.slice.ts b/src/app/store/slices/account/account.slice.ts index 06660607..9e026344 100644 --- a/src/app/store/slices/account/account.slice.ts +++ b/src/app/store/slices/account/account.slice.ts @@ -1,28 +1,30 @@ -import { createSlice } from "@reduxjs/toolkit"; - import { Network } from "@models/network"; import { WalletType } from "@models/wallet"; +import { createSlice } from "@reduxjs/toolkit"; export interface AccountState { address: string | undefined; walletType: WalletType | undefined; network: Network | undefined; + loadedAt: string | undefined; } -const initialState: AccountState = { +export const initialAccountState: AccountState = { address: undefined, walletType: undefined, network: undefined, + loadedAt: undefined, }; export const accountSlice = createSlice({ name: "account", - initialState: initialState, + initialState: initialAccountState, reducers: { login: (state, action) => { state.address = action.payload.address; state.walletType = action.payload.walletType; state.network = action.payload.network; + state.loadedAt = new Date().toJSON(); }, logout: (state) => { state.address = undefined; diff --git a/src/app/store/slices/modal/modal.slice.ts b/src/app/store/slices/modal/modal.slice.ts index b4bd0456..97f3692a 100644 --- a/src/app/store/slices/modal/modal.slice.ts +++ b/src/app/store/slices/modal/modal.slice.ts @@ -4,13 +4,13 @@ interface ModalState { isSelectWalletModalOpen: boolean; } -const initialState: ModalState = { +const initialModalState: ModalState = { isSelectWalletModalOpen: false, }; export const modalSlice = createSlice({ name: "modal", - initialState: initialState, + initialState: initialModalState, reducers: { toggleSelectWalletModalVisibility: (state) => { state.isSelectWalletModalOpen = !state.isSelectWalletModalOpen; diff --git a/src/app/store/slices/vault/vault.slice.ts b/src/app/store/slices/vault/vault.slice.ts index 43531ea0..5a061eee 100644 --- a/src/app/store/slices/vault/vault.slice.ts +++ b/src/app/store/slices/vault/vault.slice.ts @@ -6,7 +6,7 @@ interface VaultState { error: string | null; } -const initialState: VaultState = { +const initialVaultState: VaultState = { vaults: [], status: "idle", error: null, @@ -14,6 +14,6 @@ const initialState: VaultState = { export const vaultSlice = createSlice({ name: "vault", - initialState: initialState, + initialState: initialVaultState, reducers: {}, }); diff --git a/src/index.tsx b/src/index.tsx index f7f7e7bd..00acfc5c 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,17 +1,20 @@ import ReactDOM from "react-dom/client"; import { Provider as ReduxProvider } from "react-redux"; -import "@fontsource/poppins"; import { ChakraProvider } from "@chakra-ui/react"; +import "@fontsource/poppins"; +import { PersistGate } from "redux-persist/integration/react"; import { App } from "./app/app"; -import { store } from "./app/store"; +import { persistor, store } from "./app/store"; import { appTheme } from "./styles/app-theme"; ReactDOM.createRoot(document.getElementById("root")!).render( - - - + + + + + , );