refactor tokensStorage to use immortaldb

This commit is contained in:
Mikhail Mikheev 2019-03-28 19:30:03 +04:00
parent 05c6ffbce7
commit 2a4e72a88e
10 changed files with 311 additions and 163 deletions

391
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -76,8 +76,8 @@
"immutable": "^4.0.0-rc.9", "immutable": "^4.0.0-rc.9",
"material-ui-search-bar": "^1.0.0-beta.13", "material-ui-search-bar": "^1.0.0-beta.13",
"optimize-css-assets-webpack-plugin": "^5.0.1", "optimize-css-assets-webpack-plugin": "^5.0.1",
"react": "^16.8.5", "react": "^16.8.6",
"react-dom": "^16.8.5", "react-dom": "^16.8.6",
"react-final-form": "^4.1.0", "react-final-form": "^4.1.0",
"react-hot-loader": "^4.8.0", "react-hot-loader": "^4.8.0",
"react-infinite-scroll-component": "^4.5.2", "react-infinite-scroll-component": "^4.5.2",

View File

@ -24,7 +24,7 @@ const saveToken = (safeAddress: string, token: Token) => async (dispatch: ReduxD
dispatch(addToken(safeAddress, token)) dispatch(addToken(safeAddress, token))
const activeTokens = await getActiveTokens(safeAddress) const activeTokens = await getActiveTokens(safeAddress)
await setActiveTokens(safeAddress, activeTokens.push(token)) await setActiveTokens(safeAddress, activeTokens.push(token.toJS()))
setToken(safeAddress, token) setToken(safeAddress, token)
} }

View File

@ -12,7 +12,7 @@ import { makeToken, type Token, type TokenProps } from '~/logic/tokens/store/mod
import { ensureOnce } from '~/utils/singleton' import { ensureOnce } from '~/utils/singleton'
import { getActiveTokens, getTokens } from '~/logic/tokens/utils/tokensStorage' import { getActiveTokens, getTokens } from '~/logic/tokens/utils/tokensStorage'
import { getSafeEthToken } from '~/logic/tokens/utils/tokenHelpers' import { getSafeEthToken } from '~/logic/tokens/utils/tokenHelpers'
import addTokens from './addTokens' import saveTokens from './saveTokens'
import { getRelayUrl } from '~/config/index' import { getRelayUrl } from '~/config/index'
const createStandardTokenContract = async () => { const createStandardTokenContract = async () => {
@ -56,7 +56,7 @@ export const fetchTokensData = async () => {
} }
export const fetchTokens = (safeAddress: string) => async (dispatch: ReduxDispatch<GlobalState>) => { export const fetchTokens = (safeAddress: string) => async (dispatch: ReduxDispatch<GlobalState>) => {
const tokens: List<string> = await getActiveTokenAddresses(safeAddress) const tokens: List<TokenProps> = await getActiveTokens(safeAddress)
const ethBalance = await getSafeEthToken(safeAddress) const ethBalance = await getSafeEthToken(safeAddress)
const customTokens = await getTokens(safeAddress) const customTokens = await getTokens(safeAddress)
const { const {
@ -66,7 +66,7 @@ export const fetchTokens = (safeAddress: string) => async (dispatch: ReduxDispat
try { try {
const balancesRecords = await Promise.all( const balancesRecords = await Promise.all(
results.map(async (item: TokenProps) => { results.map(async (item: TokenProps) => {
const status = tokens.includes(item.address) const status = tokens.findIndex(activeToken => activeToken.name === item.name) !== -1
const funds = status ? await calculateBalanceOf(item.address, safeAddress, item.decimals) : '0' const funds = status ? await calculateBalanceOf(item.address, safeAddress, item.decimals) : '0'
return makeToken({ ...item, status, funds }) return makeToken({ ...item, status, funds })
@ -75,7 +75,7 @@ export const fetchTokens = (safeAddress: string) => async (dispatch: ReduxDispat
const customTokenRecords = await Promise.all( const customTokenRecords = await Promise.all(
customTokens.map(async (item: TokenProps) => { customTokens.map(async (item: TokenProps) => {
const status = tokens.includes(item.address) const status = tokens.findIndex(activeToken => activeToken.name === item.name) !== -1
const funds = status ? await calculateBalanceOf(item.address, safeAddress, item.decimals) : '0' const funds = status ? await calculateBalanceOf(item.address, safeAddress, item.decimals) : '0'
return makeToken({ ...item, status, funds }) return makeToken({ ...item, status, funds })
@ -83,13 +83,13 @@ export const fetchTokens = (safeAddress: string) => async (dispatch: ReduxDispat
) )
const balances: Map<string, Token> = Map().withMutations((map) => { const balances: Map<string, Token> = Map().withMutations((map) => {
balancesRecords.forEach(record => map.set(record.get('address'), record)) balancesRecords.forEach(record => map.set(record.address, record))
customTokenRecords.forEach(record => map.set(record.get('address'), record)) customTokenRecords.forEach(record => map.set(record.address, record))
map.set(ethBalance.get('address'), ethBalance) map.set(ethBalance.address, ethBalance)
}) })
return dispatch(addTokens(safeAddress, balances)) return dispatch(saveTokens(safeAddress, balances))
} catch (err) { } catch (err) {
// eslint-disable-next-line // eslint-disable-next-line
console.log('Error fetching tokens... ' + err) console.log('Error fetching tokens... ' + err)

View File

@ -4,7 +4,7 @@ import { handleActions, type ActionType } from 'redux-actions'
import { type Token } from '~/logic/tokens/store/model/token' import { type Token } from '~/logic/tokens/store/model/token'
import { ADD_TOKEN } from '~/logic/tokens/store/actions/addToken' import { ADD_TOKEN } from '~/logic/tokens/store/actions/addToken'
import { REMOVE_TOKEN } from '~/logic/tokens/store/actions/removeToken' import { REMOVE_TOKEN } from '~/logic/tokens/store/actions/removeToken'
import { ADD_TOKENS } from '~/logic/tokens/store/actions/addTokens' import { ADD_TOKENS } from '~/logic/tokens/store/actions/saveTokens'
import { DISABLE_TOKEN } from '~/logic/tokens/store/actions/disableToken' import { DISABLE_TOKEN } from '~/logic/tokens/store/actions/disableToken'
import { ENABLE_TOKEN } from '~/logic/tokens/store/actions/enableToken' import { ENABLE_TOKEN } from '~/logic/tokens/store/actions/enableToken'
@ -38,12 +38,14 @@ export default handleActions<State, *>(
return state.removeIn([safeAddress, tokenAddress]) return state.removeIn([safeAddress, tokenAddress])
}, },
[DISABLE_TOKEN]: (state: State, action: ActionType<Function>): State => { [DISABLE_TOKEN]: (state: State, action: ActionType<Function>): State => {
const { tokenAddress, safeAddress } = action.payload const { safeAddress, token } = action.payload
const { address: tokenAddress } = token
return state.setIn([safeAddress, tokenAddress, 'status'], false) return state.setIn([safeAddress, tokenAddress, 'status'], false)
}, },
[ENABLE_TOKEN]: (state: State, action: ActionType<Function>): State => { [ENABLE_TOKEN]: (state: State, action: ActionType<Function>): State => {
const { tokenAddress, safeAddress } = action.payload const { safeAddress, token } = action.payload
const { address: tokenAddress } = token
return state.setIn([safeAddress, tokenAddress, 'status'], true) return state.setIn([safeAddress, tokenAddress, 'status'], true)
}, },

View File

@ -24,15 +24,12 @@ export const getSafeEthToken = async (safeAddress: string) => {
export const calculateActiveErc20TokensFrom = (tokens: List<Token>) => { export const calculateActiveErc20TokensFrom = (tokens: List<Token>) => {
const addresses = List().withMutations(list => tokens.forEach((token: Token) => { const addresses = List().withMutations(list => tokens.forEach((token: Token) => {
if (isEther(token.get('symbol'))) { const isDeactivated = isEther(token.symbol) || !token.status
if (isDeactivated) {
return return
} }
if (!token.get('status')) { list.push(token)
return
}
list.push(token.address)
})) }))
return addresses return addresses

View File

@ -9,7 +9,7 @@ export const TOKENS_KEY = 'TOKENS'
const getActiveTokensKey = (safeAddress: string) => `${ACTIVE_TOKENS_KEY}-${safeAddress}` const getActiveTokensKey = (safeAddress: string) => `${ACTIVE_TOKENS_KEY}-${safeAddress}`
const getTokensKey = (safeAddress: string) => `${TOKENS_KEY}-${safeAddress}` const getTokensKey = (safeAddress: string) => `${TOKENS_KEY}-${safeAddress}`
export const setActiveTokens = async (safeAddress: string, tokens: List<Token>) => { export const setActiveTokens = async (safeAddress: string, tokens: List<TokenProps>) => {
try { try {
const serializedState = JSON.stringify(tokens.toJS()) const serializedState = JSON.stringify(tokens.toJS())
const key = getActiveTokensKey(safeAddress) const key = getActiveTokensKey(safeAddress)
@ -20,7 +20,7 @@ export const setActiveTokens = async (safeAddress: string, tokens: List<Token>)
} }
} }
export const getActiveTokens = async (safeAddress: string): Promise<List<Token>> => { export const getActiveTokens = async (safeAddress: string): Promise<List<TokenProps>> => {
const key = getActiveTokensKey(safeAddress) const key = getActiveTokensKey(safeAddress)
const data = await ImmortalDB.get(key) const data = await ImmortalDB.get(key)
@ -62,7 +62,10 @@ export const removeTokenFromStorage = async (safeAddress: string, token: Token)
} }
export const removeFromActiveTokens = async (safeAddress: string, token: Token) => { export const removeFromActiveTokens = async (safeAddress: string, token: Token) => {
const activeTokens = await getActiveTokenAddresses(safeAddress) const activeTokens = await getActiveTokens(safeAddress)
const index = activeTokens.indexOf(token) const index = activeTokens.findIndex(activeToken => activeToken.name === token.name)
await setActiveTokens(safeAddress, activeTokens.delete(index))
if (index !== -1) {
await setActiveTokens(safeAddress, activeTokens.delete(index))
}
} }

View File

@ -41,14 +41,8 @@ type State = {
const filterBy = (filter: string, tokens: List<Token>): List<Token> => tokens.filter( const filterBy = (filter: string, tokens: List<Token>): List<Token> => tokens.filter(
(token: Token) => !filter (token: Token) => !filter
|| token || token.symbol.toLowerCase().includes(filter.toLowerCase())
.get('symbol') || token.name.toLowerCase().includes(filter.toLowerCase()),
.toLowerCase()
.includes(filter.toLowerCase())
|| token
.get('name')
.toLowerCase()
.includes(filter.toLowerCase()),
) )
class Tokens extends React.Component<Props, State> { class Tokens extends React.Component<Props, State> {
@ -70,11 +64,9 @@ class Tokens extends React.Component<Props, State> {
if (checked) { if (checked) {
enableToken(safeAddress, token) enableToken(safeAddress, token)
} else {
return disableToken(safeAddress, token)
} }
disableToken(safeAddress, token)
} }
setImageToPlaceholder = (e) => { setImageToPlaceholder = (e) => {
@ -126,18 +118,13 @@ class Tokens extends React.Component<Props, State> {
</Block> </Block>
<MuiList className={classes.list}> <MuiList className={classes.list}>
{filteredTokens.map((token: Token) => ( {filteredTokens.map((token: Token) => (
<ListItem key={token.get('address')} className={classes.token}> <ListItem key={token.address} className={classes.token}>
<ListItemIcon> <ListItemIcon>
<Img <Img src={token.logoUri} height={28} alt={token.name} onError={this.setImageToPlaceholder} />
src={token.get('logoUri')}
height={28}
alt={token.get('name')}
onError={this.setImageToPlaceholder}
/>
</ListItemIcon> </ListItemIcon>
<ListItemText primary={token.get('symbol')} secondary={token.get('name')} /> <ListItemText primary={token.symbol} secondary={token.name} />
<ListItemSecondaryAction> <ListItemSecondaryAction>
<Switch onChange={this.onSwitch(token)} checked={token.get('status')} /> <Switch onChange={this.onSwitch(token)} checked={token.status} />
</ListItemSecondaryAction> </ListItemSecondaryAction>
</ListItem> </ListItem>
))} ))}

View File

@ -7,7 +7,7 @@ import { checkMinedTx, checkPendingTx, EXPAND_BALANCE_INDEX } from '~/test/build
import { whenExecuted } from '~/test/utils/logTransactions' import { whenExecuted } from '~/test/utils/logTransactions'
import SendToken from '~/routes/safe/component/SendToken' import SendToken from '~/routes/safe/component/SendToken'
import { makeToken, type Token } from '~/logic/tokens/store/model/token' import { makeToken, type Token } from '~/logic/tokens/store/model/token'
import addTokens from '~/logic/tokens/store/actions/addTokens' import addTokens from '~/logic/tokens/store/actions/saveTokens'
export const sendMoveTokensForm = async ( export const sendMoveTokensForm = async (
SafeDom: React$Component<any, any>, SafeDom: React$Component<any, any>,