diff --git a/src/state/apis/nft/nftApi.ts b/src/state/apis/nft/nftApi.ts index 83a9cf85ec0..13296777f4a 100644 --- a/src/state/apis/nft/nftApi.ts +++ b/src/state/apis/nft/nftApi.ts @@ -44,7 +44,7 @@ type GetNftCollectionInput = { accountIds: AccountId[] } -type NftState = { +export type NftState = { selectedNftAvatarByWalletId: Record nfts: { byId: PartialRecord diff --git a/src/state/apis/snapshot/snapshot.ts b/src/state/apis/snapshot/snapshot.ts index 21679360f1c..df2d73279ef 100644 --- a/src/state/apis/snapshot/snapshot.ts +++ b/src/state/apis/snapshot/snapshot.ts @@ -19,10 +19,7 @@ type FoxVotingPowerCryptoBalance = string const SNAPSHOT_SPACE = 'shapeshiftdao.eth' -export const initialState: { - votingPowerByModel: Record - strategies: Strategy[] | undefined -} = { +export const initialState: SnapshotState = { votingPowerByModel: { SWAPPER: undefined, THORCHAIN_LP: undefined, @@ -30,6 +27,11 @@ export const initialState: { strategies: undefined, } +export type SnapshotState = { + votingPowerByModel: Record + strategies: Strategy[] | undefined +} + export const snapshot = createSlice({ name: 'snapshot', initialState, diff --git a/src/state/migrations/clearAssets.ts b/src/state/migrations/clearAssets.ts index 72b1170f226..988dc6928ce 100644 --- a/src/state/migrations/clearAssets.ts +++ b/src/state/migrations/clearAssets.ts @@ -1,29 +1,7 @@ -import type { ReduxState } from 'state/reducer' +import type { PersistPartial } from 'redux-persist/es/persistReducer' +import type { AssetsState } from 'state/slices/assetsSlice/assetsSlice' import { initialState } from 'state/slices/assetsSlice/assetsSlice' -export const clearAssets = (state: ReduxState): ReduxState => { - return { - ...state, - assets: initialState, - // This is very ugly but also very correct - // Typically, to achieve this, we would dispatch nftapi.util.resetApiState as a side effect - // But we can't do this here because circular deps, so we have to do it manually - // https://redux-toolkit.js.org/rtk-query/api/created-api/api-slice-utils#resetapistate - assetApi: { - queries: {}, - mutations: {}, - provided: {}, - subscriptions: {}, - config: { - online: true, - focused: true, - middlewareRegistered: true, - refetchOnFocus: false, - refetchOnReconnect: true, - refetchOnMountOrArgChange: false, - keepUnusedDataFor: 60, - reducerPath: 'assetApi', - }, - }, - } +export const clearAssets = (_state: AssetsState): AssetsState & PersistPartial => { + return initialState as AssetsState & PersistPartial } diff --git a/src/state/migrations/clearMarketData.ts b/src/state/migrations/clearMarketData.ts index e0b711a8f72..e1fc2b15cf4 100644 --- a/src/state/migrations/clearMarketData.ts +++ b/src/state/migrations/clearMarketData.ts @@ -1,10 +1,8 @@ -import type { ReduxState } from 'state/reducer' +import type { PersistPartial } from 'redux-persist/es/persistReducer' import { initialState } from 'state/slices/marketDataSlice/marketDataSlice' +import type { MarketDataState } from 'state/slices/marketDataSlice/types' -export const clearMarketData = (state: ReduxState): ReduxState => { +export const clearMarketData = (_state: MarketDataState): MarketDataState & PersistPartial => { // Migration to clear marketData state - return { - ...state, - marketData: initialState, - } + return initialState as MarketDataState & PersistPartial } diff --git a/src/state/migrations/clearNfts.ts b/src/state/migrations/clearNfts.ts index 00bd4c9abd1..dcb4f01d386 100644 --- a/src/state/migrations/clearNfts.ts +++ b/src/state/migrations/clearNfts.ts @@ -1,29 +1,7 @@ +import type { PersistPartial } from 'redux-persist/es/persistReducer' +import type { NftState } from 'state/apis/nft/nftApi' import { initialState } from 'state/apis/nft/nftApi' -import type { ReduxState } from 'state/reducer' -export const clearNfts = (state: ReduxState): ReduxState => { - return { - ...state, - nft: initialState, - // This is very ugly but also very correct - // Typically, to achieve this, we would dispatch nftapi.util.resetApiState as a side effect - // But we can't do this here because circular deps, so we have to do it manually - // https://redux-toolkit.js.org/rtk-query/api/created-api/api-slice-utils#resetapistate - nftApi: { - queries: {}, - mutations: {}, - provided: {}, - subscriptions: {}, - config: { - online: true, - focused: false, - middlewareRegistered: true, - refetchOnFocus: false, - refetchOnReconnect: true, - refetchOnMountOrArgChange: false, - keepUnusedDataFor: 60, - reducerPath: 'nftApi', - }, - }, - } +export const clearNfts = (_state: NftState): NftState & PersistPartial => { + return initialState as NftState & PersistPartial } diff --git a/src/state/migrations/clearOpportunities.ts b/src/state/migrations/clearOpportunities.ts index 4e34844abf1..bcf3ad44a8b 100644 --- a/src/state/migrations/clearOpportunities.ts +++ b/src/state/migrations/clearOpportunities.ts @@ -1,11 +1,11 @@ -import type { ReduxState } from 'state/reducer' +import type { PersistPartial } from 'redux-persist/es/persistReducer' +import type { OpportunitiesState } from 'state/slices/opportunitiesSlice/types' import { initialState } from '../slices/opportunitiesSlice/opportunitiesSlice' -export const clearOpportunities = (state: ReduxState): ReduxState => { +export const clearOpportunities = ( + _state: OpportunitiesState, +): OpportunitiesState & PersistPartial => { // Migration to clear opportunitiesApi and opportunitiesApi state - return { - ...state, - opportunities: initialState, - } + return initialState as OpportunitiesState & PersistPartial } diff --git a/src/state/migrations/clearPortfolio.ts b/src/state/migrations/clearPortfolio.ts index 605e79662ff..0bff1421d94 100644 --- a/src/state/migrations/clearPortfolio.ts +++ b/src/state/migrations/clearPortfolio.ts @@ -1,29 +1,7 @@ -import type { ReduxState } from 'state/reducer' +import type { PersistPartial } from 'redux-persist/es/persistReducer' +import type { Portfolio } from 'state/slices/portfolioSlice/portfolioSliceCommon' import { initialState } from 'state/slices/portfolioSlice/portfolioSliceCommon' -export const clearPortfolio = (state: ReduxState): ReduxState => { - return { - ...state, - portfolio: initialState, - // This is very ugly but also very correct - // Typically, to achieve this, we would dispatch nftapi.util.resetApiState as a side effect - // But we can't do this here because circular deps, so we have to do it manually - // https://redux-toolkit.js.org/rtk-query/api/created-api/api-slice-utils#resetapistate - portfolioApi: { - queries: {}, - mutations: {}, - provided: {}, - subscriptions: {}, - config: { - online: true, - focused: true, - middlewareRegistered: true, - refetchOnFocus: false, - refetchOnReconnect: true, - refetchOnMountOrArgChange: false, - keepUnusedDataFor: 60, - reducerPath: 'portfolioApi', - }, - }, - } +export const clearPortfolio = (_state: Portfolio): Portfolio & PersistPartial => { + return initialState as Portfolio & PersistPartial } diff --git a/src/state/migrations/clearSnapshot.ts b/src/state/migrations/clearSnapshot.ts index 2d37a2fdccb..3a1dcb4ae27 100644 --- a/src/state/migrations/clearSnapshot.ts +++ b/src/state/migrations/clearSnapshot.ts @@ -1,10 +1,8 @@ +import type { PersistPartial } from 'redux-persist/es/persistReducer' +import type { SnapshotState } from 'state/apis/snapshot/snapshot' import { initialState } from 'state/apis/snapshot/snapshot' -import type { ReduxState } from 'state/reducer' -export const clearSnapshot = (state: ReduxState): ReduxState => { +export const clearSnapshot = (_state: SnapshotState): SnapshotState & PersistPartial => { // Migration to clear snapshot API - return { - ...state, - snapshot: initialState, - } + return initialState as SnapshotState & PersistPartial } diff --git a/src/state/migrations/clearTxHistory.ts b/src/state/migrations/clearTxHistory.ts index f78b821f719..345965b3da5 100644 --- a/src/state/migrations/clearTxHistory.ts +++ b/src/state/migrations/clearTxHistory.ts @@ -1,10 +1,8 @@ -import type { ReduxState } from 'state/reducer' +import type { PersistPartial } from 'redux-persist/es/persistReducer' +import type { TxHistory } from 'state/slices/txHistorySlice/txHistorySlice' import { initialState } from 'state/slices/txHistorySlice/txHistorySlice' -export const clearTxHistory = (state: ReduxState): ReduxState => { +export const clearTxHistory = (_state: TxHistory): TxHistory & PersistPartial => { // Migration to clear tx history state - return { - ...state, - txHistory: initialState, - } + return initialState as TxHistory & PersistPartial } diff --git a/src/state/migrations/clearWalletConnectWalletsMetadata.ts b/src/state/migrations/clearWalletConnectWalletsMetadata.ts index 2b1df52881d..a6f396dcd81 100644 --- a/src/state/migrations/clearWalletConnectWalletsMetadata.ts +++ b/src/state/migrations/clearWalletConnectWalletsMetadata.ts @@ -1,20 +1,18 @@ -import type { ReduxState } from 'state/reducer' +import type { PersistPartial } from 'redux-persist/es/persistReducer' +import type { Portfolio } from 'state/slices/portfolioSlice/portfolioSliceCommon' -export const clearWalletConnectWalletsMetadata = (state: ReduxState): ReduxState => { - const updatedWalletIds = state.portfolio.wallet.ids.filter(id => !id.startsWith('wc:')) +export const clearWalletConnectWalletsMetadata = (state: Portfolio): Portfolio & PersistPartial => { + const updatedWalletIds = state.wallet.ids.filter(id => !id.startsWith('wc:')) const updatedWalletById = Object.fromEntries( - Object.entries(state.portfolio.wallet.byId).filter(([walletId]) => !walletId.startsWith('wc:')), + Object.entries(state.wallet.byId).filter(([walletId]) => !walletId.startsWith('wc:')), ) return { ...state, - portfolio: { - ...state.portfolio, - wallet: { - ...state.portfolio.wallet, - ids: updatedWalletIds, - byId: updatedWalletById, - }, + wallet: { + ...state.wallet, + ids: updatedWalletIds, + byId: updatedWalletById, }, - } + } as Portfolio & PersistPartial } diff --git a/src/state/migrations/index.ts b/src/state/migrations/index.ts index be8791b92ce..160845039fd 100644 --- a/src/state/migrations/index.ts +++ b/src/state/migrations/index.ts @@ -1,126 +1,37 @@ +import type { MigrationManifest } from 'redux-persist' + import { clearAssets } from './clearAssets' -import { clearMarketData } from './clearMarketData' -import { clearNfts } from './clearNfts' -import { clearOpportunities } from './clearOpportunities' -import { clearPortfolio } from './clearPortfolio' -import { clearSnapshot } from './clearSnapshot' -import { clearTxHistory } from './clearTxHistory' -import { clearWalletConnectWalletsMetadata } from './clearWalletConnectWalletsMetadata' -export const migrations = { - 0: clearOpportunities, - 1: clearOpportunities, - 2: clearPortfolio, - 3: clearOpportunities, - 4: clearOpportunities, - 5: clearNfts, - 6: clearAssets, - 7: clearPortfolio, - 8: clearOpportunities, - 9: clearAssets, - 10: clearTxHistory, - 11: clearAssets, - 12: clearAssets, - 13: clearPortfolio, - 14: clearTxHistory, - 15: clearAssets, - 16: clearOpportunities, - 17: clearTxHistory, - 18: clearTxHistory, - 19: clearMarketData, - 20: clearTxHistory, - 21: clearAssets, - 22: clearTxHistory, - 23: clearPortfolio, - 24: clearTxHistory, - 25: clearAssets, - 26: clearAssets, - 27: clearPortfolio, - 28: clearAssets, - 29: clearAssets, - 30: clearTxHistory, - 31: clearAssets, - 32: clearSnapshot, - 33: clearAssets, - 34: clearTxHistory, - 35: clearAssets, - 36: clearTxHistory, - 37: clearPortfolio, - 38: clearOpportunities, - 39: clearAssets, - 40: clearAssets, - 41: clearAssets, - 42: clearAssets, - 43: clearAssets, - 44: clearAssets, - 45: clearAssets, - 46: clearAssets, - 47: clearAssets, - 48: clearAssets, - 49: clearAssets, - 50: clearPortfolio, - 51: clearAssets, - 52: clearPortfolio, - 53: clearAssets, - 54: clearAssets, - 55: clearAssets, - 56: clearPortfolio, - 57: clearAssets, - 58: clearAssets, - 59: clearAssets, - 60: clearAssets, - 61: clearOpportunities, - 62: clearAssets, - 63: clearAssets, - 64: clearPortfolio, - 65: clearAssets, - 66: clearAssets, - 67: clearAssets, - 68: clearAssets, - 69: clearAssets, - 70: clearAssets, - 71: clearAssets, - 72: clearAssets, - 73: clearAssets, - 74: clearAssets, - 75: clearAssets, - 76: clearAssets, - 77: clearAssets, - 78: clearAssets, - 79: clearAssets, - 80: clearAssets, - 81: clearAssets, - 82: clearAssets, - 83: clearAssets, - 84: clearAssets, - 85: clearAssets, - 86: clearAssets, - 87: clearWalletConnectWalletsMetadata, - 88: clearAssets, - 89: clearAssets, - 90: clearAssets, - 91: clearAssets, - 92: clearTxHistory, - 93: clearAssets, - 94: clearAssets, - 95: clearTxHistory, - 96: clearTxHistory, - 97: clearAssets, - 98: clearAssets, - 99: clearAssets, - 100: clearAssets, - 101: clearAssets, - 102: clearAssets, - 103: clearAssets, - 104: clearTxHistory, - 105: clearPortfolio, - 106: clearOpportunities, - 107: clearAssets, - 108: clearAssets, - 109: clearAssets, - 110: clearAssets, - 111: clearAssets, - 112: clearAssets, - 113: clearAssets, - 114: clearAssets, -} +export const clearTxHistoryMigrations = { + // Uncomment me when introducing the first migration for this slice + // 0: clearTxHistory, +} as unknown as Omit + +export const clearOpportunitiesMigrations = { + // Uncomment me when introducing the first migration for this slice + // 0: clearOpportunities, +} as unknown as Omit + +export const clearPortfolioMigrations = { + // Uncomment me when introducing the first migration for this slice + // 0: clearPortfolio, +} as unknown as Omit + +export const clearNftsMigrations = { + // Uncomment me when introducing the first migration for this slice + // 0: clearNfts, +} as unknown as Omit + +export const clearAssetsMigrations = { + 0: clearAssets, +} as unknown as Omit + +export const clearMarketDataMigrations = { + // Uncomment me when introducing the first migration for this slice + // 0: clearMarketData, +} as unknown as Omit + +export const clearSnapshotMigrations = { + // Uncomment me when introducing the first migration for this slice + // 0: clearSnapshot, +} as unknown as Omit diff --git a/src/state/migrations/transformClearAssets.ts b/src/state/migrations/transformClearAssets.ts index 3ead9fb4965..97c7b7e43b9 100644 --- a/src/state/migrations/transformClearAssets.ts +++ b/src/state/migrations/transformClearAssets.ts @@ -6,7 +6,7 @@ const transform = (fileInfo: FileInfo, api: API) => { root.find(j.ExportNamedDeclaration).forEach(path => { const objectExpression = j(path) - .find(j.VariableDeclarator, { id: { name: 'migrations' } }) + .find(j.VariableDeclarator, { id: { name: 'clearAssetsMigrations' } }) .find(j.ObjectExpression) .at(0) diff --git a/src/state/reducer.ts b/src/state/reducer.ts index d39e113ce92..49b785d8728 100644 --- a/src/state/reducer.ts +++ b/src/state/reducer.ts @@ -1,24 +1,42 @@ import { combineReducers } from '@reduxjs/toolkit' import localforage from 'localforage' -import { persistReducer } from 'redux-persist' +import { createMigrate, persistReducer } from 'redux-persist' import { tradeQuoteSlice } from 'state/slices/tradeQuoteSlice/tradeQuoteSlice' import { abiApi } from './apis/abi/abiApi' import { covalentApi } from './apis/covalent/covalentApi' import { fiatRampApi } from './apis/fiatRamps/fiatRamps' import { foxyApi } from './apis/foxy/foxyApi' +import type { NftState } from './apis/nft/nftApi' import { nft, nftApi } from './apis/nft/nftApi' +import type { SnapshotState } from './apis/snapshot/snapshot' import { snapshot, snapshotApi } from './apis/snapshot/snapshot' import { swapperApi } from './apis/swapper/swapperApi' import { zapper, zapperApi } from './apis/zapper/zapperApi' +import { + clearAssetsMigrations, + clearMarketDataMigrations, + clearNftsMigrations, + clearOpportunitiesMigrations, + clearPortfolioMigrations, + clearSnapshotMigrations, + clearTxHistoryMigrations, +} from './migrations' +import type { AssetsState } from './slices/assetsSlice/assetsSlice' import { assetApi, assets } from './slices/assetsSlice/assetsSlice' +import type { LocalWalletState } from './slices/localWalletSlice/localWalletSlice' import { localWalletSlice } from './slices/localWalletSlice/localWalletSlice' import { marketApi, marketData } from './slices/marketDataSlice/marketDataSlice' +import type { MarketDataState } from './slices/marketDataSlice/types' import { opportunitiesApi } from './slices/opportunitiesSlice/opportunitiesApiSlice' import { opportunities } from './slices/opportunitiesSlice/opportunitiesSlice' +import type { OpportunitiesState } from './slices/opportunitiesSlice/types' import { portfolio, portfolioApi } from './slices/portfolioSlice/portfolioSlice' +import type { Portfolio } from './slices/portfolioSlice/portfolioSliceCommon' +import type { Preferences } from './slices/preferencesSlice/preferencesSlice' import { preferences } from './slices/preferencesSlice/preferencesSlice' import { tradeInput } from './slices/tradeInputSlice/tradeInputSlice' +import type { TxHistory } from './slices/txHistorySlice/txHistorySlice' import { txHistory, txHistoryApi } from './slices/txHistorySlice/txHistorySlice' export const slices = { @@ -41,18 +59,79 @@ const preferencesPersistConfig = { blacklist: ['featureFlags'], } +const txHistoryPersistConfig = { + key: 'txHistory', + storage: localforage, + version: Math.max(...Object.keys(clearTxHistoryMigrations).map(Number)), + migrate: createMigrate(clearTxHistoryMigrations, { debug: false }), +} + +const portfolioPersistConfig = { + key: 'portfolio', + storage: localforage, + version: Math.max(...Object.keys(clearPortfolioMigrations).map(Number)), + migrate: createMigrate(clearPortfolioMigrations, { debug: false }), +} + +const opportunitiesPersistConfig = { + key: 'opportunities', + storage: localforage, + version: Math.max(...Object.keys(clearOpportunitiesMigrations).map(Number)), + migrate: createMigrate(clearOpportunitiesMigrations, { debug: false }), +} + +const nftPersistConfig = { + key: 'nft', + storage: localforage, + version: Math.max(...Object.keys(clearNftsMigrations).map(Number)), + migrate: createMigrate(clearNftsMigrations, { debug: false }), +} + +const snapshotPersistConfig = { + key: 'snapshot', + storage: localforage, + version: Math.max(...Object.keys(clearSnapshotMigrations).map(Number)), + migrate: createMigrate(clearSnapshotMigrations, { debug: false }), +} + +const localWalletSlicePersistConfig = { + key: 'localWalletSlice', + storage: localforage, + // no migrations for localWalletSlice yet - stay tuned! +} + +const marketDataPersistConfig = { + key: 'marketData', + storage: localforage, + version: Math.max(...Object.keys(clearMarketDataMigrations).map(Number)), + migrate: createMigrate(clearMarketDataMigrations, { debug: false }), +} + +const assetsPersistConfig = { + key: 'assets', + storage: localforage, + version: Math.max(...Object.keys(clearAssetsMigrations).map(Number)), + migrate: createMigrate(clearAssetsMigrations, { debug: false }), +} + export const sliceReducers = { - assets: assets.reducer, - marketData: marketData.reducer, - txHistory: txHistory.reducer, - portfolio: portfolio.reducer, - preferences: persistReducer(preferencesPersistConfig, preferences.reducer), + assets: persistReducer(assetsPersistConfig, assets.reducer), + marketData: persistReducer(marketDataPersistConfig, marketData.reducer), + txHistory: persistReducer(txHistoryPersistConfig, txHistory.reducer), + portfolio: persistReducer(portfolioPersistConfig, portfolio.reducer), + preferences: persistReducer(preferencesPersistConfig, preferences.reducer), tradeInput: tradeInput.reducer, - opportunities: opportunities.reducer, - nft: nft.reducer, + opportunities: persistReducer( + opportunitiesPersistConfig, + opportunities.reducer, + ), + nft: persistReducer(nftPersistConfig, nft.reducer), tradeQuoteSlice: tradeQuoteSlice.reducer, - snapshot: snapshot.reducer, - localWalletSlice: localWalletSlice.reducer, + snapshot: persistReducer(snapshotPersistConfig, snapshot.reducer), + localWalletSlice: persistReducer( + localWalletSlicePersistConfig, + localWalletSlice.reducer, + ), } export const apiSlices = { @@ -89,5 +168,5 @@ export const apiReducers = { [abiApi.reducerPath]: abiApi.reducer, } -export const reducer = combineReducers({ ...sliceReducers, ...apiReducers }) +export const reducer = combineReducers(Object.assign({}, sliceReducers, apiReducers)) export type ReduxState = ReturnType diff --git a/src/state/slices/localWalletSlice/localWalletSlice.ts b/src/state/slices/localWalletSlice/localWalletSlice.ts index 85bd2587f8f..f77f0bcac19 100644 --- a/src/state/slices/localWalletSlice/localWalletSlice.ts +++ b/src/state/slices/localWalletSlice/localWalletSlice.ts @@ -2,7 +2,7 @@ import type { PayloadAction } from '@reduxjs/toolkit' import { createSlice } from '@reduxjs/toolkit' import type { KeyManager } from 'context/WalletProvider/KeyManager' -interface LocalWalletState { +export type LocalWalletState = { walletType: KeyManager | null walletDeviceId: string | null nativeWalletName: string | null diff --git a/src/state/slices/opportunitiesSlice/opportunitiesSlice.test.ts b/src/state/slices/opportunitiesSlice/opportunitiesSlice.test.ts index 06040e16981..3ee7b5c5494 100644 --- a/src/state/slices/opportunitiesSlice/opportunitiesSlice.test.ts +++ b/src/state/slices/opportunitiesSlice/opportunitiesSlice.test.ts @@ -21,7 +21,13 @@ describe('opportunitiesSlice', () => { }) it('returns uninitialized properties for initialState', () => { - expect(store.getState().opportunities).toEqual(initialState) + expect(store.getState().opportunities).toEqual({ + ...initialState, + _persist: { + rehydrated: true, + version: -Infinity, + }, + }) }) describe('reducers', () => { diff --git a/src/state/slices/opportunitiesSlice/selectors/selectors.test.ts b/src/state/slices/opportunitiesSlice/selectors/selectors.test.ts index accb36907cd..fd00901c588 100644 --- a/src/state/slices/opportunitiesSlice/selectors/selectors.test.ts +++ b/src/state/slices/opportunitiesSlice/selectors/selectors.test.ts @@ -125,6 +125,7 @@ describe('opportunitiesSlice selectors', () => { }, opportunities: { ...initialState, + _persist: { version: 0, rehydrated: false }, lp, staking, userStaking, @@ -228,6 +229,7 @@ describe('opportunitiesSlice selectors', () => { const mockState = { ...mockBaseState, opportunities: { + _persist: { version: 0, rehydrated: false }, ...initialState, staking, userStaking, @@ -347,6 +349,7 @@ describe('opportunitiesSlice selectors', () => { ...mockBaseState, opportunities: { ...initialState, + _persist: { version: 0, rehydrated: false }, staking, userStaking, }, diff --git a/src/state/slices/txHistorySlice/txHistorySlice.test.ts b/src/state/slices/txHistorySlice/txHistorySlice.test.ts index eecec4afd32..38828843f25 100644 --- a/src/state/slices/txHistorySlice/txHistorySlice.test.ts +++ b/src/state/slices/txHistorySlice/txHistorySlice.test.ts @@ -18,6 +18,10 @@ describe('txHistorySlice', () => { it('returns empty object for initialState', () => { expect(store.getState().txHistory).toEqual({ + _persist: { + rehydrated: true, + version: -Infinity, + }, hydrationMeta: {}, txs: { byId: {}, diff --git a/src/state/store.ts b/src/state/store.ts index 64b3e550d29..10eaeac18ec 100644 --- a/src/state/store.ts +++ b/src/state/store.ts @@ -1,9 +1,8 @@ import { autoBatchEnhancer, configureStore } from '@reduxjs/toolkit' import { getConfig } from 'config' -import localforage from 'localforage' import type { TypedUseSelectorHook } from 'react-redux' import { useDispatch, useSelector } from 'react-redux' -import { createMigrate, PERSIST, persistReducer, persistStore, PURGE } from 'redux-persist' +import { persistStore } from 'redux-persist' import { getStateWith, registerSelectors } from 'reselect-tools' import { abiApi } from './apis/abi/abiApi' @@ -14,7 +13,6 @@ import { nftApi } from './apis/nft/nftApi' import { snapshotApi } from './apis/snapshot/snapshot' import { swapperApi } from './apis/swapper/swapperApi' import { zapper, zapperApi } from './apis/zapper/zapperApi' -import { migrations } from './migrations' import type { ReduxState } from './reducer' import { apiSlices, reducer, slices } from './reducer' import { assetApi } from './slices/assetsSlice/assetsSlice' @@ -26,15 +24,6 @@ import { txHistoryApi } from './slices/txHistorySlice/txHistorySlice' import { createSubscriptionMiddleware } from './subscriptionMiddleware' import { updateWindowStoreMiddleware } from './windowMiddleware' -const persistConfig = { - key: 'root', - version: Math.max(...Object.keys(migrations).map(Number)), - whitelist: ['txHistory', 'portfolio', 'opportunities', 'nft', 'snapshot', 'localWalletSlice'], - storage: localforage, - // @ts-ignore createMigrate typings are wrong - migrate: createMigrate(migrations, { debug: false }), -} - const apiMiddleware = [ portfolioApi.middleware, marketApi.middleware, @@ -54,8 +43,6 @@ const apiMiddleware = [ const subscriptionMiddleware = createSubscriptionMiddleware() -const persistedReducer = persistReducer(persistConfig, reducer) - export const clearState = () => { store.dispatch(slices.assets.actions.clear()) store.dispatch(slices.marketData.actions.clear()) @@ -126,23 +113,18 @@ const stateSanitizer = (state: any) => { /// This allows us to create an empty store for tests export const createStore = () => configureStore({ - reducer: persistedReducer, + reducer, enhancers: existingEnhancers => { // Add the autobatch enhancer to the store setup return existingEnhancers.concat(autoBatchEnhancer()) }, middleware: getDefaultMiddleware => getDefaultMiddleware({ - immutableCheck: { - warnAfter: 128, - ignoredActions: [PERSIST, PURGE], - }, - serializableCheck: { - ignoreState: true, - ignoreActions: true, - warnAfter: 128, - ignoredActions: [PERSIST, PURGE], - }, + // funnily enough, the checks that should check for perf. issues are actually slowing down the app + // This is actually safe, since we're not derps mutating the state directly and are using actions and immer for extra safety + // https://github.com/reduxjs/redux-toolkit/issues/415 + immutableCheck: false, + serializableCheck: false, thunk: { extraArgument: { subscribe: subscriptionMiddleware.subscribe }, }, diff --git a/src/test/mocks/store.ts b/src/test/mocks/store.ts index 403a269facd..9db9c9e1bb9 100644 --- a/src/test/mocks/store.ts +++ b/src/test/mocks/store.ts @@ -42,6 +42,10 @@ export const mockStore: ReduxState = { opportunitiesApi: mockApiFactory('opportunitiesApi' as const), abiApi: mockApiFactory('abiApi' as const), portfolio: { + _persist: { + version: 0, + rehydrated: false, + }, isAccountMetadataLoading: false, accounts: { byId: {}, @@ -134,11 +138,19 @@ export const mockStore: ReduxState = { }, }, assets: { + _persist: { + version: 0, + rehydrated: false, + }, byId: {}, ids: [], relatedAssetIndex: {}, }, marketData: { + _persist: { + version: 0, + rehydrated: false, + }, crypto: { byId: {}, ids: [], @@ -152,6 +164,10 @@ export const mockStore: ReduxState = { isMarketDataLoaded: false, }, txHistory: { + _persist: { + version: 0, + rehydrated: false, + }, txs: { byId: {}, byAccountIdAssetId: {}, @@ -160,6 +176,10 @@ export const mockStore: ReduxState = { hydrationMeta: {}, }, opportunities: { + _persist: { + version: 0, + rehydrated: false, + }, lp: { byAccountId: {}, byId: {}, @@ -176,6 +196,10 @@ export const mockStore: ReduxState = { }, }, nft: { + _persist: { + version: 0, + rehydrated: false, + }, selectedNftAvatarByWalletId: {}, nfts: { byId: {}, @@ -209,6 +233,10 @@ export const mockStore: ReduxState = { isTradeQuoteRequestAborted: false, }, snapshot: { + _persist: { + version: 0, + rehydrated: false, + }, votingPowerByModel: { SWAPPER: undefined, THORCHAIN_LP: undefined, @@ -216,6 +244,10 @@ export const mockStore: ReduxState = { strategies: undefined, }, localWalletSlice: { + _persist: { + version: 0, + rehydrated: false, + }, walletType: null, walletDeviceId: null, nativeWalletName: null,