add an action to fetch token balances

This commit is contained in:
Mikhail Mikheev 2019-04-08 19:58:01 +04:00
parent 3b27729d85
commit 8108b6bd01
6 changed files with 62 additions and 15 deletions

View File

@ -0,0 +1,27 @@
// @flow
import type { Dispatch as ReduxDispatch } from 'redux'
import { Map, List } from 'immutable'
import { type Token } from '~/logic/tokens/store/model/token'
import { type GlobalState } from '~/store/index'
import { calculateBalanceOf } from './fetchTokens'
import { addTokens } from './saveTokens'
const fetchTokenBalances = (safeAddress: string, tokens: List<Token>) => async (
dispatch: ReduxDispatch<GlobalState>,
) => {
try {
const withBalances = await Promise.all(
tokens.map(async token => token.set('funds', await calculateBalanceOf(token.address, safeAddress))),
)
const tokensMap = Map().withMutations((map) => {
withBalances.forEach(token => map.set(token.address, token))
})
dispatch(addTokens(safeAddress, tokensMap))
} catch (err) {
// eslint-disable-next-line
console.error('Error while loading active tokens from storage:', err)
}
}
export default fetchTokenBalances

View File

@ -34,7 +34,7 @@ export const getHumanFriendlyToken = ensureOnce(createHumanFriendlyTokenContract
export const getStandardTokenContract = ensureOnce(createStandardTokenContract) export const getStandardTokenContract = ensureOnce(createStandardTokenContract)
export const calculateBalanceOf = async (tokenAddress: string, address: string, decimals: number) => { export const calculateBalanceOf = async (tokenAddress: string, address: string, decimals: number = 18) => {
const erc20Token = await getStandardTokenContract() const erc20Token = await getStandardTokenContract()
let balance = 0 let balance = 0

View File

@ -19,7 +19,7 @@ const loadActiveTokens = (safeAddress: string) => async (dispatch: ReduxDispatch
} }
} catch (err) { } catch (err) {
// eslint-disable-next-line // eslint-disable-next-line
console.error('Error while getting safes from storage:', err) console.error('Error while loading active tokens from storage:', err)
} }
} }

View File

@ -6,10 +6,10 @@ import { type GlobalState } from '~/store'
import { TOKEN_REDUCER_ID } from '~/logic/tokens/store/reducer/tokens' import { TOKEN_REDUCER_ID } from '~/logic/tokens/store/reducer/tokens'
import { type Token } from '~/logic/tokens/store/model/token' import { type Token } from '~/logic/tokens/store/model/token'
const balancesSelector = (state: GlobalState) => state[TOKEN_REDUCER_ID] const tokensStateSelector = (state: GlobalState) => state[TOKEN_REDUCER_ID]
export const tokensSelector: Selector<GlobalState, RouterProps, Map<string, Token>> = createSelector( export const tokensSelector: Selector<GlobalState, RouterProps, Map<string, Token>> = createSelector(
balancesSelector, tokensStateSelector,
safeParamAddressSelector, safeParamAddressSelector,
(tokens: Map<string, Map<string, Token>>, address: string) => { (tokens: Map<string, Map<string, Token>>, address: string) => {
if (!address) { if (!address) {
@ -20,25 +20,34 @@ export const tokensSelector: Selector<GlobalState, RouterProps, Map<string, Toke
}, },
) )
export const tokenListSelector = createSelector( export const tokenListSelector: Selector<GlobalState, RouterProps, List<Token>> = createSelector(
tokensSelector, tokensSelector,
(tokens: Map<string, Token>) => tokens.toList(), (tokens: Map<string, Token>) => tokens.toList(),
) )
export const activeTokensSelector = createSelector( export const activeTokensSelector: Selector<GlobalState, RouterProps, List<Token>> = createSelector(
tokenListSelector, tokenListSelector,
(tokens: List<Token>) => tokens.filter((token: Token) => token.get('status')), (tokens: List<Token>) => tokens.filter((token: Token) => token.get('status')),
) )
export const orderedTokenListSelector = createSelector( export const orderedTokenListSelector: Selector<GlobalState, RouterProps, List<Token>> = createSelector(
tokenListSelector, tokenListSelector,
(tokens: List<Token>) => tokens.sortBy((token: Token) => token.get('symbol')), (tokens: List<Token>) => tokens.sortBy((token: Token) => token.get('symbol')),
) )
export const tokenAddressesSelector = createSelector( export const tokenAddressesSelector: Selector<GlobalState, RouterProps, List<string>> = createSelector(
tokenListSelector, tokenListSelector,
(balances: List<Token>) => { (tokens: List<Token>) => {
const addresses = List().withMutations(list => balances.map(token => list.push(token.address))) const addresses = List().withMutations(list => tokens.map(token => list.push(token.address)))
return addresses
},
)
export const activeTokenAdressesSelector: Selector<GlobalState, RouterProps, List<string>> = createSelector(
activeTokensSelector,
(tokens: List<Token>) => {
const addresses = List().withMutations(list => tokens.map(token => list.push(token.address)))
return addresses return addresses
}, },

View File

@ -2,15 +2,18 @@
import fetchSafe from '~/routes/safe/store/actions/fetchSafe' import fetchSafe from '~/routes/safe/store/actions/fetchSafe'
import { fetchTokens } from '~/logic/tokens/store/actions/fetchTokens' import { fetchTokens } from '~/logic/tokens/store/actions/fetchTokens'
import loadActiveTokens from '~/logic/tokens/store/actions/loadActiveTokens' import loadActiveTokens from '~/logic/tokens/store/actions/loadActiveTokens'
import fetchTokenBalances from '~/logic/tokens/store/actions/fetchTokenBalances'
export type Actions = { export type Actions = {
fetchSafe: typeof fetchSafe, fetchSafe: typeof fetchSafe,
fetchTokens: typeof fetchTokens, fetchTokens: typeof fetchTokens,
loadActiveTokens: typeof loadActiveTokens, loadActiveTokens: typeof loadActiveTokens,
fetchTokenBalances: typeof fetchTokenBalances
} }
export default { export default {
fetchSafe, fetchSafe,
fetchTokens, fetchTokens,
loadActiveTokens, loadActiveTokens,
fetchTokenBalances,
} }

View File

@ -16,21 +16,27 @@ const TIMEOUT = process.env.NODE_ENV === 'test' ? 1500 : 15000
class SafeView extends React.PureComponent<Props> { class SafeView extends React.PureComponent<Props> {
componentDidMount() { componentDidMount() {
const { const {
safeUrl, fetchTokenBalances, fetchSafe, loadActiveTokens, safeUrl, fetchTokenBalances, fetchSafe, loadActiveTokens, activeTokens,
} = this.props } = this.props
fetchSafe(safeUrl) fetchSafe(safeUrl)
loadActiveTokens(safeUrl) loadActiveTokens(safeUrl)
// fetchTokens(safeUrl)
if (activeTokens.size) {
fetchTokenBalances(safeUrl, activeTokens)
}
this.intervalId = setInterval(() => { this.intervalId = setInterval(() => {
// fetchTokenBalances(safeUrl) // eslint-disable-next-line
fetchTokenBalances(safeUrl, this.props.activeTokens)
fetchSafe(safeUrl) fetchSafe(safeUrl)
}, TIMEOUT) }, TIMEOUT)
} }
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
const { safe, fetchTokenBalances, loadActiveTokens } = this.props const {
safe, fetchTokenBalances, loadActiveTokens, activeTokens,
} = this.props
if (prevProps.safe) { if (prevProps.safe) {
return return
@ -39,7 +45,9 @@ class SafeView extends React.PureComponent<Props> {
if (safe) { if (safe) {
const safeAddress = safe.get('address') const safeAddress = safe.get('address')
loadActiveTokens(safeAddress) loadActiveTokens(safeAddress)
// fetchTokenBalances(safeAddress) if (activeTokens.size) {
fetchTokenBalances(safeAddress, activeTokens)
}
} }
} }