This repository has been archived by the owner on Jan 30, 2024. It is now read-only.
forked from valora-inc/wallet
-
Notifications
You must be signed in to change notification settings - Fork 2
/
store.ts
161 lines (145 loc) · 5.39 KB
/
store.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import AsyncStorage from '@react-native-async-storage/async-storage'
import { configureStore } from '@reduxjs/toolkit'
import { setupListeners } from '@reduxjs/toolkit/dist/query'
import { Middleware } from 'redux'
import { getStoredState, PersistConfig, persistReducer, persistStore } from 'redux-persist'
import FSStorage from 'redux-persist-fs-storage'
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2'
import createSagaMiddleware from 'redux-saga'
import { PerformanceEvents } from 'src/analytics/Events'
import ValoraAnalytics from 'src/analytics/ValoraAnalytics'
import { createMigrate } from 'src/redux/createMigrate'
import { migrations } from 'src/redux/migrations'
import rootReducer, { RootState } from 'src/redux/reducers'
import { rootSaga } from 'src/redux/sagas'
import { resetStateOnInvalidStoredAccount } from 'src/utils/accountChecker'
import Logger from 'src/utils/Logger'
import { ONE_DAY_IN_MILLIS } from 'src/utils/time'
const timeBetweenStoreSizeEvents = ONE_DAY_IN_MILLIS
let lastEventTime = Date.now()
const persistConfig: PersistConfig<RootState> = {
key: 'root',
// default is -1, increment as we make migrations
// See https://github.com/valora-inc/wallet/tree/main/WALLET.md#redux-state-migration
version: 51,
keyPrefix: `reduxStore-`, // the redux-persist default is `persist:` which doesn't work with some file systems.
storage: FSStorage(),
blacklist: ['geth', 'networkInfo', 'alert', 'imports', 'supercharge'],
stateReconciler: autoMergeLevel2,
migrate: async (...args) => {
const migrate = createMigrate(migrations)
const state: any = await migrate(...args)
// Do this check here once migrations have occurred, to ensure we have a RootState
return resetStateOnInvalidStoredAccount(state) as any
},
// @ts-ignore the types are currently wrong
serialize: (data: any) => {
// We're using this to send the size of the store to analytics while using the default implementation of JSON.stringify.
const stringifiedData = JSON.stringify(data)
// if data._persist or any other key is present the whole state is present (the content of the keys are
// sometimes serialized independently).
if (data._persist && Date.now() > lastEventTime + timeBetweenStoreSizeEvents) {
lastEventTime = Date.now()
ValoraAnalytics.track(PerformanceEvents.redux_store_size, {
size: stringifiedData.length,
})
}
return stringifiedData
},
deserialize: (data: string) => {
// This is the default implementation, but overriding to maintain compatibility with the serialize function
// in case the library changes.
return JSON.parse(data)
},
// @ts-ignore
timeout: null,
}
// We used to use AsyncStorage to save the state, but moved to file system storage because of problems with Android
// maximum size limits. To keep backwards compatibility, we first try to read from the file system but if nothing is found
// it means it's an old version so we read the state from AsyncStorage.
// @ts-ignore
persistConfig.getStoredState = async (config: any) => {
Logger.info('redux/store', 'persistConfig.getStoredState')
try {
// throw new Error("testing exception in getStoredState")
const state = await getStoredState(config)
if (state) {
return state
}
const oldState = await getStoredState({
...config,
storage: AsyncStorage,
keyPrefix: 'persist:',
})
if (oldState) {
return oldState
}
return null
} catch (error) {
Logger.error('redux/store', 'Failed to retrieve redux state.', error)
}
}
// For testing only!
export const _persistConfig = persistConfig
// eslint-disable-next-line no-var
declare var window: any
export const setupStore = (initialState = {}, config = persistConfig) => {
const sagaMiddleware = createSagaMiddleware()
const middlewares: Middleware[] = [sagaMiddleware]
if (__DEV__) {
const createDebugger = require('redux-flipper').default
// Sending the whole state makes the redux debugger in flipper super slow!!
// I suspect it's the exchange rates causing this!
// For now exclude the `exchange` reducer.
middlewares.push(
createDebugger({
stateWhitelist: [
'app',
'i18n',
'networkInfo',
'alert',
'goldToken',
'stableToken',
'send',
'home',
// "exchange",
'transactions',
'web3',
'identity',
'account',
'invite',
'geth',
'escrow',
'fees',
'recipients',
'localCurrency',
'imports',
'paymentRequest',
'verify',
],
})
)
}
const enhancers = []
if (__DEV__) {
const Reactotron = require('src/reactotronConfig').default
enhancers.push(Reactotron.createEnhancer())
}
const persistedReducer = persistReducer(config, rootReducer)
const createdStore = configureStore({
reducer: persistedReducer,
preloadedState: initialState,
middleware: (getDefaultMiddleware: any) =>
getDefaultMiddleware({
immutableCheck: false,
serializableCheck: false,
}).concat(...middlewares),
enhancers,
})
const createdPersistor = persistStore(createdStore)
sagaMiddleware.run(rootSaga)
return { store: createdStore, persistor: createdPersistor }
}
const { store, persistor } = setupStore()
setupListeners(store.dispatch)
export { store, persistor }