Merge pull request #1041 from gnosis/1013-undefined-error

(Fix) - #1013 undefined error
This commit is contained in:
Mikhail Mikheev 2020-06-30 18:48:33 +04:00 committed by GitHub
commit a8483a97da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 75 additions and 95 deletions

View File

@ -1,6 +1,12 @@
import { Record } from 'immutable'
export const makeAddressBookEntry = Record({
export interface AddressBookEntryProps {
address: string
name: string
isOwner: boolean
}
export const makeAddressBookEntry = Record<AddressBookEntryProps>({
address: '',
name: '',
isOwner: false,

View File

@ -1,4 +1,4 @@
import { List, Map } from 'immutable'
import { List } from 'immutable'
import { loadAddressBook } from 'src/logic/addressBook/store/actions/loadAddressBook'
import { buildAddressBook } from 'src/logic/addressBook/store/reducer/addressBook'
@ -8,11 +8,12 @@ import { safesListSelector } from 'src/routes/safe/store/selectors'
const loadAddressBookFromStorage = () => async (dispatch, getState) => {
try {
const state = getState()
let addressBook = await getAddressBookFromStorage()
if (!addressBook) {
addressBook = Map([])
let storedAdBk = await getAddressBookFromStorage()
if (!storedAdBk) {
storedAdBk = []
}
addressBook = buildAddressBook(addressBook)
let addressBook = buildAddressBook(storedAdBk)
// Fetch all the current safes, in case that we don't have a safe on the adbk, we add it
const safes = safesListSelector(state)
const adbkEntries = addressBook.keySeq().toArray()

View File

@ -1,11 +1,12 @@
import { loadFromStorage, saveToStorage } from 'src/utils/storage'
import { AddressBookEntryProps } from './../model/addressBook'
const ADDRESS_BOOK_STORAGE_KEY = 'ADDRESS_BOOK_STORAGE_KEY'
export const getAddressBookFromStorage = async () => {
const data = await loadFromStorage(ADDRESS_BOOK_STORAGE_KEY)
export const getAddressBookFromStorage = async (): Promise<Array<AddressBookEntryProps> | undefined> => {
const data = await loadFromStorage<Array<AddressBookEntryProps>>(ADDRESS_BOOK_STORAGE_KEY)
return data || []
return data
}
export const saveAddressBook = async (addressBook) => {

View File

@ -27,8 +27,8 @@ export const getLocalSafe = async (safeAddress) => {
return storedSafes[safeAddress]
}
export const getDefaultSafe = async () => {
const defaultSafe = await loadFromStorage(DEFAULT_SAFE_KEY)
export const getDefaultSafe = async (): Promise<string> => {
const defaultSafe = await loadFromStorage<string>(DEFAULT_SAFE_KEY)
return defaultSafe || ''
}

View File

@ -7,7 +7,7 @@ import { getActiveTokens } from 'src/logic/tokens/utils/tokensStorage'
const loadActiveTokens = () => async (dispatch) => {
try {
const tokens = await getActiveTokens()
const tokens = (await getActiveTokens()) || {}
// The filter of strings was made because of the issue #751. Please see: https://github.com/gnosis/safe-react/pull/755#issuecomment-612969340
const tokenRecordsList = List(
Object.values(tokens)

View File

@ -1,19 +0,0 @@
import { createAction } from 'redux-actions'
import { removeFromActiveTokens, removeTokenFromStorage } from 'src/logic/tokens/utils/tokensStorage'
export const REMOVE_TOKEN = 'REMOVE_TOKEN'
export const removeToken = createAction(REMOVE_TOKEN, (safeAddress, token) => ({
safeAddress,
token,
}))
const deleteToken = (safeAddress, token) => async (dispatch) => {
dispatch(removeToken(safeAddress, token))
await removeFromActiveTokens(safeAddress, token)
await removeTokenFromStorage(safeAddress, token)
}
export default deleteToken

View File

@ -2,7 +2,6 @@ import { Map } from 'immutable'
import { handleActions } from 'redux-actions'
import { ADD_TOKEN } from 'src/logic/tokens/store/actions/addToken'
import { REMOVE_TOKEN } from 'src/logic/tokens/store/actions/removeToken'
import { ADD_TOKENS } from 'src/logic/tokens/store/actions/saveTokens'
import { makeToken } from 'src/logic/tokens/store/model/token'
@ -27,12 +26,6 @@ export default handleActions(
return state.set(tokenAddress, makeToken(token))
},
[REMOVE_TOKEN]: (state, action) => {
const { token } = action.payload
const { address: tokenAddress } = token
return state.remove(tokenAddress)
},
},
Map(),
)

View File

@ -1,6 +1,7 @@
import { List } from 'immutable'
import { Map } from 'immutable'
import { loadFromStorage, saveToStorage } from 'src/utils/storage'
import { TokenProps, Token } from './../store/model/token'
export const ACTIVE_TOKENS_KEY = 'ACTIVE_TOKENS'
export const CUSTOM_TOKENS_KEY = 'CUSTOM_TOKENS'
@ -9,42 +10,16 @@ export const CUSTOM_TOKENS_KEY = 'CUSTOM_TOKENS'
// to avoid iterating a large amount of data of tokens from the backend
// Custom tokens should be saved too unless they're deleted (marking them as inactive doesn't count)
export const saveActiveTokens = async (tokens) => {
export const saveActiveTokens = async (tokens: Map<string, Token>): Promise<void> => {
try {
await saveToStorage(ACTIVE_TOKENS_KEY, tokens.toJS())
await saveToStorage(ACTIVE_TOKENS_KEY, tokens.toJS() as Record<string, TokenProps>)
} catch (err) {
console.error('Error storing tokens in localstorage', err)
}
}
export const getActiveTokens = async () => {
const data = await loadFromStorage(ACTIVE_TOKENS_KEY)
export const getActiveTokens = async (): Promise<Record<string, TokenProps> | undefined> => {
const data = await loadFromStorage<Record<string, TokenProps>>(ACTIVE_TOKENS_KEY)
return data || {}
}
export const getCustomTokens = async () => {
const data = await loadFromStorage(CUSTOM_TOKENS_KEY)
return data ? List(data) : List()
}
export const removeTokenFromStorage = async (safeAddress, token) => {
const data = await getCustomTokens()
try {
const index = data.indexOf(token)
await saveToStorage(CUSTOM_TOKENS_KEY, data.remove(index))
} catch (err) {
console.error('Error removing token in localstorage', err)
}
}
export const removeFromActiveTokens = async (safeAddress, token) => {
const activeTokens = await getActiveTokens()
const index = activeTokens.findIndex((activeToken) => activeToken.name === token.name)
if (index !== -1) {
await saveActiveTokens(safeAddress)
}
return data
}

View File

@ -10,10 +10,10 @@ const watchedActions = [ADD_PROVIDER, REMOVE_PROVIDER]
const LAST_USED_PROVIDER_KEY = 'LAST_USED_PROVIDER'
export const loadLastUsedProvider = async () => {
const lastUsedProvider = await loadFromStorage(LAST_USED_PROVIDER_KEY)
export const loadLastUsedProvider = async (): Promise<string | undefined> => {
const lastUsedProvider = await loadFromStorage<string>(LAST_USED_PROVIDER_KEY)
return lastUsedProvider || ''
return lastUsedProvider
}
let watcherInterval = null

View File

@ -7,6 +7,7 @@ import { LOAD_ADDRESS, OPEN_ADDRESS, SAFELIST_ADDRESS, SAFE_PARAM_ADDRESS, WELCO
import Loader from 'src/components/Loader'
import { defaultSafeSelector } from 'src/routes/safe/store/selectors'
import { useAnalytics } from 'src/utils/googleAnalytics'
import { DEFAULT_SAFE_INITIAL_STATE } from 'src/routes/safe/store/reducer/safe'
const Welcome = React.lazy(() => import('./welcome/container'))
@ -44,7 +45,7 @@ const Routes = ({ location }) => {
return <Redirect to={WELCOME_ADDRESS} />
}
if (typeof defaultSafe === 'undefined') {
if (defaultSafe === DEFAULT_SAFE_INITIAL_STATE) {
return <Loader />
}

View File

@ -16,17 +16,25 @@ import { SAFELIST_ADDRESS } from 'src/routes/routes'
import { buildSafe } from 'src/routes/safe/store/actions/fetchSafe'
import { history } from 'src/store'
import { loadFromStorage } from 'src/utils/storage'
import { Dispatch } from 'redux'
import { SafeOwner } from '../../safe/store/models/safe'
import { List } from 'immutable'
export const loadSafe = async (safeName, safeAddress, owners, addSafe) => {
export const loadSafe = async (
safeName: string,
safeAddress: string,
owners: List<SafeOwner>,
addSafe: Dispatch<any>,
): Promise<void> => {
const safeProps = await buildSafe(safeAddress, safeName)
safeProps.owners = owners
await addSafe(safeProps)
const storedSafes = (await loadFromStorage(SAFES_KEY)) || {}
storedSafes[safeAddress] = safeProps
saveSafes(storedSafes)
await saveSafes(storedSafes)
await addSafe(safeProps)
}
class Load extends React.Component<any> {

View File

@ -103,7 +103,7 @@ const Open = ({ addSafe, network, provider, userAccount }) => {
// check if there is a safe being created
useEffect(() => {
const load = async () => {
const pendingCreation = await loadFromStorage(SAFE_PENDING_CREATION_STORAGE_KEY)
const pendingCreation = await loadFromStorage<{ txHash: string }>(SAFE_PENDING_CREATION_STORAGE_KEY)
if (pendingCreation && pendingCreation.txHash) {
setSafeCreationPendingInfo(pendingCreation)
setShowProgress(true)
@ -133,7 +133,7 @@ const Open = ({ addSafe, network, provider, userAccount }) => {
}
const onSafeCreated = async (safeAddress) => {
const pendingCreation = await loadFromStorage(SAFE_PENDING_CREATION_STORAGE_KEY)
const pendingCreation = await loadFromStorage<{ txHash: string }>(SAFE_PENDING_CREATION_STORAGE_KEY)
const name = getSafeNameFrom(pendingCreation)
const ownersNames = getNamesFrom(pendingCreation)
@ -167,7 +167,7 @@ const Open = ({ addSafe, network, provider, userAccount }) => {
}
const onRetry = async () => {
const values = await loadFromStorage(SAFE_PENDING_CREATION_STORAGE_KEY)
const values = await loadFromStorage<{ txHash: string }>(SAFE_PENDING_CREATION_STORAGE_KEY)
delete values.txHash
await saveToStorage(SAFE_PENDING_CREATION_STORAGE_KEY, values)
setSafeCreationPendingInfo(values)

View File

@ -1,6 +1,7 @@
import { List } from 'immutable'
import { makeOwner } from 'src/routes/safe/store/models/owner'
import { SafeOwner } from '../../safe/store/models/safe'
export const getAccountsFrom = (values) => {
const accounts = Object.keys(values)
@ -18,7 +19,7 @@ export const getNamesFrom = (values) => {
return accounts.map((account) => values[account]).slice(0, values.owners)
}
export const getOwnersFrom = (names, addresses) => {
export const getOwnersFrom = (names, addresses): List<SafeOwner> => {
const owners = names.map((name, index) => makeOwner({ name, address: addresses[index] }))
return List(owners)

View File

@ -21,7 +21,7 @@ import {
} from 'src/routes/safe/store/selectors'
import { loadFromStorage, saveToStorage } from 'src/utils/storage'
import { isSameHref } from 'src/utils/url'
import { SafeApp } from './types'
import { SafeApp, StoredSafeApp } from './types'
const APPS_STORAGE_KEY = 'APPS_STORAGE_KEY'
const APPS_LEGAL_DISCLAIMER_STORAGE_KEY = 'APPS_LEGAL_DISCLAIMER_STORAGE_KEY'
@ -195,7 +195,7 @@ function Apps({ closeModal, closeSnackbar, enqueueSnackbar, openModal }) {
setAppList(copyAppList)
// update storage list
const persistedAppList = (await loadFromStorage(APPS_STORAGE_KEY)) || []
const persistedAppList = (await loadFromStorage<StoredSafeApp[]>(APPS_STORAGE_KEY)) || []
let storageApp = persistedAppList.find((a) => a.url === app.url)
if (!storageApp) {
@ -303,7 +303,7 @@ function Apps({ closeModal, closeSnackbar, enqueueSnackbar, openModal }) {
// recover apps from storage:
// * third-party apps added by the user
// * disabled status for both static and third-party apps
const persistedAppList = (await loadFromStorage(APPS_STORAGE_KEY)) || []
const persistedAppList = (await loadFromStorage<StoredSafeApp[]>(APPS_STORAGE_KEY)) || []
const list = [...persistedAppList]
staticAppsList.forEach((staticApp) => {

View File

@ -6,3 +6,8 @@ export type SafeApp = {
disabled?: boolean
error: boolean
}
export type StoredSafeApp = {
url: string
disabled?: boolean
}

View File

@ -13,6 +13,7 @@ import updateSafe from 'src/routes/safe/store/actions/updateSafe'
import { makeOwner } from 'src/routes/safe/store/models/owner'
import { checksumAddress } from 'src/utils/checksumAddress'
import { SafeOwner } from '../models/safe'
const buildOwnersFrom = (
safeOwners,
@ -51,7 +52,7 @@ export const buildSafe = async (safeAdd, safeName, latestMasterContractVersion?:
const threshold = Number(thresholdStr)
const nonce = Number(nonceStr)
const owners = List(buildOwnersFrom(remoteOwners, localSafe))
const owners = List<SafeOwner>(buildOwnersFrom(remoteOwners, localSafe))
const needsUpdate = safeNeedsUpdate(currentVersion, latestMasterContractVersion)
const featuresEnabled = enabledFeatures(currentVersion)

View File

@ -38,7 +38,7 @@ const sendAwaitingTransactionNotification = async (
return
}
let lastTimeUserLoggedInForSafes = (await loadFromStorage(LAST_TIME_USED_LOGGED_IN_ID)) || []
let lastTimeUserLoggedInForSafes = (await loadFromStorage<Record<string, string>>(LAST_TIME_USED_LOGGED_IN_ID)) || {}
const lastTimeUserLoggedIn =
lastTimeUserLoggedInForSafes && lastTimeUserLoggedInForSafes[safeAddress]
? lastTimeUserLoggedInForSafes[safeAddress]

View File

@ -1,10 +1,15 @@
import { List, Map, Record, RecordOf, Set } from 'immutable'
export type SafeOwner = {
name: string
address: string
}
export type SafeRecordProps = {
name: string
address: string
threshold: number
ethBalance: number
ethBalance: string
owners: List<{ name: string; address: string }>
activeTokens: Set<string>
activeAssets: Set<string>
@ -23,7 +28,7 @@ const makeSafe = Record<SafeRecordProps>({
name: '',
address: '',
threshold: 0,
ethBalance: 0,
ethBalance: '0',
owners: List([]),
activeTokens: Set(),
activeAssets: Set(),

View File

@ -16,6 +16,7 @@ import makeSafe from 'src/routes/safe/store/models/safe'
import { checksumAddress } from 'src/utils/checksumAddress'
export const SAFE_REDUCER_ID = 'safes'
export const DEFAULT_SAFE_INITIAL_STATE = 'NOT_ASKED'
export const buildSafe = (storedSafe) => {
const names = storedSafe.owners.map((owner) => owner.name)
@ -125,10 +126,8 @@ export default handleActions(
[SET_LATEST_MASTER_CONTRACT_VERSION]: (state, action) => state.set('latestMasterContractVersion', action.payload),
},
Map({
// $FlowFixMe
defaultSafe: undefined,
defaultSafe: DEFAULT_SAFE_INITIAL_STATE,
safes: Map(),
// $FlowFixMe
latestMasterContractVersion: '',
}),
)

View File

@ -10,7 +10,7 @@ export const storage = new ImmortalStorage(stores)
const PREFIX = `v2_${getNetwork()}`
export const loadFromStorage = async (key) => {
export const loadFromStorage = async <T = unknown>(key: string): Promise<T | undefined> => {
try {
const stringifiedValue = await storage.get(`${PREFIX}__${key}`)
if (stringifiedValue === null || stringifiedValue === undefined) {
@ -24,7 +24,10 @@ export const loadFromStorage = async (key) => {
}
}
export const saveToStorage = async (key, value) => {
export const saveToStorage = async (
key: string,
value: Record<string, unknown> | boolean | string | number | Array<unknown>,
): Promise<void> => {
try {
const stringifiedValue = JSON.stringify(value)
await storage.set(`${PREFIX}__${key}`, stringifiedValue)
@ -33,7 +36,7 @@ export const saveToStorage = async (key, value) => {
}
}
export const removeFromStorage = async (key) => {
export const removeFromStorage = async (key: string): Promise<void> => {
try {
await storage.remove(`${PREFIX}__${key}`)
} catch (err) {