WA-232 fetching balance of activated custom tokens
This commit is contained in:
parent
95caa29f69
commit
da6345b1cc
|
@ -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 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 { makeToken, type Token } from '~/routes/tokens/store/model/token'
|
||||||
import addTokenAction from '~/routes/tokens/store/actions/addTokens'
|
import addTokenAction from '~/routes/tokens/store/actions/addTokens'
|
||||||
|
import enableTokenAction from '~/routes/tokens/store/actions/enabletoken'
|
||||||
import Review from './Review'
|
import Review from './Review'
|
||||||
|
|
||||||
export const getSteps = () => [
|
export const getSteps = () => [
|
||||||
|
@ -15,7 +16,8 @@ export const getSteps = () => [
|
||||||
type Props = {
|
type Props = {
|
||||||
tokens: string[],
|
tokens: string[],
|
||||||
safeAddress: string,
|
safeAddress: string,
|
||||||
addToken: typeof addTokenAction
|
addToken: typeof addTokenAction,
|
||||||
|
enableToken: typeof enableTokenAction,
|
||||||
}
|
}
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
|
@ -24,7 +26,7 @@ type State = {
|
||||||
|
|
||||||
export const ADD_TOKEN_RESET_BUTTON_TEXT = 'RESET'
|
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 address = values[TOKEN_ADDRESS_PARAM]
|
||||||
const name = values[TOKEN_NAME_PARAM]
|
const name = values[TOKEN_NAME_PARAM]
|
||||||
const symbol = values[TOKEN_SYMBOL_PARAM]
|
const symbol = values[TOKEN_SYMBOL_PARAM]
|
||||||
|
@ -41,6 +43,7 @@ export const addTokenFnc = async (values: Object, addToken, safeAddress: string)
|
||||||
removable: true,
|
removable: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await enableToken(safeAddress, token)
|
||||||
return addToken(safeAddress, token)
|
return addToken(safeAddress, token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,9 +53,9 @@ class AddToken extends React.Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
onAddToken = async (values: Object) => {
|
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 = () => {
|
onReset = () => {
|
||||||
|
|
|
@ -38,10 +38,17 @@ class TokenLayout extends React.PureComponent<TokenProps, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
onAddToken = () => {
|
onAddToken = () => {
|
||||||
const { addresses, safeAddress, addToken } = this.props
|
const {
|
||||||
|
addresses, safeAddress, addToken, enableToken,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
component: <AddToken addToken={addToken} tokens={addresses.toArray()} safeAddress={safeAddress} />,
|
component: <AddToken
|
||||||
|
addToken={addToken}
|
||||||
|
enableToken={enableToken}
|
||||||
|
tokens={addresses.toArray()}
|
||||||
|
safeAddress={safeAddress}
|
||||||
|
/>,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { getWeb3 } from '~/wallets/getWeb3'
|
||||||
import { type GlobalState } from '~/store/index'
|
import { type GlobalState } from '~/store/index'
|
||||||
import { makeToken, type Token, type TokenProps } from '~/routes/tokens/store/model/token'
|
import { makeToken, type Token, type TokenProps } from '~/routes/tokens/store/model/token'
|
||||||
import { ensureOnce } from '~/utils/singleton'
|
import { ensureOnce } from '~/utils/singleton'
|
||||||
import { getTokens } from '~/utils/localStorage/tokens'
|
import { getActiveTokenAddresses, getTokens } from '~/utils/localStorage/tokens'
|
||||||
import { getSafeEthToken } from '~/utils/tokens'
|
import { getSafeEthToken } from '~/utils/tokens'
|
||||||
import { enhancedFetch } from '~/utils/fetch'
|
import { enhancedFetch } from '~/utils/fetch'
|
||||||
import addTokens from './addTokens'
|
import addTokens from './addTokens'
|
||||||
|
@ -48,9 +48,9 @@ export const fetchTokensData = async () => {
|
||||||
|
|
||||||
export const fetchTokens = (safeAddress: string) =>
|
export const fetchTokens = (safeAddress: string) =>
|
||||||
async (dispatch: ReduxDispatch<GlobalState>) => {
|
async (dispatch: ReduxDispatch<GlobalState>) => {
|
||||||
const tokens: List<string> = getTokens(safeAddress)
|
const tokens: List<string> = getActiveTokenAddresses(safeAddress)
|
||||||
const ethBalance = await getSafeEthToken(safeAddress)
|
const ethBalance = await getSafeEthToken(safeAddress)
|
||||||
|
const customTokens = getTokens(safeAddress)
|
||||||
const json = await exports.fetchTokensData()
|
const json = await exports.fetchTokensData()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -61,10 +61,18 @@ export const fetchTokens = (safeAddress: string) =>
|
||||||
return makeToken({ ...item, status, funds })
|
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) => {
|
const balances: Map<string, Token> = Map().withMutations((map) => {
|
||||||
balancesRecords.forEach(record => map.set(record.get('address'), record))
|
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))
|
return dispatch(addTokens(safeAddress, balances))
|
||||||
|
|
|
@ -6,7 +6,7 @@ import addTokens, { ADD_TOKENS } from '~/routes/tokens/store/actions/addTokens'
|
||||||
import { type Token } from '~/routes/tokens/store/model/token'
|
import { type Token } from '~/routes/tokens/store/model/token'
|
||||||
import disableToken, { DISABLE_TOKEN } from '~/routes/tokens/store/actions/disableToken'
|
import disableToken, { DISABLE_TOKEN } from '~/routes/tokens/store/actions/disableToken'
|
||||||
import enableToken, { ENABLE_TOKEN } from '~/routes/tokens/store/actions/enableToken'
|
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 { ensureOnce } from '~/utils/singleton'
|
||||||
import { calculateActiveErc20TokensFrom } from '~/utils/tokens'
|
import { calculateActiveErc20TokensFrom } from '~/utils/tokens'
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ export const TOKEN_REDUCER_ID = 'tokens'
|
||||||
|
|
||||||
export type State = Map<string, Map<string, Token>>
|
export type State = Map<string, Map<string, Token>>
|
||||||
|
|
||||||
const setTokensOnce = ensureOnce(setTokens)
|
const setTokensOnce = ensureOnce(setActiveTokenAddresses)
|
||||||
|
|
||||||
export default handleActions({
|
export default handleActions({
|
||||||
[ADD_TOKENS]: (state: State, action: ActionType<typeof addTokens>): State => {
|
[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 => {
|
[ADD_TOKEN]: (state: State, action: ActionType<typeof addToken>): State => {
|
||||||
const { safeAddress, token } = action.payload
|
const { safeAddress, token } = action.payload
|
||||||
const activeTokens = getTokens(safeAddress)
|
const activeTokens = getActiveTokenAddresses(safeAddress)
|
||||||
activeTokens.push(token.get('address'))
|
activeTokens.push(token.get('address'))
|
||||||
setTokens(activeTokens)
|
setActiveTokenAddresses(activeTokens)
|
||||||
|
|
||||||
return state.setIn([safeAddress, token.get('address')], token)
|
return state.setIn([safeAddress, token.get('address')], token)
|
||||||
},
|
},
|
||||||
[DISABLE_TOKEN]: (state: State, action: ActionType<typeof disableToken>): State => {
|
[DISABLE_TOKEN]: (state: State, action: ActionType<typeof disableToken>): State => {
|
||||||
const { address, safeAddress, symbol } = action.payload
|
const { address, safeAddress, symbol } = action.payload
|
||||||
|
|
||||||
const activeTokens = getTokens(safeAddress)
|
const activeTokens = getActiveTokenAddresses(safeAddress)
|
||||||
const index = activeTokens.indexOf(address)
|
const index = activeTokens.indexOf(address)
|
||||||
setTokens(safeAddress, activeTokens.delete(index))
|
setActiveTokenAddresses(safeAddress, activeTokens.delete(index))
|
||||||
|
|
||||||
return state.setIn([safeAddress, symbol, 'status'], false)
|
return state.setIn([safeAddress, symbol, 'status'], false)
|
||||||
},
|
},
|
||||||
[ENABLE_TOKEN]: (state: State, action: ActionType<typeof enableToken>): State => {
|
[ENABLE_TOKEN]: (state: State, action: ActionType<typeof enableToken>): State => {
|
||||||
const { address, safeAddress, symbol } = action.payload
|
const { address, safeAddress, symbol } = action.payload
|
||||||
|
|
||||||
const activeTokens = getTokens(safeAddress)
|
const activeTokens = getActiveTokenAddresses(safeAddress)
|
||||||
setTokens(safeAddress, activeTokens.push(address))
|
setActiveTokenAddresses(safeAddress, activeTokens.push(address))
|
||||||
|
|
||||||
return state.setIn([safeAddress, symbol, 'status'], true)
|
return state.setIn([safeAddress, symbol, 'status'], true)
|
||||||
},
|
},
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { travelToTokens } from '~/test/builder/safe.dom.utils'
|
||||||
import { sleep } from '~/utils/timer'
|
import { sleep } from '~/utils/timer'
|
||||||
import { buildMathPropsFrom } from '~/test/utils/buildReactRouterProps'
|
import { buildMathPropsFrom } from '~/test/utils/buildReactRouterProps'
|
||||||
import { tokenListSelector, activeTokensSelector } from '~/routes/tokens/store/selectors'
|
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 { enableFirstToken, testToken } from '~/test/builder/tokens.dom.utils'
|
||||||
import * as fetchTokensModule from '~/routes/tokens/store/actions/fetchTokens'
|
import * as fetchTokensModule from '~/routes/tokens/store/actions/fetchTokens'
|
||||||
import * as enhancedFetchModule from '~/utils/fetch'
|
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 () => {
|
it('localStorage always returns a list', async () => {
|
||||||
const store = aNewStore()
|
const store = aNewStore()
|
||||||
const safeAddress = await aMinedSafe(store)
|
const safeAddress = await aMinedSafe(store)
|
||||||
let tokens: List<string> = getTokens(safeAddress)
|
let tokens: List<string> = getActiveTokenAddresses(safeAddress)
|
||||||
expect(tokens).toEqual(List([]))
|
expect(tokens).toEqual(List([]))
|
||||||
|
|
||||||
await store.dispatch(fetchTokensModule.fetchTokens(safeAddress))
|
await store.dispatch(fetchTokensModule.fetchTokens(safeAddress))
|
||||||
tokens = getTokens(safeAddress)
|
tokens = getActiveTokenAddresses(safeAddress)
|
||||||
expect(tokens.count()).toBe(0)
|
expect(tokens.count()).toBe(0)
|
||||||
|
|
||||||
await enableFirstToken(store, safeAddress)
|
await enableFirstToken(store, safeAddress)
|
||||||
tokens = getTokens(safeAddress)
|
tokens = getActiveTokenAddresses(safeAddress)
|
||||||
expect(tokens.count()).toBe(1)
|
expect(tokens.count()).toBe(1)
|
||||||
|
|
||||||
await store.dispatch(fetchTokensModule.fetchTokens(safeAddress))
|
await store.dispatch(fetchTokensModule.fetchTokens(safeAddress))
|
||||||
tokens = getTokens(safeAddress)
|
tokens = getActiveTokenAddresses(safeAddress)
|
||||||
expect(tokens.count()).toBe(1)
|
expect(tokens.count()).toBe(1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,7 +5,6 @@ import { type Owner } from '~/routes/safe/store/model/owner'
|
||||||
export const SAFES_KEY = 'SAFES'
|
export const SAFES_KEY = 'SAFES'
|
||||||
export const TX_KEY = 'TX'
|
export const TX_KEY = 'TX'
|
||||||
export const OWNERS_KEY = 'OWNERS'
|
export const OWNERS_KEY = 'OWNERS'
|
||||||
export const TOKENS_KEY = 'TOKENS'
|
|
||||||
|
|
||||||
export const load = (key: string) => {
|
export const load = (key: string) => {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { List } from 'immutable'
|
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}`
|
const getTokensKey = (safeAddress: string) => `${TOKENS_KEY}-${safeAddress}`
|
||||||
|
|
||||||
export const setTokens = (safeAddress: string, tokens: List<string>) => {
|
export const setActiveTokenAddresses = (safeAddress: string, tokens: List<string>) => {
|
||||||
try {
|
try {
|
||||||
const serializedState = JSON.stringify(tokens)
|
const serializedState = JSON.stringify(tokens)
|
||||||
const key = getTokensKey(safeAddress)
|
const key = getActiveTokensKey(safeAddress)
|
||||||
localStorage.setItem(key, serializedState)
|
localStorage.setItem(key, serializedState)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
|
@ -15,14 +20,35 @@ export const setTokens = (safeAddress: string, tokens: List<string>) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getTokens = (safeAddress: string): List<string> => {
|
export const getActiveTokenAddresses = (safeAddress: string): List<string> => {
|
||||||
const key = getTokensKey(safeAddress)
|
const key = getActiveTokensKey(safeAddress)
|
||||||
const data = load(key)
|
const data = load(key)
|
||||||
|
|
||||||
return data ? List(data) : List()
|
return data ? List(data) : List()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const storedTokensBefore = (safeAddress: string) => {
|
export const storedTokensBefore = (safeAddress: string) => {
|
||||||
const key = getTokensKey(safeAddress)
|
const key = getActiveTokensKey(safeAddress)
|
||||||
return localStorage.getItem(key) === null
|
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')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue