WA-234 Loading safes info from Ethereum Node
This commit is contained in:
parent
3428329398
commit
aec0b50200
|
@ -10,8 +10,12 @@ import PageFrame from '~/components/layout/PageFrame'
|
||||||
import { history, store } from '~/store'
|
import { history, store } from '~/store'
|
||||||
import theme from '~/theme/mui'
|
import theme from '~/theme/mui'
|
||||||
import AppRoutes from '~/routes'
|
import AppRoutes from '~/routes'
|
||||||
|
import fetchSafes from '~/routes/safe/store/actions/fetchSafes'
|
||||||
|
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
|
|
||||||
|
store.dispatch(fetchSafes())
|
||||||
|
|
||||||
const Root = () => (
|
const Root = () => (
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<MuiThemeProvider theme={theme}>
|
<MuiThemeProvider theme={theme}>
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
// @flow
|
||||||
|
import type { Dispatch as ReduxDispatch } from 'redux'
|
||||||
|
import { List, Map } from 'immutable'
|
||||||
|
import { type GlobalState } from '~/store/index'
|
||||||
|
import { makeOwner } from '~/routes/safe/store/model/owner'
|
||||||
|
import { type SafeProps, type Safe, makeSafe } from '~/routes/safe/store/model/safe'
|
||||||
|
import { makeDailyLimit } from '~/routes/safe/store/model/dailyLimit'
|
||||||
|
import { getDailyLimitFrom } from '~/routes/safe/component/Withdrawn/withdrawn'
|
||||||
|
import { getGnosisSafeInstanceAt } from '~/wallets/safeContracts'
|
||||||
|
import { load, SAFES_KEY } from '~/utils/localStorage'
|
||||||
|
import updateSafes from '~/routes/safe/store/actions/updateSafes'
|
||||||
|
|
||||||
|
const buildOwnersFrom = (safeOwners: string[], storedOwners: Object[]) => (
|
||||||
|
safeOwners.map((ownerAddress: string) => {
|
||||||
|
const foundOwner = storedOwners.find(owner => owner.address === ownerAddress)
|
||||||
|
return makeOwner(foundOwner || { name: 'UNKNOWN', address: ownerAddress })
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const buildSafe = async (storedSafe: Object) => {
|
||||||
|
const safeAddress = storedSafe.address
|
||||||
|
const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress)
|
||||||
|
|
||||||
|
const dailyLimit = makeDailyLimit(await getDailyLimitFrom(safeAddress, 0))
|
||||||
|
const threshold = Number(await gnosisSafe.getThreshold())
|
||||||
|
const owners = List(buildOwnersFrom(await gnosisSafe.getOwners(), storedSafe.owners))
|
||||||
|
|
||||||
|
const safe: SafeProps = {
|
||||||
|
address: safeAddress,
|
||||||
|
dailyLimit,
|
||||||
|
name: storedSafe.name,
|
||||||
|
threshold,
|
||||||
|
owners,
|
||||||
|
}
|
||||||
|
|
||||||
|
return makeSafe(safe)
|
||||||
|
}
|
||||||
|
|
||||||
|
const buildSafesFrom = async (loadedSafes: Object): Promise<Map<string, Safe>> => {
|
||||||
|
const safes = Map()
|
||||||
|
|
||||||
|
const keys = Object.keys(loadedSafes)
|
||||||
|
const safeRecords = await Promise.all(keys.map((address: string) => buildSafe(loadedSafes[address])))
|
||||||
|
|
||||||
|
return safes.withMutations(async (map) => {
|
||||||
|
safeRecords.forEach((safe: Safe) => map.set(safe.get('address'), safe))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default () => async (dispatch: ReduxDispatch<GlobalState>) => {
|
||||||
|
const storedSafes = load(SAFES_KEY)
|
||||||
|
const safes = storedSafes ? await buildSafesFrom(storedSafes) : Map()
|
||||||
|
|
||||||
|
return dispatch(updateSafes(safes))
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
// @flow
|
||||||
|
import { createAction } from 'redux-actions'
|
||||||
|
|
||||||
|
export const UPDATE_SAFES = 'UPDATE_SAFES'
|
||||||
|
|
||||||
|
const updateSafesInBatch = createAction(UPDATE_SAFES)
|
||||||
|
|
||||||
|
export default updateSafesInBatch
|
|
@ -1,37 +1,18 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { Map, List } from 'immutable'
|
import { Map } from 'immutable'
|
||||||
import { handleActions, type ActionType } from 'redux-actions'
|
import { handleActions, type ActionType } from 'redux-actions'
|
||||||
import addSafe, { ADD_SAFE } from '~/routes/safe/store/actions/addSafe'
|
import addSafe, { ADD_SAFE } from '~/routes/safe/store/actions/addSafe'
|
||||||
import updateDailyLimit, { UPDATE_DAILY_LIMIT } from '~/routes/safe/store/actions/updateDailyLimit'
|
import updateDailyLimit, { UPDATE_DAILY_LIMIT } from '~/routes/safe/store/actions/updateDailyLimit'
|
||||||
import { makeOwner } from '~/routes/safe/store/model/owner'
|
|
||||||
import { type Safe, makeSafe } from '~/routes/safe/store/model/safe'
|
import { type Safe, makeSafe } from '~/routes/safe/store/model/safe'
|
||||||
import { load, saveSafes, SAFES_KEY } from '~/utils/localStorage'
|
import { saveSafes } from '~/utils/localStorage'
|
||||||
import { makeDailyLimit } from '~/routes/safe/store/model/dailyLimit'
|
import { makeDailyLimit } from '~/routes/safe/store/model/dailyLimit'
|
||||||
import updateThreshold, { UPDATE_THRESHOLD } from '~/routes/safe/store/actions/updateThreshold'
|
import updateThreshold, { UPDATE_THRESHOLD } from '~/routes/safe/store/actions/updateThreshold'
|
||||||
|
import updateSafes, { UPDATE_SAFES } from '~/routes/safe/store/actions/updateSafes'
|
||||||
|
|
||||||
export const SAFE_REDUCER_ID = 'safes'
|
export const SAFE_REDUCER_ID = 'safes'
|
||||||
|
|
||||||
export type State = Map<string, Safe>
|
export type State = Map<string, Safe>
|
||||||
|
|
||||||
const buildSafesFrom = (loadedSafes: Object): State => {
|
|
||||||
const safes: State = Map()
|
|
||||||
|
|
||||||
return safes.withMutations((map: State) => {
|
|
||||||
Object.keys(loadedSafes).forEach((address) => {
|
|
||||||
const safe = loadedSafes[address]
|
|
||||||
safe.owners = List(safe.owners.map((owner => makeOwner(owner))))
|
|
||||||
safe.dailyLimit = makeDailyLimit({ value: safe.dailyLimit.value, spentToday: safe.dailyLimit.spentToday })
|
|
||||||
return map.set(address, makeSafe(safe))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export const safeInitialState = (): State => {
|
|
||||||
const storedSafes = load(SAFES_KEY)
|
|
||||||
|
|
||||||
return storedSafes ? buildSafesFrom(storedSafes) : Map()
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
type Action<T> = {
|
type Action<T> = {
|
||||||
key: string,
|
key: string,
|
||||||
|
@ -44,6 +25,8 @@ action: AddSafeType
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default handleActions({
|
export default handleActions({
|
||||||
|
[UPDATE_SAFES]: (state: State, action: ActionType<typeof updateSafes>): State =>
|
||||||
|
action.payload,
|
||||||
[ADD_SAFE]: (state: State, action: ActionType<typeof addSafe>): State => {
|
[ADD_SAFE]: (state: State, action: ActionType<typeof addSafe>): State => {
|
||||||
const safes = state.set(action.payload.address, makeSafe(action.payload))
|
const safes = state.set(action.payload.address, makeSafe(action.payload))
|
||||||
saveSafes(safes.toJSON())
|
saveSafes(safes.toJSON())
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { combineReducers, createStore, applyMiddleware, compose } from 'redux'
|
import { combineReducers, createStore, applyMiddleware, compose } from 'redux'
|
||||||
import thunk from 'redux-thunk'
|
import thunk from 'redux-thunk'
|
||||||
import safeReducer, { safeInitialState, SAFE_REDUCER_ID } from '~/routes/safe/store/reducer/safe'
|
import safeReducer, { SAFE_REDUCER_ID } from '~/routes/safe/store/reducer/safe'
|
||||||
import addSafe from '~/routes/safe/store/actions/addSafe'
|
import addSafe from '~/routes/safe/store/actions/addSafe'
|
||||||
import * as SafeFields from '~/routes/open/components/fields'
|
import * as SafeFields from '~/routes/open/components/fields'
|
||||||
import { getAccountsFrom, getNamesFrom } from '~/routes/open/utils/safeDataExtractor'
|
import { getAccountsFrom, getNamesFrom } from '~/routes/open/utils/safeDataExtractor'
|
||||||
|
@ -56,26 +56,6 @@ const providerReducerTests = () => {
|
||||||
// THEN
|
// THEN
|
||||||
expect(safes.get(address)).toEqual(SafeFactory.oneOwnerSafe())
|
expect(safes.get(address)).toEqual(SafeFactory.oneOwnerSafe())
|
||||||
})
|
})
|
||||||
|
|
||||||
it('reducer loads information from localStorage', async () => {
|
|
||||||
// GIVEN in beforeEach method
|
|
||||||
|
|
||||||
// WHEN
|
|
||||||
store.dispatch(addSafe(
|
|
||||||
formValues[SafeFields.FIELD_NAME],
|
|
||||||
formValues.address,
|
|
||||||
formValues[SafeFields.FIELD_CONFIRMATIONS],
|
|
||||||
formValues[SafeFields.FIELD_DAILY_LIMIT],
|
|
||||||
getNamesFrom(formValues),
|
|
||||||
getAccountsFrom(formValues),
|
|
||||||
))
|
|
||||||
|
|
||||||
const anotherStore = aStore({ [SAFE_REDUCER_ID]: safeInitialState() })
|
|
||||||
const safes = anotherStore.getState()[SAFE_REDUCER_ID]
|
|
||||||
|
|
||||||
// THEN
|
|
||||||
expect(safeInitialState()).toEqual(safes)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { routerMiddleware, routerReducer } from 'react-router-redux'
|
||||||
import { combineReducers, createStore, applyMiddleware, compose, type Reducer, type Store } from 'redux'
|
import { combineReducers, createStore, applyMiddleware, compose, type Reducer, type Store } from 'redux'
|
||||||
import thunk from 'redux-thunk'
|
import thunk from 'redux-thunk'
|
||||||
import provider, { PROVIDER_REDUCER_ID, type State as ProviderState } from '~/wallets/store/reducer/provider'
|
import provider, { PROVIDER_REDUCER_ID, type State as ProviderState } from '~/wallets/store/reducer/provider'
|
||||||
import safe, { SAFE_REDUCER_ID, safeInitialState, type State as SafeState } from '~/routes/safe/store/reducer/safe'
|
import safe, { SAFE_REDUCER_ID, type State as SafeState } from '~/routes/safe/store/reducer/safe'
|
||||||
import balances, { BALANCE_REDUCER_ID, type State as BalancesState } from '~/routes/safe/store/reducer/balances'
|
import balances, { BALANCE_REDUCER_ID, type State as BalancesState } from '~/routes/safe/store/reducer/balances'
|
||||||
import transactions, { type State as TransactionsState, transactionsInitialState, TRANSACTIONS_REDUCER_ID } from '~/routes/safe/store/reducer/transactions'
|
import transactions, { type State as TransactionsState, transactionsInitialState, TRANSACTIONS_REDUCER_ID } from '~/routes/safe/store/reducer/transactions'
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@ const reducers: Reducer<GlobalState> = combineReducers({
|
||||||
})
|
})
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
[SAFE_REDUCER_ID]: safeInitialState(),
|
|
||||||
[TRANSACTIONS_REDUCER_ID]: transactionsInitialState(),
|
[TRANSACTIONS_REDUCER_ID]: transactionsInitialState(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue