WIP: code cleanup and fix typings

This commit is contained in:
fernandomg 2020-06-29 15:46:00 -03:00
parent 3eba845314
commit ebf8d149a2
9 changed files with 159 additions and 129 deletions

View File

@ -4,7 +4,11 @@ import TableRow from '@material-ui/core/TableRow'
import TableSortLabel from '@material-ui/core/TableSortLabel'
import * as React from 'react'
export const cellWidth = (width) => {
interface CellWidth {
maxWidth: string
}
export const cellWidth = (width: string | number): CellWidth | undefined => {
if (!width) {
return undefined
}

View File

@ -32,17 +32,11 @@ export const WALLET_PROVIDER = {
}
export const ETHEREUM_NETWORK_IDS = {
// $FlowFixMe
1: ETHEREUM_NETWORK.MAINNET,
// $FlowFixMe
2: ETHEREUM_NETWORK.MORDEN,
// $FlowFixMe
3: ETHEREUM_NETWORK.ROPSTEN,
// $FlowFixMe
4: ETHEREUM_NETWORK.RINKEBY,
// $FlowFixMe
5: ETHEREUM_NETWORK.GOERLI,
// $FlowFixMe
42: ETHEREUM_NETWORK.KOVAN,
}

View File

@ -2,14 +2,15 @@ import { handleActions } from 'redux-actions'
import { ADD_PROVIDER } from 'src/logic/wallets/store/actions/addProvider'
import { REMOVE_PROVIDER } from 'src/logic/wallets/store/actions/removeProvider'
import { makeProvider } from 'src/logic/wallets/store/model/provider'
import { makeProvider, ProviderRecord, ProviderProps } from 'src/logic/wallets/store/model/provider'
export const PROVIDER_REDUCER_ID = 'providers'
export default handleActions(
{
[ADD_PROVIDER]: (state, { payload }) => makeProvider(payload),
[REMOVE_PROVIDER]: () => makeProvider(),
[ADD_PROVIDER]: (state: { providers: ProviderProps }, { payload }: { payload: ProviderProps }): ProviderRecord =>
makeProvider(payload),
[REMOVE_PROVIDER]: (): ProviderRecord => makeProvider(),
},
makeProvider(),
)

View File

@ -2,28 +2,30 @@ import { createSelector } from 'reselect'
import { ETHEREUM_NETWORK, ETHEREUM_NETWORK_IDS } from 'src/logic/wallets/getWeb3'
import { PROVIDER_REDUCER_ID } from 'src/logic/wallets/store/reducer/provider'
import { GnosisState } from 'src/store'
import { ProviderRecord } from '../model/provider'
export const providerSelector = (state) => state[PROVIDER_REDUCER_ID]
export const providerSelector = (state: GnosisState): ProviderRecord => state[PROVIDER_REDUCER_ID]
export const userAccountSelector = createSelector(providerSelector, (provider) => {
export const userAccountSelector = createSelector(providerSelector, (provider: ProviderRecord): string => {
const account = provider.get('account')
return account || ''
})
export const providerNameSelector = createSelector(providerSelector, (provider) => {
export const providerNameSelector = createSelector(providerSelector, (provider: ProviderRecord): string | undefined => {
const name = provider.get('name')
return name ? name.toLowerCase() : undefined
})
export const networkSelector = createSelector(providerSelector, (provider) => {
export const networkSelector = createSelector(providerSelector, (provider: ProviderRecord): string => {
const networkId = provider.get('network')
const network = ETHEREUM_NETWORK_IDS[networkId] || ETHEREUM_NETWORK.UNKNOWN
return network
return ETHEREUM_NETWORK_IDS[networkId] || ETHEREUM_NETWORK.UNKNOWN
})
export const loadedSelector = createSelector(providerSelector, (provider) => provider.get('loaded'))
export const loadedSelector = createSelector(providerSelector, (provider: ProviderRecord): boolean =>
provider.get('loaded'),
)
export const availableSelector = createSelector(providerSelector, (provider) => provider.get('available'))
export const availableSelector = createSelector(providerSelector, (provider: ProviderRecord): boolean =>
provider.get('available'),
)

View File

@ -10,30 +10,31 @@ export const getModuleData = (modules: Set<string>): List<{ [MODULES_TABLE_ADDRE
}
interface TableColumn {
id: string
order: boolean
disablePadding: boolean
label: string
align?: 'inherit' | 'left' | 'center' | 'right' | 'justify'
custom: boolean
align?: string
disablePadding: boolean
id: string
label: string
order: boolean
width?: number
}
export const generateColumns = (): List<TableColumn> => {
const addressColumn: TableColumn = {
id: MODULES_TABLE_ADDRESS_ID,
order: false,
disablePadding: false,
label: 'Address',
custom: false,
align: 'left',
custom: false,
disablePadding: false,
id: MODULES_TABLE_ADDRESS_ID,
label: 'Address',
order: false,
}
const actionsColumn: TableColumn = {
id: MODULES_TABLE_ACTIONS_ID,
order: false,
disablePadding: false,
label: '',
custom: true,
disablePadding: false,
id: MODULES_TABLE_ACTIONS_ID,
label: '',
order: false,
}
return List([addressColumn, actionsColumn])

View File

@ -1,101 +1,86 @@
import { Set } from 'immutable'
import { GenericModal, ModalFooterConfirmation } from '@gnosis.pm/safe-react-components'
import { makeStyles } from '@material-ui/core/styles'
// import { useSnackbar } from 'notistack'
import React, { useState } from 'react'
import { /*useDispatch, */ useSelector } from 'react-redux'
import TableContainer from '@material-ui/core/TableContainer'
import cn from 'classnames'
import { Set } from 'immutable'
import { useSnackbar } from 'notistack'
import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
// import ChangeThreshold from './ChangeThreshold'
import { generateColumns, MODULES_TABLE_ADDRESS_ID, getModuleData } from './dataFetcher'
import { styles } from './style'
import BinIcon from '../assets/icons/bin.svg'
import Modal from 'src/components/Modal'
import DividerLine from 'src/components/DividerLine'
import Identicon from 'src/components/Identicon'
import Block from 'src/components/layout/Block'
import Bold from 'src/components/layout/Bold'
// import Button from 'src/components/layout/Button'
import Heading from 'src/components/layout/Heading'
import Img from 'src/components/layout/Img'
import Paragraph from 'src/components/layout/Paragraph'
// import Row from 'src/components/layout/Row'
// import { getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts'
// import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions'
// import { grantedSelector } from 'src/routes/safe/container/selector'
// import createTransaction from 'src/routes/safe/store/actions/createTransaction'
import Row from 'src/components/layout/Row'
import { TableCell, TableRow } from 'src/components/layout/Table'
import Table from 'src/components/Table'
import { getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts'
import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions'
import { grantedSelector } from 'src/routes/safe/container/selector'
import createTransaction from 'src/routes/safe/store/actions/createTransaction'
import {
// safeOwnersSelector,
// safeParamAddressFromStateSelector,
// safeThresholdSelector,
safeParamAddressFromStateSelector,
safeNonceSelector,
safeModulesSelector,
} from 'src/routes/safe/store/selectors'
import DividerLine from 'src/components/DividerLine'
import TableContainer from '@material-ui/core/TableContainer'
import Table from '../../../../../components/Table'
import TableRow from '@material-ui/core/TableRow'
import TableCell from '@material-ui/core/TableCell'
import { cellWidth } from '../../../../../components/Table/TableHead'
import OwnerAddressTableCell from '../ManageOwners/OwnerAddressTableCell'
import Row from '../../../../../components/layout/Row'
import Img from '../../../../../components/layout/Img'
// import RenameOwnerIcon from '../ManageOwners/assets/icons/rename-owner.svg'
// import ReplaceOwnerIcon from '../ManageOwners/assets/icons/replace-owner.svg'
import RemoveOwnerIcon from '../assets/icons/bin.svg'
import { generateColumns, MODULES_TABLE_ADDRESS_ID, getModuleData } from './dataFetcher'
import { grantedSelector } from '../../../container/selector'
// import RemoveOwnerModal from '../ManageOwners/RemoveOwnerModal'
// import { getOwnersWithNameFromAddressBook } from '../../../../../logic/addressBook/utils'
// import { getOwnerData } from '../ManageOwners/dataFetcher'
export const REMOVE_MODULE_BTN_TEST_ID = 'remove-module-btn'
export const MODULES_ROW_TEST_ID = 'owners-row'
const useStyles = makeStyles(styles)
const useToggle = (initialOn = false) => {
const [on, setOn] = useState(initialOn)
const toggle = () => setOn(!on)
return { on, toggle }
}
const Advanced: React.FC = () => {
const classes = useStyles()
const columns = generateColumns()
const autoColumns = columns.filter(({ custom }) => !custom)
// const { enqueueSnackbar, closeSnackbar } = useSnackbar()
// const dispatch = useDispatch()
const { on, toggle } = useToggle()
const safeAddress = useSelector(safeParamAddressFromStateSelector)
const nonce = useSelector(safeNonceSelector)
const granted = useSelector(grantedSelector)
const modules = useSelector(safeModulesSelector)
console.log(modules)
const moduleData = getModuleData(Set(modules))
// const ownersAdbk = getOwnersWithNameFromAddressBook(addressBook, owners)
// const ownerData = getOwnerData(ownersAdbk)
// const safeAddress = useSelector(safeParamAddressFromStateSelector)
// const owners = useSelector(safeOwnersSelector)
const [viewRemoveModuleModal, setViewRemoveModuleModal] = React.useState(false)
const hideRemoveModuleModal = () => setViewRemoveModuleModal(false)
// const onChangeThreshold = async (newThreshold) => {
// const safeInstance = await getGnosisSafeInstanceAt(safeAddress)
// const txData = safeInstance.contract.methods.changeThreshold(newThreshold).encodeABI()
//
// dispatch(
// createTransaction({
// safeAddress,
// to: safeAddress,
// valueInWei: 0,
// txData,
// notifiedTransaction: TX_NOTIFICATION_TYPES.SETTINGS_CHANGE_TX,
// enqueueSnackbar,
// closeSnackbar,
// } as any),
// )
// }
const [selectedModule, setSelectedModule] = React.useState(null)
const triggerRemoveSelectedModule = (moduleAddress: string): void => {
setSelectedModule(moduleAddress)
setViewRemoveModuleModal(true)
}
const { enqueueSnackbar, closeSnackbar } = useSnackbar()
const dispatch = useDispatch()
const removeSelectedModule = async (): Promise<void> => {
const safeInstance = await getGnosisSafeInstanceAt(safeAddress)
const txData = safeInstance.contract.methods.disableModule(selectedModule).encodeABI()
dispatch(
createTransaction({
safeAddress,
to: safeAddress,
valueInWei: '0',
txData,
notifiedTransaction: TX_NOTIFICATION_TYPES.SETTINGS_CHANGE_TX,
enqueueSnackbar,
closeSnackbar,
}),
)
}
return (
<>
{/* Nonce */}
<Block className={classes.container}>
<Heading tag="h2">Safe Nonce</Heading>
<Paragraph>
@ -107,6 +92,8 @@ const Advanced: React.FC = () => {
</Paragraph>
</Block>
<DividerLine withArrow={false} />
{/* Modules */}
<Block className={classes.container}>
<Heading tag="h2">Safe Modules</Heading>
<Paragraph>
@ -145,23 +132,31 @@ const Advanced: React.FC = () => {
key={index}
tabIndex={-1}
>
{autoColumns.map((column: any) => (
<TableCell align={column.align} component="td" key={column.id} style={cellWidth(column.width)}>
{column.id === MODULES_TABLE_ADDRESS_ID ? (
<OwnerAddressTableCell address={row[column.id]} showLinks />
{autoColumns.map((column) => {
const columnId = column.id
const rowElement = row[columnId]
return (
<TableCell align={column.align} component="td" key={columnId}>
{columnId === MODULES_TABLE_ADDRESS_ID ? (
<Block justify="left">
<Identicon address={rowElement} diameter={32} />
<Paragraph style={{ marginLeft: 10 }}>{rowElement}</Paragraph>
</Block>
) : (
row[column.id]
rowElement
)}
</TableCell>
))}
)
})}
<TableCell component="td">
<Row align="end" className={classes.actions}>
{granted && (
<Img
alt="Remove module"
className={classes.removeModuleIcon}
onClick={toggle}
src={RemoveOwnerIcon}
onClick={triggerRemoveSelectedModule}
src={BinIcon}
testId={REMOVE_MODULE_BTN_TEST_ID}
/>
)}
@ -174,21 +169,21 @@ const Advanced: React.FC = () => {
</TableContainer>
)}
</Block>
{/*<RemoveModuleModal*/}
{/* isOpen={showRemoveModal}*/}
{/* onClose={onHide('RemoveModal')}*/}
{/* ownerAddress={selectedModalAddress}*/}
{/* ownerName={selectedModalName}*/}
{/*/>*/}
<Modal description="Disable Module" handleClose={toggle} open={on} title="Disable Module">
{/*<ChangeThreshold*/}
{/* onChangeThreshold={onChangeThreshold}*/}
{/* onClose={toggle}*/}
{/* owners={owners}*/}
{/* safeAddress={safeAddress}*/}
{/* threshold={threshold}*/}
{/*/>*/}
</Modal>
{viewRemoveModuleModal && (
<GenericModal
onClose={hideRemoveModuleModal}
title="Disable Module"
body={<div>This is the body</div>}
footer={
<ModalFooterConfirmation
okText="Remove"
cancelText="Cancel"
handleCancel={hideRemoveModuleModal}
handleOk={removeSelectedModule}
/>
}
/>
)}
</>
)
}

View File

@ -1,5 +1,6 @@
import { push } from 'connected-react-router'
import { List, Map } from 'immutable'
import { WithSnackbarProps } from 'notistack'
import { batch } from 'react-redux'
import semverSatisfies from 'semver/functions/satisfies'
@ -35,6 +36,8 @@ import { makeConfirmation } from '../models/confirmation'
import fetchTransactions from './transactions/fetchTransactions'
import { safeTransactionsSelector } from 'src/routes/safe/store/selectors'
import { TransactionStatus, TxArgs } from 'src/routes/safe/store/models/types/transaction'
import { Dispatch } from 'redux'
import { GnosisState } from 'src/store'
export const removeTxFromStore = (tx, safeAddress, dispatch, state) => {
if (tx.isCancellationTx) {
@ -79,6 +82,18 @@ export const storeTx = async (tx, safeAddress, dispatch, state) => {
}
}
interface CreateTransaction extends WithSnackbarProps {
navigateToTransactionsTab?: boolean
notifiedTransaction: string
operation?: number
origin?: string
safeAddress: string
to: string
txData: string
txNonce?: number | string
valueInWei: string
}
const createTransaction = ({
safeAddress,
to,
@ -91,7 +106,7 @@ const createTransaction = ({
operation = CALL,
navigateToTransactionsTab = true,
origin = null,
}) => async (dispatch, getState) => {
}: CreateTransaction) => async (dispatch: Dispatch, getState: () => GnosisState): Promise<void> => {
const state = getState()
if (navigateToTransactionsTab) {

View File

@ -181,7 +181,7 @@ const baseSafe = makeSafe()
export const safeFieldSelector = (field: keyof SafeRecordProps) => (
safe: SafeRecord,
): SafeRecord[keyof SafeRecordProps] => safe.get(field, baseSafe.get(field))
): SafeRecord[keyof SafeRecordProps] | null => (safe ? safe.get(field, baseSafe.get(field)) : null)
export const safeNameSelector = createSelector(safeSelector, safeFieldSelector('name'))

View File

@ -1,6 +1,6 @@
import { connectRouter, routerMiddleware } from 'connected-react-router'
import { createHashHistory } from 'history'
import { applyMiddleware, combineReducers, compose, createStore } from 'redux'
import { applyMiddleware, combineReducers, compose, createStore, CombinedState } from 'redux'
import thunk from 'redux-thunk'
import addressBookMiddleware from 'src/logic/addressBook/store/middleware/addressBookMiddleware'
@ -29,6 +29,8 @@ import incomingTransactions, {
} from 'src/routes/safe/store/reducer/incomingTransactions'
import safe, { SAFE_REDUCER_ID } from 'src/routes/safe/store/reducer/safe'
import transactions, { TRANSACTIONS_REDUCER_ID } from 'src/routes/safe/store/reducer/transactions'
import { ProviderRecord } from '../logic/wallets/store/model/provider'
import { SafeRecordProps } from '../routes/safe/store/models/safe'
export const history = createHashHistory({ hashType: 'slash' })
@ -63,6 +65,22 @@ const reducers = combineReducers({
[CURRENT_SESSION_REDUCER_ID]: currentSession,
})
export type GnosisState = CombinedState<{
[PROVIDER_REDUCER_ID]: ProviderRecord
[SAFE_REDUCER_ID]: SafeRecordProps
// [NFT_ASSETS_REDUCER_ID]: nftAssetReducer,
// [NFT_TOKENS_REDUCER_ID]: nftTokensReducer,
// [TOKEN_REDUCER_ID]: tokens,
// [TRANSACTIONS_REDUCER_ID]: transactions,
// [CANCELLATION_TRANSACTIONS_REDUCER_ID]: cancellationTransactions,
// [INCOMING_TRANSACTIONS_REDUCER_ID]: incomingTransactions,
// [NOTIFICATIONS_REDUCER_ID]: notifications,
// [CURRENCY_VALUES_KEY]: currencyValues,
// [COOKIES_REDUCER_ID]: cookies,
// [ADDRESS_BOOK_REDUCER_ID]: addressBook,
// [CURRENT_SESSION_REDUCER_ID]: currentSession,
}>
export const store: any = createStore(reducers, finalCreateStore)
export const aNewStore = (localState?: any) => createStore(reducers, localState, finalCreateStore)