load safes from localstorage on app load
This commit is contained in:
parent
01baabc7cb
commit
e33c90c230
File diff suppressed because it is too large
Load Diff
|
@ -142,7 +142,7 @@
|
||||||
"ethereumjs-abi": "^0.6.7",
|
"ethereumjs-abi": "^0.6.7",
|
||||||
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
||||||
"file-loader": "^3.0.1",
|
"file-loader": "^3.0.1",
|
||||||
"flow-bin": "^0.95.1",
|
"flow-bin": "0.96.0",
|
||||||
"fs-extra": "^7.0.1",
|
"fs-extra": "^7.0.1",
|
||||||
"html-loader": "^0.5.5",
|
"html-loader": "^0.5.5",
|
||||||
"html-webpack-plugin": "^3.0.4",
|
"html-webpack-plugin": "^3.0.4",
|
||||||
|
|
|
@ -4,5 +4,9 @@ import 'babel-polyfill'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import Root from '~/components/Root'
|
import Root from '~/components/Root'
|
||||||
|
import { store } from '~/store'
|
||||||
|
import loadSafesFromStorage from '~/routes/safe/store/actions/loadSafesFromStorage'
|
||||||
|
|
||||||
|
store.dispatch(loadSafesFromStorage())
|
||||||
|
|
||||||
ReactDOM.render(<Root />, document.getElementById('root'))
|
ReactDOM.render(<Root />, document.getElementById('root'))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { type Owner } from '~/routes/safe/store/model/owner'
|
import { type Owner } from '~/routes/safe/store/model/owner'
|
||||||
import { List, Map } from 'immutable'
|
import { List, Map } from 'immutable'
|
||||||
import { storage, loadFromStorage } from '~/utils/storage'
|
import { loadFromStorage, saveToStorage } from '~/utils/storage'
|
||||||
|
|
||||||
export const SAFES_KEY = 'SAFES'
|
export const SAFES_KEY = 'SAFES'
|
||||||
export const TX_KEY = 'TX'
|
export const TX_KEY = 'TX'
|
||||||
|
@ -19,8 +19,7 @@ export const getSafeName = async (safeAddress: string) => {
|
||||||
|
|
||||||
export const saveSafes = async (safes: Object) => {
|
export const saveSafes = async (safes: Object) => {
|
||||||
try {
|
try {
|
||||||
const serializedState = JSON.stringify(safes)
|
await saveToStorage(SAFES_KEY, safes)
|
||||||
await storage.set(SAFES_KEY, serializedState)
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
console.log('Error storing safe info in localstorage')
|
console.log('Error storing safe info in localstorage')
|
||||||
|
@ -30,8 +29,7 @@ export const saveSafes = async (safes: Object) => {
|
||||||
export const setOwners = async (safeAddress: string, owners: List<Owner>) => {
|
export const setOwners = async (safeAddress: string, owners: List<Owner>) => {
|
||||||
try {
|
try {
|
||||||
const ownersAsMap = Map(owners.map((owner: Owner) => [owner.get('address').toLowerCase(), owner.get('name')]))
|
const ownersAsMap = Map(owners.map((owner: Owner) => [owner.get('address').toLowerCase(), owner.get('name')]))
|
||||||
const serializedState = JSON.stringify(ownersAsMap)
|
await saveToStorage(`${OWNERS_KEY}-${safeAddress}`, ownersAsMap)
|
||||||
await storage.set(`${OWNERS_KEY}-${safeAddress}`, serializedState)
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
console.log('Error storing owners in localstorage')
|
console.log('Error storing owners in localstorage')
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { List } from 'immutable'
|
import { List } from 'immutable'
|
||||||
import { type Token, type TokenProps } from '~/logic/tokens/store/model/token'
|
import { type Token, type TokenProps } from '~/logic/tokens/store/model/token'
|
||||||
import { storage, loadFromStorage } from '~/utils/storage'
|
import { loadFromStorage, saveToStorage } from '~/utils/storage'
|
||||||
|
|
||||||
export const ACTIVE_TOKENS_KEY = 'ACTIVE_TOKENS'
|
export const ACTIVE_TOKENS_KEY = 'ACTIVE_TOKENS'
|
||||||
export const TOKENS_KEY = 'TOKENS'
|
export const TOKENS_KEY = 'TOKENS'
|
||||||
|
@ -11,9 +11,8 @@ const getTokensKey = (safeAddress: string) => `${TOKENS_KEY}-${safeAddress}`
|
||||||
|
|
||||||
export const setActiveTokens = async (safeAddress: string, tokens: List<TokenProps>) => {
|
export const setActiveTokens = async (safeAddress: string, tokens: List<TokenProps>) => {
|
||||||
try {
|
try {
|
||||||
const serializedState = JSON.stringify(tokens.toJS())
|
|
||||||
const key = getActiveTokensKey(safeAddress)
|
const key = getActiveTokensKey(safeAddress)
|
||||||
await storage.set(key, serializedState)
|
await saveToStorage(key, tokens.toJS())
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
console.log('Error storing tokens in localstorage')
|
console.log('Error storing tokens in localstorage')
|
||||||
|
@ -38,9 +37,8 @@ export const setToken = async (safeAddress: string, token: Token) => {
|
||||||
const data: List<TokenProps> = await getTokens(safeAddress)
|
const data: List<TokenProps> = await getTokens(safeAddress)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const serializedState = JSON.stringify(data.push(token))
|
|
||||||
const key = getTokensKey(safeAddress)
|
const key = getTokensKey(safeAddress)
|
||||||
await storage.set(key, serializedState)
|
await saveToStorage(key, data.push(token))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
console.log('Error adding token in localstorage')
|
console.log('Error adding token in localstorage')
|
||||||
|
@ -52,9 +50,8 @@ export const removeTokenFromStorage = async (safeAddress: string, token: Token)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const index = data.indexOf(token)
|
const index = data.indexOf(token)
|
||||||
const serializedState = JSON.stringify(data.remove(index))
|
|
||||||
const key = getTokensKey(safeAddress)
|
const key = getTokensKey(safeAddress)
|
||||||
await storage.set(key, serializedState)
|
await saveToStorage(key, data.remove(index))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
console.log('Error removing token in localstorage')
|
console.log('Error removing token in localstorage')
|
||||||
|
|
|
@ -20,7 +20,7 @@ type ActionReturn = {
|
||||||
safe: Safe,
|
safe: Safe,
|
||||||
}
|
}
|
||||||
|
|
||||||
const addSafe = createAction<string, *, *>(
|
export const addSafe = createAction<string, *, *>(
|
||||||
ADD_SAFE,
|
ADD_SAFE,
|
||||||
(safe: Safe): ActionReturn => ({
|
(safe: Safe): ActionReturn => ({
|
||||||
safe,
|
safe,
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { makeTransaction, type Transaction } from '~/routes/safe/store/model/tra
|
||||||
import { makeConfirmation } from '~/routes/safe/store/model/confirmation'
|
import { makeConfirmation } from '~/routes/safe/store/model/confirmation'
|
||||||
import { loadSafeSubjects } from '~/utils/storage/transactions'
|
import { loadSafeSubjects } from '~/utils/storage/transactions'
|
||||||
import { buildTxServiceUrlFrom, type TxServiceType } from '~/logic/safe/safeTxHistory'
|
import { buildTxServiceUrlFrom, type TxServiceType } from '~/logic/safe/safeTxHistory'
|
||||||
import { getOwners } from '~/utils/storage'
|
import { getOwners } from '~/logic/safe/utils'
|
||||||
import { EMPTY_DATA } from '~/logic/wallets/ethTransactions'
|
import { EMPTY_DATA } from '~/logic/wallets/ethTransactions'
|
||||||
import addTransactions from './addTransactions'
|
import addTransactions from './addTransactions'
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
// @flow
|
||||||
|
import type { Dispatch as ReduxDispatch } from 'redux'
|
||||||
|
import { type GlobalState } from '~/store/index'
|
||||||
|
import { SAFES_KEY } from '~/logic/safe/utils'
|
||||||
|
import { type SafeProps } from '~/routes/safe/store/model/safe'
|
||||||
|
import { loadFromStorage } from '~/utils/storage'
|
||||||
|
import { addSafe } from './addSafe'
|
||||||
|
import { buildSafe } from '../reducer/safe';
|
||||||
|
|
||||||
|
export default () => async (dispatch: ReduxDispatch<GlobalState>) => {
|
||||||
|
try {
|
||||||
|
const safes: ?{ [string]: SafeProps } = await loadFromStorage(SAFES_KEY)
|
||||||
|
|
||||||
|
if (safes) {
|
||||||
|
Object.values(safes).forEach((safeProps: SafeProps) => {
|
||||||
|
dispatch(addSafe(buildSafe(safeProps)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
console.error('Error while getting safes from storage:', err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
|
@ -45,8 +45,8 @@ const buildSafesFrom = (loadedSafes: Object): Map<string, Safe> => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const safesInitialState = (): State => {
|
export const safesInitialState = async (): Promise<State> => {
|
||||||
const storedSafes = loadFromStorage(SAFES_KEY)
|
const storedSafes = await loadFromStorage(SAFES_KEY)
|
||||||
const safes = storedSafes ? buildSafesFrom(storedSafes) : Map()
|
const safes = storedSafes ? buildSafesFrom(storedSafes) : Map()
|
||||||
|
|
||||||
return safes
|
return safes
|
||||||
|
|
|
@ -18,4 +18,4 @@ const SafeList = ({ safes, provider }: Props) => (
|
||||||
</Page>
|
</Page>
|
||||||
)
|
)
|
||||||
|
|
||||||
export default connect(selector)(SafeList)
|
export default connect<*, *, *, *>(selector)(SafeList)
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
} from 'redux'
|
} from 'redux'
|
||||||
import thunk from 'redux-thunk'
|
import thunk from 'redux-thunk'
|
||||||
import provider, { PROVIDER_REDUCER_ID, type State as ProviderState } from '~/logic/wallets/store/reducer/provider'
|
import provider, { PROVIDER_REDUCER_ID, type State as ProviderState } from '~/logic/wallets/store/reducer/provider'
|
||||||
import safe, { SAFE_REDUCER_ID, type State as SafeState, safesInitialState } from '~/routes/safe/store/reducer/safe'
|
import safe, { SAFE_REDUCER_ID, type State as SafeState } from '~/routes/safe/store/reducer/safe'
|
||||||
import tokens, { TOKEN_REDUCER_ID, type State as TokensState } from '~/logic/tokens/store/reducer/tokens'
|
import tokens, { TOKEN_REDUCER_ID, type State as TokensState } from '~/logic/tokens/store/reducer/tokens'
|
||||||
import transactions, {
|
import transactions, {
|
||||||
type State as TransactionsState,
|
type State as TransactionsState,
|
||||||
|
@ -36,10 +36,6 @@ const reducers: Reducer<GlobalState> = combineReducers({
|
||||||
[TRANSACTIONS_REDUCER_ID]: transactions,
|
[TRANSACTIONS_REDUCER_ID]: transactions,
|
||||||
})
|
})
|
||||||
|
|
||||||
const initialState = {
|
export const store: Store<GlobalState> = createStore(reducers, finalCreateStore)
|
||||||
[SAFE_REDUCER_ID]: safesInitialState(),
|
|
||||||
}
|
|
||||||
|
|
||||||
export const store: Store<GlobalState> = createStore(reducers, initialState, finalCreateStore)
|
|
||||||
|
|
||||||
export const aNewStore = (localState?: Object): Store<GlobalState> => createStore(reducers, localState, finalCreateStore)
|
export const aNewStore = (localState?: Object): Store<GlobalState> => createStore(reducers, localState, finalCreateStore)
|
||||||
|
|
|
@ -40,7 +40,7 @@ describe('Safe - redux load safe', () => {
|
||||||
expect(safe.get('address')).toBe(safeAddress)
|
expect(safe.get('address')).toBe(safeAddress)
|
||||||
expect(safe.get('owners')).toEqual(List([makeOwner({ name: 'UNKNOWN', address: accounts[0] })]))
|
expect(safe.get('owners')).toEqual(List([makeOwner({ name: 'UNKNOWN', address: accounts[0] })]))
|
||||||
|
|
||||||
expect(safesInitialState()).toEqual(safes)
|
expect(await safesInitialState()).toEqual(safes)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('if safe is not present but owners, store and persist it with stored names', async () => {
|
it('if safe is not present but owners, store and persist it with stored names', async () => {
|
||||||
|
@ -64,7 +64,7 @@ describe('Safe - redux load safe', () => {
|
||||||
expect(safe.get('address')).toBe(safeAddress)
|
expect(safe.get('address')).toBe(safeAddress)
|
||||||
expect(safe.get('owners')).toEqual(List([makeOwner({ name: ownerName, address: accounts[0] })]))
|
expect(safe.get('owners')).toEqual(List([makeOwner({ name: ownerName, address: accounts[0] })]))
|
||||||
|
|
||||||
expect(safesInitialState()).toEqual(safes)
|
expect(await safesInitialState()).toEqual(safes)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('if safe is present but no owners, store and persist it with default names', async () => {
|
it('if safe is present but no owners, store and persist it with default names', async () => {
|
||||||
|
@ -86,7 +86,7 @@ describe('Safe - redux load safe', () => {
|
||||||
expect(safe.get('address')).toBe(safeAddress)
|
expect(safe.get('address')).toBe(safeAddress)
|
||||||
expect(safe.get('owners')).toEqual(List([makeOwner({ name: 'UNKNOWN', address: accounts[0] })]))
|
expect(safe.get('owners')).toEqual(List([makeOwner({ name: 'UNKNOWN', address: accounts[0] })]))
|
||||||
|
|
||||||
expect(safesInitialState()).toEqual(safes)
|
expect(await safesInitialState()).toEqual(safes)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('if safe is present but owners, store and persist it with stored names', async () => {
|
it('if safe is present but owners, store and persist it with stored names', async () => {
|
||||||
|
@ -107,6 +107,6 @@ describe('Safe - redux load safe', () => {
|
||||||
expect(safe.get('address')).toBe(safeAddress)
|
expect(safe.get('address')).toBe(safeAddress)
|
||||||
expect(safe.get('owners')).toEqual(List([makeOwner({ name: 'Adol 1 Eth Account', address: accounts[0] })]))
|
expect(safe.get('owners')).toEqual(List([makeOwner({ name: 'Adol 1 Eth Account', address: accounts[0] })]))
|
||||||
|
|
||||||
expect(safesInitialState()).toEqual(safes)
|
expect(await safesInitialState()).toEqual(safes)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -10,20 +10,22 @@ const PREFIX = 'v1'
|
||||||
|
|
||||||
export const loadFromStorage = async (key: string): Promise<*> => {
|
export const loadFromStorage = async (key: string): Promise<*> => {
|
||||||
try {
|
try {
|
||||||
const serializedState = await storage.get(`${PREFIX}__${key}`)
|
const stringifiedValue = await storage.get(`${PREFIX}__${key}`)
|
||||||
if (serializedState === null || serializedState === undefined) {
|
if (stringifiedValue === null || stringifiedValue === undefined) {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSON.parse(serializedState)
|
return JSON.parse(stringifiedValue)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
console.error(`Failed to load ${key} from storage:`, err)
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const saveInStorage = async (key: string, value: string): Promise<*> => {
|
export const saveToStorage = async (key: string, value: *): Promise<*> => {
|
||||||
try {
|
try {
|
||||||
await storage.set(`${PREFIX}__${key}`, value)
|
const stringifiedValue = JSON.stringify(value)
|
||||||
|
await storage.set(`${PREFIX}__${key}`, stringifiedValue)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Failed to save ${key} in the storage:`, err)
|
console.error(`Failed to save ${key} in the storage:`, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { Map } from 'immutable'
|
import { Map } from 'immutable'
|
||||||
import { loadFromStorage } from '~/utils/storage'
|
import { loadFromStorage, saveToStorage } from '~/utils/storage'
|
||||||
|
|
||||||
const getSignaturesKeyFrom = (safeAddress: string) => `TXS-SIGNATURES-${safeAddress}`
|
const getSignaturesKeyFrom = (safeAddress: string) => `TXS-SIGNATURES-${safeAddress}`
|
||||||
|
|
||||||
|
@ -13,8 +13,7 @@ export const storeSignature = async (safeAddress: string, nonce: number, signatu
|
||||||
const existingSignatures = subjects.get(key)
|
const existingSignatures = subjects.get(key)
|
||||||
const signatures = existingSignatures ? existingSignatures + signature : signature
|
const signatures = existingSignatures ? existingSignatures + signature : signature
|
||||||
const updatedSubjects = subjects.set(key, signatures)
|
const updatedSubjects = subjects.set(key, signatures)
|
||||||
const serializedState = JSON.stringify(updatedSubjects)
|
await saveToStorage(signaturesKey, updatedSubjects)
|
||||||
localStorage.setItem(signaturesKey, serializedState)
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
console.log('Error storing signatures in localstorage')
|
console.log('Error storing signatures in localstorage')
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { Map } from 'immutable'
|
import { Map } from 'immutable'
|
||||||
import { loadFromStorage } from '~/utils/storage'
|
import { loadFromStorage, saveToStorage } from '~/utils/storage'
|
||||||
|
|
||||||
const getSubjectKeyFrom = (safeAddress: string) => `TXS-SUBJECTS-${safeAddress}`
|
const getSubjectKeyFrom = (safeAddress: string) => `TXS-SUBJECTS-${safeAddress}`
|
||||||
|
|
||||||
|
@ -10,8 +10,7 @@ export const storeSubject = async (safeAddress: string, nonce: number, subject:
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const updatedSubjects = subjects.set(nonce, subject)
|
const updatedSubjects = subjects.set(nonce, subject)
|
||||||
const serializedState = JSON.stringify(updatedSubjects)
|
saveToStorage(key, updatedSubjects)
|
||||||
localStorage.setItem(key, serializedState)
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
console.log('Error storing transaction subject in localstorage')
|
console.log('Error storing transaction subject in localstorage')
|
||||||
|
|
Loading…
Reference in New Issue