From 2711673f42f76125f4e91f7f0e1e778a081e7b8c Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Wed, 9 Sep 2020 18:56:46 +0400 Subject: [PATCH 1/3] fix currency middleware, actinos, cleanup & bugfix --- .../store/actions/fetchCurrencyValues.ts | 46 ------------------- .../store/actions/fetchSelectedCurrency.ts | 19 ++++++++ .../store/actions/setSelectedCurrency.ts | 13 +++++- .../currencyValues/store/middleware/index.ts | 10 ++-- .../store/utils/currencyValuesStorage.ts | 13 +++--- src/logic/safe/hooks/useFetchTokens.tsx | 4 +- src/logic/safe/store/reducer/safe.ts | 4 +- .../components/CurrencyDropdown/index.tsx | 2 +- 8 files changed, 47 insertions(+), 64 deletions(-) delete mode 100644 src/logic/currencyValues/store/actions/fetchCurrencyValues.ts create mode 100644 src/logic/currencyValues/store/actions/fetchSelectedCurrency.ts diff --git a/src/logic/currencyValues/store/actions/fetchCurrencyValues.ts b/src/logic/currencyValues/store/actions/fetchCurrencyValues.ts deleted file mode 100644 index 79a90fce6d..0000000000 --- a/src/logic/currencyValues/store/actions/fetchCurrencyValues.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { List } from 'immutable' -import { batch } from 'react-redux' - -import { setCurrencyBalances } from 'src/logic/currencyValues/store/actions/setCurrencyBalances' -import { setCurrencyRate } from 'src/logic/currencyValues/store/actions/setCurrencyRate' -import { setSelectedCurrency } from 'src/logic/currencyValues/store/actions/setSelectedCurrency' -import { AVAILABLE_CURRENCIES, CurrencyRateValue } from 'src/logic/currencyValues/store/model/currencyValues' -import { loadCurrencyValues } from 'src/logic/currencyValues/store/utils/currencyValuesStorage' -import { Dispatch } from 'redux' - -export const fetchCurrencyValues = (safeAddress: string) => async ( - dispatch: Dispatch, -): Promise => { - try { - const storedCurrencies = await loadCurrencyValues() - const storedCurrency = storedCurrencies[safeAddress] - if (!storedCurrency) { - return batch(() => { - dispatch(setCurrencyBalances(safeAddress, List([]))) - dispatch(setSelectedCurrency(safeAddress, AVAILABLE_CURRENCIES.USD)) - dispatch(setCurrencyRate(safeAddress, 1)) - }) - } - // Loads the stored state on redux - Object.entries(storedCurrencies).forEach((kv) => { - const safeAddr = kv[0] - const value = kv[1] - - let { currencyRate, selectedCurrency }: CurrencyRateValue = value - - // Fallback for users that got an undefined saved on localStorage - if (!selectedCurrency || selectedCurrency === AVAILABLE_CURRENCIES.USD) { - currencyRate = 1 - selectedCurrency = AVAILABLE_CURRENCIES.USD - } - - batch(() => { - dispatch(setSelectedCurrency(safeAddr, selectedCurrency)) - dispatch(setCurrencyRate(safeAddr, currencyRate)) - }) - }) - } catch (err) { - console.error('Error fetching currency values', err) - } - return Promise.resolve() -} diff --git a/src/logic/currencyValues/store/actions/fetchSelectedCurrency.ts b/src/logic/currencyValues/store/actions/fetchSelectedCurrency.ts new file mode 100644 index 0000000000..42898646b7 --- /dev/null +++ b/src/logic/currencyValues/store/actions/fetchSelectedCurrency.ts @@ -0,0 +1,19 @@ +import { setCurrencyBalances } from 'src/logic/currencyValues/store/actions/setCurrencyBalances' +import { setCurrencyRate } from 'src/logic/currencyValues/store/actions/setCurrencyRate' +import { setSelectedCurrency } from 'src/logic/currencyValues/store/actions/setSelectedCurrency' +import { AVAILABLE_CURRENCIES } from 'src/logic/currencyValues/store/model/currencyValues' +import { loadSelectedCurrency } from 'src/logic/currencyValues/store/utils/currencyValuesStorage' +import { Dispatch } from 'redux' + +export const fetchSelectedCurrency = (safeAddress: string) => async ( + dispatch: Dispatch, +): Promise => { + try { + const storedSelectedCurrency = await loadSelectedCurrency() + + dispatch(setSelectedCurrency(safeAddress, storedSelectedCurrency || AVAILABLE_CURRENCIES.USD)) + } catch (err) { + console.error('Error fetching currency values', err) + } + return Promise.resolve() +} diff --git a/src/logic/currencyValues/store/actions/setSelectedCurrency.ts b/src/logic/currencyValues/store/actions/setSelectedCurrency.ts index ea3f13cafa..3b0774a075 100644 --- a/src/logic/currencyValues/store/actions/setSelectedCurrency.ts +++ b/src/logic/currencyValues/store/actions/setSelectedCurrency.ts @@ -1,12 +1,23 @@ import { createAction } from 'redux-actions' +import { ThunkDispatch } from 'redux-thunk' +import { AnyAction } from 'redux' +import { AppReduxState } from 'src/store' import { AVAILABLE_CURRENCIES } from '../model/currencyValues' +import fetchCurrencyRate from 'src/logic/currencyValues/store/actions/fetchCurrencyRate' export const SET_CURRENT_CURRENCY = 'SET_CURRENT_CURRENCY' -export const setSelectedCurrency = createAction( +const setCurrentCurrency = createAction( SET_CURRENT_CURRENCY, (safeAddress: string, selectedCurrency: AVAILABLE_CURRENCIES) => ({ safeAddress, selectedCurrency, }), ) + +export const setSelectedCurrency = (safeAddress: string, selectedCurrency: AVAILABLE_CURRENCIES) => ( + dispatch: ThunkDispatch, +): void => { + dispatch(setCurrentCurrency(safeAddress, selectedCurrency)) + dispatch(fetchCurrencyRate(safeAddress, selectedCurrency)) +} diff --git a/src/logic/currencyValues/store/middleware/index.ts b/src/logic/currencyValues/store/middleware/index.ts index cc55be57eb..a361f593c8 100644 --- a/src/logic/currencyValues/store/middleware/index.ts +++ b/src/logic/currencyValues/store/middleware/index.ts @@ -1,16 +1,16 @@ -import fetchCurrencyRate from 'src/logic/currencyValues/store/actions/fetchCurrencyRate' import { SET_CURRENT_CURRENCY } from 'src/logic/currencyValues/store/actions/setSelectedCurrency' +import { saveSelectedCurrency } from 'src/logic/currencyValues/store/utils/currencyValuesStorage' const watchedActions = [SET_CURRENT_CURRENCY] -const currencyValuesStorageMiddleware = (store) => (next) => async (action) => { +const currencyValuesStorageMiddleware = () => (next) => async (action) => { const handledAction = next(action) if (watchedActions.includes(action.type)) { - const { dispatch } = store switch (action.type) { case SET_CURRENT_CURRENCY: { - const { safeAddress, selectedCurrency } = action.payload - dispatch(fetchCurrencyRate(safeAddress, selectedCurrency)) + const { selectedCurrency } = action.payload + + saveSelectedCurrency(selectedCurrency) break } diff --git a/src/logic/currencyValues/store/utils/currencyValuesStorage.ts b/src/logic/currencyValues/store/utils/currencyValuesStorage.ts index 0aabece435..ba71634983 100644 --- a/src/logic/currencyValues/store/utils/currencyValuesStorage.ts +++ b/src/logic/currencyValues/store/utils/currencyValuesStorage.ts @@ -1,16 +1,15 @@ import { loadFromStorage, saveToStorage } from 'src/utils/storage' -import { CurrencyRateValue } from '../model/currencyValues' -import { Map } from 'immutable' +import { AVAILABLE_CURRENCIES } from '../model/currencyValues' -const CURRENCY_VALUES_STORAGE_KEY = 'CURRENCY_VALUES_STORAGE_KEY' -export const saveCurrencyValues = async (currencyValues: Map): Promise => { +const SELECTED_CURRENCY_STORAGE_KEY = 'SELECTED_CURRENCY' +export const saveSelectedCurrency = async (selectedCurrency: AVAILABLE_CURRENCIES): Promise => { try { - await saveToStorage(CURRENCY_VALUES_STORAGE_KEY, currencyValues) + await saveToStorage(SELECTED_CURRENCY_STORAGE_KEY, selectedCurrency) } catch (err) { console.error('Error storing currency values info in localstorage', err) } } -export const loadCurrencyValues = async (): Promise> => { - return (await loadFromStorage(CURRENCY_VALUES_STORAGE_KEY)) || {} +export const loadSelectedCurrency = async (): Promise => { + return await loadFromStorage(SELECTED_CURRENCY_STORAGE_KEY) } diff --git a/src/logic/safe/hooks/useFetchTokens.tsx b/src/logic/safe/hooks/useFetchTokens.tsx index 32003528b8..2932d16a19 100644 --- a/src/logic/safe/hooks/useFetchTokens.tsx +++ b/src/logic/safe/hooks/useFetchTokens.tsx @@ -3,7 +3,7 @@ import { batch, useDispatch } from 'react-redux' import { useLocation } from 'react-router-dom' import fetchCollectibles from 'src/logic/collectibles/store/actions/fetchCollectibles' -import { fetchCurrencyValues } from 'src/logic/currencyValues/store/actions/fetchCurrencyValues' +import { fetchSelectedCurrency } from 'src/logic/currencyValues/store/actions/fetchSelectedCurrency' import activateAssetsByBalance from 'src/logic/tokens/store/actions/activateAssetsByBalance' import fetchSafeTokens from 'src/logic/tokens/store/actions/fetchSafeTokens' import { fetchTokens } from 'src/logic/tokens/store/actions/fetchTokens' @@ -19,7 +19,7 @@ export const useFetchTokens = (safeAddress: string): void => { batch(() => { // fetch tokens there to get symbols for tokens in TXs list dispatch(fetchTokens()) - dispatch(fetchCurrencyValues(safeAddress)) + dispatch(fetchSelectedCurrency(safeAddress)) dispatch(fetchSafeTokens(safeAddress)) }) } diff --git a/src/logic/safe/store/reducer/safe.ts b/src/logic/safe/store/reducer/safe.ts index 4b28b145ea..c71314ba3f 100644 --- a/src/logic/safe/store/reducer/safe.ts +++ b/src/logic/safe/store/reducer/safe.ts @@ -51,7 +51,7 @@ export default handleActions( return state.updateIn( ['safes', safeAddress], makeSafe({ name: 'LOADED SAFE', address: safeAddress }), - (prevSafe) => prevSafe.merge(safe), + (prevSafe) => prevSafe.mergeDeep(safe), ) }, [ACTIVATE_TOKEN_FOR_ALL_SAFES]: (state: SafeReducerMap, action) => { @@ -77,7 +77,7 @@ export default handleActions( // with initial props and it would overwrite existing ones if (state.hasIn(['safes', safe.address])) { - return state.updateIn(['safes', safe.address], (prevSafe) => prevSafe.merge(safe)) + return state.updateIn(['safes', safe.address], (prevSafe) => prevSafe.mergeDeep(safe)) } return state.setIn(['safes', safe.address], makeSafe(safe)) diff --git a/src/routes/safe/components/CurrencyDropdown/index.tsx b/src/routes/safe/components/CurrencyDropdown/index.tsx index 08d99d3c38..862c02516e 100644 --- a/src/routes/safe/components/CurrencyDropdown/index.tsx +++ b/src/routes/safe/components/CurrencyDropdown/index.tsx @@ -24,7 +24,7 @@ import etherIcon from 'src/assets/icons/icon_etherTokens.svg' const CurrencyDropdown = (): React.ReactElement | null => { const currenciesList = Object.values(AVAILABLE_CURRENCIES) - const safeAddress = useSelector(safeParamAddressFromStateSelector) + const safeAddress = useSelector(safeParamAddressFromStateSelector) as string const dispatch = useDispatch() const [anchorEl, setAnchorEl] = useState(null) const selectedCurrency = useSelector(currentCurrencySelector) From 82e6804cb79f21dad4b24a928d052e557151b257 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 15 Sep 2020 11:35:01 +0400 Subject: [PATCH 2/3] mergeDeep in reducer --- src/logic/safe/store/reducer/safe.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/logic/safe/store/reducer/safe.ts b/src/logic/safe/store/reducer/safe.ts index 7a1e9b4b69..40f4ece197 100644 --- a/src/logic/safe/store/reducer/safe.ts +++ b/src/logic/safe/store/reducer/safe.ts @@ -51,7 +51,7 @@ export default handleActions( return state.updateIn( ['safes', safeAddress], makeSafe({ name: 'LOADED SAFE', address: safeAddress }), - (prevSafe) => prevSafe.merge(safe), + (prevSafe) => prevSafe.mergeDeep(safe), ) }, [ACTIVATE_TOKEN_FOR_ALL_SAFES]: (state: SafeReducerMap, action) => { @@ -65,7 +65,7 @@ export default handleActions( const safeActiveTokens = map.getIn(['safes', safeAddress, 'activeTokens']) const activeTokens = safeActiveTokens.add(tokenAddress) - map.updateIn(['safes', safeAddress], (prevSafe) => prevSafe.merge({ activeTokens })) + map.updateIn(['safes', safeAddress], (prevSafe) => prevSafe.mergeDeep({ activeTokens })) }) }) }, From c7af266e0a54dd9ee023dd0dbef9d06c116ba0b3 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 15 Sep 2020 15:06:48 +0400 Subject: [PATCH 3/3] dont modify state in add_safe if same already exists --- src/logic/safe/store/reducer/safe.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/logic/safe/store/reducer/safe.ts b/src/logic/safe/store/reducer/safe.ts index 0de8db5755..becddb8320 100644 --- a/src/logic/safe/store/reducer/safe.ts +++ b/src/logic/safe/store/reducer/safe.ts @@ -51,7 +51,7 @@ export default handleActions( return state.updateIn( ['safes', safeAddress], makeSafe({ name: 'LOADED SAFE', address: safeAddress }), - (prevSafe) => prevSafe.mergeDeep(safe), + (prevSafe) => prevSafe.merge(safe), ) }, [ACTIVATE_TOKEN_FOR_ALL_SAFES]: (state: SafeReducerMap, action) => { @@ -77,7 +77,7 @@ export default handleActions( // with initial props and it would overwrite existing ones if (state.hasIn(['safes', safe.address])) { - return state.updateIn(['safes', safe.address], (prevSafe) => prevSafe.merge(safe)) + return state } return state.setIn(['safes', safe.address], makeSafe(safe))