Merge pull request #1411 from gnosis/release/v2.12.0

Backmerge 2.12.0 to development
This commit is contained in:
Daniel Sanchez 2020-09-29 17:18:23 +02:00 committed by GitHub
commit 24f2828a7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 101 additions and 65 deletions

View File

@ -1,6 +1,6 @@
{
"name": "safe-react",
"version": "2.11.1",
"version": "2.12.0",
"description": "Allowing crypto users manage funds in a safer way",
"website": "https://github.com/gnosis/safe-react#readme",
"bugs": {

View File

@ -1,17 +1,9 @@
import updateSafe from './updateSafe'
import { Set } from 'immutable'
import updateAssetsList from './updateAssetsList'
import { Dispatch } from 'src/logic/safe/store/actions/types.d'
// the selector uses ownProps argument/router props to get the address of the safe
// so in order to use it I had to recreate the same structure
// const generateMatchProps = (safeAddress: string) => ({
// match: {
// params: {
// [SAFE_PARAM_ADDRESS]: safeAddress,
// },
// },
// })
const updateActiveAssets = (safeAddress, activeAssets) => async (dispatch) => {
dispatch(updateSafe({ address: safeAddress, activeAssets }))
const updateActiveAssets = (safeAddress: string, activeAssets: Set<string>) => (dispatch: Dispatch): void => {
dispatch(updateAssetsList({ safeAddress, activeAssets }))
}
export default updateActiveAssets

View File

@ -1,6 +1,6 @@
import updateSafe from './updateSafe'
import { Set } from 'immutable'
import { Dispatch } from 'redux'
import updateTokensList from './updateTokensList'
import { Dispatch } from 'src/logic/safe/store/actions/types.d'
// the selector uses ownProps argument/router props to get the address of the safe
// so in order to use it I had to recreate the same structure
@ -13,7 +13,7 @@ import { Dispatch } from 'redux'
// })
const updateActiveTokens = (safeAddress: string, activeTokens: Set<string>) => (dispatch: Dispatch): void => {
dispatch(updateSafe({ address: safeAddress, activeTokens }))
dispatch(updateTokensList({ safeAddress, activeTokens }))
}
export default updateActiveTokens

View File

@ -0,0 +1,7 @@
import { createAction } from 'redux-actions'
export const UPDATE_ASSETS_LIST = 'UPDATE_ASSETS_LIST'
const updateAssetsList = createAction(UPDATE_ASSETS_LIST)
export default updateAssetsList

View File

@ -1,7 +1,9 @@
import updateSafe from './updateSafe'
import { Set } from 'immutable'
import updateAssetsList from './updateAssetsList'
import { Dispatch } from 'src/logic/safe/store/actions/types.d'
const updateBlacklistedAssets = (safeAddress, blacklistedAssets) => async (dispatch) => {
dispatch(updateSafe({ address: safeAddress, blacklistedAssets }))
const updateBlacklistedAssets = (safeAddress: string, blacklistedAssets: Set<string>) => (dispatch: Dispatch): void => {
dispatch(updateAssetsList({ safeAddress, blacklistedAssets }))
}
export default updateBlacklistedAssets

View File

@ -1,9 +1,9 @@
import updateSafe from './updateSafe'
import { Dispatch } from 'redux'
import { Set } from 'immutable'
import updateTokensList from './updateTokensList'
import { Dispatch } from 'src/logic/safe/store/actions/types.d'
const updateBlacklistedTokens = (safeAddress: string, blacklistedTokens: Set<string>) => (dispatch: Dispatch): void => {
dispatch(updateSafe({ address: safeAddress, blacklistedTokens }))
dispatch(updateTokensList({ safeAddress, blacklistedTokens }))
}
export default updateBlacklistedTokens

View File

@ -0,0 +1,7 @@
import { createAction } from 'redux-actions'
export const UPDATE_TOKENS_LIST = 'UPDATE_TOKENS_LIST'
const updateTokenList = createAction(UPDATE_TOKENS_LIST)
export default updateTokenList

View File

@ -11,6 +11,8 @@ import { REMOVE_SAFE_OWNER } from 'src/logic/safe/store/actions/removeSafeOwner'
import { REPLACE_SAFE_OWNER } from 'src/logic/safe/store/actions/replaceSafeOwner'
import { SET_DEFAULT_SAFE } from 'src/logic/safe/store/actions/setDefaultSafe'
import { UPDATE_SAFE } from 'src/logic/safe/store/actions/updateSafe'
import { UPDATE_TOKENS_LIST } from 'src/logic/safe/store/actions/updateTokensList'
import { UPDATE_ASSETS_LIST } from 'src/logic/safe/store/actions/updateAssetsList'
import { getActiveTokensAddressesForAllSafes, safesMapSelector } from 'src/logic/safe/store/selectors'
import { checksumAddress } from 'src/utils/checksumAddress'
import { makeAddressBookEntry } from 'src/logic/addressBook/model/addressBook'
@ -31,6 +33,8 @@ const watchedActions = [
REPLACE_SAFE_OWNER,
EDIT_SAFE_OWNER,
ACTIVATE_TOKEN_FOR_ALL_SAFES,
UPDATE_TOKENS_LIST,
UPDATE_ASSETS_LIST,
SET_DEFAULT_SAFE,
]

View File

@ -11,11 +11,14 @@ import { REPLACE_SAFE_OWNER } from 'src/logic/safe/store/actions/replaceSafeOwne
import { SET_DEFAULT_SAFE } from 'src/logic/safe/store/actions/setDefaultSafe'
import { SET_LATEST_MASTER_CONTRACT_VERSION } from 'src/logic/safe/store/actions/setLatestMasterContractVersion'
import { UPDATE_SAFE } from 'src/logic/safe/store/actions/updateSafe'
import { UPDATE_TOKENS_LIST } from 'src/logic/safe/store/actions/updateTokensList'
import { UPDATE_ASSETS_LIST } from 'src/logic/safe/store/actions/updateAssetsList'
import { makeOwner } from 'src/logic/safe/store/models/owner'
import makeSafe, { SafeRecordProps } from 'src/logic/safe/store/models/safe'
import { checksumAddress } from 'src/utils/checksumAddress'
import { SafeReducerMap } from 'src/routes/safe/store/reducer/types/safe'
import { ADD_OR_UPDATE_SAFE } from 'src/logic/safe/store/actions/addOrUpdateSafe'
import { sameAddress } from 'src/logic/wallets/ethAddresses'
export const SAFE_REDUCER_ID = 'safes'
export const DEFAULT_SAFE_INITIAL_STATE = 'NOT_ASKED'
@ -51,10 +54,10 @@ const updateSafeProps = (prevSafe, safe) => {
// We check each safe property sent in action.payload
safeProperties.forEach((key) => {
if (safe[key] && typeof safe[key] === 'object') {
if (safe[key].length) {
if (safe[key].length >= 0) {
// If type is array we update the array
record.update(key, () => safe[key])
} else if (safe[key].size) {
} else if (safe[key].size >= 0) {
// If type is Immutable List we replace current List
// If type is Object we do a merge
List.isList(safe[key])
@ -130,6 +133,14 @@ export default handleActions(
[ADD_SAFE_OWNER]: (state: SafeReducerMap, action) => {
const { ownerAddress, ownerName, safeAddress } = action.payload
const addressFound = state
.getIn(['safes', safeAddress])
.owners.find((owner) => sameAddress(owner.address, ownerAddress))
if (addressFound) {
return state
}
return state.updateIn(['safes', safeAddress], (prevSafe) =>
prevSafe.merge({
owners: prevSafe.owners.push(makeOwner({ address: ownerAddress, name: ownerName })),
@ -167,6 +178,24 @@ export default handleActions(
return prevSafe.merge({ owners: updatedOwners })
})
},
[UPDATE_TOKENS_LIST]: (state: SafeReducerMap, action) => {
// Only activeTokens or blackListedTokens is required
const { safeAddress, activeTokens, blacklistedTokens } = action.payload
const key = activeTokens ? 'activeTokens' : 'blacklistedTokens'
const list = activeTokens ?? blacklistedTokens
return state.updateIn(['safes', safeAddress], (prevSafe) => prevSafe.set(key, list))
},
[UPDATE_ASSETS_LIST]: (state: SafeReducerMap, action) => {
// Only activeAssets or blackListedAssets is required
const { safeAddress, activeAssets, blacklistedAssets } = action.payload
const key = activeAssets ? 'activeAssets' : 'blacklistedAssets'
const list = activeAssets ?? blacklistedAssets
return state.updateIn(['safes', safeAddress], (prevSafe) => prevSafe.set(key, list))
},
[SET_DEFAULT_SAFE]: (state: SafeReducerMap, action) => state.set('defaultSafe', action.payload),
[SET_LATEST_MASTER_CONTRACT_VERSION]: (state: SafeReducerMap, action) =>
state.set('latestMasterContractVersion', action.payload),

View File

@ -30,15 +30,13 @@ describe('Feature > Balances', () => {
const expectedResult = '100'
// when
store.dispatch(updateActiveTokens(safeAddress, Set([token.address])))
store.dispatch(updateSafe({ address: safeAddress, balances }))
store.dispatch(updateActiveTokens(safeAddress, Set([token.address])))
const safe = safesMapSelector(store.getState()).get(safeAddress)
//@ts-ignore
const balanceResult = safe.get('balances').get(token.address)
//@ts-ignore
const activeTokens = safe.get('activeTokens')
const tokenIsActive = activeTokens.has(token.address)
const balanceResult = safe?.get('balances').get(token.address)
const activeTokens = safe?.get('activeTokens')
const tokenIsActive = activeTokens?.has(token.address)
// then
expect(balanceResult).toBe(expectedResult)
@ -53,8 +51,7 @@ describe('Feature > Balances', () => {
// when
store.dispatch(updateSafe({ address: safeAddress, ethBalance: etherAmount }))
const safe = safesMapSelector(store.getState()).get(safeAddress)
//@ts-ignore
const balanceResult = safe.get('ethBalance')
const balanceResult = safe?.get('ethBalance')
// then
expect(balanceResult).toBe(expectedResult)

View File

@ -4,7 +4,7 @@ import { makeStyles } from '@material-ui/core/styles'
import Search from '@material-ui/icons/Search'
import cn from 'classnames'
import SearchBar from 'material-ui-search-bar'
import React, { useEffect, useState } from 'react'
import React, { useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { FixedSizeList } from 'react-window'
@ -55,11 +55,6 @@ const AssetsList = (props) => {
const [blacklistedAssetsAddresses, setBlacklistedAssetsAddresses] = useState(blacklistedAssets)
const nftAssetsList = useSelector(nftAssetsListSelector)
useEffect(() => {
dispatch(updateActiveAssets(safeAddress, activeAssetsAddresses))
dispatch(updateBlacklistedAssets(safeAddress, blacklistedAssetsAddresses))
}, [activeAssetsAddresses, blacklistedAssetsAddresses, dispatch, safeAddress])
const onCancelSearch = () => {
setFilterValue('')
}
@ -73,19 +68,22 @@ const AssetsList = (props) => {
}
const onSwitch = (asset) => () => {
const { address } = asset
const activeAssetsAddressesResult = activeAssetsAddresses.contains(address)
? activeAssetsAddresses.remove(address)
: activeAssetsAddresses.add(address)
const blacklistedAssetsAddressesResult = activeAssetsAddresses.has(address)
? blacklistedAssetsAddresses.add(address)
: blacklistedAssetsAddresses.remove(address)
setActiveAssetsAddresses(activeAssetsAddressesResult)
setBlacklistedAssetsAddresses(blacklistedAssetsAddressesResult)
return {
activeAssetsAddresses: activeAssetsAddressesResult,
blacklistedAssetsAddresses: blacklistedAssetsAddressesResult,
let newActiveAssetsAddresses
let newBlacklistedAssetsAddresses
if (activeAssetsAddresses.has(asset.address)) {
newActiveAssetsAddresses = activeAssetsAddresses.delete(asset.address)
newBlacklistedAssetsAddresses = blacklistedAssetsAddresses.add(asset.address)
} else {
newActiveAssetsAddresses = activeAssetsAddresses.add(asset.address)
newBlacklistedAssetsAddresses = blacklistedAssetsAddresses.delete(asset.address)
}
// Set local state
setActiveAssetsAddresses(newActiveAssetsAddresses)
setBlacklistedAssetsAddresses(newBlacklistedAssetsAddresses)
// Dispatch to global state
dispatch(updateActiveAssets(safeAddress, newActiveAssetsAddresses))
dispatch(updateBlacklistedAssets(safeAddress, newBlacklistedAssetsAddresses))
}
const createItemData = (assetsList) => {

View File

@ -5,7 +5,7 @@ import Search from '@material-ui/icons/Search'
import cn from 'classnames'
import { List, Set } from 'immutable'
import SearchBar from 'material-ui-search-bar'
import * as React from 'react'
import React, { useState } from 'react'
import { FixedSizeList } from 'react-window'
import TokenRow from './TokenRow'
@ -17,7 +17,6 @@ import Button from 'src/components/layout/Button'
import Divider from 'src/components/layout/Divider'
import Hairline from 'src/components/layout/Hairline'
import Row from 'src/components/layout/Row'
import { useEffect, useState } from 'react'
import { Token } from 'src/logic/tokens/store/model/token'
import { useDispatch } from 'react-redux'
import updateBlacklistedTokens from 'src/logic/safe/store/actions/updateBlacklistedTokens'
@ -51,13 +50,6 @@ export const TokenList = (props: Props): React.ReactElement => {
const [filter, setFilter] = useState('')
const dispatch = useDispatch()
useEffect(() => {
return () => {
dispatch(updateActiveTokens(safeAddress, activeTokensAddresses))
dispatch(updateBlacklistedTokens(safeAddress, blacklistedTokensAddresses))
}
}, [dispatch, safeAddress, activeTokensAddresses, blacklistedTokensAddresses])
const searchClasses = {
input: classes.searchInput,
root: classes.searchRoot,
@ -75,14 +67,22 @@ export const TokenList = (props: Props): React.ReactElement => {
}
const onSwitch = (token: Token) => () => {
let newActiveTokensAddresses
let newBlacklistedTokensAddresses
if (activeTokensAddresses.has(token.address)) {
const newTokens = activeTokensAddresses.remove(token.address)
setActiveTokensAddresses(newTokens)
setBlacklistedTokensAddresses(blacklistedTokensAddresses.add(token.address))
newActiveTokensAddresses = activeTokensAddresses.delete(token.address)
newBlacklistedTokensAddresses = blacklistedTokensAddresses.add(token.address)
} else {
setActiveTokensAddresses(activeTokensAddresses.add(token.address))
setBlacklistedTokensAddresses(blacklistedTokensAddresses.remove(token.address))
newActiveTokensAddresses = activeTokensAddresses.add(token.address)
newBlacklistedTokensAddresses = blacklistedTokensAddresses.delete(token.address)
}
// Set local state
setActiveTokensAddresses(newActiveTokensAddresses)
setBlacklistedTokensAddresses(newBlacklistedTokensAddresses)
// Dispatch to global state
dispatch(updateActiveTokens(safeAddress, newActiveTokensAddresses))
dispatch(updateBlacklistedTokens(safeAddress, newBlacklistedTokensAddresses))
}
const createItemData = (