WA-232 fetching balance of activated custom tokens

This commit is contained in:
apanizo 2018-07-18 12:14:38 +02:00
parent 95caa29f69
commit da6345b1cc
7 changed files with 73 additions and 30 deletions

View File

@ -6,6 +6,7 @@ import FirstPage, { TOKEN_ADDRESS_PARAM } from '~/routes/tokens/component/AddTok
import SecondPage, { TOKEN_SYMBOL_PARAM, TOKEN_DECIMALS_PARAM, TOKEN_LOGO_URL_PARAM, TOKEN_NAME_PARAM } from '~/routes/tokens/component/AddToken/SecondPage'
import { makeToken, type Token } from '~/routes/tokens/store/model/token'
import addTokenAction from '~/routes/tokens/store/actions/addTokens'
import enableTokenAction from '~/routes/tokens/store/actions/enabletoken'
import Review from './Review'
export const getSteps = () => [
@ -15,7 +16,8 @@ export const getSteps = () => [
type Props = {
tokens: string[],
safeAddress: string,
addToken: typeof addTokenAction
addToken: typeof addTokenAction,
enableToken: typeof enableTokenAction,
}
type State = {
@ -24,7 +26,7 @@ type State = {
export const ADD_TOKEN_RESET_BUTTON_TEXT = 'RESET'
export const addTokenFnc = async (values: Object, addToken, safeAddress: string) => {
export const addTokenFnc = async (values: Object, addToken, enableToken, safeAddress: string) => {
const address = values[TOKEN_ADDRESS_PARAM]
const name = values[TOKEN_NAME_PARAM]
const symbol = values[TOKEN_SYMBOL_PARAM]
@ -41,6 +43,7 @@ export const addTokenFnc = async (values: Object, addToken, safeAddress: string)
removable: true,
})
await enableToken(safeAddress, token)
return addToken(safeAddress, token)
}
@ -50,9 +53,9 @@ class AddToken extends React.Component<Props, State> {
}
onAddToken = async (values: Object) => {
const { addToken, safeAddress } = this.props
const { addToken, enableToken, safeAddress } = this.props
return addTokenFnc(values, addToken, safeAddress)
return addTokenFnc(values, addToken, enableToken, safeAddress)
}
onReset = () => {

View File

@ -38,10 +38,17 @@ class TokenLayout extends React.PureComponent<TokenProps, State> {
}
onAddToken = () => {
const { addresses, safeAddress, addToken } = this.props
const {
addresses, safeAddress, addToken, enableToken,
} = this.props
this.setState({
component: <AddToken addToken={addToken} tokens={addresses.toArray()} safeAddress={safeAddress} />,
component: <AddToken
addToken={addToken}
enableToken={enableToken}
tokens={addresses.toArray()}
safeAddress={safeAddress}
/>,
})
}

View File

@ -8,7 +8,7 @@ import { getWeb3 } from '~/wallets/getWeb3'
import { type GlobalState } from '~/store/index'
import { makeToken, type Token, type TokenProps } from '~/routes/tokens/store/model/token'
import { ensureOnce } from '~/utils/singleton'
import { getTokens } from '~/utils/localStorage/tokens'
import { getActiveTokenAddresses, getTokens } from '~/utils/localStorage/tokens'
import { getSafeEthToken } from '~/utils/tokens'
import { enhancedFetch } from '~/utils/fetch'
import addTokens from './addTokens'
@ -48,9 +48,9 @@ export const fetchTokensData = async () => {
export const fetchTokens = (safeAddress: string) =>
async (dispatch: ReduxDispatch<GlobalState>) => {
const tokens: List<string> = getTokens(safeAddress)
const tokens: List<string> = getActiveTokenAddresses(safeAddress)
const ethBalance = await getSafeEthToken(safeAddress)
const customTokens = getTokens(safeAddress)
const json = await exports.fetchTokensData()
try {
@ -61,10 +61,18 @@ export const fetchTokens = (safeAddress: string) =>
return makeToken({ ...item, status, funds })
}))
const customTokenRecords = await Promise.all(customTokens.map(async (item: TokenProps) => {
const status = tokens.includes(item.address)
const funds = status ? await calculateBalanceOf(item.address, safeAddress, item.decimals) : '0'
return makeToken({ ...item, status, funds })
}))
const balances: Map<string, Token> = Map().withMutations((map) => {
balancesRecords.forEach(record => map.set(record.get('address'), record))
customTokenRecords.forEach(record => map.set(record.get('address'), record))
map.set('ETH', ethBalance)
map.set(ethBalance.get('address'), ethBalance)
})
return dispatch(addTokens(safeAddress, balances))

View File

@ -6,7 +6,7 @@ import addTokens, { ADD_TOKENS } from '~/routes/tokens/store/actions/addTokens'
import { type Token } from '~/routes/tokens/store/model/token'
import disableToken, { DISABLE_TOKEN } from '~/routes/tokens/store/actions/disableToken'
import enableToken, { ENABLE_TOKEN } from '~/routes/tokens/store/actions/enableToken'
import { setTokens, getTokens } from '~/utils/localStorage/tokens'
import { setActiveTokenAddresses, getActiveTokenAddresses } from '~/utils/localStorage/tokens'
import { ensureOnce } from '~/utils/singleton'
import { calculateActiveErc20TokensFrom } from '~/utils/tokens'
@ -14,7 +14,7 @@ export const TOKEN_REDUCER_ID = 'tokens'
export type State = Map<string, Map<string, Token>>
const setTokensOnce = ensureOnce(setTokens)
const setTokensOnce = ensureOnce(setActiveTokenAddresses)
export default handleActions({
[ADD_TOKENS]: (state: State, action: ActionType<typeof addTokens>): State => {
@ -33,26 +33,26 @@ export default handleActions({
},
[ADD_TOKEN]: (state: State, action: ActionType<typeof addToken>): State => {
const { safeAddress, token } = action.payload
const activeTokens = getTokens(safeAddress)
const activeTokens = getActiveTokenAddresses(safeAddress)
activeTokens.push(token.get('address'))
setTokens(activeTokens)
setActiveTokenAddresses(activeTokens)
return state.setIn([safeAddress, token.get('address')], token)
},
[DISABLE_TOKEN]: (state: State, action: ActionType<typeof disableToken>): State => {
const { address, safeAddress, symbol } = action.payload
const activeTokens = getTokens(safeAddress)
const activeTokens = getActiveTokenAddresses(safeAddress)
const index = activeTokens.indexOf(address)
setTokens(safeAddress, activeTokens.delete(index))
setActiveTokenAddresses(safeAddress, activeTokens.delete(index))
return state.setIn([safeAddress, symbol, 'status'], false)
},
[ENABLE_TOKEN]: (state: State, action: ActionType<typeof enableToken>): State => {
const { address, safeAddress, symbol } = action.payload
const activeTokens = getTokens(safeAddress)
setTokens(safeAddress, activeTokens.push(address))
const activeTokens = getActiveTokenAddresses(safeAddress)
setActiveTokenAddresses(safeAddress, activeTokens.push(address))
return state.setIn([safeAddress, symbol, 'status'], true)
},

View File

@ -13,7 +13,7 @@ import { travelToTokens } from '~/test/builder/safe.dom.utils'
import { sleep } from '~/utils/timer'
import { buildMathPropsFrom } from '~/test/utils/buildReactRouterProps'
import { tokenListSelector, activeTokensSelector } from '~/routes/tokens/store/selectors'
import { getTokens } from '~/utils/localStorage/tokens'
import { getActiveTokenAddresses } from '~/utils/localStorage/tokens'
import { enableFirstToken, testToken } from '~/test/builder/tokens.dom.utils'
import * as fetchTokensModule from '~/routes/tokens/store/actions/fetchTokens'
import * as enhancedFetchModule from '~/utils/fetch'
@ -108,19 +108,19 @@ describe('DOM > Feature > Enable and disable default tokens', () => {
it('localStorage always returns a list', async () => {
const store = aNewStore()
const safeAddress = await aMinedSafe(store)
let tokens: List<string> = getTokens(safeAddress)
let tokens: List<string> = getActiveTokenAddresses(safeAddress)
expect(tokens).toEqual(List([]))
await store.dispatch(fetchTokensModule.fetchTokens(safeAddress))
tokens = getTokens(safeAddress)
tokens = getActiveTokenAddresses(safeAddress)
expect(tokens.count()).toBe(0)
await enableFirstToken(store, safeAddress)
tokens = getTokens(safeAddress)
tokens = getActiveTokenAddresses(safeAddress)
expect(tokens.count()).toBe(1)
await store.dispatch(fetchTokensModule.fetchTokens(safeAddress))
tokens = getTokens(safeAddress)
tokens = getActiveTokenAddresses(safeAddress)
expect(tokens.count()).toBe(1)
})
})

View File

@ -5,7 +5,6 @@ import { type Owner } from '~/routes/safe/store/model/owner'
export const SAFES_KEY = 'SAFES'
export const TX_KEY = 'TX'
export const OWNERS_KEY = 'OWNERS'
export const TOKENS_KEY = 'TOKENS'
export const load = (key: string) => {
try {

View File

@ -1,13 +1,18 @@
// @flow
import { List } from 'immutable'
import { load, TOKENS_KEY } from '~/utils/localStorage'
import { load } from '~/utils/localStorage'
import { type Token, type TokenProps } from '~/routes/tokens/store/model/token'
export const ACTIVE_TOKENS_KEY = 'ACTIVE_TOKENS'
export const TOKENS_KEY = 'TOKENS'
const getActiveTokensKey = (safeAddress: string) => `${ACTIVE_TOKENS_KEY}-${safeAddress}`
const getTokensKey = (safeAddress: string) => `${TOKENS_KEY}-${safeAddress}`
export const setTokens = (safeAddress: string, tokens: List<string>) => {
export const setActiveTokenAddresses = (safeAddress: string, tokens: List<string>) => {
try {
const serializedState = JSON.stringify(tokens)
const key = getTokensKey(safeAddress)
const key = getActiveTokensKey(safeAddress)
localStorage.setItem(key, serializedState)
} catch (err) {
// eslint-disable-next-line
@ -15,14 +20,35 @@ export const setTokens = (safeAddress: string, tokens: List<string>) => {
}
}
export const getTokens = (safeAddress: string): List<string> => {
const key = getTokensKey(safeAddress)
export const getActiveTokenAddresses = (safeAddress: string): List<string> => {
const key = getActiveTokensKey(safeAddress)
const data = load(key)
return data ? List(data) : List()
}
export const storedTokensBefore = (safeAddress: string) => {
const key = getTokensKey(safeAddress)
const key = getActiveTokensKey(safeAddress)
return localStorage.getItem(key) === null
}
export const getTokens: List<TokenProps> = (safeAddress: string) => {
const key = getTokensKey(safeAddress)
const data = load(key)
return data ? List(data) : List()
}
export const setToken = (safeAddress: string, token: Token) => {
const data: List<Token> = getTokens(safeAddress)
data.push(token)
try {
const serializedState = JSON.stringify(data)
const key = getTokensKey(safeAddress)
localStorage.setItem(key, serializedState)
} catch (err) {
// eslint-disable-next-line
console.log('Error adding token in localstorage')
}
}