Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: blazingly fast #7799

Merged
merged 11 commits into from
Sep 25, 2024
2 changes: 1 addition & 1 deletion src/state/apis/nft/nftApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ type GetNftCollectionInput = {
accountIds: AccountId[]
}

type NftState = {
export type NftState = {
selectedNftAvatarByWalletId: Record<WalletId, AssetId>
nfts: {
byId: PartialRecord<AssetId, NftItem>
Expand Down
10 changes: 6 additions & 4 deletions src/state/apis/snapshot/snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,19 @@ type FoxVotingPowerCryptoBalance = string

const SNAPSHOT_SPACE = 'shapeshiftdao.eth'

export const initialState: {
votingPowerByModel: Record<ParameterModel, string | undefined>
strategies: Strategy[] | undefined
} = {
export const initialState: SnapshotState = {
votingPowerByModel: {
SWAPPER: undefined,
THORCHAIN_LP: undefined,
},
strategies: undefined,
}

export type SnapshotState = {
votingPowerByModel: Record<ParameterModel, string | undefined>
strategies: Strategy[] | undefined
}

export const snapshot = createSlice({
name: 'snapshot',
initialState,
Expand Down
4 changes: 3 additions & 1 deletion src/state/migrations/clearNfts.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
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,
nft: initialState as NftState & PersistPartial,
// 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
Expand Down
4 changes: 3 additions & 1 deletion src/state/migrations/clearOpportunities.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import type { PersistPartial } from 'redux-persist/es/persistReducer'
import type { ReduxState } from 'state/reducer'
import type { OpportunitiesState } from 'state/slices/opportunitiesSlice/types'

import { initialState } from '../slices/opportunitiesSlice/opportunitiesSlice'

export const clearOpportunities = (state: ReduxState): ReduxState => {
// Migration to clear opportunitiesApi and opportunitiesApi state
return {
...state,
opportunities: initialState,
opportunities: initialState as OpportunitiesState & PersistPartial,
}
}
4 changes: 3 additions & 1 deletion src/state/migrations/clearPortfolio.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { PersistPartial } from 'redux-persist/es/persistReducer'
import type { ReduxState } from 'state/reducer'
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,
portfolio: initialState as Portfolio & PersistPartial,
// 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
Expand Down
4 changes: 3 additions & 1 deletion src/state/migrations/clearSnapshot.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
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 => {
// Migration to clear snapshot API
return {
...state,
snapshot: initialState,
snapshot: initialState as SnapshotState & PersistPartial,
}
}
4 changes: 3 additions & 1 deletion src/state/migrations/clearTxHistory.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { PersistPartial } from 'redux-persist/es/persistReducer'
import type { ReduxState } from 'state/reducer'
import type { TxHistory } from 'state/slices/txHistorySlice/txHistorySlice'
import { initialState } from 'state/slices/txHistorySlice/txHistorySlice'

export const clearTxHistory = (state: ReduxState): ReduxState => {
// Migration to clear tx history state
return {
...state,
txHistory: initialState,
txHistory: initialState as TxHistory & PersistPartial,
}
}
9 changes: 8 additions & 1 deletion src/state/migrations/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { MigrationManifest } from 'redux-persist'

import { clearAssets } from './clearAssets'
import { clearMarketData } from './clearMarketData'
import { clearNfts } from './clearNfts'
Expand Down Expand Up @@ -122,4 +124,9 @@ export const migrations = {
111: clearAssets,
112: clearAssets,
113: clearAssets,
}
114: clearAssets,
115: clearAssets,
116: clearAssets,
117: clearAssets,
118: clearTxHistory,
} as unknown as Omit<MigrationManifest, '_persist'>
gomesalexandre marked this conversation as resolved.
Show resolved Hide resolved
81 changes: 73 additions & 8 deletions src/state/reducer.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
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 { migrations } from './migrations'
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 { 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 = {
Expand All @@ -39,20 +47,77 @@ const preferencesPersistConfig = {
key: 'preferences',
storage: localforage,
blacklist: ['featureFlags'],
version: Math.max(...Object.keys(migrations).map(Number)),
// @ts-ignore createMigrate typings are wrong
migrate: createMigrate(migrations, { debug: false }),
}

const txHistoryPersistConfig = {
key: 'txHistory',
storage: localforage,
version: Math.max(...Object.keys(migrations).map(Number)),
// @ts-ignore createMigrate typings are wrong
migrate: createMigrate(migrations, { debug: false }),
}

const portfolioPersistConfig = {
key: 'portfolio',
storage: localforage,
version: Math.max(...Object.keys(migrations).map(Number)),
// @ts-ignore createMigrate typings are wrong
migrate: createMigrate(migrations, { debug: false }),
}

const opportunitiesPersistConfig = {
key: 'opportunities',
storage: localforage,
version: Math.max(...Object.keys(migrations).map(Number)),
// @ts-ignore createMigrate typings are wrong
migrate: createMigrate(migrations, { debug: false }),
}

const nftPersistConfig = {
key: 'nft',
storage: localforage,
version: Math.max(...Object.keys(migrations).map(Number)),
// @ts-ignore createMigrate typings are wrong
migrate: createMigrate(migrations, { debug: false }),
}

const snapshotPersistConfig = {
key: 'snapshot',
storage: localforage,
version: Math.max(...Object.keys(migrations).map(Number)),
// @ts-ignore createMigrate typings are wrong
migrate: createMigrate(migrations, { debug: false }),
}

const localWalletSlicePersistConfig = {
key: 'localWalletSlice',
storage: localforage,
version: Math.max(...Object.keys(migrations).map(Number)),
// @ts-ignore createMigrate typings are wrong
migrate: createMigrate(migrations, { debug: false }),
}

export const sliceReducers = {
assets: assets.reducer,
marketData: marketData.reducer,
txHistory: txHistory.reducer,
portfolio: portfolio.reducer,
preferences: persistReducer(preferencesPersistConfig, preferences.reducer),
txHistory: persistReducer<TxHistory>(txHistoryPersistConfig, txHistory.reducer),
portfolio: persistReducer<Portfolio>(portfolioPersistConfig, portfolio.reducer),
preferences: persistReducer<Preferences>(preferencesPersistConfig, preferences.reducer),
tradeInput: tradeInput.reducer,
opportunities: opportunities.reducer,
nft: nft.reducer,
opportunities: persistReducer<OpportunitiesState>(
opportunitiesPersistConfig,
opportunities.reducer,
),
nft: persistReducer<NftState>(nftPersistConfig, nft.reducer),
tradeQuoteSlice: tradeQuoteSlice.reducer,
snapshot: snapshot.reducer,
localWalletSlice: localWalletSlice.reducer,
snapshot: persistReducer<SnapshotState>(snapshotPersistConfig, snapshot.reducer),
localWalletSlice: persistReducer<LocalWalletState>(
localWalletSlicePersistConfig,
localWalletSlice.reducer,
),
}

export const apiSlices = {
Expand Down
2 changes: 1 addition & 1 deletion src/state/slices/localWalletSlice/localWalletSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ describe('opportunitiesSlice selectors', () => {
},
opportunities: {
...initialState,
_persist: { version: 0, rehydrated: false },
lp,
staking,
userStaking,
Expand Down Expand Up @@ -228,6 +229,7 @@ describe('opportunitiesSlice selectors', () => {
const mockState = {
...mockBaseState,
opportunities: {
_persist: { version: 0, rehydrated: false },
...initialState,
staking,
userStaking,
Expand Down Expand Up @@ -347,6 +349,7 @@ describe('opportunitiesSlice selectors', () => {
...mockBaseState,
opportunities: {
...initialState,
_persist: { version: 0, rehydrated: false },
staking,
userStaking,
},
Expand Down
17 changes: 2 additions & 15 deletions src/state/store.ts
Original file line number Diff line number Diff line change
@@ -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 { PERSIST, persistStore, PURGE } from 'redux-persist'
import { getStateWith, registerSelectors } from 'reselect-tools'

import { abiApi } from './apis/abi/abiApi'
Expand All @@ -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'
Expand All @@ -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,
Expand All @@ -54,8 +43,6 @@ const apiMiddleware = [

const subscriptionMiddleware = createSubscriptionMiddleware()

const persistedReducer = persistReducer(persistConfig, reducer)
gomesalexandre marked this conversation as resolved.
Show resolved Hide resolved

export const clearState = () => {
store.dispatch(slices.assets.actions.clear())
store.dispatch(slices.marketData.actions.clear())
Expand Down Expand Up @@ -126,7 +113,7 @@ 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())
Expand Down
24 changes: 24 additions & 0 deletions src/test/mocks/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {},
Expand Down Expand Up @@ -151,6 +155,10 @@ export const mockStore: ReduxState = {
isMarketDataLoaded: false,
},
txHistory: {
_persist: {
version: 0,
rehydrated: false,
},
txs: {
byId: {},
byAccountIdAssetId: {},
Expand All @@ -159,6 +167,10 @@ export const mockStore: ReduxState = {
hydrationMeta: {},
},
opportunities: {
_persist: {
version: 0,
rehydrated: false,
},
lp: {
byAccountId: {},
byId: {},
Expand All @@ -175,6 +187,10 @@ export const mockStore: ReduxState = {
},
},
nft: {
_persist: {
version: 0,
rehydrated: false,
},
selectedNftAvatarByWalletId: {},
nfts: {
byId: {},
Expand Down Expand Up @@ -208,13 +224,21 @@ export const mockStore: ReduxState = {
isTradeQuoteRequestAborted: false,
},
snapshot: {
_persist: {
version: 0,
rehydrated: false,
},
votingPowerByModel: {
SWAPPER: undefined,
THORCHAIN_LP: undefined,
},
strategies: undefined,
},
localWalletSlice: {
_persist: {
version: 0,
rehydrated: false,
},
walletType: null,
walletDeviceId: null,
nativeWalletName: null,
Expand Down
Loading