* Replace 'Manage Tokens' with 'Manage List' * prevent 301 redirects * Add `BLACKLISTED_TOKENS` key to persist through immortal * Add store/action to extract _activate tokens by its balance_ - keeps already activated tokens - discards blacklisted tokens - adds tokens whose vales are bigger than zero and are not blacklisted * Add `blacklistedTokens` list to safe's store * Display activeTokensByBalance in 'Balances' screen * Enable token's blacklisting functionality in Tokens List * Retrieve balance from API * Rename action to `activateTokensByBalance` * Fix linting errors - line too long - required return * Do not persist a separate list into `BLACKLISTED_TOKENS`
This commit is contained in:
parent
85ff11796e
commit
21b7a59f20
|
@ -0,0 +1,16 @@
|
|||
// @flow
|
||||
import axios from 'axios'
|
||||
import { getTxServiceHost } from '~/config/index'
|
||||
|
||||
const fetchTokenBalanceList = (safeAddress: string) => {
|
||||
const apiUrl = getTxServiceHost()
|
||||
const url = `${apiUrl}safes/${safeAddress}/balances/`
|
||||
|
||||
return axios.get(url, {
|
||||
params: {
|
||||
limit: 300,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export default fetchTokenBalanceList
|
|
@ -4,7 +4,7 @@ import { getRelayUrl } from '~/config/index'
|
|||
|
||||
const fetchTokenList = () => {
|
||||
const apiUrl = getRelayUrl()
|
||||
const url = `${apiUrl}/tokens`
|
||||
const url = `${apiUrl}tokens/`
|
||||
|
||||
return axios.get(url, {
|
||||
params: {
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
// @flow
|
||||
import type { Dispatch as ReduxDispatch } from 'redux'
|
||||
import { Set } from 'immutable'
|
||||
import { type GetState, type GlobalState } from '~/store'
|
||||
import updateActiveTokens from '~/routes/safe/store/actions/updateActiveTokens'
|
||||
import {
|
||||
safeActiveTokensSelectorBySafe,
|
||||
safeBlacklistedTokensSelectorBySafe,
|
||||
safesMapSelector,
|
||||
} from '~/routes/safe/store/selectors'
|
||||
import fetchTokenBalanceList from '~/logic/tokens/api/fetchTokenBalanceList'
|
||||
import updateSafe from '~/routes/safe/store/actions/updateSafe'
|
||||
|
||||
const activateTokensByBalance = (safeAddress: string) => async (
|
||||
dispatch: ReduxDispatch<GlobalState>,
|
||||
getState: GetState,
|
||||
) => {
|
||||
try {
|
||||
const result = await fetchTokenBalanceList(safeAddress)
|
||||
const safes = safesMapSelector(getState())
|
||||
const alreadyActiveTokens = safeActiveTokensSelectorBySafe(safeAddress, safes)
|
||||
const blacklistedTokens = safeBlacklistedTokensSelectorBySafe(safeAddress, safes)
|
||||
|
||||
// addresses: potentially active tokens by balance
|
||||
// balances: tokens' balance returned by the backend
|
||||
const { addresses, balances } = result.data.reduce((acc, { tokenAddress, balance }) => ({
|
||||
addresses: [...acc.addresses, tokenAddress],
|
||||
balances: [...acc.balances, balance],
|
||||
}), { addresses: [], balances: [] })
|
||||
|
||||
// update balance list for the safe
|
||||
dispatch(updateSafe({ address: safeAddress, balances: Set(balances) }))
|
||||
|
||||
// active tokens by balance, excluding those already blacklisted and the `null` address
|
||||
const activeByBalance = addresses.filter((address) => address !== null && !blacklistedTokens.includes(address))
|
||||
|
||||
// need to persist those already active tokens, despite its balances
|
||||
const activeTokens = alreadyActiveTokens.toSet().union(activeByBalance)
|
||||
|
||||
// update list of active tokens
|
||||
dispatch(updateActiveTokens(safeAddress, activeTokens))
|
||||
} catch (err) {
|
||||
console.error('Error fetching token list', err)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export default activateTokensByBalance
|
|
@ -2,7 +2,7 @@
|
|||
import { createAction } from 'redux-actions'
|
||||
import type { Dispatch as ReduxDispatch } from 'redux'
|
||||
import { type Token } from '~/logic/tokens/store/model/token'
|
||||
import { removeTokenFromStorage, removeFromActiveTokens } from '~/logic/tokens/utils/tokensStorage'
|
||||
import { removeFromActiveTokens, removeTokenFromStorage } from '~/logic/tokens/utils/tokensStorage'
|
||||
import { type GlobalState } from '~/store/index'
|
||||
|
||||
export const REMOVE_TOKEN = 'REMOVE_TOKEN'
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
import fetchTokens from '~/logic/tokens/store/actions/fetchTokens'
|
||||
import { addToken } from '~/logic/tokens/store/actions/addToken'
|
||||
import updateActiveTokens from '~/routes/safe/store/actions/updateActiveTokens'
|
||||
import updateBlacklistedTokens from '~/routes/safe/store/actions/updateBlacklistedTokens'
|
||||
import activateTokenForAllSafes from '~/routes/safe/store/actions/activateTokenForAllSafes'
|
||||
|
||||
export type Actions = {
|
||||
fetchTokens: Function,
|
||||
updateActiveTokens: Function,
|
||||
updateBlacklistedTokens: typeof updateBlacklistedTokens,
|
||||
addToken: Function,
|
||||
activateTokenForAllSafes: Function,
|
||||
}
|
||||
|
@ -15,5 +17,6 @@ export default {
|
|||
fetchTokens,
|
||||
addToken,
|
||||
updateActiveTokens,
|
||||
updateBlacklistedTokens,
|
||||
activateTokenForAllSafes,
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ type Props = Actions & {
|
|||
tokens: List<Token>,
|
||||
safeAddress: string,
|
||||
activeTokens: List<Token>,
|
||||
blacklistedTokens: List<Token>,
|
||||
}
|
||||
type ActiveScreen = 'tokenList' | 'addCustomToken'
|
||||
|
||||
|
@ -32,8 +33,10 @@ const Tokens = (props: Props) => {
|
|||
classes,
|
||||
tokens,
|
||||
activeTokens,
|
||||
blacklistedTokens,
|
||||
fetchTokens,
|
||||
updateActiveTokens,
|
||||
updateBlacklistedTokens,
|
||||
safeAddress,
|
||||
addToken,
|
||||
activateTokenForAllSafes,
|
||||
|
@ -43,7 +46,7 @@ const Tokens = (props: Props) => {
|
|||
<>
|
||||
<Row align="center" grow className={classes.heading}>
|
||||
<Paragraph size="xl" noMargin weight="bolder">
|
||||
Manage Tokens
|
||||
Manage List
|
||||
</Paragraph>
|
||||
<IconButton onClick={onClose} disableRipple data-testid={MANAGE_TOKENS_MODAL_CLOSE_BUTTON_TEST_ID}>
|
||||
<Close className={classes.close} />
|
||||
|
@ -54,8 +57,10 @@ const Tokens = (props: Props) => {
|
|||
<TokenList
|
||||
tokens={tokens}
|
||||
activeTokens={activeTokens}
|
||||
blacklistedTokens={blacklistedTokens}
|
||||
fetchTokens={fetchTokens}
|
||||
updateActiveTokens={updateActiveTokens}
|
||||
updateBlacklistedTokens={updateBlacklistedTokens}
|
||||
safeAddress={safeAddress}
|
||||
setActiveScreen={setActiveScreen}
|
||||
/>
|
||||
|
|
|
@ -25,14 +25,17 @@ type Props = {
|
|||
tokens: List<Token>,
|
||||
safeAddress: string,
|
||||
activeTokens: List<Token>,
|
||||
fetchTokens: Function,
|
||||
blacklistedTokens: List<Token>,
|
||||
updateActiveTokens: Function,
|
||||
updateBlacklistedTokens: Function,
|
||||
setActiveScreen: Function,
|
||||
}
|
||||
|
||||
type State = {
|
||||
filter: string,
|
||||
activeTokensAddresses: Set<string>,
|
||||
initialActiveTokensAddresses: Set<string>,
|
||||
blacklistedTokensAddresses: Set<string>,
|
||||
}
|
||||
|
||||
const filterBy = (filter: string, tokens: List<Token>): List<Token> => tokens.filter(
|
||||
|
@ -52,13 +55,10 @@ class Tokens extends React.Component<Props, State> {
|
|||
state = {
|
||||
filter: '',
|
||||
activeTokensAddresses: Set([]),
|
||||
initialActiveTokensAddresses: Set([]),
|
||||
blacklistedTokensAddresses: Set([]),
|
||||
activeTokensCalculated: false,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { fetchTokens } = this.props
|
||||
|
||||
fetchTokens()
|
||||
blacklistedTokensCalculated: false,
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
|
@ -70,17 +70,29 @@ class Tokens extends React.Component<Props, State> {
|
|||
|
||||
return {
|
||||
activeTokensAddresses: Set(activeTokens.map(({ address }) => address)),
|
||||
initialActiveTokensAddresses: Set(activeTokens.map(({ address }) => address)),
|
||||
activeTokensCalculated: true,
|
||||
}
|
||||
}
|
||||
|
||||
if (!prevState.blacklistedTokensCalculated) {
|
||||
const { blacklistedTokens } = nextProps
|
||||
|
||||
return {
|
||||
blacklistedTokensAddresses: blacklistedTokens,
|
||||
blacklistedTokensCalculated: true,
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const { activeTokensAddresses } = this.state
|
||||
const { updateActiveTokens, safeAddress } = this.props
|
||||
const { activeTokensAddresses, blacklistedTokensAddresses } = this.state
|
||||
const { updateActiveTokens, updateBlacklistedTokens, safeAddress } = this.props
|
||||
|
||||
updateActiveTokens(safeAddress, activeTokensAddresses)
|
||||
updateBlacklistedTokens(safeAddress, blacklistedTokensAddresses)
|
||||
}
|
||||
|
||||
onCancelSearch = () => {
|
||||
|
@ -92,17 +104,20 @@ class Tokens extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
onSwitch = (token: Token) => () => {
|
||||
const { activeTokensAddresses } = this.state
|
||||
this.setState((prevState) => {
|
||||
const activeTokensAddresses = prevState.activeTokensAddresses.has(token.address)
|
||||
? prevState.activeTokensAddresses.remove(token.address)
|
||||
: prevState.activeTokensAddresses.add(token.address)
|
||||
|
||||
let { blacklistedTokensAddresses } = prevState
|
||||
if (activeTokensAddresses.has(token.address)) {
|
||||
this.setState({
|
||||
activeTokensAddresses: activeTokensAddresses.remove(token.address),
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
activeTokensAddresses: activeTokensAddresses.add(token.address),
|
||||
})
|
||||
blacklistedTokensAddresses = prevState.blacklistedTokensAddresses.remove(token.address)
|
||||
} else if (prevState.initialActiveTokensAddresses.has(token.address)) {
|
||||
blacklistedTokensAddresses = prevState.blacklistedTokensAddresses.add(token.address)
|
||||
}
|
||||
|
||||
return ({ ...prevState, activeTokensAddresses, blacklistedTokensAddresses })
|
||||
})
|
||||
}
|
||||
|
||||
createItemData = (tokens, activeTokensAddresses) => ({
|
||||
|
|
|
@ -38,6 +38,9 @@ type Props = {
|
|||
granted: boolean,
|
||||
tokens: List<Token>,
|
||||
activeTokens: List<Token>,
|
||||
blacklistedTokens: List<Token>,
|
||||
activateTokensByBalance: Function,
|
||||
fetchTokens: Function,
|
||||
safeAddress: string,
|
||||
safeName: string,
|
||||
ethBalance: string,
|
||||
|
@ -57,6 +60,7 @@ class Balances extends React.Component<Props, State> {
|
|||
},
|
||||
showReceive: false,
|
||||
}
|
||||
props.fetchTokens()
|
||||
}
|
||||
|
||||
onShow = (action: Action) => () => {
|
||||
|
@ -85,6 +89,17 @@ class Balances extends React.Component<Props, State> {
|
|||
})
|
||||
}
|
||||
|
||||
handleChange = (e: SyntheticInputEvent<HTMLInputElement>) => {
|
||||
const { checked } = e.target
|
||||
|
||||
this.setState(() => ({ hideZero: checked }))
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
const { activateTokensByBalance, safeAddress } = this.props
|
||||
activateTokensByBalance(safeAddress)
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
showToken, showReceive, sendFunds,
|
||||
|
@ -95,6 +110,7 @@ class Balances extends React.Component<Props, State> {
|
|||
tokens,
|
||||
safeAddress,
|
||||
activeTokens,
|
||||
blacklistedTokens,
|
||||
safeName,
|
||||
ethBalance,
|
||||
createTransaction,
|
||||
|
@ -110,10 +126,10 @@ class Balances extends React.Component<Props, State> {
|
|||
<Row align="center" className={classes.message}>
|
||||
<Col xs={12} end="sm">
|
||||
<ButtonLink size="lg" onClick={this.onShow('Token')} testId="manage-tokens-btn">
|
||||
Manage Tokens
|
||||
Manage List
|
||||
</ButtonLink>
|
||||
<Modal
|
||||
title="Manage Tokens"
|
||||
title="Manage List"
|
||||
description="Enable and disable tokens to be listed"
|
||||
handleClose={this.onHide('Token')}
|
||||
open={showToken}
|
||||
|
@ -123,6 +139,7 @@ class Balances extends React.Component<Props, State> {
|
|||
onClose={this.onHide('Token')}
|
||||
safeAddress={safeAddress}
|
||||
activeTokens={activeTokens}
|
||||
blacklistedTokens={blacklistedTokens}
|
||||
/>
|
||||
</Modal>
|
||||
</Col>
|
||||
|
|
|
@ -60,9 +60,12 @@ const Layout = (props: Props) => {
|
|||
granted,
|
||||
tokens,
|
||||
activeTokens,
|
||||
blacklistedTokens,
|
||||
createTransaction,
|
||||
processTransaction,
|
||||
fetchTransactions,
|
||||
activateTokensByBalance,
|
||||
fetchTokens,
|
||||
updateSafe,
|
||||
transactions,
|
||||
userAddress,
|
||||
|
@ -156,8 +159,11 @@ const Layout = (props: Props) => {
|
|||
ethBalance={ethBalance}
|
||||
tokens={tokens}
|
||||
activeTokens={activeTokens}
|
||||
blacklistedTokens={blacklistedTokens}
|
||||
granted={granted}
|
||||
safeAddress={address}
|
||||
activateTokensByBalance={activateTokensByBalance}
|
||||
fetchTokens={fetchTokens}
|
||||
safeName={name}
|
||||
createTransaction={createTransaction}
|
||||
/>
|
||||
|
|
|
@ -7,6 +7,7 @@ import processTransaction from '~/routes/safe/store/actions/processTransaction'
|
|||
import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions'
|
||||
import updateSafe from '~/routes/safe/store/actions/updateSafe'
|
||||
import fetchTokens from '~/logic/tokens/store/actions/fetchTokens'
|
||||
import activateTokensByBalance from '~/logic/tokens/store/actions/activateTokensByBalance'
|
||||
|
||||
export type Actions = {
|
||||
fetchSafe: typeof fetchSafe,
|
||||
|
@ -17,6 +18,7 @@ export type Actions = {
|
|||
fetchTokens: typeof fetchTokens,
|
||||
processTransaction: typeof processTransaction,
|
||||
fetchEtherBalance: typeof fetchEtherBalance,
|
||||
activateTokensByBalance: typeof activateTokensByBalance
|
||||
}
|
||||
|
||||
export default {
|
||||
|
@ -26,6 +28,7 @@ export default {
|
|||
processTransaction,
|
||||
fetchTokens,
|
||||
fetchTransactions,
|
||||
activateTokensByBalance,
|
||||
updateSafe,
|
||||
fetchEtherBalance,
|
||||
checkAndUpdateSafeOwners,
|
||||
|
|
|
@ -102,6 +102,7 @@ class SafeView extends React.Component<Props, State> {
|
|||
safe,
|
||||
provider,
|
||||
activeTokens,
|
||||
blacklistedTokens,
|
||||
granted,
|
||||
userAddress,
|
||||
network,
|
||||
|
@ -109,6 +110,8 @@ class SafeView extends React.Component<Props, State> {
|
|||
createTransaction,
|
||||
processTransaction,
|
||||
fetchTransactions,
|
||||
activateTokensByBalance,
|
||||
fetchTokens,
|
||||
updateSafe,
|
||||
transactions,
|
||||
} = this.props
|
||||
|
@ -117,6 +120,7 @@ class SafeView extends React.Component<Props, State> {
|
|||
<Page>
|
||||
<Layout
|
||||
activeTokens={activeTokens}
|
||||
blacklistedTokens={blacklistedTokens}
|
||||
tokens={tokens}
|
||||
provider={provider}
|
||||
safe={safe}
|
||||
|
@ -126,6 +130,8 @@ class SafeView extends React.Component<Props, State> {
|
|||
createTransaction={createTransaction}
|
||||
processTransaction={processTransaction}
|
||||
fetchTransactions={fetchTransactions}
|
||||
activateTokensByBalance={activateTokensByBalance}
|
||||
fetchTokens={fetchTokens}
|
||||
updateSafe={updateSafe}
|
||||
transactions={transactions}
|
||||
sendFunds={sendFunds}
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
safeSelector,
|
||||
safeActiveTokensSelector,
|
||||
safeBalancesSelector,
|
||||
safeBlacklistedTokensSelector,
|
||||
type RouterProps,
|
||||
type SafeSelectorProps,
|
||||
} from '~/routes/safe/store/selectors'
|
||||
|
@ -25,6 +26,7 @@ export type SelectorProps = {
|
|||
provider: string,
|
||||
tokens: List<Token>,
|
||||
activeTokens: List<Token>,
|
||||
blacklistedTokens: List<Token>,
|
||||
userAddress: string,
|
||||
network: string,
|
||||
safeUrl: string,
|
||||
|
@ -135,6 +137,7 @@ export default createStructuredSelector<Object, *>({
|
|||
provider: providerNameSelector,
|
||||
tokens: orderedTokenListSelector,
|
||||
activeTokens: extendedSafeTokensSelector,
|
||||
blacklistedTokens: safeBlacklistedTokensSelector,
|
||||
granted: grantedSelector,
|
||||
userAddress: userAccountSelector,
|
||||
network: networkSelector,
|
||||
|
|
|
@ -19,7 +19,7 @@ export const calculateBalanceOf = async (tokenAddress: string, safeAddress: stri
|
|||
const token = await erc20Token.at(tokenAddress)
|
||||
balance = await token.balanceOf(safeAddress)
|
||||
} catch (err) {
|
||||
console.error('Failed to fetch token balances: ', err)
|
||||
console.error('Failed to fetch token balances: ', tokenAddress, err)
|
||||
}
|
||||
|
||||
return new BigNumber(balance).div(10 ** decimals).toString()
|
||||
|
@ -50,7 +50,6 @@ const fetchTokenBalances = (safeAddress: string, tokens: List<Token>) => async (
|
|||
|
||||
dispatch(updateSafe({ address: safeAddress, balances }))
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line
|
||||
console.error('Error when fetching token balances:', err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// @flow
|
||||
import { Set } from 'immutable'
|
||||
import type { Dispatch as ReduxDispatch } from 'redux'
|
||||
import { type GlobalState } from '~/store'
|
||||
import updateSafe from './updateSafe'
|
||||
|
||||
const updateBlacklistedTokens = (safeAddress: string, blacklistedTokens: Set<string>) => async (
|
||||
dispatch: ReduxDispatch<GlobalState>,
|
||||
) => {
|
||||
dispatch(updateSafe({ address: safeAddress, blacklistedTokens }))
|
||||
}
|
||||
|
||||
export default updateBlacklistedTokens
|
|
@ -1,5 +1,5 @@
|
|||
// @flow
|
||||
import type { Store, AnyAction } from 'redux'
|
||||
import type { AnyAction, Store } from 'redux'
|
||||
import { List } from 'immutable'
|
||||
import { ADD_SAFE } from '~/routes/safe/store/actions/addSafe'
|
||||
import { UPDATE_SAFE } from '~/routes/safe/store/actions/updateSafe'
|
||||
|
@ -10,10 +10,12 @@ import { REPLACE_SAFE_OWNER } from '~/routes/safe/store/actions/replaceSafeOwner
|
|||
import { EDIT_SAFE_OWNER } from '~/routes/safe/store/actions/editSafeOwner'
|
||||
import { type GlobalState } from '~/store/'
|
||||
import {
|
||||
saveSafes, setOwners, removeOwners, saveDefaultSafe,
|
||||
removeOwners,
|
||||
saveDefaultSafe,
|
||||
saveSafes,
|
||||
setOwners,
|
||||
} from '~/logic/safe/utils'
|
||||
import { safesMapSelector, getActiveTokensAddressesForAllSafes } from '~/routes/safe/store/selectors'
|
||||
|
||||
import { getActiveTokensAddressesForAllSafes, safesMapSelector } from '~/routes/safe/store/selectors'
|
||||
import { tokensSelector } from '~/logic/tokens/store/selectors'
|
||||
import type { Token } from '~/logic/tokens/store/model/token'
|
||||
import { makeOwner } from '~/routes/safe/store/models/owner'
|
||||
|
|
|
@ -12,6 +12,7 @@ export type SafeProps = {
|
|||
owners: List<Owner>,
|
||||
balances?: Map<string, string>,
|
||||
activeTokens: Set<string>,
|
||||
blacklistedTokens: Set<string>,
|
||||
ethBalance?: string,
|
||||
}
|
||||
|
||||
|
@ -22,6 +23,7 @@ const SafeRecord: RecordFactory<SafeProps> = Record({
|
|||
ethBalance: 0,
|
||||
owners: List([]),
|
||||
activeTokens: new Set(),
|
||||
blacklistedTokens: new Set(),
|
||||
balances: Map({}),
|
||||
})
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ export const buildSafe = (storedSafe: SafeProps) => {
|
|||
const addresses = storedSafe.owners.map((owner: OwnerProps) => owner.address)
|
||||
const owners = buildOwnersFrom(Array.from(names), Array.from(addresses))
|
||||
const activeTokens = Set(storedSafe.activeTokens)
|
||||
const blacklistedTokens = Set(storedSafe.blacklistedTokens)
|
||||
const balances = Map(storedSafe.balances)
|
||||
|
||||
const safe: SafeProps = {
|
||||
|
@ -29,6 +30,7 @@ export const buildSafe = (storedSafe: SafeProps) => {
|
|||
owners,
|
||||
balances,
|
||||
activeTokens,
|
||||
blacklistedTokens,
|
||||
}
|
||||
|
||||
return safe
|
||||
|
|
|
@ -106,6 +106,21 @@ export const safeActiveTokensSelector: Selector<GlobalState, RouterProps, List<s
|
|||
},
|
||||
)
|
||||
|
||||
export const safeBlacklistedTokensSelector: Selector<GlobalState, RouterProps, List<string>> = createSelector(
|
||||
safeSelector,
|
||||
(safe: Safe) => {
|
||||
if (!safe) {
|
||||
return List()
|
||||
}
|
||||
|
||||
return safe.blacklistedTokens
|
||||
},
|
||||
)
|
||||
|
||||
export const safeActiveTokensSelectorBySafe = (safeAddress: string, safes: Map<string, Safe>): List<string> => safes.get(safeAddress).get('activeTokens')
|
||||
|
||||
export const safeBlacklistedTokensSelectorBySafe = (safeAddress: string, safes: Map<string, Safe>): List<string> => safes.get(safeAddress).get('blacklistedTokens')
|
||||
|
||||
export const safeBalancesSelector: Selector<GlobalState, RouterProps, Map<string, string>> = createSelector(
|
||||
safeSelector,
|
||||
(safe: Safe) => {
|
||||
|
@ -132,7 +147,23 @@ export const getActiveTokensAddressesForAllSafes: Selector<GlobalState, any, Set
|
|||
},
|
||||
)
|
||||
|
||||
export const getBlacklistedTokensAddressesForAllSafes: Selector<GlobalState, any, Set<string>> = createSelector(
|
||||
safesListSelector,
|
||||
(safes: List<Safe>) => {
|
||||
const addresses = Set().withMutations((set) => {
|
||||
safes.forEach((safe: Safe) => {
|
||||
safe.blacklistedTokens.forEach((tokenAddress) => {
|
||||
set.add(tokenAddress)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
return addresses
|
||||
},
|
||||
)
|
||||
|
||||
export default createStructuredSelector<Object, *>({
|
||||
safe: safeSelector,
|
||||
tokens: safeActiveTokensSelector,
|
||||
blacklistedTokens: safeBlacklistedTokensSelector,
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue