diff --git a/.eslintrc.js b/.eslintrc.js index a4bfe751..714447af 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -18,6 +18,8 @@ module.exports = { 'react-hooks/rules-of-hooks': 'error', 'react-hooks/exhaustive-deps': 'warn', 'react/prop-types': 'off', + // Remove when resolved issue with strictNullChecks + 'react/display-name': 'off', '@typescript-eslint/camelcase': 'off', '@typescript-eslint/no-var-requires': 'off', '@typescript-eslint/no-empty-function': 'off', diff --git a/package.json b/package.json index 358c706f..6f30948f 100644 --- a/package.json +++ b/package.json @@ -178,7 +178,7 @@ "bignumber.js": "9.0.0", "bnc-onboard": "1.12.0", "classnames": "^2.2.6", - "concurrently": "^5.3.0", + "concurrently": "^5.2.0", "connected-react-router": "6.8.0", "coveralls": "^3.1.0", "currency-flags": "2.1.2", @@ -190,19 +190,19 @@ "eth-sig-util": "^2.5.3", "ethereum-blockies-base64": "^1.0.2", "ethereumjs-abi": "0.6.8", - "exponential-backoff": "^3.1.0", + "exponential-backoff": "^3.0.1", "express": "^4.17.1", "final-form": "^4.20.1", "final-form-calculate": "^1.3.1", "history": "4.10.1", - "immortal-db": "^1.1.0", + "immortal-db": "^1.0.3", "immutable": "^4.0.0-rc.12", "js-cookie": "^2.2.1", "lodash.debounce": "^4.0.8", "lodash.memoize": "^4.1.2", - "material-ui-search-bar": "^1.0.0", + "material-ui-search-bar": "^1.0.0-beta.13", "notistack": "https://github.com/gnosis/notistack.git#v0.9.4", - "open": "^7.2.0", + "open": "^7.1.0", "polished": "3.6.6", "qrcode.react": "1.0.0", "query-string": "6.13.1", @@ -215,7 +215,7 @@ "react-qr-reader": "^2.2.1", "react-redux": "7.2.1", "react-router-dom": "5.2.0", - "react-scripts": "^3.4.3", + "react-scripts": "^3.4.1", "react-window": "^1.8.5", "recompose": "^0.30.0", "redux": "4.0.5", @@ -263,7 +263,7 @@ "eslint-plugin-import": "2.22.0", "eslint-plugin-jsx-a11y": "^6.3.1", "eslint-plugin-prettier": "^3.1.4", - "eslint-plugin-react": "^7.20.6", + "eslint-plugin-react": "^7.20.5", "eslint-plugin-sort-destructure-keys": "1.3.5", "ethereumjs-abi": "0.6.8", "husky": "^4.2.5", @@ -272,9 +272,9 @@ "prettier": "2.1.1", "react-app-rewired": "^2.1.6", "react-docgen-typescript-loader": "^3.7.2", - "truffle": "5.1.41", + "truffle": "5.1.36", "typechain": "^2.0.0", "typescript": "3.9.7", - "wait-on": "5.2.0" + "wait-on": "5.1.0" } } diff --git a/src/components/App/ReceiveModal.tsx b/src/components/App/ModalReceive.tsx similarity index 59% rename from src/components/App/ReceiveModal.tsx rename to src/components/App/ModalReceive.tsx index 535a50bd..30df6668 100644 --- a/src/components/App/ReceiveModal.tsx +++ b/src/components/App/ModalReceive.tsx @@ -1,8 +1,9 @@ import IconButton from '@material-ui/core/IconButton' -import { createStyles, makeStyles } from '@material-ui/core/styles' +import { withStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import QRCode from 'qrcode.react' import * as React from 'react' +import { useSelector } from 'react-redux' import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' @@ -13,79 +14,72 @@ import Col from 'src/components/layout/Col' import Hairline from 'src/components/layout/Hairline' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' +import { safeNameSelector, safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors' import { lg, md, screenSm, secondaryText, sm } from 'src/theme/variables' import { copyToClipboard } from 'src/utils/clipboard' -const useStyles = makeStyles( - createStyles({ - heading: { - padding: `${md} ${lg}`, - justifyContent: 'space-between', - maxHeight: '75px', - boxSizing: 'border-box', +const styles = () => ({ + heading: { + padding: `${md} ${lg}`, + justifyContent: 'space-between', + maxHeight: '75px', + boxSizing: 'border-box', + }, + close: { + height: lg, + width: lg, + fill: secondaryText, + }, + qrContainer: { + backgroundColor: '#fff', + padding: md, + borderRadius: '6px', + border: `1px solid ${secondaryText}`, + }, + annotation: { + margin: lg, + marginBottom: 0, + }, + safeName: { + margin: `${md} 0`, + }, + buttonRow: { + height: '84px', + justifyContent: 'center', + '& > button': { + fontFamily: 'Averta', + fontSize: md, + boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)', }, - close: { - height: lg, - width: lg, - fill: secondaryText, - }, - qrContainer: { - backgroundColor: '#fff', - padding: md, - borderRadius: '6px', - border: `1px solid ${secondaryText}`, - }, - annotation: { - margin: lg, - marginBottom: 0, - }, - safeName: { - margin: `${md} 0`, - }, - buttonRow: { - height: '84px', - justifyContent: 'center', - '& > button': { - fontFamily: 'Averta', - fontSize: md, - boxShadow: '1px 2px 10px 0 rgba(212, 212, 211, 0.59)', - }, - }, - addressContainer: { - flexDirection: 'column', - justifyContent: 'center', - margin: `${lg} 0`, + }, + addressContainer: { + flexDirection: 'column', + justifyContent: 'center', + margin: `${lg} 0`, - [`@media (min-width: ${screenSm}px)`]: { - flexDirection: 'row', - }, + [`@media (min-width: ${screenSm}px)`]: { + flexDirection: 'row', }, - address: { - marginLeft: sm, - marginRight: sm, - maxWidth: '70%', - overflowWrap: 'break-word', + }, + address: { + marginLeft: sm, + marginRight: sm, + maxWidth: '70%', + overflowWrap: 'break-word', - [`@media (min-width: ${screenSm}px)`]: { - maxWidth: 'none', - }, + [`@media (min-width: ${screenSm}px)`]: { + maxWidth: 'none', }, - }), -) - -type Props = { - onClose: () => void - safeAddress: string - safeName: string -} - -const ReceiveModal = ({ onClose, safeAddress, safeName }: Props) => { - const classes = useStyles() + }, +}) +const Receive = ({ classes, onClose }) => { + const safeAddress = useSelector(safeParamAddressFromStateSelector) + const safeName = useSelector(safeNameSelector) return ( <> - + Receive funds @@ -128,4 +122,4 @@ const ReceiveModal = ({ onClose, safeAddress, safeName }: Props) => { ) } -export default ReceiveModal +export default withStyles(styles as any)(Receive) diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index ee90992a..7d889c67 100644 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -30,7 +30,7 @@ import { currentCurrencySelector, safeFiatBalancesTotalSelector } from 'src/logi import { formatAmountInUsFormat } from 'src/logic/tokens/utils/formatAmount' import { grantedSelector } from 'src/routes/safe/container/selector' -import Receive from './ReceiveModal' +import Receive from './ModalReceive' import { useSidebarItems } from 'src/components/AppLayout/Sidebar/useSidebarItems' const notificationStyles = { @@ -79,8 +79,7 @@ const App: React.FC = ({ children }) => { const sendFunds = safeActionsState.sendFunds as { isOpen: boolean; selectedToken: string } const formattedTotalBalance = currentSafeBalance ? formatAmountInUsFormat(currentSafeBalance) : '' - const balance = - !!formattedTotalBalance && !!currentCurrency ? `${formattedTotalBalance} ${currentCurrency}` : undefined + const balance = !!formattedTotalBalance && !!currentCurrency ? `${formattedTotalBalance} ${currentCurrency}` : null useEffect(() => { if (matchSafe?.isExact) { @@ -134,16 +133,14 @@ const App: React.FC = ({ children }) => { selectedToken={sendFunds.selectedToken} /> - {safeAddress && safeName && ( - - - - )} + + + diff --git a/src/components/AppLayout/AppLayout.stories.tsx b/src/components/AppLayout/AppLayout.stories.tsx index 00868482..778e0dad 100644 --- a/src/components/AppLayout/AppLayout.stories.tsx +++ b/src/components/AppLayout/AppLayout.stories.tsx @@ -50,7 +50,7 @@ export const Base = (): React.ReactElement => { safeAddress="0xEE63624cC4Dd2355B16b35eFaadF3F7450A9438B" safeName="someName" granted={true} - balance={undefined} + balance={null} onToggleSafeList={() => console.log} onReceiveClick={() => console.log} onNewTransactionClick={() => console.log} diff --git a/src/components/AppLayout/Header/index.tsx b/src/components/AppLayout/Header/index.tsx index 5636fbd6..fb9bd465 100644 --- a/src/components/AppLayout/Header/index.tsx +++ b/src/components/AppLayout/Header/index.tsx @@ -50,7 +50,7 @@ const HeaderComponent = (): React.ReactElement => { } const getProviderInfoBased = () => { - if (!loaded || !provider) { + if (!loaded) { return } diff --git a/src/components/AppLayout/Sidebar/SafeHeader/index.tsx b/src/components/AppLayout/Sidebar/SafeHeader/index.tsx index 03e129d9..82df813f 100644 --- a/src/components/AppLayout/Sidebar/SafeHeader/index.tsx +++ b/src/components/AppLayout/Sidebar/SafeHeader/index.tsx @@ -79,10 +79,10 @@ const UnStyledButton = styled.button` ` type Props = { - address: string | undefined - safeName: string | undefined + address: string | null + safeName: string granted: boolean - balance: string | undefined + balance: string | null onToggleSafeList: () => void onReceiveClick: () => void onNewTransactionClick: () => void diff --git a/src/components/AppLayout/Sidebar/index.tsx b/src/components/AppLayout/Sidebar/index.tsx index c4d19ddd..f59c3b0e 100644 --- a/src/components/AppLayout/Sidebar/index.tsx +++ b/src/components/AppLayout/Sidebar/index.tsx @@ -38,9 +38,9 @@ const HelpCenterLink = styled.a` } ` type Props = { - safeAddress?: string - safeName?: string - balance?: string + safeAddress: string | null + safeName: string | null + balance: string | null granted: boolean onToggleSafeList: () => void onReceiveClick: () => void @@ -57,32 +57,34 @@ const Sidebar = ({ onToggleSafeList, onReceiveClick, onNewTransactionClick, -}: Props): React.ReactElement => ( - <> - +}: Props): React.ReactElement => { + return ( + <> + - {items.length ? ( - <> + {items.length ? ( + <> + + + + ) : null} + + - - - ) : null} - - - - - - - - -) + + + + + + ) +} export default Sidebar diff --git a/src/components/AppLayout/index.tsx b/src/components/AppLayout/index.tsx index 4e477dc1..20bd8c89 100644 --- a/src/components/AppLayout/index.tsx +++ b/src/components/AppLayout/index.tsx @@ -60,9 +60,9 @@ export const FooterWrapper = styled.footer` type Props = { sidebarItems: ListItemType[] - safeAddress: string | undefined - safeName: string | undefined - balance: string | undefined + safeAddress: string | null + safeName: string | null + balance: string | null granted: boolean onToggleSafeList: () => void onReceiveClick: () => void diff --git a/src/components/SafeListSidebar/SafeList/index.tsx b/src/components/SafeListSidebar/SafeList/index.tsx index 23ecd436..efe0f070 100644 --- a/src/components/SafeListSidebar/SafeList/index.tsx +++ b/src/components/SafeListSidebar/SafeList/index.tsx @@ -82,7 +82,7 @@ const useStyles = makeStyles({ }) type Props = { - currentSafe: string | undefined + currentSafe: string | null defaultSafe: DefaultSafe safes: SafeRecord[] onSafeClick: () => void diff --git a/src/components/Table/TableHead.tsx b/src/components/Table/TableHead.tsx index 94e8b1c1..6d341fa6 100644 --- a/src/components/Table/TableHead.tsx +++ b/src/components/Table/TableHead.tsx @@ -8,7 +8,7 @@ interface CellWidth { maxWidth: string } -export const cellWidth = (width?: string | number): CellWidth | undefined => { +export const cellWidth = (width: string | number): CellWidth | undefined => { if (!width) { return undefined } diff --git a/src/logic/addressBook/store/selectors/index.ts b/src/logic/addressBook/store/selectors/index.ts index b03fbdf1..973b40a6 100644 --- a/src/logic/addressBook/store/selectors/index.ts +++ b/src/logic/addressBook/store/selectors/index.ts @@ -4,7 +4,6 @@ import { createSelector } from 'reselect' import { ADDRESS_BOOK_REDUCER_ID } from 'src/logic/addressBook/store/reducer/addressBook' import { AddressBookMap } from 'src/logic/addressBook/store/reducer/types/addressBook.d' -import { AddressBookEntryRecord } from 'src/logic/addressBook/model/addressBook' import { safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors' export const addressBookMapSelector = (state: AppReduxState): AddressBookMap => @@ -14,8 +13,8 @@ export const getAddressBook = createSelector( addressBookMapSelector, safeParamAddressFromStateSelector, (addressBook, safeAddress) => { - let result: List = List([]) - if (addressBook && safeAddress) { + let result = List([]) + if (addressBook) { result = addressBook.get(safeAddress, List()) } return result diff --git a/src/logic/addressBook/utils/index.ts b/src/logic/addressBook/utils/index.ts index a3e05749..22cd11e8 100644 --- a/src/logic/addressBook/utils/index.ts +++ b/src/logic/addressBook/utils/index.ts @@ -19,7 +19,7 @@ export const saveAddressBook = async (addressBook) => { } } -export const getAddressesListFromAdbk = (addressBook: List) => addressBook.map((entry: any) => entry.address) +export const getAddressesListFromAdbk = (addressBook) => Array.from(addressBook).map((entry: any) => entry.address) export const getNameFromAdbk = (addressBook, userAddress) => { const entry = addressBook.find((addressBookItem) => addressBookItem.address === userAddress) diff --git a/src/logic/contractInteraction/sources/ABIService/index.ts b/src/logic/contractInteraction/sources/ABIService/index.ts index c9dc15b7..c9b62c5f 100644 --- a/src/logic/contractInteraction/sources/ABIService/index.ts +++ b/src/logic/contractInteraction/sources/ABIService/index.ts @@ -2,19 +2,14 @@ import { AbiItem } from 'web3-utils' import { web3ReadOnly as web3 } from 'src/logic/wallets/getWeb3' -export interface AllowedAbiItem extends AbiItem { - name: string - type: 'function' -} - -export interface AbiItemExtended extends AllowedAbiItem { +export interface AbiItemExtended extends AbiItem { action: string methodSignature: string signatureHash: string } export const getMethodSignature = ({ inputs, name }: AbiItem): string => { - const params = inputs?.map((x) => x.type).join(',') + const params = inputs.map((x) => x.type).join(',') return `${name}(${params})` } @@ -40,17 +35,12 @@ export const isAllowedMethod = ({ name, type }: AbiItem): boolean => { } export const getMethodAction = ({ stateMutability }: AbiItem): 'read' | 'write' => { - if (!stateMutability) { - return 'write' - } - return ['view', 'pure'].includes(stateMutability) ? 'read' : 'write' } export const extractUsefulMethods = (abi: AbiItem[]): AbiItemExtended[] => { - const allowedAbiItems = abi.filter(isAllowedMethod) as AllowedAbiItem[] - - return allowedAbiItems + return abi + .filter(isAllowedMethod) .map( (method): AbiItemExtended => ({ action: getMethodAction(method), @@ -58,11 +48,9 @@ export const extractUsefulMethods = (abi: AbiItem[]): AbiItemExtended[] => { ...method, }), ) - .sort(({ name: a }, { name: b }) => { - return a.toLowerCase() > b.toLowerCase() ? 1 : -1 - }) + .sort(({ name: a }, { name: b }) => (a.toLowerCase() > b.toLowerCase() ? 1 : -1)) } export const isPayable = (method: AbiItem | AbiItemExtended): boolean => { - return !!method?.payable + return method.payable } diff --git a/src/logic/currencyValues/api/fetchTokenCurrenciesBalances.ts b/src/logic/currencyValues/api/fetchTokenCurrenciesBalances.ts index e6316472..3ed8fa9d 100644 --- a/src/logic/currencyValues/api/fetchTokenCurrenciesBalances.ts +++ b/src/logic/currencyValues/api/fetchTokenCurrenciesBalances.ts @@ -6,12 +6,15 @@ import { TokenProps } from 'src/logic/tokens/store/model/token' export type BalanceEndpoint = { balance: string balanceUsd: string - tokenAddress: string + tokenAddress?: string token?: TokenProps usdConversion: string } -const fetchTokenCurrenciesBalances = (safeAddress: string): Promise> => { +const fetchTokenCurrenciesBalances = (safeAddress?: string): Promise> => { + if (!safeAddress) { + return null + } const apiUrl = getTxServiceHost() const url = `${apiUrl}safes/${safeAddress}/balances/usd/` diff --git a/src/logic/currencyValues/store/actions/fetchCurrencyValues.ts b/src/logic/currencyValues/store/actions/fetchCurrencyValues.ts index 79a90fce..b109f93e 100644 --- a/src/logic/currencyValues/store/actions/fetchCurrencyValues.ts +++ b/src/logic/currencyValues/store/actions/fetchCurrencyValues.ts @@ -12,7 +12,7 @@ export const fetchCurrencyValues = (safeAddress: string) => async ( dispatch: Dispatch, ): Promise => { try { - const storedCurrencies = await loadCurrencyValues() + const storedCurrencies: Map | unknown = await loadCurrencyValues() const storedCurrency = storedCurrencies[safeAddress] if (!storedCurrency) { return batch(() => { diff --git a/src/logic/currencyValues/store/middleware/index.ts b/src/logic/currencyValues/store/middleware/index.ts index cc55be57..92445da4 100644 --- a/src/logic/currencyValues/store/middleware/index.ts +++ b/src/logic/currencyValues/store/middleware/index.ts @@ -1,11 +1,18 @@ import fetchCurrencyRate from 'src/logic/currencyValues/store/actions/fetchCurrencyRate' +import { SET_CURRENCY_BALANCES } from 'src/logic/currencyValues/store/actions/setCurrencyBalances' +import { SET_CURRENCY_RATE } from 'src/logic/currencyValues/store/actions/setCurrencyRate' import { SET_CURRENT_CURRENCY } from 'src/logic/currencyValues/store/actions/setSelectedCurrency' +import { currencyValuesSelector } from 'src/logic/currencyValues/store/selectors' +import { saveCurrencyValues } from 'src/logic/currencyValues/store/utils/currencyValuesStorage' +import { AVAILABLE_CURRENCIES, CurrencyRateValue } from '../model/currencyValues' +import { Map } from 'immutable' -const watchedActions = [SET_CURRENT_CURRENCY] +const watchedActions = [SET_CURRENT_CURRENCY, SET_CURRENCY_RATE, SET_CURRENCY_BALANCES] const currencyValuesStorageMiddleware = (store) => (next) => async (action) => { const handledAction = next(action) if (watchedActions.includes(action.type)) { + const state = store.getState() const { dispatch } = store switch (action.type) { case SET_CURRENT_CURRENCY: { @@ -13,6 +20,22 @@ const currencyValuesStorageMiddleware = (store) => (next) => async (action) => { dispatch(fetchCurrencyRate(safeAddress, selectedCurrency)) break } + case SET_CURRENCY_RATE: + case SET_CURRENCY_BALANCES: { + const currencyValues = currencyValuesSelector(state) + + const currencyValuesWithoutBalances: Map = currencyValues.map((currencyValue) => { + const currencyRate: number = currencyValue.get('currencyRate') + const selectedCurrency: AVAILABLE_CURRENCIES = currencyValue.get('selectedCurrency') + return { + currencyRate, + selectedCurrency, + } + }) + + await saveCurrencyValues(currencyValuesWithoutBalances) + break + } default: break diff --git a/src/logic/currencyValues/store/selectors/index.ts b/src/logic/currencyValues/store/selectors/index.ts index b1789174..141654c1 100644 --- a/src/logic/currencyValues/store/selectors/index.ts +++ b/src/logic/currencyValues/store/selectors/index.ts @@ -16,7 +16,7 @@ export const safeFiatBalancesSelector = createSelector( currencyValuesSelector, safeParamAddressFromStateSelector, (currencyValues, safeAddress): CurrencyReducerMap | undefined => { - if (!currencyValues || !safeAddress) return + if (!currencyValues) return return currencyValues.get(safeAddress) }, ) diff --git a/src/logic/currencyValues/store/utils/currencyValuesStorage.ts b/src/logic/currencyValues/store/utils/currencyValuesStorage.ts index 0aabece4..6a265fc8 100644 --- a/src/logic/currencyValues/store/utils/currencyValuesStorage.ts +++ b/src/logic/currencyValues/store/utils/currencyValuesStorage.ts @@ -11,6 +11,6 @@ export const saveCurrencyValues = async (currencyValues: Map> => { +export const loadCurrencyValues = async (): Promise | unknown> => { return (await loadFromStorage(CURRENCY_VALUES_STORAGE_KEY)) || {} } diff --git a/src/logic/currentSession/store/actions/loadCurrentSessionFromStorage.ts b/src/logic/currentSession/store/actions/loadCurrentSessionFromStorage.ts index 517d24ec..b3dde217 100644 --- a/src/logic/currentSession/store/actions/loadCurrentSessionFromStorage.ts +++ b/src/logic/currentSession/store/actions/loadCurrentSessionFromStorage.ts @@ -5,9 +5,7 @@ import { getCurrentSessionFromStorage } from 'src/logic/currentSession/utils' const loadCurrentSessionFromStorage = () => async (dispatch) => { const currentSession = await getCurrentSessionFromStorage() - if (currentSession) { - dispatch(loadCurrentSession(makeCurrentSession(currentSession))) - } + dispatch(loadCurrentSession(makeCurrentSession(currentSession ? currentSession : {}))) } export default loadCurrentSessionFromStorage diff --git a/src/logic/currentSession/store/model/currentSession.ts b/src/logic/currentSession/store/model/currentSession.ts index 629327e8..c5be51ca 100644 --- a/src/logic/currentSession/store/model/currentSession.ts +++ b/src/logic/currentSession/store/model/currentSession.ts @@ -1,9 +1,5 @@ import { Record } from 'immutable' -type SessionProps = { - viewedSafes: string[] -} - -export const makeCurrentSession = Record({ +export const makeCurrentSession = Record({ viewedSafes: [], }) diff --git a/src/logic/currentSession/store/reducer/currentSession.ts b/src/logic/currentSession/store/reducer/currentSession.ts index 2d63c914..228bfc9e 100644 --- a/src/logic/currentSession/store/reducer/currentSession.ts +++ b/src/logic/currentSession/store/reducer/currentSession.ts @@ -7,10 +7,6 @@ import { saveCurrentSessionToStorage } from 'src/logic/currentSession/utils' export const CURRENT_SESSION_REDUCER_ID = 'currentSession' -export type SerializedSessionState = { - viewedSafes: string[] -} - export default handleActions( { [LOAD_CURRENT_SESSION]: (state, action) => state.merge(Map(action.payload)), diff --git a/src/logic/currentSession/utils/index.ts b/src/logic/currentSession/utils/index.ts index 2913e889..cbfa1a14 100644 --- a/src/logic/currentSession/utils/index.ts +++ b/src/logic/currentSession/utils/index.ts @@ -1,10 +1,8 @@ import { loadFromStorage, saveToStorage } from 'src/utils/storage' -import { SerializedSessionState } from 'src/logic/currentSession/store/reducer/currentSession' const CURRENT_SESSION_STORAGE_KEY = 'CURRENT_SESSION' -export const getCurrentSessionFromStorage = async (): Promise => - loadFromStorage(CURRENT_SESSION_STORAGE_KEY) +export const getCurrentSessionFromStorage = async () => loadFromStorage(CURRENT_SESSION_STORAGE_KEY) export const saveCurrentSessionToStorage = async (currentSession) => { try { diff --git a/src/logic/hooks/useDebounce.tsx b/src/logic/hooks/useDebounce.tsx index 2a19734f..e9abbb43 100644 --- a/src/logic/hooks/useDebounce.tsx +++ b/src/logic/hooks/useDebounce.tsx @@ -16,7 +16,7 @@ interface DebounceOptions { export const useDebouncedCallback = unknown>( callback: T, delay = 0, - options?: DebounceOptions, + options: DebounceOptions, ): T & { cancel: () => void } => useCallback(debounce(callback, delay, options), [callback, delay, options]) export const useDebounce = (value: T, delay = 0, options?: DebounceOptions): T => { diff --git a/src/logic/notifications/notificationBuilder.tsx b/src/logic/notifications/notificationBuilder.tsx index fd815385..b49b2aa1 100644 --- a/src/logic/notifications/notificationBuilder.tsx +++ b/src/logic/notifications/notificationBuilder.tsx @@ -15,7 +15,7 @@ const setNotificationOrigin = (notification: Notification, origin: string): Noti } const appInfo = getAppInfoFromOrigin(origin) - return { ...notification, message: `${appInfo ? appInfo.name : 'Unknown origin'}: ${notification.message}` } + return { ...notification, message: `${appInfo.name}: ${notification.message}` } } const getStandardTxNotificationsQueue = ( diff --git a/src/logic/safe/hooks/useLoadSafe.tsx b/src/logic/safe/hooks/useLoadSafe.tsx index 9d6e15df..048adb85 100644 --- a/src/logic/safe/hooks/useLoadSafe.tsx +++ b/src/logic/safe/hooks/useLoadSafe.tsx @@ -10,7 +10,7 @@ import fetchTransactions from 'src/logic/safe/store/actions/transactions/fetchTr import fetchSafeCreationTx from 'src/logic/safe/store/actions/fetchSafeCreationTx' import { Dispatch } from 'src/logic/safe/store/actions/types.d' -export const useLoadSafe = (safeAddress?: string): void => { +export const useLoadSafe = (safeAddress: string): void => { const dispatch = useDispatch() useEffect(() => { diff --git a/src/logic/safe/hooks/useSafeScheduledUpdates.tsx b/src/logic/safe/hooks/useSafeScheduledUpdates.tsx index 66c474a2..d2415eb3 100644 --- a/src/logic/safe/hooks/useSafeScheduledUpdates.tsx +++ b/src/logic/safe/hooks/useSafeScheduledUpdates.tsx @@ -8,9 +8,9 @@ import { checkAndUpdateSafe } from 'src/logic/safe/store/actions/fetchSafe' import fetchTransactions from 'src/logic/safe/store/actions/transactions/fetchTransactions' import { TIMEOUT } from 'src/utils/constants' -export const useSafeScheduledUpdates = (safeAddress?: string): void => { +export const useSafeScheduledUpdates = (safeAddress: string): void => { const dispatch = useDispatch() - const timer = useRef() + const timer = useRef(null) useEffect(() => { // using this variable to prevent setting a timeout when the component is already unmounted or the effect @@ -29,7 +29,7 @@ export const useSafeScheduledUpdates = (safeAddress?: string): void => { if (mounted) { timer.current = setTimeout(() => { - fetchSafeData(address) + fetchSafeData(safeAddress) }, TIMEOUT * 3) } } diff --git a/src/logic/safe/store/actions/allTransactions/loadAllTransactions.ts b/src/logic/safe/store/actions/allTransactions/loadAllTransactions.ts index d98b59b6..25148bdc 100644 --- a/src/logic/safe/store/actions/allTransactions/loadAllTransactions.ts +++ b/src/logic/safe/store/actions/allTransactions/loadAllTransactions.ts @@ -30,8 +30,8 @@ const getAllTransactionsUri = (safeAddress: string): string => { const fetchAllTransactions = async ( urlParams: ServiceUriParams, - eTag?: string, -): Promise<{ responseEtag?: string; results: Transaction[]; count?: number }> => { + eTag: string | null, +): Promise<{ responseEtag: string; results: Transaction[]; count?: number }> => { const { safeAddress, limit, offset, orderBy, queued, trusted } = urlParams try { const url = getAllTransactionsUri(safeAddress) diff --git a/src/logic/safe/store/actions/createTransaction.ts b/src/logic/safe/store/actions/createTransaction.ts index 8affa5fe..6f0424a7 100644 --- a/src/logic/safe/store/actions/createTransaction.ts +++ b/src/logic/safe/store/actions/createTransaction.ts @@ -100,7 +100,7 @@ interface CreateTransactionArgs { navigateToTransactionsTab?: boolean notifiedTransaction: string operation?: number - origin?: string | null + origin?: string safeAddress: string to: string txData?: string diff --git a/src/logic/safe/store/actions/fetchSafe.ts b/src/logic/safe/store/actions/fetchSafe.ts index 6821a997..bd95676e 100644 --- a/src/logic/safe/store/actions/fetchSafe.ts +++ b/src/logic/safe/store/actions/fetchSafe.ts @@ -18,7 +18,7 @@ import { Action, Dispatch } from 'redux' import { SENTINEL_ADDRESS } from 'src/logic/contracts/safeContracts' import { AppReduxState } from 'src/store' -const buildOwnersFrom = (safeOwners: string[], localSafe?: SafeRecordProps): List => { +const buildOwnersFrom = (safeOwners: string[], localSafe: SafeRecordProps): List => { const ownersList = safeOwners.map((ownerAddress) => { const convertedAdd = checksumAddress(ownerAddress) @@ -85,7 +85,7 @@ export const buildSafe = async ( needsUpdate, featuresEnabled, balances: Map(), - latestIncomingTxBlock: 0, + latestIncomingTxBlock: null, activeAssets: Set(), activeTokens: Set(), blacklistedAssets: Set(), diff --git a/src/logic/safe/store/actions/loadSafesFromStorage.ts b/src/logic/safe/store/actions/loadSafesFromStorage.ts index de752b0e..e4a36dd9 100644 --- a/src/logic/safe/store/actions/loadSafesFromStorage.ts +++ b/src/logic/safe/store/actions/loadSafesFromStorage.ts @@ -1,15 +1,15 @@ -import { Dispatch } from 'redux' +import { addSafe } from './addSafe' import { SAFES_KEY } from 'src/logic/safe/utils' -import { SafeRecordProps } from 'src/logic/safe/store/models/safe' -import { buildSafe } from 'src/logic/safe/store/reducer/safe' -import { loadFromStorage } from 'src/utils/storage' -import { addSafe } from './addSafe' +import { buildSafe } from 'src/logic/safe/store/reducer/safe' + +import { loadFromStorage } from 'src/utils/storage' +import { Dispatch } from 'redux' const loadSafesFromStorage = () => async (dispatch: Dispatch): Promise => { try { - const safes = await loadFromStorage>(SAFES_KEY) + const safes = await loadFromStorage(SAFES_KEY) if (safes) { Object.values(safes).forEach((safeProps) => { diff --git a/src/logic/safe/store/actions/processTransaction.ts b/src/logic/safe/store/actions/processTransaction.ts index 3a147939..0791584c 100644 --- a/src/logic/safe/store/actions/processTransaction.ts +++ b/src/logic/safe/store/actions/processTransaction.ts @@ -34,7 +34,7 @@ const processTransaction = ({ approveAndExecute, notifiedTransaction, safeAddres const safeInstance = await getGnosisSafeInstanceAt(safeAddress) const lastTx = await getLastTx(safeAddress) - const nonce = await getNewTxNonce(undefined, lastTx, safeInstance) + const nonce = await getNewTxNonce(null, lastTx, safeInstance) const isExecution = approveAndExecute || (await shouldExecuteTransaction(safeInstance, nonce, lastTx)) const safeVersion = await getCurrentSafeVersion(safeInstance) diff --git a/src/logic/safe/store/actions/transactions/fetchTransactions/fetchTransactions.ts b/src/logic/safe/store/actions/transactions/fetchTransactions/fetchTransactions.ts index f4907bed..d413879c 100644 --- a/src/logic/safe/store/actions/transactions/fetchTransactions/fetchTransactions.ts +++ b/src/logic/safe/store/actions/transactions/fetchTransactions/fetchTransactions.ts @@ -27,7 +27,7 @@ async function fetchTransactions( txType: TransactionTypes.INCOMING | TransactionTypes.OUTGOING, safeAddress: string, eTag: string | null, -): Promise<{ eTag: string | null; results: TxServiceModel[] | IncomingTxServiceModel[] }> { +): Promise<{ eTag: string; results: TxServiceModel[] | IncomingTxServiceModel[] }> { try { const url = getServiceUrl(txType, safeAddress) const response = await axios.get(url, eTag ? { headers: { 'If-None-Match': eTag } } : undefined) diff --git a/src/logic/safe/store/actions/transactions/fetchTransactions/index.ts b/src/logic/safe/store/actions/transactions/fetchTransactions/index.ts index 09d00a05..07161d80 100644 --- a/src/logic/safe/store/actions/transactions/fetchTransactions/index.ts +++ b/src/logic/safe/store/actions/transactions/fetchTransactions/index.ts @@ -39,9 +39,8 @@ export default (safeAddress: string): ThunkAction, AppReduxState, } const incomingTransactions = await loadIncomingTransactions(safeAddress) - const safeIncomingTxs = incomingTransactions.get(safeAddress) - if (safeIncomingTxs?.size) { + if (incomingTransactions.get(safeAddress).size) { dispatch(addIncomingTransactions(incomingTransactions)) } } catch (error) { diff --git a/src/logic/safe/store/actions/transactions/fetchTransactions/loadIncomingTransactions.ts b/src/logic/safe/store/actions/transactions/fetchTransactions/loadIncomingTransactions.ts index ec79aa23..170a6311 100644 --- a/src/logic/safe/store/actions/transactions/fetchTransactions/loadIncomingTransactions.ts +++ b/src/logic/safe/store/actions/transactions/fetchTransactions/loadIncomingTransactions.ts @@ -73,8 +73,8 @@ const batchIncomingTxsTokenDataRequest = (txs: IncomingTxServiceModel[]) => { ) } -let previousETag: string | null = null -export const loadIncomingTransactions = async (safeAddress: string): Promise>> => { +let previousETag = null +export const loadIncomingTransactions = async (safeAddress: string) => { const { eTag, results } = await fetchTransactions(TransactionTypes.INCOMING, safeAddress, previousETag) previousETag = eTag diff --git a/src/logic/safe/store/actions/transactions/fetchTransactions/loadOutgoingTransactions.ts b/src/logic/safe/store/actions/transactions/fetchTransactions/loadOutgoingTransactions.ts index 89d53d95..67f9b4ca 100644 --- a/src/logic/safe/store/actions/transactions/fetchTransactions/loadOutgoingTransactions.ts +++ b/src/logic/safe/store/actions/transactions/fetchTransactions/loadOutgoingTransactions.ts @@ -27,7 +27,8 @@ export type TxServiceModel = { blockNumber?: number | null confirmations: ConfirmationServiceModel[] confirmationsRequired: number - data: string | null + creationTx?: boolean | null + data?: string | null dataDecoded?: DataDecoded ethGasPrice: string executionDate?: string | null @@ -39,15 +40,15 @@ export type TxServiceModel = { isExecuted: boolean isSuccessful: boolean modified: string - nonce: number + nonce?: number | null operation: number - origin: string | null + origin?: string | null refundReceiver: string safe: string safeTxGas: number safeTxHash: string signatures: string - submissionDate: string | null + submissionDate?: string | null to: string transactionHash?: string | null value: string @@ -77,7 +78,7 @@ export type BatchProcessTxsProps = OutgoingTxs & { */ const extractCancelAndOutgoingTxs = (safeAddress: string, outgoingTxs: TxServiceModel[]): OutgoingTxs => { return outgoingTxs.reduce( - (acc: { cancellationTxs: Record; outgoingTxs: TxServiceModel[] }, transaction) => { + (acc, transaction) => { if ( isCancelTransaction(transaction, safeAddress) && outgoingTxs.find((tx) => tx.nonce === transaction.nonce && !isCancelTransaction(tx, safeAddress)) @@ -163,7 +164,7 @@ const batchProcessOutgoingTransactions = async ({ // outgoing transactions const outgoingTxsWithData = outgoingTxs.length ? await batchRequestContractCode(outgoingTxs) : [] - const outgoing: Transaction[] = [] + const outgoing = [] for (const [tx, txCode] of outgoingTxsWithData) { outgoing.push( await buildTx({ @@ -181,7 +182,7 @@ const batchProcessOutgoingTransactions = async ({ return { cancel, outgoing } } -let previousETag: string | null = null +let previousETag = null export const loadOutgoingTransactions = async (safeAddress: string): Promise => { const defaultResponse = { cancel: Map(), diff --git a/src/logic/safe/store/actions/transactions/utils/transactionHelpers.ts b/src/logic/safe/store/actions/transactions/utils/transactionHelpers.ts index db802632..05b89bb8 100644 --- a/src/logic/safe/store/actions/transactions/utils/transactionHelpers.ts +++ b/src/logic/safe/store/actions/transactions/utils/transactionHelpers.ts @@ -19,7 +19,6 @@ import { TransactionTypes, TransactionTypeValues, TxArgs, - RefundParams, } from 'src/logic/safe/store/models/types/transaction' import { CANCELLATION_TRANSACTIONS_REDUCER_ID } from 'src/logic/safe/store/reducer/cancellationTransactions' import { SAFE_REDUCER_ID } from 'src/logic/safe/store/reducer/safe' @@ -66,15 +65,15 @@ export const isModifySettingsTransaction = (tx: TxServiceModel, safeAddress: str } export const isMultiSendTransaction = (tx: TxServiceModel): boolean => { - return !isEmptyData(tx.data) && tx.data?.substring(0, 10) === '0x8d80ff0a' && Number(tx.value) === 0 + return !isEmptyData(tx.data) && tx.data.substring(0, 10) === '0x8d80ff0a' && Number(tx.value) === 0 } export const isUpgradeTransaction = (tx: TxServiceModel): boolean => { return ( !isEmptyData(tx.data) && isMultiSendTransaction(tx) && - tx.data?.substr(308, 8) === '7de7edef' && // 7de7edef - changeMasterCopy (308, 8) - tx.data?.substr(550, 8) === 'f08a0323' // f08a0323 - setFallbackHandler (550, 8) + tx.data.substr(308, 8) === '7de7edef' && // 7de7edef - changeMasterCopy (308, 8) + tx.data.substr(550, 8) === 'f08a0323' // f08a0323 - setFallbackHandler (550, 8) ) } @@ -84,7 +83,7 @@ export const isOutgoingTransaction = (tx: TxServiceModel, safeAddress: string): export const isCustomTransaction = async ( tx: TxServiceModel, - txCode: string | null, + txCode: string, safeAddress: string, knownTokens: Map, ): Promise => { @@ -99,9 +98,9 @@ export const isCustomTransaction = async ( export const getRefundParams = async ( tx: TxServiceModel, tokenInfo: (string) => Promise<{ decimals: number; symbol: string } | null>, -): Promise => { +): Promise => { const txGasPrice = Number(tx.gasPrice) - let refundParams: RefundParams | null = null + let refundParams = null if (txGasPrice > 0) { let refundSymbol = 'ETH' @@ -274,6 +273,7 @@ export const buildTx = async ({ blockNumber: tx.blockNumber, cancelled: isTxCancelled, confirmations, + creationTx: tx.creationTx, customTx: isCustomTx, data: tx.data ? tx.data : EMPTY_DATA, dataDecoded: tx.dataDecoded, @@ -326,7 +326,7 @@ export const mockTransaction = (tx: TxToMock, safeAddress: string, state: AppRed return buildTx({ cancellationTxs, - currentUser: undefined, + currentUser: null, knownTokens, outgoingTxs, safe, @@ -345,7 +345,7 @@ export const updateStoredTransactionsStatus = (dispatch: (any) => void, walletRe dispatch( addOrUpdateTransactions({ safeAddress, - transactions: transactions.withMutations((list: any[]) => + transactions: transactions.withMutations((list) => list.map((tx) => tx.set('status', calculateTransactionStatus(tx, safe, walletRecord.account))), ), }), diff --git a/src/logic/safe/store/actions/utils.ts b/src/logic/safe/store/actions/utils.ts index 2a4cf33a..2dee2f09 100644 --- a/src/logic/safe/store/actions/utils.ts +++ b/src/logic/safe/store/actions/utils.ts @@ -4,7 +4,7 @@ import axios from 'axios' import { buildTxServiceUrl } from 'src/logic/safe/transactions/txHistory' -export const getLastTx = async (safeAddress: string): Promise => { +export const getLastTx = async (safeAddress: string): Promise => { try { const url = buildTxServiceUrl(safeAddress) const response = await axios.get(url, { params: { limit: 1 } }) @@ -17,24 +17,23 @@ export const getLastTx = async (safeAddress: string): Promise => { - if (typeof txNonce === 'string' && !Number.isInteger(Number.parseInt(txNonce, 10))) { + if (!Number.isInteger(Number.parseInt(txNonce, 10))) { return lastTx === null ? // use current's safe nonce as fallback (await safeInstance.methods.nonce().call()).toString() : `${lastTx.nonce + 1}` } - - return txNonce as string + return txNonce } export const shouldExecuteTransaction = async ( safeInstance: GnosisSafe, nonce: string, - lastTx: TxServiceModel | null, + lastTx: TxServiceModel, ): Promise => { const threshold = await safeInstance.methods.getThreshold().call() @@ -46,7 +45,7 @@ export const shouldExecuteTransaction = async ( // by the user using the exec button. const canExecuteCurrentTransaction = lastTx && lastTx.isExecuted - return isFirstTransaction || !!canExecuteCurrentTransaction + return isFirstTransaction || canExecuteCurrentTransaction } return false diff --git a/src/logic/safe/store/middleware/notificationsMiddleware.ts b/src/logic/safe/store/middleware/notificationsMiddleware.ts index 1499a8f2..c30f5fa1 100644 --- a/src/logic/safe/store/middleware/notificationsMiddleware.ts +++ b/src/logic/safe/store/middleware/notificationsMiddleware.ts @@ -85,7 +85,7 @@ const notificationsMiddleware = (store) => (next) => async (action) => { const safes = safesMapSelector(state) const currentSafe = safes.get(safeAddress) - if (!currentSafe || !isUserAnOwner(currentSafe, userAddress) || awaitingTransactions.size === 0) { + if (!isUserAnOwner(currentSafe, userAddress) || awaitingTransactions.size === 0) { break } diff --git a/src/logic/safe/store/models/types/transaction.ts b/src/logic/safe/store/models/types/transaction.ts index 1ecd114a..150233b8 100644 --- a/src/logic/safe/store/models/types/transaction.ts +++ b/src/logic/safe/store/models/types/transaction.ts @@ -33,7 +33,6 @@ export enum PendingActionType { REJECT = 'reject', } export type PendingActionValues = PendingActionType[keyof PendingActionType] -export type RefundParams = { fee: string; symbol: string } export type TransactionProps = { baseGas: number @@ -44,7 +43,7 @@ export type TransactionProps = { creator: string creationTx: boolean customTx: boolean - data: string | null + data?: string | null dataDecoded: DataDecoded | null decimals?: (number | string) | null decodedParams: DecodedParams | null @@ -52,7 +51,7 @@ export type TransactionProps = { executionTxHash?: string | null executor: string factoryAddress: string - fee: string | null // It will be replace with the new TXs types. + fee?: string // It will be replace with the new TXs types. gasPrice: string gasToken: string isCancellationTx: boolean @@ -64,18 +63,18 @@ export type TransactionProps = { masterCopy: string modifySettingsTx: boolean multiSendTx: boolean - nonce: number + nonce?: number | null operation: number origin: string | null ownersWithPendingActions: Map> recipient: string - refundParams: RefundParams | null + refundParams: any refundReceiver: string safeTxGas: number safeTxHash: string setupData: string - status: TransactionStatus - submissionDate: string | null + status?: TransactionStatus + submissionDate?: string | null symbol?: string | null transactionHash: string | null transfers?: Transfer[] @@ -88,7 +87,7 @@ export type Transaction = RecordOf export type TxArgs = { baseGas: number - data: string + data?: string | null gasPrice: string gasToken: string nonce: number diff --git a/src/logic/safe/store/reducer/safe.ts b/src/logic/safe/store/reducer/safe.ts index 4b28b145..7a1e9b4b 100644 --- a/src/logic/safe/store/reducer/safe.ts +++ b/src/logic/safe/store/reducer/safe.ts @@ -37,7 +37,7 @@ export const buildSafe = (storedSafe: SafeRecordProps): SafeRecordProps => { blacklistedTokens, activeAssets, blacklistedAssets, - latestIncomingTxBlock: 0, + latestIncomingTxBlock: null, modules: null, } } diff --git a/src/logic/safe/store/selectors/allTransactions.ts b/src/logic/safe/store/selectors/allTransactions.ts index e8729e61..211a6def 100644 --- a/src/logic/safe/store/selectors/allTransactions.ts +++ b/src/logic/safe/store/selectors/allTransactions.ts @@ -12,11 +12,11 @@ export const allTransactionsSelector = createSelector(getTransactionsStateSelect export const safeAllTransactionsSelector = createSelector( safeParamAddressFromStateSelector, allTransactionsSelector, - (safeAddress, transactions) => (safeAddress ? transactions[safeAddress]?.transactions : []), + (safeAddress, transactions) => transactions[safeAddress]?.transactions || [], ) export const safeTotalTransactionsAmountSelector = createSelector( safeParamAddressFromStateSelector, allTransactionsSelector, - (safeAddress, transactions) => (safeAddress ? transactions[safeAddress]?.totalTransactionsCount : 0), + (safeAddress, transactions) => transactions[safeAddress]?.totalTransactionsCount || 0, ) diff --git a/src/logic/safe/store/selectors/index.ts b/src/logic/safe/store/selectors/index.ts index 0e153a5d..9c6d3f9c 100644 --- a/src/logic/safe/store/selectors/index.ts +++ b/src/logic/safe/store/selectors/index.ts @@ -36,7 +36,7 @@ const cancellationTransactionsSelector = (state: AppReduxState) => state[CANCELL const incomingTransactionsSelector = (state: AppReduxState) => state[INCOMING_TRANSACTIONS_REDUCER_ID] -export const safeParamAddressFromStateSelector = (state: AppReduxState): string | undefined => { +export const safeParamAddressFromStateSelector = (state: AppReduxState): string | null => { const match = matchPath<{ safeAddress: string }>(state.router.location.pathname, { path: `${SAFELIST_ADDRESS}/:safeAddress`, }) @@ -45,7 +45,7 @@ export const safeParamAddressFromStateSelector = (state: AppReduxState): string return checksumAddress(match.params.safeAddress) } - return undefined + return null } export const safeParamAddressSelector = ( @@ -177,16 +177,16 @@ export const safeBlacklistedAssetsSelector = createSelector( ) export const safeActiveAssetsSelectorBySafe = (safeAddress: string, safes: SafesMap): Set => - safes.get(safeAddress)?.get('activeAssets') || Set() + safes.get(safeAddress).get('activeAssets') export const safeBlacklistedAssetsSelectorBySafe = (safeAddress: string, safes: SafesMap): Set => - safes.get(safeAddress)?.get('blacklistedAssets') || Set() + safes.get(safeAddress).get('blacklistedAssets') const baseSafe = makeSafe() export const safeFieldSelector = (field: K) => ( safe: SafeRecord, -): SafeRecordProps[K] | undefined => (safe ? safe.get(field, baseSafe.get(field)) : undefined) +): SafeRecordProps[K] | null => (safe ? safe.get(field, baseSafe.get(field)) : null) export const safeNameSelector = createSelector(safeSelector, safeFieldSelector('name')) diff --git a/src/logic/safe/transactions/awaitingTransactions.ts b/src/logic/safe/transactions/awaitingTransactions.ts index 85ea6568..ff05bb0e 100644 --- a/src/logic/safe/transactions/awaitingTransactions.ts +++ b/src/logic/safe/transactions/awaitingTransactions.ts @@ -1,13 +1,8 @@ import { List } from 'immutable' import { isPendingTransaction } from 'src/logic/safe/store/actions/transactions/utils/transactionHelpers' -import { Transaction } from 'src/logic/safe/store/models/types/transaction' -export const getAwaitingTransactions = ( - allTransactions: List, - cancellationTxs, - userAccount: string, -): List => { +export const getAwaitingTransactions = (allTransactions = List([]), cancellationTxs, userAccount: string) => { return allTransactions.filter((tx) => { const cancelTx = !!tx.nonce && !isNaN(Number(tx.nonce)) ? cancellationTxs.get(`${tx.nonce}`) : null diff --git a/src/logic/safe/transactions/gasNew.ts b/src/logic/safe/transactions/gasNew.ts index 91015c62..9a54fcb7 100644 --- a/src/logic/safe/transactions/gasNew.ts +++ b/src/logic/safe/transactions/gasNew.ts @@ -25,7 +25,7 @@ const estimateDataGasCosts = (data: string): number => { return accumulator + 16 } - return data.match(/.{2}/g)?.reduce(reducer, 0) + return data.match(/.{2}/g).reduce(reducer, 0) } export const estimateTxGasCosts = async ( @@ -38,11 +38,6 @@ export const estimateTxGasCosts = async ( try { const web3 = getWeb3() const from = await getAccountFrom(web3) - - if (!from) { - return 0 - } - const safeInstance = (new web3.eth.Contract(GnosisSafeSol.abi as AbiItem[], safeAddress) as unknown) as GnosisSafe const nonce = await safeInstance.methods.nonce().call() const threshold = await safeInstance.methods.getThreshold().call() diff --git a/src/logic/safe/transactions/offchainSigner/ethSigner.ts b/src/logic/safe/transactions/offchainSigner/ethSigner.ts index 08f0dc86..005a983e 100644 --- a/src/logic/safe/transactions/offchainSigner/ethSigner.ts +++ b/src/logic/safe/transactions/offchainSigner/ethSigner.ts @@ -39,7 +39,7 @@ export const ethSigner = async ({ return reject(err) } - if (signature?.result == null) { + if (signature.result == null) { reject(new Error(ETH_SIGN_NOT_SUPPORTED_ERROR_MSG)) return } diff --git a/src/logic/safe/utils/safeStorage.ts b/src/logic/safe/utils/safeStorage.ts index 3ef09f7c..c782db82 100644 --- a/src/logic/safe/utils/safeStorage.ts +++ b/src/logic/safe/utils/safeStorage.ts @@ -2,18 +2,11 @@ import { loadFromStorage, saveToStorage } from 'src/utils/storage' import { SafeRecordProps } from 'src/logic/safe/store/models/safe' export const SAFES_KEY = 'SAFES' +export const TX_KEY = 'TX' export const DEFAULT_SAFE_KEY = 'DEFAULT_SAFE' -type StoredSafes = Record - -export const loadStoredSafes = async (): Promise => { - const safes = await loadFromStorage(SAFES_KEY) - - return safes -} - export const getSafeName = async (safeAddress: string): Promise => { - const safes = await loadStoredSafes() + const safes = await loadFromStorage(SAFES_KEY) if (!safes) { return undefined } @@ -30,9 +23,9 @@ export const saveSafes = async (safes) => { } } -export const getLocalSafe = async (safeAddress: string): Promise => { - const storedSafes = await loadStoredSafes() - return storedSafes?.[safeAddress] +export const getLocalSafe = async (safeAddress: string): Promise => { + const storedSafes = (await loadFromStorage(SAFES_KEY)) || {} + return storedSafes[safeAddress] || null } export const getDefaultSafe = async (): Promise => { diff --git a/src/logic/safe/utils/safeVersion.ts b/src/logic/safe/utils/safeVersion.ts index 38c47e69..f0ab2736 100644 --- a/src/logic/safe/utils/safeVersion.ts +++ b/src/logic/safe/utils/safeVersion.ts @@ -11,15 +11,13 @@ export const FEATURES = [ { name: 'ERC1155', validVersion: '>=1.1.1' }, ] -type Feature = typeof FEATURES[number] - -export const safeNeedsUpdate = (currentVersion?: string, latestVersion?: string): boolean => { +export const safeNeedsUpdate = (currentVersion: string, latestVersion: string): boolean => { if (!currentVersion || !latestVersion) { return false } - const current = semverValid(currentVersion) as string - const latest = semverValid(latestVersion) as string + const current = semverValid(currentVersion) + const latest = semverValid(latestVersion) return latest ? semverLessThan(current, latest) : false } @@ -28,7 +26,7 @@ export const getCurrentSafeVersion = (gnosisSafeInstance: GnosisSafe): Promise - FEATURES.reduce((acc: string[], feature: Feature) => { + FEATURES.reduce((acc, feature) => { if (semverSatisfies(version, feature.validVersion)) { acc.push(feature.name) } @@ -46,11 +44,11 @@ export const checkIfSafeNeedsUpdate = async ( lastSafeVersion: string, ): Promise => { if (!gnosisSafeInstance || !lastSafeVersion) { - throw new Error('checkIfSafeNeedsUpdate: No Safe Instance or version provided') + return null } const safeMasterVersion = await getCurrentSafeVersion(gnosisSafeInstance) - const current = semverValid(safeMasterVersion) as string - const latest = semverValid(lastSafeVersion) as string + const current = semverValid(safeMasterVersion) + const latest = semverValid(lastSafeVersion) const needUpdate = safeNeedsUpdate(safeMasterVersion, lastSafeVersion) return { current, latest, needUpdate } diff --git a/src/logic/tokens/store/actions/fetchSafeTokens.ts b/src/logic/tokens/store/actions/fetchSafeTokens.ts index 608256c6..79df1067 100644 --- a/src/logic/tokens/store/actions/fetchSafeTokens.ts +++ b/src/logic/tokens/store/actions/fetchSafeTokens.ts @@ -48,7 +48,7 @@ const extractDataFromResult = (currentTokens: TokenState) => ( if (tokenAddress === null) { acc.ethBalance = humanReadableValue(balance, 18) } else { - acc.balances = acc.balances.merge({ [tokenAddress]: humanReadableValue(balance, Number(token?.decimals)) }) + acc.balances = acc.balances.merge({ [tokenAddress]: humanReadableValue(balance, Number(token.decimals)) }) if (currentTokens && !currentTokens.get(tokenAddress)) { acc.tokens = acc.tokens.push(makeToken({ address: tokenAddress, ...token })) @@ -57,7 +57,7 @@ const extractDataFromResult = (currentTokens: TokenState) => ( acc.currencyList = acc.currencyList.push( makeBalanceCurrency({ - currencyName: balanceUsd ? AVAILABLE_CURRENCIES.USD : undefined, + currencyName: balanceUsd ? AVAILABLE_CURRENCIES.USD : null, tokenAddress, balanceInBaseCurrency: balanceUsd, balanceInSelectedCurrency: balanceUsd, diff --git a/src/logic/tokens/store/actions/fetchTokens.ts b/src/logic/tokens/store/actions/fetchTokens.ts index 068e1aae..a2156698 100644 --- a/src/logic/tokens/store/actions/fetchTokens.ts +++ b/src/logic/tokens/store/actions/fetchTokens.ts @@ -57,7 +57,11 @@ const getTokenValues = (tokenAddress) => methods: ['decimals', 'name', 'symbol'], }) -export const getTokenInfos = async (tokenAddress: string): Promise => { +export const getTokenInfos = async (tokenAddress: string): Promise => { + if (!tokenAddress) { + return null + } + const { tokens } = store.getState() const localToken = tokens.get(tokenAddress) @@ -70,7 +74,7 @@ export const getTokenInfos = async (tokenAddress: string): Promise => // } catch { // return 'Not a token address' // } - const call = await web3.eth.call({ to: tokenAddress, data: web3.utils.sha3('totalSupply()') as string }) + const call = await web3.eth.call({ to: tokenAddress, data: web3.utils.sha3('totalSupply()') }) return call !== '0x' } export const isTokenTransfer = (tx: TxServiceModel): boolean => { - return !isEmptyData(tx.data) && tx.data?.substring(0, 10) === '0xa9059cbb' && Number(tx.value) === 0 + return !isEmptyData(tx.data) && tx.data.substring(0, 10) === '0xa9059cbb' && Number(tx.value) === 0 } export const isSendERC721Transaction = ( tx: TxServiceModel, - txCode: string | null, + txCode: string, knownTokens: Map, ): boolean => { // "0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85" - ens token contract, includes safeTransferFrom @@ -78,7 +78,7 @@ export const getERC20DecimalsAndSymbol = async ( try { const storedTokenInfo = await getTokenInfos(tokenAddress) - if (!storedTokenInfo) { + if (storedTokenInfo === null) { const [tokenDecimals, tokenSymbol] = await generateBatchRequests({ abi: ALTERNATIVE_TOKEN_ABI, address: tokenAddress, @@ -96,7 +96,7 @@ export const getERC20DecimalsAndSymbol = async ( export const isSendERC20Transaction = async ( tx: TxServiceModel, - txCode: string | null, + txCode: string, knownTokens: Map, ): Promise => { let isSendTokenTx = !isSendERC721Transaction(tx, txCode, knownTokens) && isTokenTransfer(tx) diff --git a/src/logic/wallets/ethAddresses.ts b/src/logic/wallets/ethAddresses.ts index c68989b8..6882b0d9 100644 --- a/src/logic/wallets/ethAddresses.ts +++ b/src/logic/wallets/ethAddresses.ts @@ -2,7 +2,7 @@ import { List } from 'immutable' import { SafeRecord } from 'src/logic/safe/store/models/safe' export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' -export const sameAddress = (firstAddress: string | undefined, secondAddress: string | undefined): boolean => { +export const sameAddress = (firstAddress: string, secondAddress: string): boolean => { if (!firstAddress) { return false } diff --git a/src/logic/wallets/getWeb3.ts b/src/logic/wallets/getWeb3.ts index c3c7b0f4..17e06a13 100644 --- a/src/logic/wallets/getWeb3.ts +++ b/src/logic/wallets/getWeb3.ts @@ -96,7 +96,7 @@ const isSmartContractWallet = async (web3Provider: Web3, account: string): Promi } export const getProviderInfo = async (web3Instance: Web3, providerName = 'Wallet'): Promise => { - const account = (await getAccountFrom(web3Instance)) || '' + const account = await getAccountFrom(web3Instance) const network = await getNetworkIdFrom(web3Instance) const smartContractWallet = await isSmartContractWallet(web3Instance, account) const hardwareWallet = isHardwareWallet(providerName) diff --git a/src/logic/wallets/store/middlewares/providerWatcher.ts b/src/logic/wallets/store/middlewares/providerWatcher.ts index fa938cf6..0dedb32d 100644 --- a/src/logic/wallets/store/middlewares/providerWatcher.ts +++ b/src/logic/wallets/store/middlewares/providerWatcher.ts @@ -16,7 +16,8 @@ export const loadLastUsedProvider = async (): Promise => { return lastUsedProvider } -let watcherInterval +let watcherInterval = null + const providerWatcherMware = (store) => (next) => async (action) => { const handledAction = next(action) diff --git a/src/routes/load/components/DetailsForm/index.tsx b/src/routes/load/components/DetailsForm/index.tsx index a14c37be..e3325549 100644 --- a/src/routes/load/components/DetailsForm/index.tsx +++ b/src/routes/load/components/DetailsForm/index.tsx @@ -120,8 +120,6 @@ const DetailsForm = ({ errors, form }: DetailsFormProps): React.ReactElement => fieldMutator={(val) => { form.mutators.setValue(FIELD_LOAD_ADDRESS, val) }} - // eslint-disable-next-line - // @ts-ignore inputAdornment={ noErrorsOn(FIELD_LOAD_ADDRESS, errors) && { endAdornment: ( @@ -158,15 +156,12 @@ const DetailsForm = ({ errors, form }: DetailsFormProps): React.ReactElement => ) } -const DetailsPage = () => - function LoadSafeDetails(controls: React.ReactNode, { errors, form }: StepperPageFormProps): React.ReactElement { - return ( - <> - - - - - ) - } +const DetailsPage = () => (controls: React.ReactNode, { errors, form }: StepperPageFormProps): React.ReactElement => ( + <> + + + + +) export default DetailsPage diff --git a/src/routes/load/components/OwnerList/index.tsx b/src/routes/load/components/OwnerList/index.tsx index cf371bf6..57f38276 100644 --- a/src/routes/load/components/OwnerList/index.tsx +++ b/src/routes/load/components/OwnerList/index.tsx @@ -79,7 +79,7 @@ const calculateSafeValues = (owners, threshold, values) => { } const OwnerListComponent = (props) => { - const [owners, setOwners] = useState([]) + const [owners, setOwners] = useState([]) const { classes, updateInitialProps, values } = props useEffect(() => { @@ -156,15 +156,12 @@ const OwnerListComponent = (props) => { const OwnerListPage = withStyles(styles as any)(OwnerListComponent) -const OwnerList = ({ updateInitialProps }, network) => - function LoadSafeOwnerList(controls, { values }): React.ReactElement { - return ( - <> - - - - - ) - } +const OwnerList = ({ updateInitialProps }, network) => (controls, { values }) => ( + <> + + + + +) export default OwnerList diff --git a/src/routes/load/container/Load.tsx b/src/routes/load/container/Load.tsx index 49809c26..689f460e 100644 --- a/src/routes/load/container/Load.tsx +++ b/src/routes/load/container/Load.tsx @@ -6,11 +6,12 @@ import { FIELD_LOAD_ADDRESS, FIELD_LOAD_NAME } from '../components/fields' import Page from 'src/components/layout/Page' import { getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts' -import { saveSafes, loadStoredSafes } from 'src/logic/safe/utils' +import { SAFES_KEY, saveSafes } from 'src/logic/safe/utils' import { getNamesFrom, getOwnersFrom } from 'src/routes/open/utils/safeDataExtractor' import { SAFELIST_ADDRESS } from 'src/routes/routes' import { buildSafe } from 'src/logic/safe/store/actions/fetchSafe' import { history } from 'src/store' +import { loadFromStorage } from 'src/utils/storage' import { SafeOwner, SafeRecordProps } from 'src/logic/safe/store/models/safe' import { List } from 'immutable' import { checksumAddress } from 'src/utils/checksumAddress' @@ -26,7 +27,7 @@ export const loadSafe = async ( const safeProps = await buildSafe(safeAddress, safeName) safeProps.owners = owners - const storedSafes = (await loadStoredSafes()) || {} + const storedSafes = (await loadFromStorage(SAFES_KEY)) || {} storedSafes[safeAddress] = safeProps diff --git a/src/routes/open/components/SafeOwnersConfirmationsForm/index.tsx b/src/routes/open/components/SafeOwnersConfirmationsForm/index.tsx index 6a52c842..58d2e204 100644 --- a/src/routes/open/components/SafeOwnersConfirmationsForm/index.tsx +++ b/src/routes/open/components/SafeOwnersConfirmationsForm/index.tsx @@ -138,8 +138,6 @@ const SafeOwners = (props) => { fieldMutator={(val) => { form.mutators.setValue(addressName, val) }} - // eslint-disable-next-line - // @ts-ignore inputAdornment={ noErrorsOn(addressName, errors) && { endAdornment: ( @@ -219,21 +217,18 @@ const SafeOwners = (props) => { const SafeOwnersForm = withStyles(styles as any)(withRouter(SafeOwners)) -const SafeOwnersPage = ({ updateInitialProps }) => - function OpenSafeOwnersPage(controls, { errors, form, values }) { - return ( - <> - - - - - ) - } +const SafeOwnersPage = ({ updateInitialProps }) => (controls, { errors, form, values }) => ( + <> + + + + +) export default SafeOwnersPage diff --git a/src/routes/open/container/Open.tsx b/src/routes/open/container/Open.tsx index 3865e166..e1f95690 100644 --- a/src/routes/open/container/Open.tsx +++ b/src/routes/open/container/Open.tsx @@ -161,7 +161,7 @@ const Open = ({ addSafe, network, provider, userAccount }: OwnProps): React.Reac pathname: `${SAFELIST_ADDRESS}/${safeProps.address}/balances`, state: { name, - tx: pendingCreation?.txHash, + tx: pendingCreation.txHash, }, } @@ -177,7 +177,7 @@ const Open = ({ addSafe, network, provider, userAccount }: OwnProps): React.Reac const onRetry = async () => { const values = await loadFromStorage<{ txHash: string }>(SAFE_PENDING_CREATION_STORAGE_KEY) - delete values?.txHash + delete values.txHash await saveToStorage(SAFE_PENDING_CREATION_STORAGE_KEY, values) setSafeCreationPendingInfo(values) createSafeProxy() diff --git a/src/routes/opening/index.tsx b/src/routes/opening/index.tsx index efe99000..3b7f3d5b 100644 --- a/src/routes/opening/index.tsx +++ b/src/routes/opening/index.tsx @@ -105,7 +105,7 @@ const BackButton = styled(Button)` const SafeDeployment = ({ creationTxHash, onCancel, onRetry, onSuccess, provider, submittedPromise }: any) => { const [loading, setLoading] = useState(true) const [stepIndex, setStepIndex] = useState(0) - const [safeCreationTxHash, setSafeCreationTxHash] = useState('') + const [safeCreationTxHash, setSafeCreationTxHash] = useState() const [createdSafeAddress, setCreatedSafeAddress] = useState() const [error, setError] = useState(false) @@ -242,7 +242,7 @@ const SafeDeployment = ({ creationTxHash, onCancel, onRetry, onSuccess, provider useEffect(() => { let interval - const awaitUntilSafeIsDeployed = async (safeCreationTxHash: string) => { + const awaitUntilSafeIsDeployed = async () => { try { const web3 = getWeb3() const receipt = await web3.eth.getTransactionReceipt(safeCreationTxHash) @@ -283,9 +283,7 @@ const SafeDeployment = ({ creationTxHash, onCancel, onRetry, onSuccess, provider return } - if (typeof safeCreationTxHash === 'string') { - awaitUntilSafeIsDeployed(safeCreationTxHash) - } + awaitUntilSafeIsDeployed() return () => { clearInterval(interval) @@ -296,7 +294,7 @@ const SafeDeployment = ({ creationTxHash, onCancel, onRetry, onSuccess, provider return } - let FooterComponent + let FooterComponent = null if (error) { FooterComponent = ErrorFooter } else if (steps[stepIndex].footerComponent) { diff --git a/src/routes/safe/components/AddressBook/index.tsx b/src/routes/safe/components/AddressBook/index.tsx index 9362b09e..8239f4a1 100644 --- a/src/routes/safe/components/AddressBook/index.tsx +++ b/src/routes/safe/components/AddressBook/index.tsx @@ -50,7 +50,7 @@ const AddressBookTable = ({ classes }) => { const safesList = useSelector(safesListSelector) const entryAddressToEditOrCreateNew = useSelector(addressBookQueryParamsSelector) const addressBook = useSelector(getAddressBook) - const [selectedEntry, setSelectedEntry] = useState(null) + const [selectedEntry, setSelectedEntry] = useState(null) const [editCreateEntryModalOpen, setEditCreateEntryModalOpen] = useState(false) const [deleteEntryModalOpen, setDeleteEntryModalOpen] = useState(false) const [sendFundsModalOpen, setSendFundsModalOpen] = useState(false) @@ -70,7 +70,7 @@ const AddressBookTable = ({ classes }) => { if (entryAddressToEditOrCreateNew) { const checksumEntryAdd = checksumAddress(entryAddressToEditOrCreateNew) const key = addressBook.findKey((entry) => entry.address === checksumEntryAdd) - if (key && key >= 0) { + if (key >= 0) { // Edit old entry const value = addressBook.get(key) setSelectedEntry({ entry: value, index: key }) diff --git a/src/routes/safe/components/AllTransactions/index.tsx b/src/routes/safe/components/AllTransactions/index.tsx index 955f5ecf..816819e4 100644 --- a/src/routes/safe/components/AllTransactions/index.tsx +++ b/src/routes/safe/components/AllTransactions/index.tsx @@ -38,7 +38,7 @@ const Transactions = (): React.ReactElement => { {transactionsByPage.map((tx: Transaction, index) => { let txHash = '' if ('transactionHash' in tx) { - txHash = tx.transactionHash as string + txHash = tx.transactionHash } if ('txHash' in tx) { txHash = tx.txHash diff --git a/src/routes/safe/components/Apps/AddAppForm/AppAgreement.tsx b/src/routes/safe/components/Apps/AddAppForm/AppAgreement.tsx index 929a3fd2..cc1ba29a 100644 --- a/src/routes/safe/components/Apps/AddAppForm/AppAgreement.tsx +++ b/src/routes/safe/components/Apps/AddAppForm/AppAgreement.tsx @@ -14,7 +14,7 @@ const AppAgreement = (): React.ReactElement => { const { visited } = useFormState({ subscription: { visited: true } }) // trick to prevent having the field validated by default. Not sure why this happens in this form - const validate = !visited?.agreementAccepted ? undefined : required + const validate = !visited.agreementAccepted ? undefined : required return ( void }): null => { +export const AppInfoUpdater = ({ onAppInfo }: { onAppInfo: (appInfo: SafeApp) => void }): React.ReactElement => { const { input: { value: appUrl }, } = useField('appUrl', { subscription: { value: true } }) @@ -52,7 +52,7 @@ const AppUrl = ({ appList }: { appList: SafeApp[] }): React.ReactElement => { const { visited } = useFormState({ subscription: { visited: true } }) // trick to prevent having the field validated by default. Not sure why this happens in this form - const validate = !visited?.appUrl ? undefined : composeValidators(required, validateUrl, uniqueApp(appList)) + const validate = !visited.appUrl ? undefined : composeValidators(required, validateUrl, uniqueApp(appList)) return ( diff --git a/src/routes/safe/components/Apps/AddAppForm/SubmitButtonStatus.tsx b/src/routes/safe/components/Apps/AddAppForm/SubmitButtonStatus.tsx index b79a888f..dcd6d129 100644 --- a/src/routes/safe/components/Apps/AddAppForm/SubmitButtonStatus.tsx +++ b/src/routes/safe/components/Apps/AddAppForm/SubmitButtonStatus.tsx @@ -9,14 +9,14 @@ interface SubmitButtonStatusProps { onSubmitButtonStatusChange: (disabled: boolean) => void } -const SubmitButtonStatus = ({ appInfo, onSubmitButtonStatusChange }: SubmitButtonStatusProps): null => { +const SubmitButtonStatus = ({ appInfo, onSubmitButtonStatusChange }: SubmitButtonStatusProps): React.ReactElement => { const { valid, validating, visited } = useFormState({ subscription: { valid: true, validating: true, visited: true }, }) React.useEffect(() => { // if non visited, fields were not evaluated yet. Then, the default value is considered invalid - const fieldsVisited = visited?.agreementAccepted && visited.appUrl + const fieldsVisited = visited.agreementAccepted && visited.appUrl onSubmitButtonStatusChange(validating || !valid || !fieldsVisited || !isAppManifestValid(appInfo)) }, [validating, valid, visited, onSubmitButtonStatusChange, appInfo]) diff --git a/src/routes/safe/components/Apps/AddAppForm/index.tsx b/src/routes/safe/components/Apps/AddAppForm/index.tsx index 292f522f..a88b3f4a 100644 --- a/src/routes/safe/components/Apps/AddAppForm/index.tsx +++ b/src/routes/safe/components/Apps/AddAppForm/index.tsx @@ -40,7 +40,7 @@ const INITIAL_VALUES: AddAppFormValues = { } const APP_INFO: SafeApp = { - id: '', + id: undefined, url: '', name: '', iconUrl: appsIconSvg, diff --git a/src/routes/safe/components/Apps/components/AppFrame.tsx b/src/routes/safe/components/Apps/components/AppFrame.tsx index 9d021a81..31ddeaef 100644 --- a/src/routes/safe/components/Apps/components/AppFrame.tsx +++ b/src/routes/safe/components/Apps/components/AppFrame.tsx @@ -54,7 +54,7 @@ const AppFrame = forwardRef(function AppFrameC const redirectToBalance = () => history.push(`${SAFELIST_ADDRESS}/${safeAddress}/balances`) if (!selectedApp) { - return
+ return null } if (!consentReceived) { diff --git a/src/routes/safe/components/Apps/components/ConfirmTransactionModal.tsx b/src/routes/safe/components/Apps/components/ConfirmTransactionModal.tsx index 14abd10a..5c75f847 100644 --- a/src/routes/safe/components/Apps/components/ConfirmTransactionModal.tsx +++ b/src/routes/safe/components/Apps/components/ConfirmTransactionModal.tsx @@ -31,7 +31,7 @@ const isTxValid = (t: Transaction): boolean => { } const isAddressValid = mustBeEthereumAddress(t.to) === undefined - return isAddressValid && !!t.data && typeof t.data === 'string' + return isAddressValid && t.data && typeof t.data === 'string' } const Wrapper = styled.div` @@ -84,7 +84,7 @@ const ConfirmTransactionModal = ({ onCancel, onUserConfirm, onClose, -}: OwnProps): React.ReactElement | null => { +}: OwnProps): React.ReactElement => { const dispatch = useDispatch() if (!isOpen) { return null diff --git a/src/routes/safe/components/Apps/components/ManageApps.tsx b/src/routes/safe/components/Apps/components/ManageApps.tsx index 26ccb494..9d0de55d 100644 --- a/src/routes/safe/components/Apps/components/ManageApps.tsx +++ b/src/routes/safe/components/Apps/components/ManageApps.tsx @@ -14,8 +14,6 @@ type Props = { onAppRemoved: (appId: string) => void } -type AppListItem = SafeApp & { checked: boolean } - const ManageApps = ({ appList, onAppAdded, onAppToggle, onAppRemoved }: Props): React.ReactElement => { const [isOpen, setIsOpen] = useState(false) const [isSubmitDisabled, setIsSubmitDisabled] = useState(true) @@ -30,7 +28,7 @@ const ManageApps = ({ appList, onAppAdded, onAppToggle, onAppRemoved }: Props): const closeModal = () => setIsOpen(false) - const getItemList = (): AppListItem[] => + const getItemList = () => appList.map((a) => { return { ...a, checked: !a.disabled } }) diff --git a/src/routes/safe/components/Apps/hooks/useAppList.ts b/src/routes/safe/components/Apps/hooks/useAppList.ts index fc48a716..dc08c919 100644 --- a/src/routes/safe/components/Apps/hooks/useAppList.ts +++ b/src/routes/safe/components/Apps/hooks/useAppList.ts @@ -42,7 +42,7 @@ const useAppList = (): UseAppListReturnType => { } }) - let apps: SafeApp[] = [] + let apps = [] // using the appURL to recover app info for (let index = 0; index < list.length; index++) { try { diff --git a/src/routes/safe/components/Apps/hooks/useIframeMessageHandler.ts b/src/routes/safe/components/Apps/hooks/useIframeMessageHandler.ts index 2fdd17c5..59cab2d4 100644 --- a/src/routes/safe/components/Apps/hooks/useIframeMessageHandler.ts +++ b/src/routes/safe/components/Apps/hooks/useIframeMessageHandler.ts @@ -44,7 +44,7 @@ const useIframeMessageHandler = ( selectedApp: SafeApp | undefined, openConfirmationModal: (txs: Transaction[], requestId: RequestId) => void, closeModal: () => void, - iframeRef: MutableRefObject, + iframeRef: MutableRefObject, ): ReturnType => { const { enqueueSnackbar, closeSnackbar } = useSnackbar() const safeName = useSelector(safeNameSelector) @@ -60,8 +60,8 @@ const useIframeMessageHandler = ( requestId: requestId || Math.trunc(window.performance.now()), } - if (iframeRef && selectedApp) { - iframeRef.current?.contentWindow?.postMessage(requestWithMessage, selectedApp.url) + if (iframeRef?.current && selectedApp) { + iframeRef.current.contentWindow.postMessage(requestWithMessage, selectedApp.url) } }, [iframeRef, selectedApp], @@ -77,9 +77,7 @@ const useIframeMessageHandler = ( switch (msg.data.messageId) { case SDK_MESSAGES.SEND_TRANSACTIONS: { - if (msg.data.data) { - openConfirmationModal(msg.data.data, requestId) - } + openConfirmationModal(msg.data.data, requestId) break } @@ -87,9 +85,9 @@ const useIframeMessageHandler = ( const message = { messageId: INTERFACE_MESSAGES.ON_SAFE_INFO, data: { - safeAddress: safeAddress as string, - network, - ethBalance: ethBalance as string, + safeAddress, + network: network, + ethBalance, }, } @@ -106,7 +104,7 @@ const useIframeMessageHandler = ( if (message.origin === window.origin) { return } - if (!selectedApp?.url.includes(message.origin)) { + if (!selectedApp.url.includes(message.origin)) { console.error(`ThirdPartyApp: A message was received from an unknown origin ${message.origin}`) return } diff --git a/src/routes/safe/components/Apps/index.tsx b/src/routes/safe/components/Apps/index.tsx index 4bc44cd6..d54dd1b0 100644 --- a/src/routes/safe/components/Apps/index.tsx +++ b/src/routes/safe/components/Apps/index.tsx @@ -7,7 +7,6 @@ import styled, { css } from 'styled-components' import ManageApps from './components/ManageApps' import AppFrame from './components/AppFrame' import { useAppList } from './hooks/useAppList' -import { SafeApp } from './types.d' import LCL from 'src/components/ListContentLayout' import { networkSelector } from 'src/logic/wallets/store/selectors' @@ -64,7 +63,7 @@ const Apps = (): React.ReactElement => { const [confirmTransactionModal, setConfirmTransactionModal] = useState( INITIAL_CONFIRM_TX_MODAL_STATE, ) - const iframeRef = useRef(null) + const iframeRef = useRef() const { trackEvent } = useAnalytics() const granted = useSelector(grantedSelector) @@ -147,14 +146,14 @@ const Apps = (): React.ReactElement => { sendMessageToIframe({ messageId: INTERFACE_MESSAGES.ON_SAFE_INFO, data: { - safeAddress: safeAddress as string, + safeAddress, network, - ethBalance: ethBalance as string, + ethBalance, }, }) }, [ethBalance, network, safeAddress, selectedApp, sendMessageToIframe]) - if (loadingAppList || !appList.length || !safeAddress) { + if (loadingAppList || !appList.length) { return ( @@ -200,10 +199,10 @@ const Apps = (): React.ReactElement => { !appInfo.error export const getAppInfoFromUrl = memoize( - async (appUrl: string): Promise => { - let res = { id: '', url: appUrl, name: 'unknown', iconUrl: appsIconSvg, error: true, description: '' } + async (appUrl?: string): Promise => { + let res = { id: undefined, url: appUrl, name: 'unknown', iconUrl: appsIconSvg, error: true, description: '' } if (!appUrl?.length) { return res diff --git a/src/routes/safe/components/Balances/Collectibles/index.tsx b/src/routes/safe/components/Balances/Collectibles/index.tsx index c06b7227..d3a88e23 100644 --- a/src/routes/safe/components/Balances/Collectibles/index.tsx +++ b/src/routes/safe/components/Balances/Collectibles/index.tsx @@ -79,7 +79,7 @@ const Collectibles = (): React.ReactElement => { const classes = useStyles() const [selectedToken, setSelectedToken] = React.useState({}) const [sendNFTsModalOpen, setSendNFTsModalOpen] = React.useState(false) - const { address, ethBalance, name } = useSelector(safeSelector) || {} + const { address, ethBalance, name } = useSelector(safeSelector) const nftTokens = useSelector(nftTokensSelector) const activeAssetsList = useSelector(activeNftAssetsListSelector) const { trackEvent } = useAnalytics() diff --git a/src/routes/safe/components/Balances/SendModal/SafeInfo/index.tsx b/src/routes/safe/components/Balances/SendModal/SafeInfo/index.tsx index d2b49300..5cd13863 100644 --- a/src/routes/safe/components/Balances/SendModal/SafeInfo/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/SafeInfo/index.tsx @@ -5,7 +5,7 @@ import AddressInfo from 'src/components/AddressInfo' import { safeSelector } from 'src/logic/safe/store/selectors' const SafeInfo = () => { - const { address: safeAddress = '', ethBalance, name: safeName } = useSelector(safeSelector) || {} + const { address: safeAddress = '', ethBalance, name: safeName } = useSelector(safeSelector) return } diff --git a/src/routes/safe/components/Balances/SendModal/screens/AddressBookInput/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/AddressBookInput/index.tsx index 84e18a99..6079daef 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/AddressBookInput/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/AddressBookInput/index.tsx @@ -22,9 +22,9 @@ export interface AddressBookProps { pristine: boolean recipientAddress?: string setSelectedEntry: ( - entry: { address?: string; name?: string } | React.SetStateAction<{ address: string; name: string }> | null, + entry: { address?: string; name?: string } | React.SetStateAction<{ address: string; name: string }>, ) => void - setIsValidAddress: (valid: boolean) => void + setIsValidAddress: (valid?: boolean) => void } const useStyles = makeStyles(styles) @@ -157,7 +157,7 @@ const AddressBookInput = ({ optionsArray.filter((item) => { const inputLowerCase = inputValue.toLowerCase() const foundName = item.name.toLowerCase().includes(inputLowerCase) - const foundAddress = item.address?.toLowerCase().includes(inputLowerCase) + const foundAddress = item.address.toLowerCase().includes(inputLowerCase) return foundName || foundAddress }) } @@ -212,11 +212,6 @@ const AddressBookInput = ({ )} renderOption={(adbkEntry) => { const { address, name } = adbkEntry - - if (!address) { - return - } - return (
diff --git a/src/routes/safe/components/Balances/SendModal/screens/ChooseTxType/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ChooseTxType/index.tsx index 19d4ff90..596eff59 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ChooseTxType/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ChooseTxType/index.tsx @@ -62,8 +62,8 @@ const useStyles = makeStyles({ const ChooseTxType = ({ onClose, recipientAddress, setActiveScreen }) => { const classes = useStyles() - const { featuresEnabled } = useSelector(safeSelector) || {} - const erc721Enabled = featuresEnabled?.includes('ERC721') + const { featuresEnabled } = useSelector(safeSelector) + const erc721Enabled = featuresEnabled.includes('ERC721') const [disableContractInteraction, setDisableContractInteraction] = React.useState(!!recipientAddress) React.useEffect(() => { diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/EthAddressInput/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/EthAddressInput/index.tsx index 1ef7ac19..c51b58d0 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/EthAddressInput/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/EthAddressInput/index.tsx @@ -11,7 +11,6 @@ import { mustBeEthereumAddress, mustBeEthereumContractAddress, required, - Validator, } from 'src/components/forms/validator' import Col from 'src/components/layout/Col' import Row from 'src/components/layout/Row' @@ -35,12 +34,8 @@ const EthAddressInput = ({ text, }: EthAddressInputProps): React.ReactElement => { const classes = useStyles() - const validatorsList = [ - isRequired && required, - mustBeEthereumAddress, - isContract && mustBeEthereumContractAddress, - ] as Validator[] - const validate = composeValidators(...validatorsList.filter((validator) => validator)) + const validatorsList = [isRequired && required, mustBeEthereumAddress, isContract && mustBeEthereumContractAddress] + const validate = composeValidators(...validatorsList.filter((_) => _)) const { pristine } = useFormState({ subscription: { pristine: true } }) const { input: { value }, diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/EthValue/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/EthValue/index.tsx index afda6213..48482ae7 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/EthValue/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/EthValue/index.tsx @@ -20,18 +20,14 @@ const useStyles = makeStyles(styles) interface EthValueProps { onSetMax: (ethBalance: string) => void } -const EthValue = ({ onSetMax }: EthValueProps): React.ReactElement | null => { +const EthValue = ({ onSetMax }: EthValueProps) => { const classes = useStyles() - const { ethBalance } = useSelector(safeSelector) || {} + const { ethBalance } = useSelector(safeSelector) const { input: { value: method }, } = useField('selectedMethod', { subscription: { value: true } }) const disabled = !isPayable(method) - if (!ethBalance) { - return null - } - return disabled ? null : ( <> diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/MethodsDropdown/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/MethodsDropdown/index.tsx index 82ebacdf..b804ea13 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/MethodsDropdown/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/MethodsDropdown/index.tsx @@ -16,7 +16,7 @@ import { NO_CONTRACT } from 'src/routes/safe/components/Balances/SendModal/scree import CheckIcon from 'src/routes/safe/components/CurrencyDropdown/img/check.svg' import { useDropdownStyles } from 'src/routes/safe/components/CurrencyDropdown/style' import { DropdownListTheme } from 'src/theme/mui' -import { extractUsefulMethods, AbiItemExtended } from 'src/logic/contractInteraction/sources/ABIService' +import { extractUsefulMethods } from 'src/logic/contractInteraction/sources/ABIService' const MENU_WIDTH = '452px' @@ -24,7 +24,7 @@ interface MethodsDropdownProps { onChange: (method: AbiItem) => void } -const MethodsDropdown = ({ onChange }: MethodsDropdownProps): React.ReactElement | null => { +const MethodsDropdown = ({ onChange }: MethodsDropdownProps) => { const classes = useDropdownStyles({ buttonWidth: MENU_WIDTH }) const { input: { value: abi }, @@ -34,8 +34,8 @@ const MethodsDropdown = ({ onChange }: MethodsDropdownProps): React.ReactElement initialValues: { selectedMethod: selectedMethodByDefault }, } = useFormState({ subscription: { initialValues: true } }) const [selectedMethod, setSelectedMethod] = React.useState(selectedMethodByDefault ? selectedMethodByDefault : {}) - const [methodsList, setMethodsList] = React.useState([]) - const [methodsListFiltered, setMethodsListFiltered] = React.useState([]) + const [methodsList, setMethodsList] = React.useState([]) + const [methodsListFiltered, setMethodsListFiltered] = React.useState([]) const [anchorEl, setAnchorEl] = React.useState(null) const [searchParams, setSearchParams] = React.useState('') @@ -50,7 +50,7 @@ const MethodsDropdown = ({ onChange }: MethodsDropdownProps): React.ReactElement }, [abi]) React.useEffect(() => { - setMethodsListFiltered(methodsList.filter(({ name }) => name?.toLowerCase().includes(searchParams.toLowerCase()))) + setMethodsListFiltered(methodsList.filter(({ name }) => name.toLowerCase().includes(searchParams.toLowerCase()))) }, [methodsList, searchParams]) const handleClick = (event) => { diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/RenderInputParams/InputComponent/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/RenderInputParams/InputComponent/index.tsx index 9c8af66c..bbad4ed0 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/RenderInputParams/InputComponent/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/RenderInputParams/InputComponent/index.tsx @@ -15,7 +15,7 @@ type Props = { placeholder: string } -const InputComponent = ({ type, keyValue, placeholder }: Props): React.ReactElement | null => { +const InputComponent = ({ type, keyValue, placeholder }: Props): React.ReactElement => { if (!type) { return null } diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/RenderInputParams/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/RenderInputParams/index.tsx index 47b3b6c6..70cc2d79 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/RenderInputParams/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/RenderInputParams/index.tsx @@ -7,18 +7,18 @@ import InputComponent from './InputComponent' import { generateFormFieldKey } from '../utils' import { AbiItemExtended } from 'src/logic/contractInteraction/sources/ABIService' -const RenderInputParams = (): React.ReactElement | null => { +const RenderInputParams = (): React.ReactElement => { const { meta: { valid: validABI }, } = useField('abi', { subscription: { valid: true, value: true } }) const { input: { value: method }, }: { input: { value: AbiItemExtended } } = useField('selectedMethod', { subscription: { value: true } }) - const renderInputs = validABI && !!method && method.inputs?.length + const renderInputs = validABI && !!method && method.inputs.length return !renderInputs ? null : ( <> - {method.inputs?.map(({ name, type }, index) => { + {method.inputs.map(({ name, type }, index) => { const placeholder = name ? `${name} (${type})` : type const key = generateFormFieldKey(type, method.signatureHash, index) diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Review/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Review/index.tsx index 5d2d1c10..99c00ff8 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Review/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Review/index.tsx @@ -40,11 +40,11 @@ type Props = { tx: TransactionReviewType } -const ContractInteractionReview = ({ onClose, onPrev, tx }: Props): React.ReactElement => { +const ContractInteractionReview = ({ onClose, onPrev, tx }: Props) => { const { enqueueSnackbar, closeSnackbar } = useSnackbar() const classes = useStyles() const dispatch = useDispatch() - const { address: safeAddress } = useSelector(safeSelector) || {} + const { address: safeAddress } = useSelector(safeSelector) const [gasCosts, setGasCosts] = useState('< 0.001') useEffect(() => { @@ -54,7 +54,7 @@ const ContractInteractionReview = ({ onClose, onPrev, tx }: Props): React.ReactE const { fromWei, toBN } = getWeb3().utils const txData = tx.data ? tx.data.trim() : '' - const estimatedGasCosts = await estimateTxGasCosts(safeAddress as string, tx.contractAddress as string, txData) + const estimatedGasCosts = await estimateTxGasCosts(safeAddress, tx.contractAddress, txData) const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') const formattedGasCosts = formatAmount(gasCostsAsEth) @@ -102,7 +102,7 @@ const ContractInteractionReview = ({ onClose, onPrev, tx }: Props): React.ReactE - + @@ -129,11 +129,11 @@ const ContractInteractionReview = ({ onClose, onPrev, tx }: Props): React.ReactE - {tx.selectedMethod?.name} + {tx.selectedMethod.name} - {tx.selectedMethod?.inputs?.map(({ name, type }, index) => { - const key = generateFormFieldKey(type, tx.selectedMethod?.signatureHash || '', index) + {tx.selectedMethod.inputs.map(({ name, type }, index) => { + const key = generateFormFieldKey(type, tx.selectedMethod.signatureHash, index) const value: string = getValueFromTxInputs(key, type, tx) return ( diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ReviewCustomTx/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ReviewCustomTx/index.tsx index b47b8f2f..c27dfa5f 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ReviewCustomTx/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ReviewCustomTx/index.tsx @@ -1,6 +1,7 @@ import IconButton from '@material-ui/core/IconButton' import { makeStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' +import { useSnackbar } from 'notistack' import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' @@ -38,9 +39,10 @@ type Props = { const useStyles = makeStyles(styles) const ReviewCustomTx = ({ onClose, onPrev, tx }: Props): React.ReactElement => { + const { enqueueSnackbar, closeSnackbar } = useSnackbar() const classes = useStyles() const dispatch = useDispatch() - const { address: safeAddress } = useSelector(safeSelector) || {} + const { address: safeAddress } = useSelector(safeSelector) const [gasCosts, setGasCosts] = useState('< 0.001') useEffect(() => { @@ -50,7 +52,7 @@ const ReviewCustomTx = ({ onClose, onPrev, tx }: Props): React.ReactElement => { const { fromWei, toBN } = getWeb3().utils const txData = tx.data ? tx.data.trim() : '' - const estimatedGasCosts = await estimateTxGasCosts(safeAddress as string, tx.contractAddress as string, txData) + const estimatedGasCosts = await estimateTxGasCosts(safeAddress, tx.contractAddress, txData) const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') const formattedGasCosts = formatAmount(gasCostsAsEth) @@ -74,12 +76,14 @@ const ReviewCustomTx = ({ onClose, onPrev, tx }: Props): React.ReactElement => { dispatch( createTransaction({ - safeAddress: safeAddress as string, - to: txRecipient as string, + safeAddress, + to: txRecipient, valueInWei: txValue, txData, notifiedTransaction: TX_NOTIFICATION_TYPES.STANDARD_TX, - }), + enqueueSnackbar, + closeSnackbar, + } as any), ) onClose() @@ -114,15 +118,15 @@ const ReviewCustomTx = ({ onClose, onPrev, tx }: Props): React.ReactElement => { - + {tx.contractAddress} - - + + diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/SendCustomTx/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/SendCustomTx/index.tsx index 118ccec0..c481f080 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/SendCustomTx/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/SendCustomTx/index.tsx @@ -52,7 +52,7 @@ const useStyles = makeStyles(styles) const SendCustomTx: React.FC = ({ initialValues, onClose, onNext, contractAddress, switchMethod, isABI }) => { const classes = useStyles() - const { ethBalance } = useSelector(safeSelector) || {} + const { ethBalance } = useSelector(safeSelector) const [qrModalOpen, setQrModalOpen] = useState(false) const [selectedEntry, setSelectedEntry] = useState<{ address?: string; name?: string } | null>({ address: contractAddress || initialValues.contractAddress, @@ -230,7 +230,7 @@ const SendCustomTx: React.FC = ({ initialValues, onClose, onNext, contrac placeholder="Value*" text="Value*" type="text" - validate={composeValidators(mustBeFloat, maxValue(ethBalance || '0'), minValue(0))} + validate={composeValidators(mustBeFloat, maxValue(ethBalance), minValue(0))} /> diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx index 31d28b3f..5d8048ef 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/index.tsx @@ -49,7 +49,7 @@ const ContractInteraction: React.FC = ({ isABI, }) => { const classes = useStyles() - const { address: safeAddress = '' } = useSelector(safeSelector) || {} + const { address: safeAddress = '' } = useSelector(safeSelector) let setCallResults React.useMemo(() => { diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils/index.ts b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils/index.ts index 52922fd0..c6a41b91 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils/index.ts +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils/index.ts @@ -59,7 +59,7 @@ export const formMutators: Record { const modified = - state.lastFormState?.values.selectedMethod && state.lastFormState.values.selectedMethod.name !== args[0].name + state.lastFormState.values.selectedMethod && state.lastFormState.values.selectedMethod.name !== args[0].name if (modified) { utils.changeValue(state, 'callResults', () => '') @@ -115,8 +115,8 @@ export const createTxObject = ( ): ContractSendMethod => { const web3 = getWeb3() const contract: any = new web3.eth.Contract([method], contractAddress) - const { inputs, name = '', signatureHash } = method - const args = inputs?.map(extractMethodArgs(signatureHash, values)) || [] + const { inputs, name, signatureHash } = method + const args = inputs.map(extractMethodArgs(signatureHash, values)) return contract.methods[name](...args) } diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewCollectible/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewCollectible/index.tsx index 1b7cb68d..a87afba9 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewCollectible/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewCollectible/index.tsx @@ -43,7 +43,7 @@ const ReviewCollectible = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx const classes = useStyles() const shortener = textShortener() const dispatch = useDispatch() - const { address: safeAddress } = useSelector(safeSelector) || {} + const { address: safeAddress } = useSelector(safeSelector) const nftTokens = useSelector(nftTokensSelector) const [gasCosts, setGasCosts] = useState('< 0.001') const txToken = nftTokens.find( @@ -66,7 +66,7 @@ const ReviewCollectible = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx const tokenInstance = await ERC721Token.at(tx.assetAddress) const txData = tokenInstance.contract.methods[methodToCall](...params).encodeABI() - const estimatedGasCosts = await estimateTxGasCosts(safeAddress as string, tx.recipientAddress, txData) + const estimatedGasCosts = await estimateTxGasCosts(safeAddress, tx.recipientAddress, txData) const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') const formattedGasCosts = formatAmount(gasCostsAsEth) @@ -148,7 +148,7 @@ const ReviewCollectible = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx {txToken.name} - {shortener(txToken.name)} (Token ID: {shortener(txToken.tokenId as string)}) + {shortener(txToken.name)} (Token ID: {shortener(txToken.tokenId)}) )} diff --git a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.tsx index 0ee764bb..b6de2579 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ReviewTx/index.tsx @@ -3,7 +3,7 @@ import { makeStyles } from '@material-ui/core/styles' import Close from '@material-ui/icons/Close' import { BigNumber } from 'bignumber.js' import { withSnackbar } from 'notistack' -import React, { useEffect, useState, useMemo } from 'react' +import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import ArrowDown from '../assets/arrow-down.svg' @@ -39,14 +39,14 @@ const useStyles = makeStyles(styles as any) const ReviewTx = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx }) => { const classes = useStyles() const dispatch = useDispatch() - const { address: safeAddress } = useSelector(safeSelector) || {} + const { address: safeAddress } = useSelector(safeSelector) const tokens = useSelector(extendedSafeTokensSelector) const [gasCosts, setGasCosts] = useState('< 0.001') const [data, setData] = useState('') - const txToken = useMemo(() => tokens.find((token) => token.address === tx.token), [tokens, tx.token]) - const isSendingETH = txToken?.address === ETH_ADDRESS - const txRecipient = isSendingETH ? tx.recipientAddress : txToken?.address + const txToken = tokens.find((token) => token.address === tx.token) + const isSendingETH = txToken.address === ETH_ADDRESS + const txRecipient = isSendingETH ? tx.recipientAddress : txToken.address useEffect(() => { let isCurrent = true @@ -54,22 +54,18 @@ const ReviewTx = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx }) => { const estimateGas = async () => { const { fromWei, toBN } = getWeb3().utils - if (!txToken) { - return - } - let txData = EMPTY_DATA if (!isSendingETH) { const StandardToken = await getHumanFriendlyToken() - const tokenInstance = await StandardToken.at(txToken.address as string) + const tokenInstance = await StandardToken.at(txToken.address) const decimals = await tokenInstance.decimals() const txAmount = new BigNumber(tx.amount).times(10 ** decimals.toNumber()).toString() txData = tokenInstance.contract.methods.transfer(tx.recipientAddress, txAmount).encodeABI() } - const estimatedGasCosts = await estimateTxGasCosts(safeAddress as string, txRecipient, txData) + const estimatedGasCosts = await estimateTxGasCosts(safeAddress, txRecipient, txData) const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') const formattedGasCosts = formatAmount(gasCostsAsEth) @@ -84,7 +80,7 @@ const ReviewTx = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx }) => { return () => { isCurrent = false } - }, [isSendingETH, safeAddress, tx.amount, tx.recipientAddress, txRecipient, txToken]) + }, [isSendingETH, safeAddress, tx.amount, tx.recipientAddress, txRecipient, txToken.address]) const submitTx = async () => { const web3 = getWeb3() @@ -159,14 +155,9 @@ const ReviewTx = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx }) => { - {txToken?.name - - {tx.amount} {txToken?.symbol} + {txToken.name} + + {tx.amount} {txToken.symbol} diff --git a/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/index.tsx index 8a070426..637085a7 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/index.tsx @@ -53,7 +53,7 @@ const SendCollectible = ({ initialValues, onClose, onNext, recipientAddress, sel name: '', }) const [pristine, setPristine] = useState(true) - const [isValidAddress, setIsValidAddress] = useState(false) + const [isValidAddress, setIsValidAddress] = useState(true) React.useMemo(() => { if (selectedEntry === null && pristine) { @@ -129,7 +129,7 @@ const SendCollectible = ({ initialValues, onClose, onNext, recipientAddress, sel
{ if (e.keyCode !== 9) { - setSelectedEntry({ address: '', name: 'string' }) + setSelectedEntry(null) } }} role="listbox" @@ -150,7 +150,7 @@ const SendCollectible = ({ initialValues, onClose, onNext, recipientAddress, sel setSelectedEntry({ address: '', name: 'string' })} + onClick={() => setSelectedEntry(null)} weight="bolder" > {selectedEntry.name} @@ -158,7 +158,7 @@ const SendCollectible = ({ initialValues, onClose, onNext, recipientAddress, sel setSelectedEntry({ address: '', name: 'string' })} + onClick={() => setSelectedEntry(null)} weight="bolder" > {selectedEntry.address} diff --git a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx index ba3d0b40..8b78fc79 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx @@ -58,7 +58,7 @@ const SendFunds = ({ initialValues, onClose, onNext, recipientAddress, selectedT }) const [pristine, setPristine] = useState(true) - const [isValidAddress, setIsValidAddress] = useState(false) + const [isValidAddress, setIsValidAddress] = useState(true) React.useMemo(() => { if (selectedEntry === null && pristine) { @@ -130,7 +130,7 @@ const SendFunds = ({ initialValues, onClose, onNext, recipientAddress, selectedT
{ if (e.keyCode !== 9) { - setSelectedEntry({ address: '', name: 'string' }) + setSelectedEntry(null) } }} role="listbox" @@ -151,7 +151,7 @@ const SendFunds = ({ initialValues, onClose, onNext, recipientAddress, selectedT setSelectedEntry({ address: '', name: 'string' })} + onClick={() => setSelectedEntry(null)} weight="bolder" > {selectedEntry.name} @@ -159,7 +159,7 @@ const SendFunds = ({ initialValues, onClose, onNext, recipientAddress, selectedT setSelectedEntry({ address: '', name: 'string' })} + onClick={() => setSelectedEntry(null)} weight="bolder" > {selectedEntry.address} @@ -204,7 +204,7 @@ const SendFunds = ({ initialValues, onClose, onNext, recipientAddress, selectedT Amount mutators.setMax(selectedTokenRecord?.balance)} + onClick={() => mutators.setMax(selectedTokenRecord.balance)} weight="bold" testId="send-max-btn" > @@ -230,7 +230,7 @@ const SendFunds = ({ initialValues, onClose, onNext, recipientAddress, selectedT required, mustBeFloat, minValue(0, false), - maxValue(selectedTokenRecord?.balance || 0), + maxValue(selectedTokenRecord?.balance), )} /> diff --git a/src/routes/safe/components/Balances/dataFetcher.ts b/src/routes/safe/components/Balances/dataFetcher.ts index 6604e244..16737cc7 100644 --- a/src/routes/safe/components/Balances/dataFetcher.ts +++ b/src/routes/safe/components/Balances/dataFetcher.ts @@ -61,7 +61,7 @@ export const getBalanceData = ( symbol: token.symbol, }, assetOrder: token.name, - [BALANCE_TABLE_BALANCE_ID]: `${formatAmountInUsFormat(token.balance?.toString() || '0')} ${token.symbol}`, + [BALANCE_TABLE_BALANCE_ID]: `${formatAmountInUsFormat(token.balance.toString())} ${token.symbol}`, balanceOrder: Number(token.balance), [FIXED]: token.symbol === 'ETH', [BALANCE_TABLE_VALUE_ID]: getTokenPriceInCurrency(token, currencySelected, currencyValues, currencyRate), diff --git a/src/routes/safe/components/Balances/index.tsx b/src/routes/safe/components/Balances/index.tsx index 1f5489c6..21c7fb7e 100644 --- a/src/routes/safe/components/Balances/index.tsx +++ b/src/routes/safe/components/Balances/index.tsx @@ -2,7 +2,7 @@ import { makeStyles } from '@material-ui/core/styles' import React, { useEffect, useState } from 'react' import { useSelector } from 'react-redux' -import Receive from 'src/components/App/ReceiveModal' +import Receive from 'src/components/App/ModalReceive' import Tokens from './Tokens' import { styles } from './style' @@ -15,11 +15,7 @@ import Row from 'src/components/layout/Row' import { SAFELIST_ADDRESS } from 'src/routes/routes' import SendModal from 'src/routes/safe/components/Balances/SendModal' import CurrencyDropdown from 'src/routes/safe/components/CurrencyDropdown' -import { - safeFeaturesEnabledSelector, - safeParamAddressFromStateSelector, - safeNameSelector, -} from 'src/logic/safe/store/selectors' +import { safeFeaturesEnabledSelector, safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors' import { wrapInSuspense } from 'src/utils/wrapInSuspense' import { useFetchTokens } from 'src/logic/safe/hooks/useFetchTokens' @@ -37,7 +33,7 @@ const INITIAL_STATE = { showManageCollectibleModal: false, sendFunds: { isOpen: false, - selectedToken: '', + selectedToken: undefined, }, showReceive: false, } @@ -53,12 +49,11 @@ const Balances = (): React.ReactElement => { const address = useSelector(safeParamAddressFromStateSelector) const featuresEnabled = useSelector(safeFeaturesEnabledSelector) - const safeName = useSelector(safeNameSelector) - useFetchTokens(address as string) + useFetchTokens(address) useEffect(() => { - const erc721Enabled = Boolean(featuresEnabled?.includes('ERC721')) + const erc721Enabled = featuresEnabled && featuresEnabled.includes('ERC721') setState((prevState) => ({ ...prevState, @@ -89,7 +84,7 @@ const Balances = (): React.ReactElement => { ...prevState, sendFunds: { isOpen: false, - selectedToken: '', + selectedToken: undefined, }, })) } @@ -229,7 +224,7 @@ const Balances = (): React.ReactElement => { paperClassName={receiveModal} title="Receive Tokens" > - onHide('Receive')} /> + onHide('Receive')} /> ) diff --git a/src/routes/safe/components/CurrencyDropdown/index.tsx b/src/routes/safe/components/CurrencyDropdown/index.tsx index 08d99d3c..63cf986b 100644 --- a/src/routes/safe/components/CurrencyDropdown/index.tsx +++ b/src/routes/safe/components/CurrencyDropdown/index.tsx @@ -22,7 +22,7 @@ import { setImageToPlaceholder } from '../Balances/utils' import Img from 'src/components/layout/Img/index' import etherIcon from 'src/assets/icons/icon_etherTokens.svg' -const CurrencyDropdown = (): React.ReactElement | null => { +const CurrencyDropdown = (): React.ReactElement => { const currenciesList = Object.values(AVAILABLE_CURRENCIES) const safeAddress = useSelector(safeParamAddressFromStateSelector) const dispatch = useDispatch() @@ -48,11 +48,7 @@ const CurrencyDropdown = (): React.ReactElement | null => { handleClose() } - if (!selectedCurrency) { - return null - } - - return ( + return !selectedCurrency ? null : ( <>
{ @@ -66,8 +65,8 @@ function getPendingOwnersConfirmations( const ownersWithNoConfirmationsSorted = ownersWithNoConfirmations .map((owner) => ({ - hasPendingAcceptActions: !!confirmationPendingActions?.includes(owner), - hasPendingRejectActions: !!confirmationRejectActions?.includes(owner), + hasPendingAcceptActions: confirmationPendingActions.includes(owner), + hasPendingRejectActions: confirmationRejectActions.includes(owner), owner, })) // Reorders the list of unconfirmed owners, owners with pendingActions should be first @@ -120,7 +119,7 @@ const OwnersColumn = ({ } else { showOlderTxAnnotation = (thresholdReached && !canExecute) || (cancelThresholdReached && !canExecuteCancel) } - const owners = useSelector(safeOwnersSelector) as List + const owners = useSelector(safeOwnersSelector) const threshold = useSelector(safeThresholdSelector) const userAddress = useSelector(userAccountSelector) const [ownersWhoConfirmed, currentUserAlreadyConfirmed] = getOwnersConfirmations(tx, userAddress) diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/RejectTxModal/index.tsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/RejectTxModal/index.tsx index e5372d4c..3aa449fa 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/RejectTxModal/index.tsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/RejectTxModal/index.tsx @@ -34,7 +34,7 @@ type Props = { const RejectTxModal = ({ isOpen, onClose, tx }: Props): React.ReactElement => { const [gasCosts, setGasCosts] = useState('< 0.001') const dispatch = useDispatch() - const safeAddress = useSelector(safeParamAddressFromStateSelector) as string + const safeAddress = useSelector(safeParamAddressFromStateSelector) const classes = useStyles() useEffect(() => { diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/Value.tsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/Value.tsx index 409440a5..fed5bafe 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/Value.tsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/Value.tsx @@ -30,7 +30,7 @@ interface RenderValueProps { const EtherscanLink = ({ method, type, value }: RenderValueProps): React.ReactElement => { const classes = useStyles() - const [cut, setCut] = React.useState(0) + const [cut, setCut] = React.useState(undefined) const { width } = useWindowDimensions() React.useEffect(() => { diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/utils.ts b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/utils.ts index d204b863..15dabaaa 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/utils.ts +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/TxDescription/utils.ts @@ -12,7 +12,7 @@ const getSafeVersion = (data) => { } interface TxData { - data?: string | null + data?: string recipient?: string module?: string action?: string @@ -34,12 +34,12 @@ export const getTxData = (tx: Transaction): TxData => { if (tx.decodedParams) { if (tx.isTokenTransfer) { - const { to } = tx.decodedParams.transfer || {} + const { to } = tx.decodedParams.transfer txData.recipient = to txData.isTokenTransfer = true } else if (tx.isCollectibleTransfer) { const { safeTransferFrom, transfer, transferFrom } = tx.decodedParams - const { to, value } = safeTransferFrom || transferFrom || transfer || {} + const { to, value } = safeTransferFrom || transferFrom || transfer txData.recipient = to txData.tokenId = value txData.isCollectibleTransfer = true diff --git a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.tsx b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.tsx index 7bd08ad8..0e19683b 100644 --- a/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.tsx +++ b/src/routes/safe/components/Transactions/TxsTable/ExpandedTx/index.tsx @@ -39,10 +39,10 @@ const ExpandedTx = ({ cancelTx, tx }: ExpandedTxProps): React.ReactElement => { const classes = useStyles() const nonce = useSelector(safeNonceSelector) - const threshold = useSelector(safeThresholdSelector) as number - const [openModal, setOpenModal] = useState<'approveTx' | 'executeRejectTx' | 'rejectTx'>() + const threshold = useSelector(safeThresholdSelector) + const [openModal, setOpenModal] = useState(null) const openApproveModal = () => setOpenModal('approveTx') - const closeModal = () => setOpenModal(undefined) + const closeModal = () => setOpenModal(null) const isIncomingTx = !!INCOMING_TX_TYPES[tx.type] const isCreationTx = tx.type === TransactionTypes.CREATION diff --git a/src/routes/safe/components/Transactions/TxsTable/TxType/index.tsx b/src/routes/safe/components/Transactions/TxsTable/TxType/index.tsx index 28c54f67..fbe5a860 100644 --- a/src/routes/safe/components/Transactions/TxsTable/TxType/index.tsx +++ b/src/routes/safe/components/Transactions/TxsTable/TxType/index.tsx @@ -35,7 +35,7 @@ const typeToLabel = { } interface TxTypeProps { - origin: string | null + origin?: string txType: keyof typeof typeToLabel } @@ -45,11 +45,7 @@ const TxType = ({ origin, txType }: TxTypeProps): React.ReactElement => { const [forceCustom, setForceCustom] = useState(false) useEffect(() => { - const getAppInfo = async (origin: string | null) => { - if (!origin) { - return - } - + const getAppInfo = async () => { const parsedOrigin = getAppInfoFromOrigin(origin) if (!parsedOrigin) { @@ -64,7 +60,11 @@ const TxType = ({ origin, txType }: TxTypeProps): React.ReactElement => { setLoading(false) } - getAppInfo(origin) + if (!origin) { + return + } + + getAppInfo() }, [origin, txType]) if (forceCustom || !origin) { diff --git a/src/routes/safe/components/Transactions/TxsTable/columns.tsx b/src/routes/safe/components/Transactions/TxsTable/columns.tsx index 39eca8d5..4f385bf6 100644 --- a/src/routes/safe/components/Transactions/TxsTable/columns.tsx +++ b/src/routes/safe/components/Transactions/TxsTable/columns.tsx @@ -50,10 +50,7 @@ export const getIncomingTxAmount = (tx: Transaction, formatted = true): string = return `1 ${tx.symbol}` } - return getAmountWithSymbol( - { decimals: tx.decimals as string, symbol: tx.symbol as string, value: tx.value }, - formatted, - ) + return getAmountWithSymbol(tx, formatted) } export const getTxAmount = (tx: Transaction, formatted = true): string => { @@ -68,10 +65,10 @@ export const getTxAmount = (tx: Transaction, formatted = true): string => { return NOT_AVAILABLE } - return getAmountWithSymbol({ decimals: decimals as string, symbol: symbol as string, value }, formatted) + return getAmountWithSymbol({ decimals, symbol, value }, formatted) } -export interface TableData { +interface TableData { amount: string cancelTx?: Transaction date: string @@ -84,15 +81,15 @@ export interface TableData { const getIncomingTxTableData = (tx: Transaction): TableData => ({ [TX_TABLE_ID]: tx.blockNumber?.toString() ?? '', - [TX_TABLE_TYPE_ID]: , - [TX_TABLE_DATE_ID]: formatDate(tx.executionDate || '0'), - [buildOrderFieldFrom(TX_TABLE_DATE_ID)]: getTime(parseISO(tx.executionDate || '0')), + [TX_TABLE_TYPE_ID]: , + [TX_TABLE_DATE_ID]: formatDate(tx.executionDate), + [buildOrderFieldFrom(TX_TABLE_DATE_ID)]: getTime(parseISO(tx.executionDate)), [TX_TABLE_AMOUNT_ID]: getIncomingTxAmount(tx), [TX_TABLE_STATUS_ID]: tx.status, [TX_TABLE_RAW_TX_ID]: tx, }) -const getTransactionTableData = (tx: Transaction, cancelTx?: Transaction): TableData => { +const getTransactionTableData = (tx: Transaction, cancelTx: Transaction): TableData => { const txDate = tx.submissionDate return { diff --git a/src/routes/safe/components/Transactions/TxsTable/index.tsx b/src/routes/safe/components/Transactions/TxsTable/index.tsx index 522c277a..e7e43cdc 100644 --- a/src/routes/safe/components/Transactions/TxsTable/index.tsx +++ b/src/routes/safe/components/Transactions/TxsTable/index.tsx @@ -44,8 +44,8 @@ const TxsTable = ({ classes }) => { const filteredData = getTxTableData(transactions, cancellationTransactions) .sort((tx1, tx2) => { // First order by nonce - const aNonce = tx1.tx?.nonce - const bNonce = tx1.tx?.nonce + const aNonce = tx1.tx.nonce + const bNonce = tx1.tx.nonce if (aNonce && bNonce) { const difference = aNonce - bNonce if (difference !== 0) { diff --git a/src/routes/safe/components/Transactions/TxsTable/test/column.test.ts b/src/routes/safe/components/Transactions/TxsTable/test/column.test.ts index 75f9fffb..89b0a499 100644 --- a/src/routes/safe/components/Transactions/TxsTable/test/column.test.ts +++ b/src/routes/safe/components/Transactions/TxsTable/test/column.test.ts @@ -1,6 +1,6 @@ import { List, Map } from 'immutable' import { makeTransaction } from 'src/logic/safe/store/models/transaction' -import { getTxTableData, TX_TABLE_RAW_CANCEL_TX_ID, TableData } from 'src/routes/safe/components/Transactions/TxsTable/columns' +import { getTxTableData, TX_TABLE_RAW_CANCEL_TX_ID } from 'src/routes/safe/components/Transactions/TxsTable/columns' describe('TxsTable Columns > getTxTableData', () => { it('should include CancelTx object inside TxTableData', () => { @@ -10,7 +10,7 @@ describe('TxsTable Columns > getTxTableData', () => { // When const txTableData = getTxTableData(List([mockedTransaction]), Map( { '1': mockedCancelTransaction })) - const txRow = txTableData.first() as TableData + const txRow = txTableData.first() // Then expect(txRow[TX_TABLE_RAW_CANCEL_TX_ID]).toEqual(mockedCancelTransaction) @@ -22,7 +22,7 @@ describe('TxsTable Columns > getTxTableData', () => { // When const txTableData = getTxTableData(List([mockedTransaction]), Map( { '2': mockedCancelTransaction })) - const txRow = txTableData.first() as TableData + const txRow = txTableData.first() // Then expect(txRow[TX_TABLE_RAW_CANCEL_TX_ID]).toBeUndefined() diff --git a/src/routes/safe/container/hooks/useTransactions.ts b/src/routes/safe/container/hooks/useTransactions.tsx similarity index 98% rename from src/routes/safe/container/hooks/useTransactions.ts rename to src/routes/safe/container/hooks/useTransactions.tsx index d8c08424..a08f649d 100644 --- a/src/routes/safe/container/hooks/useTransactions.ts +++ b/src/routes/safe/container/hooks/useTransactions.tsx @@ -19,7 +19,7 @@ export const useTransactions = (props: Props): { transactions: Transaction[]; to const { offset, limit } = props const dispatch = useDispatch() const transactions = useSelector(safeAllTransactionsSelector) - const safeAddress = useSelector(safeParamAddressFromStateSelector) as string + const safeAddress = useSelector(safeParamAddressFromStateSelector) const totalTransactionsCount = useSelector(safeTotalTransactionsAmountSelector) useEffect(() => { async function loadNewTxs() { diff --git a/src/routes/safe/container/index.tsx b/src/routes/safe/container/index.tsx index 2ca98cbf..c504a71f 100644 --- a/src/routes/safe/container/index.tsx +++ b/src/routes/safe/container/index.tsx @@ -29,7 +29,7 @@ const Container = (): React.ReactElement => { title: null, body: null, footer: null, - onClose: () => {}, + onClose: null, }) const safeAddress = useSelector(safeParamAddressFromStateSelector) @@ -42,7 +42,7 @@ const Container = (): React.ReactElement => { const closeGenericModal = () => { if (modal.onClose) { - modal.onClose?.() + modal.onClose() } setModal({ @@ -50,7 +50,7 @@ const Container = (): React.ReactElement => { title: null, body: null, footer: null, - onClose: () => {}, + onClose: null, }) } @@ -59,26 +59,22 @@ const Container = (): React.ReactElement => { wrapInSuspense(, null)} /> wrapInSuspense(, null)} /> - wrapInSuspense(, null)} /> + wrapInSuspense(, null)} /> + wrapInSuspense(, null)} /> wrapInSuspense(, null)} - /> - wrapInSuspense(, null)} /> - + {modal.isOpen && } diff --git a/src/routes/safe/container/selector.ts b/src/routes/safe/container/selector.ts index f27581d9..821790cd 100644 --- a/src/routes/safe/container/selector.ts +++ b/src/routes/safe/container/selector.ts @@ -33,7 +33,7 @@ export const extendedSafeTokensSelector = createSelector( const extendedTokens = Map().withMutations((map) => { safeTokens.forEach((tokenAddress) => { const baseToken = tokensList.get(tokenAddress) - const tokenBalance = balances?.get(tokenAddress) + const tokenBalance = balances.get(tokenAddress) if (baseToken) { map.set(tokenAddress, baseToken.set('balance', tokenBalance || '0')) diff --git a/src/routes/safe/store/actions/transactions/utils/multiSendDecodedDetails.ts b/src/routes/safe/store/actions/transactions/utils/multiSendDecodedDetails.ts index b03c4751..461051c4 100644 --- a/src/routes/safe/store/actions/transactions/utils/multiSendDecodedDetails.ts +++ b/src/routes/safe/store/actions/transactions/utils/multiSendDecodedDetails.ts @@ -56,7 +56,7 @@ export const extractMultiSendDetails = (parameter: Parameter): MultiSendDetails[ export const extractMultiSendDataDecoded = (tx: Transaction): MultiSendDataDecoded => { const transfersDetails = tx.transfers?.map(extractTransferDetails) - const txDetails = tx.dataDecoded?.parameters[0] ? extractMultiSendDetails(tx.dataDecoded?.parameters[0]) : undefined + const txDetails = extractMultiSendDetails(tx.dataDecoded?.parameters[0]) return { txDetails, transfersDetails } } diff --git a/src/routes/safe/store/actions/transactions/utils/transferDetails.ts b/src/routes/safe/store/actions/transactions/utils/transferDetails.ts index 12363dff..6b00126f 100644 --- a/src/routes/safe/store/actions/transactions/utils/transferDetails.ts +++ b/src/routes/safe/store/actions/transactions/utils/transferDetails.ts @@ -20,7 +20,7 @@ const isIncomingTransfer = (transfer: Transfer): boolean => { export const extractERC20TransferDetails = (transfer: Transfer): ERC20TransferDetails => { const erc20TransferDetails = { tokenAddress: transfer.tokenInfo?.address || TxConstants.UNKNOWN, - value: humanReadableValue(transfer.value || 0, transfer.tokenInfo?.decimals), + value: humanReadableValue(transfer.value, transfer.tokenInfo?.decimals), name: transfer.tokenInfo?.name || transfer.tokenInfo?.symbol || TxConstants.UNKNOWN, txHash: transfer.transactionHash, } @@ -59,7 +59,7 @@ export const extractERC721TransferDetails = (transfer: Transfer): ERC721Transfer export const extractETHTransferDetails = (transfer: Transfer): ETHTransferDetails => { const ethTransferDetails = { - value: humanReadableValue(transfer.value || 0), + value: humanReadableValue(transfer.value), txHash: transfer.transactionHash, } if (isIncomingTransfer(transfer)) { diff --git a/src/test/safe.dom.balances.ts b/src/test/safe.dom.balances.ts index 3923cc2f..142228fc 100644 --- a/src/test/safe.dom.balances.ts +++ b/src/test/safe.dom.balances.ts @@ -1,72 +1,72 @@ -// // -// import { waitForElement } from '@testing-library/react' -// import { Set, Map } from 'immutable' -// import { aNewStore } from 'src/store' -// import { sleep } from 'src/utils/timer' -// import { aMinedSafe } from 'src/test/builder/safe.redux.builder' -// import { sendTokenTo, sendEtherTo } from 'src/test/utils/tokenMovements' -// import { renderSafeView } from 'src/test/builder/safe.dom.utils' -// import { dispatchAddTokenToList } from 'src/test/utils/transactions/moveTokens.helper' -// // import { calculateBalanceOf } from 'src/routes/safe/store/actions/fetchTokenBalances' -// import updateActiveTokens from 'src/logic/safe/store/actions/updateActiveTokens' -// import '@testing-library/jest-dom/extend-expect' -// import updateSafe from 'src/logic/safe/store/actions/updateSafe' -// import { BALANCE_ROW_TEST_ID } from 'src/routes/safe/components/Balances' -// import { getBalanceInEtherOf } from 'src/logic/wallets/getWeb3' -export const TODO = 'TODO' -// describe('DOM > Feature > Balances', () => { -// let store -// let safeAddress -// beforeEach(async () => { -// store = aNewStore() -// safeAddress = await aMinedSafe(store) -// }) +// +import { waitForElement } from '@testing-library/react' +import { Set, Map } from 'immutable' +import { aNewStore } from 'src/store' +import { sleep } from 'src/utils/timer' +import { aMinedSafe } from 'src/test/builder/safe.redux.builder' +import { sendTokenTo, sendEtherTo } from 'src/test/utils/tokenMovements' +import { renderSafeView } from 'src/test/builder/safe.dom.utils' +import { dispatchAddTokenToList } from 'src/test/utils/transactions/moveTokens.helper' +// import { calculateBalanceOf } from 'src/routes/safe/store/actions/fetchTokenBalances' +import updateActiveTokens from 'src/logic/safe/store/actions/updateActiveTokens' +import '@testing-library/jest-dom/extend-expect' +import updateSafe from 'src/logic/safe/store/actions/updateSafe' +import { BALANCE_ROW_TEST_ID } from 'src/routes/safe/components/Balances' +import { getBalanceInEtherOf } from 'src/logic/wallets/getWeb3' -// it('Updates token balances automatically', async () => { -// const tokensAmount = '100' -// const tokenAddress = await sendTokenTo(safeAddress, tokensAmount) -// await dispatchAddTokenToList(store, tokenAddress) +describe('DOM > Feature > Balances', () => { + let store + let safeAddress + beforeEach(async () => { + store = aNewStore() + safeAddress = await aMinedSafe(store) + }) -// const SafeDom = await renderSafeView(store, safeAddress) + it('Updates token balances automatically', async () => { + const tokensAmount = '100' + const tokenAddress = await sendTokenTo(safeAddress, tokensAmount) + await dispatchAddTokenToList(store, tokenAddress) -// // Activate token -// const safeTokenBalance = undefined -// // const safeTokenBalance = await calculateBalanceOf(tokenAddress, safeAddress, 18) -// // expect(safeTokenBalance).toBe(tokensAmount) + const SafeDom = await renderSafeView(store, safeAddress) -// const balances = Map({ -// [tokenAddress]: safeTokenBalance, -// }) -// store.dispatch(updateActiveTokens(safeAddress, Set([tokenAddress]))) -// store.dispatch(updateSafe({ address: safeAddress, balances })) -// await sleep(1000) + // Activate token + const safeTokenBalance = undefined + // const safeTokenBalance = await calculateBalanceOf(tokenAddress, safeAddress, 18) + // expect(safeTokenBalance).toBe(tokensAmount) -// const balanceRows = SafeDom.getAllByTestId(BALANCE_ROW_TEST_ID) -// expect(balanceRows.length).toBe(2) + const balances = Map({ + [tokenAddress]: safeTokenBalance, + }) + store.dispatch(updateActiveTokens(safeAddress, Set([tokenAddress]))) + store.dispatch(updateSafe({ address: safeAddress, balances })) + await sleep(1000) -// await waitForElement(() => SafeDom.getByText(`${tokensAmount} OMG`)) + const balanceRows = SafeDom.getAllByTestId(BALANCE_ROW_TEST_ID) + expect(balanceRows.length).toBe(2) -// await sendTokenTo(safeAddress, tokensAmount) + await waitForElement(() => SafeDom.getByText(`${tokensAmount} OMG`)) -// await waitForElement(() => SafeDom.getByText(`${parseInt(tokensAmount, 10) * 2} OMG`)) -// }) + await sendTokenTo(safeAddress, tokensAmount) -// it('Updates ether balance automatically', async () => { -// const etherAmount = '1' -// await sendEtherTo(safeAddress, etherAmount) + await waitForElement(() => SafeDom.getByText(`${parseInt(tokensAmount, 10) * 2} OMG`)) + }) -// const SafeDom = await renderSafeView(store, safeAddress) + it('Updates ether balance automatically', async () => { + const etherAmount = '1' + await sendEtherTo(safeAddress, etherAmount) -// const safeEthBalance = await getBalanceInEtherOf(safeAddress) -// expect(safeEthBalance).toBe(etherAmount) + const SafeDom = await renderSafeView(store, safeAddress) -// const balanceRows = SafeDom.getAllByTestId(BALANCE_ROW_TEST_ID) -// expect(balanceRows.length).toBe(1) + const safeEthBalance = await getBalanceInEtherOf(safeAddress) + expect(safeEthBalance).toBe(etherAmount) -// await waitForElement(() => SafeDom.getByText(`${etherAmount} ETH`)) + const balanceRows = SafeDom.getAllByTestId(BALANCE_ROW_TEST_ID) + expect(balanceRows.length).toBe(1) -// await sendEtherTo(safeAddress, etherAmount) + await waitForElement(() => SafeDom.getByText(`${etherAmount} ETH`)) -// await waitForElement(() => SafeDom.getByText(`${parseInt(etherAmount, 10) * 2} ETH`)) -// }) -// }) + await sendEtherTo(safeAddress, etherAmount) + + await waitForElement(() => SafeDom.getByText(`${parseInt(etherAmount, 10) * 2} ETH`)) + }) +}) diff --git a/src/test/tokens.dom.adding.ts b/src/test/tokens.dom.adding.ts index 79f770af..fa1c5b0f 100644 --- a/src/test/tokens.dom.adding.ts +++ b/src/test/tokens.dom.adding.ts @@ -1,82 +1,83 @@ -// import { fireEvent } from '@testing-library/react' -// import { getWeb3 } from 'src/logic/wallets/getWeb3' -// import { getFirstTokenContract } from 'src/test/utils/tokenMovements' -// import { aNewStore } from 'src/store' -// import { aMinedSafe } from 'src/test/builder/safe.redux.builder' -// import { renderSafeView } from 'src/test/builder/safe.dom.utils' -// import { sleep } from 'src/utils/timer' -// import { clickOnManageTokens, clickOnAddCustomToken } from 'src/test/utils/DOMNavigation' -// import * as fetchTokensModule from 'src/logic/tokens/store/actions/fetchTokens' -// import { -// ADD_CUSTOM_TOKEN_ADDRESS_INPUT_TEST_ID, -// ADD_CUSTOM_TOKEN_SYMBOLS_INPUT_TEST_ID, -// ADD_CUSTOM_TOKEN_DECIMALS_INPUT_TEST_ID, -// ADD_CUSTOM_TOKEN_FORM, -// } from 'src/routes/safe/components/Balances/Tokens/screens/AddCustomToken' -// import { BALANCE_ROW_TEST_ID } from 'src/routes/safe/components/Balances/' -// import '@testing-library/jest-dom/extend-expect' -export const TODO = 'TODO' -// // https://github.com/testing-library/@testing-library/react/issues/281 -// const originalError = console.error -// beforeAll(() => { -// console.error = (...args) => { -// if (/Warning.*not wrapped in act/.test(args[0])) { -// return -// } -// originalError.call(console, ...args) -// } -// }) +// +import { fireEvent } from '@testing-library/react' +import { getWeb3 } from 'src/logic/wallets/getWeb3' +import { getFirstTokenContract } from 'src/test/utils/tokenMovements' +import { aNewStore } from 'src/store' +import { aMinedSafe } from 'src/test/builder/safe.redux.builder' +import { renderSafeView } from 'src/test/builder/safe.dom.utils' +import { sleep } from 'src/utils/timer' +import { clickOnManageTokens, clickOnAddCustomToken } from 'src/test/utils/DOMNavigation' +import * as fetchTokensModule from 'src/logic/tokens/store/actions/fetchTokens' +import { + ADD_CUSTOM_TOKEN_ADDRESS_INPUT_TEST_ID, + ADD_CUSTOM_TOKEN_SYMBOLS_INPUT_TEST_ID, + ADD_CUSTOM_TOKEN_DECIMALS_INPUT_TEST_ID, + ADD_CUSTOM_TOKEN_FORM, +} from 'src/routes/safe/components/Balances/Tokens/screens/AddCustomToken' +import { BALANCE_ROW_TEST_ID } from 'src/routes/safe/components/Balances/' +import '@testing-library/jest-dom/extend-expect' -// afterAll(() => { -// console.error = originalError -// }) +// https://github.com/testing-library/@testing-library/react/issues/281 +const originalError = console.error +beforeAll(() => { + console.error = (...args) => { + if (/Warning.*not wrapped in act/.test(args[0])) { + return + } + originalError.call(console, ...args) + } +}) -// describe('DOM > Feature > Add custom ERC 20 Tokens', () => { -// let web3 -// let accounts -// let erc20Token +afterAll(() => { + console.error = originalError +}) -// beforeAll(async () => { -// web3 = getWeb3() -// accounts = await web3.eth.getAccounts() -// erc20Token = await getFirstTokenContract(web3, accounts[0]) -// }) +describe('DOM > Feature > Add custom ERC 20 Tokens', () => { + let web3 + let accounts + let erc20Token -// it('adds and displays an erc 20 token after filling the form', async () => { -// // GIVEN -// const store = aNewStore() -// const safeAddress = await aMinedSafe(store) -// await store.dispatch(fetchTokensModule.fetchTokens() as any) -// const TokensDom = renderSafeView(store, safeAddress) -// await sleep(400) + beforeAll(async () => { + web3 = getWeb3() + accounts = await web3.eth.getAccounts() + erc20Token = await getFirstTokenContract(web3, accounts[0]) + }) -// // WHEN -// clickOnManageTokens(TokensDom) -// clickOnAddCustomToken(TokensDom) -// await sleep(200) + it('adds and displays an erc 20 token after filling the form', async () => { + // GIVEN + const store = aNewStore() + const safeAddress = await aMinedSafe(store) + await store.dispatch(fetchTokensModule.fetchTokens() as any) + const TokensDom = renderSafeView(store, safeAddress) + await sleep(400) -// // Fill address -// const addTokenForm = TokensDom.getByTestId(ADD_CUSTOM_TOKEN_FORM) -// const addressInput = TokensDom.getByTestId(ADD_CUSTOM_TOKEN_ADDRESS_INPUT_TEST_ID) -// fireEvent.change(addressInput, { target: { value: erc20Token.address } }) -// await sleep(500) + // WHEN + clickOnManageTokens(TokensDom) + clickOnAddCustomToken(TokensDom) + await sleep(200) -// // Check if it loaded symbol/decimals correctly -// const symbolInput: any = TokensDom.getByTestId(ADD_CUSTOM_TOKEN_SYMBOLS_INPUT_TEST_ID) -// const decimalsInput: any = TokensDom.getByTestId(ADD_CUSTOM_TOKEN_DECIMALS_INPUT_TEST_ID) + // Fill address + const addTokenForm = TokensDom.getByTestId(ADD_CUSTOM_TOKEN_FORM) + const addressInput = TokensDom.getByTestId(ADD_CUSTOM_TOKEN_ADDRESS_INPUT_TEST_ID) + fireEvent.change(addressInput, { target: { value: erc20Token.address } }) + await sleep(500) -// const tokenSymbol = await erc20Token.symbol() -// const tokenDecimals = await erc20Token.decimals() -// expect(symbolInput.value).toBe(tokenSymbol) -// expect(decimalsInput.value).toBe(tokenDecimals.toString()) + // Check if it loaded symbol/decimals correctly + const symbolInput: any = TokensDom.getByTestId(ADD_CUSTOM_TOKEN_SYMBOLS_INPUT_TEST_ID) + const decimalsInput: any = TokensDom.getByTestId(ADD_CUSTOM_TOKEN_DECIMALS_INPUT_TEST_ID) -// // Submit form -// fireEvent.submit(addTokenForm) -// await sleep(300) + const tokenSymbol = await erc20Token.symbol() + const tokenDecimals = await erc20Token.decimals() + expect(symbolInput.value).toBe(tokenSymbol) + expect(decimalsInput.value).toBe(tokenDecimals.toString()) -// // check if token is displayed -// const balanceRows = TokensDom.getAllByTestId(BALANCE_ROW_TEST_ID) -// expect(balanceRows.length).toBe(2) -// expect(balanceRows[1]).toHaveTextContent(tokenSymbol) -// }) -// }) + // Submit form + fireEvent.submit(addTokenForm) + await sleep(300) + + // check if token is displayed + const balanceRows = TokensDom.getAllByTestId(BALANCE_ROW_TEST_ID) + expect(balanceRows.length).toBe(2) + expect(balanceRows[1]).toHaveTextContent(tokenSymbol) + }) +}) diff --git a/src/test/tokens.dom.enabling.ts b/src/test/tokens.dom.enabling.ts index 0a3ea15c..1f22bff7 100644 --- a/src/test/tokens.dom.enabling.ts +++ b/src/test/tokens.dom.enabling.ts @@ -1,91 +1,92 @@ -// import { waitForElement } from '@testing-library/react' -// import { List } from 'immutable' -// import { getWeb3 } from 'src/logic/wallets/getWeb3' -// import { getFirstTokenContract, getSecondTokenContract } from 'src/test/utils/tokenMovements' -// import { aNewStore } from 'src/store' -// import { aMinedSafe } from 'src/test/builder/safe.redux.builder' -// import { renderSafeView } from 'src/test/builder/safe.dom.utils' -// import { sleep } from 'src/utils/timer' -// import saveTokens from 'src/logic/tokens/store/actions/saveTokens' -// import { clickOnManageTokens, closeManageTokensModal, toggleToken } from './utils/DOMNavigation' -// import { BALANCE_ROW_TEST_ID } from 'src/routes/safe/components/Balances' -// import { makeToken } from 'src/logic/tokens/store/model/token' -// import '@testing-library/jest-dom/extend-expect' -// import { getActiveTokens } from 'src/logic/tokens/utils/tokensStorage' -export const TODO = 'TODO' -// describe('DOM > Feature > Enable and disable default tokens', () => { -// let web3 -// let accounts -// let firstErc20Token -// let secondErc20Token -// let testTokens +// +import { waitForElement } from '@testing-library/react' +import { List } from 'immutable' +import { getWeb3 } from 'src/logic/wallets/getWeb3' +import { getFirstTokenContract, getSecondTokenContract } from 'src/test/utils/tokenMovements' +import { aNewStore } from 'src/store' +import { aMinedSafe } from 'src/test/builder/safe.redux.builder' +import { renderSafeView } from 'src/test/builder/safe.dom.utils' +import { sleep } from 'src/utils/timer' +import saveTokens from 'src/logic/tokens/store/actions/saveTokens' +import { clickOnManageTokens, closeManageTokensModal, toggleToken } from './utils/DOMNavigation' +import { BALANCE_ROW_TEST_ID } from 'src/routes/safe/components/Balances' +import { makeToken } from 'src/logic/tokens/store/model/token' +import '@testing-library/jest-dom/extend-expect' +import { getActiveTokens } from 'src/logic/tokens/utils/tokensStorage' -// beforeAll(async () => { -// web3 = getWeb3() -// accounts = await web3.eth.getAccounts() +describe('DOM > Feature > Enable and disable default tokens', () => { + let web3 + let accounts + let firstErc20Token + let secondErc20Token + let testTokens -// firstErc20Token = await getFirstTokenContract(web3, accounts[0]) -// secondErc20Token = await getSecondTokenContract(web3, accounts[0]) -// testTokens = List([ -// makeToken({ -// address: firstErc20Token.address, -// name: 'First Token Example', -// symbol: 'FTE', -// decimals: 18, -// logoUri: 'https://upload.wikimedia.org/wikipedia/commons/c/c0/Earth_simple_icon.png', -// }), -// makeToken({ -// address: secondErc20Token.address, -// name: 'Second Token Example', -// symbol: 'STE', -// decimals: 18, -// logoUri: 'https://upload.wikimedia.org/wikipedia/commons/c/c0/Earth_simple_icon.png', -// }), -// ]) -// }) + beforeAll(async () => { + web3 = getWeb3() + accounts = await web3.eth.getAccounts() -// it('allows to enable and disable tokens, stores active ones in the local storage', async () => { -// // GIVEN -// const store = aNewStore() -// const safeAddress = await aMinedSafe(store) -// await store.dispatch(saveTokens(testTokens)) + firstErc20Token = await getFirstTokenContract(web3, accounts[0]) + secondErc20Token = await getSecondTokenContract(web3, accounts[0]) + testTokens = List([ + makeToken({ + address: firstErc20Token.address, + name: 'First Token Example', + symbol: 'FTE', + decimals: 18, + logoUri: 'https://upload.wikimedia.org/wikipedia/commons/c/c0/Earth_simple_icon.png', + }), + makeToken({ + address: secondErc20Token.address, + name: 'Second Token Example', + symbol: 'STE', + decimals: 18, + logoUri: 'https://upload.wikimedia.org/wikipedia/commons/c/c0/Earth_simple_icon.png', + }), + ]) + }) -// // WHEN -// const TokensDom = await renderSafeView(store, safeAddress) + it('allows to enable and disable tokens, stores active ones in the local storage', async () => { + // GIVEN + const store = aNewStore() + const safeAddress = await aMinedSafe(store) + await store.dispatch(saveTokens(testTokens)) -// // Check if only ETH is enabled -// let balanceRows = await waitForElement(() => TokensDom.getAllByTestId(BALANCE_ROW_TEST_ID)) -// expect(balanceRows.length).toBe(1) + // WHEN + const TokensDom = await renderSafeView(store, safeAddress) -// // THEN -// clickOnManageTokens(TokensDom) -// await toggleToken(TokensDom, 'FTE') -// await toggleToken(TokensDom, 'STE') -// closeManageTokensModal(TokensDom) + // Check if only ETH is enabled + let balanceRows = await waitForElement(() => TokensDom.getAllByTestId(BALANCE_ROW_TEST_ID)) + expect(balanceRows.length).toBe(1) -// // Wait for active tokens to save -// await sleep(1500) + // THEN + clickOnManageTokens(TokensDom) + await toggleToken(TokensDom, 'FTE') + await toggleToken(TokensDom, 'STE') + closeManageTokensModal(TokensDom) -// // Check if tokens were enabled -// balanceRows = TokensDom.getAllByTestId(BALANCE_ROW_TEST_ID) -// expect(balanceRows.length).toBe(3) -// expect(balanceRows[1]).toHaveTextContent('FTE') -// expect(balanceRows[2]).toHaveTextContent('STE') -// const tokensFromStorage = await getActiveTokens() + // Wait for active tokens to save + await sleep(1500) -// expect(Object.keys(tokensFromStorage)).toContain(firstErc20Token.address) -// expect(Object.keys(tokensFromStorage)).toContain(secondErc20Token.address) + // Check if tokens were enabled + balanceRows = TokensDom.getAllByTestId(BALANCE_ROW_TEST_ID) + expect(balanceRows.length).toBe(3) + expect(balanceRows[1]).toHaveTextContent('FTE') + expect(balanceRows[2]).toHaveTextContent('STE') + const tokensFromStorage = await getActiveTokens() -// // disable tokens -// clickOnManageTokens(TokensDom) -// await toggleToken(TokensDom, 'FTE') -// await toggleToken(TokensDom, 'STE') -// closeManageTokensModal(TokensDom) -// await sleep(1500) + expect(Object.keys(tokensFromStorage)).toContain(firstErc20Token.address) + expect(Object.keys(tokensFromStorage)).toContain(secondErc20Token.address) -// // check if tokens were disabled -// balanceRows = TokensDom.getAllByTestId(BALANCE_ROW_TEST_ID) -// expect(balanceRows.length).toBe(1) -// expect(balanceRows[0]).toHaveTextContent('ETH') -// }) -// }) + // disable tokens + clickOnManageTokens(TokensDom) + await toggleToken(TokensDom, 'FTE') + await toggleToken(TokensDom, 'STE') + closeManageTokensModal(TokensDom) + await sleep(1500) + + // check if tokens were disabled + balanceRows = TokensDom.getAllByTestId(BALANCE_ROW_TEST_ID) + expect(balanceRows.length).toBe(1) + expect(balanceRows[0]).toHaveTextContent('ETH') + }) +}) diff --git a/src/test/utils/tokenMovements.ts b/src/test/utils/tokenMovements.ts index e15863d8..85ffe7e0 100644 --- a/src/test/utils/tokenMovements.ts +++ b/src/test/utils/tokenMovements.ts @@ -56,13 +56,13 @@ export const getFirstTokenContract = undefined //ensureOnce(createTokenOMGContra export const getSecondTokenContract = undefined //ensureOnce(createTokenRDNContract) export const get6DecimalsTokenContract = undefined //ensureOnce(create6DecimalsTokenContract) -// export const sendTokenTo = async (safe, value, tokenContract?: any) => { -// const web3 = getWeb3() -// const accounts = await web3.eth.getAccounts() +export const sendTokenTo = async (safe, value, tokenContract?: any) => { + const web3 = getWeb3() + const accounts = await web3.eth.getAccounts() -// const OMGToken = tokenContract || (await getFirstTokenContract(web3, accounts[0])) -// const nativeValue = toNative(value, 18) -// await OMGToken.transfer(safe, nativeValue.valueOf(), { from: accounts[0], gas: '5000000' }) + const OMGToken = tokenContract || (await getFirstTokenContract(web3, accounts[0])) + const nativeValue = toNative(value, 18) + await OMGToken.transfer(safe, nativeValue.valueOf(), { from: accounts[0], gas: '5000000' }) -// return OMGToken.address -// } + return OMGToken.address +} diff --git a/src/utils/checksumAddress.ts b/src/utils/checksumAddress.ts index b0cd1fdc..674509a3 100644 --- a/src/utils/checksumAddress.ts +++ b/src/utils/checksumAddress.ts @@ -1,5 +1,6 @@ import { getWeb3 } from 'src/logic/wallets/getWeb3' export const checksumAddress = (address: string): string => { + if (!address) return null return getWeb3().utils.toChecksumAddress(address) } diff --git a/src/utils/clipboard.ts b/src/utils/clipboard.ts index d540a71c..e2b45a91 100644 --- a/src/utils/clipboard.ts +++ b/src/utils/clipboard.ts @@ -1,15 +1,15 @@ -export const copyToClipboard = (text: string): void => { +export const copyToClipboard = (text) => { const range = document.createRange() range.selectNodeContents(document.body) - document?.getSelection()?.addRange(range) + document.getSelection().addRange(range) - function listener(e: ClipboardEvent) { - e.clipboardData?.setData('text/plain', text) + function listener(e) { + e.clipboardData.setData('text/plain', text) e.preventDefault() } document.addEventListener('copy', listener) document.execCommand('copy') document.removeEventListener('copy', listener) - document?.getSelection()?.removeAllRanges() + document.getSelection().removeAllRanges() } diff --git a/src/utils/intercom.ts b/src/utils/intercom.ts index 6fb98cbf..8c2f7ee9 100644 --- a/src/utils/intercom.ts +++ b/src/utils/intercom.ts @@ -13,7 +13,7 @@ export const loadIntercom = () => { s.async = true s.src = `https://widget.intercom.io/widget/${APP_ID}` const x = d.getElementsByTagName('script')[0] - x?.parentNode?.insertBefore(s, x) + x.parentNode.insertBefore(s, x) s.onload = () => { ;(window as any).Intercom('boot', { diff --git a/src/utils/storage/signatures.ts b/src/utils/storage/signatures.ts new file mode 100644 index 00000000..1684fea4 --- /dev/null +++ b/src/utils/storage/signatures.ts @@ -0,0 +1,30 @@ +import { Map } from 'immutable' + +import { loadFromStorage, saveToStorage } from 'src/utils/storage' + +const getSignaturesKeyFrom = (safeAddress) => `TXS-SIGNATURES-${safeAddress}` + +export const storeSignature = async (safeAddress, nonce, signature) => { + const signaturesKey = getSignaturesKeyFrom(safeAddress) + const subjects = Map(await loadFromStorage(signaturesKey)) || Map() + + try { + const key = `${nonce}` + const existingSignatures = subjects.get(key) + const signatures = existingSignatures ? existingSignatures + signature : signature + const updatedSubjects = subjects.set(key, signatures) + await saveToStorage(signaturesKey, updatedSubjects) + } catch (err) { + console.error('Error storing signatures in localstorage', err) + } +} + +export const getSignaturesFrom = (safeAddress, nonce) => { + const key = getSignaturesKeyFrom(safeAddress) + const data = loadFromStorage(key) + + const signatures = data ? Map(data as any) : Map() + const txSigs = signatures.get(String(nonce)) || '' + + return `0x${txSigs}` +} diff --git a/src/utils/storage/transactions.ts b/src/utils/storage/transactions.ts new file mode 100644 index 00000000..855f5f34 --- /dev/null +++ b/src/utils/storage/transactions.ts @@ -0,0 +1,17 @@ +import { Map } from 'immutable' + +import { loadFromStorage, saveToStorage } from 'src/utils/storage' + +const getSubjectKeyFrom = (safeAddress) => `TXS-SUBJECTS-${safeAddress}` + +export const storeSubject = async (safeAddress, nonce, subject) => { + const key = getSubjectKeyFrom(safeAddress) + const subjects = Map(await loadFromStorage(key)) || Map() + + try { + const updatedSubjects = subjects.set(nonce, subject) + saveToStorage(key, updatedSubjects) + } catch (err) { + console.error('Error storing transaction subject in localstorage', err) + } +} diff --git a/src/utils/strings.ts b/src/utils/strings.ts index ec142be7..f7d41ded 100644 --- a/src/utils/strings.ts +++ b/src/utils/strings.ts @@ -16,7 +16,15 @@ export const textShortener = ({ charsEnd = 10, charsStart = 10, ellipsis = '...' * @param text * @returns {string|?string} */ - (text = ''): string => { + (text = null) => { + if (typeof text !== 'string') { + throw new TypeError(` A string is required. ${typeof text} was provided instead.`) + } + + if (!text) { + return '' + } + const amountOfCharsToKeep = charsEnd + charsStart const finalStringLength = amountOfCharsToKeep + ellipsis.length diff --git a/tsconfig.json b/tsconfig.json index 61c5bcc1..ede637e7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,6 @@ "noImplicitAny": false, "allowSyntheticDefaultImports": true, "strict": false, - "strictNullChecks": true, "forceConsistentCasingInFileNames": true, "module": "esnext", "moduleResolution": "node", diff --git a/yarn.lock b/yarn.lock index 72b0a659..12eda847 100644 --- a/yarn.lock +++ b/yarn.lock @@ -186,10 +186,11 @@ lodash "^4.17.19" "@babel/helper-explode-assignable-expression@^7.10.4": - version "7.11.4" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz#2d8e3470252cc17aba917ede7803d4a7a276a41b" - integrity sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ== + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz#40a1cd917bff1288f699a94a75b37a1a2dbd8c7c" + integrity sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A== dependencies: + "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" "@babel/helper-function-name@^7.10.4": @@ -262,13 +263,14 @@ lodash "^4.17.19" "@babel/helper-remap-async-to-generator@^7.10.4": - version "7.11.4" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz#4474ea9f7438f18575e30b0cac784045b402a12d" - integrity sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA== + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.4.tgz#fce8bea4e9690bbe923056ded21e54b4e8b68ed5" + integrity sha512-86Lsr6NNw3qTNl+TBcF1oRZMaVzJtbWTyTko+CQL/tvNvcGYEFKbLXDPxtW0HKk3McNOk4KzY55itGWCAGK5tg== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-wrap-function" "^7.10.4" "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" "@babel/helper-replace-supers@^7.10.4": @@ -1522,7 +1524,7 @@ resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5" integrity sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ== -"@hapi/address@^4.1.0": +"@hapi/address@^4.0.1": version "4.1.0" resolved "https://registry.yarnpkg.com/@hapi/address/-/address-4.1.0.tgz#d60c5c0d930e77456fdcde2598e77302e2955e1d" integrity sha512-SkszZf13HVgGmChdHo/PxchnSaCJ6cetVqLzyciudzZRT0jcOouIF/Q93mgjw8cce+D+4F4C1Z/WrfFN+O3VHQ== @@ -1559,6 +1561,17 @@ "@hapi/hoek" "8.x.x" "@hapi/topo" "3.x.x" +"@hapi/joi@^17.1.1": + version "17.1.1" + resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-17.1.1.tgz#9cc8d7e2c2213d1e46708c6260184b447c661350" + integrity sha512-p4DKeZAoeZW4g3u7ZeRo+vCDuSDgSvtsB/NpfjXEHTUjSeINAi/RrVOWiVQ1isaoLzMvFEhe8n5065mQq1AdQg== + dependencies: + "@hapi/address" "^4.0.1" + "@hapi/formula" "^2.0.0" + "@hapi/hoek" "^9.0.0" + "@hapi/pinpoint" "^2.0.0" + "@hapi/topo" "^5.0.0" + "@hapi/pinpoint@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@hapi/pinpoint/-/pinpoint-2.0.0.tgz#805b40d4dbec04fc116a73089494e00f073de8df" @@ -2554,14 +2567,14 @@ loglevel "^1.6.8" "@toruslabs/torus-embed@^1.8.2": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@toruslabs/torus-embed/-/torus-embed-1.8.3.tgz#3c1e5c6ca755628381529402650f00e5c0e4d407" - integrity sha512-wI+mDF3oj6QsHPcLrApVEXmddBcIzrB5JMdxR/V5Jag2Rlk3bRFf7VkxI4mXz0+Qf+He6+fa2VXWCITZMlaDeQ== + version "1.8.2" + resolved "https://registry.yarnpkg.com/@toruslabs/torus-embed/-/torus-embed-1.8.2.tgz#6652b8f751c5f041749ccbfcaa0c08ced5f4f278" + integrity sha512-SlApK4BavoQYNenoQxjUs9/rrqrGDK5+Z9coABA6J7pLcbSL7QnBl8bKwTTYhI9Hri2GRbUM8XzNNpZfy5RiIQ== dependencies: "@chaitanyapotti/random-id" "^1.0.3" "@toruslabs/fetch-node-details" "^2.3.0" "@toruslabs/http-helpers" "^1.3.4" - "@toruslabs/torus.js" "^2.2.5" + "@toruslabs/torus.js" "^2.2.4" create-hash "^1.2.0" deepmerge "^4.2.2" eth-json-rpc-errors "^2.0.2" @@ -2577,7 +2590,7 @@ safe-event-emitter "^1.0.1" web3 "^0.20.7" -"@toruslabs/torus.js@^2.2.5": +"@toruslabs/torus.js@^2.2.4": version "2.2.5" resolved "https://registry.yarnpkg.com/@toruslabs/torus.js/-/torus.js-2.2.5.tgz#8994ae7727d980e2c0600b1154d547260ea52ec4" integrity sha512-fxrIQmtNo4p3uEy5KdiIrZiB32KGPtaV70PoPg/vQB4IL/gjrQSYSIcC0VyP04yBfjHLccJe/HKOhlofpKcjAg== @@ -3746,9 +3759,9 @@ aes-js@3.1.2, aes-js@^3.1.1: integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + version "3.0.1" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" + integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== dependencies: clean-stack "^2.0.0" indent-string "^4.0.0" @@ -6434,7 +6447,7 @@ concat-stream@^1.5.0, concat-stream@^1.5.1, concat-stream@^1.6.2: readable-stream "^2.2.2" typedarray "^0.0.6" -concurrently@^5.3.0: +concurrently@^5.2.0: version "5.3.0" resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-5.3.0.tgz#7500de6410d043c912b2da27de3202cb489b1e7b" integrity sha512-8MhqOB6PWlBfA2vJ8a0bSFKATOdWlHiQlk11IfmQBPaHVP8oP2gsh2MObE6UR3hqDHqvaIvLTyceNW6obVuFHQ== @@ -7703,9 +7716,9 @@ ejs@^2.7.4: integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== ejs@^3.1.3: - version "3.1.5" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.5.tgz#aed723844dc20acb4b170cd9ab1017e476a0d93b" - integrity sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w== + version "3.1.3" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.3.tgz#514d967a8894084d18d3d47bd169a1c0560f093d" + integrity sha512-wmtrUGyfSC23GC/B1SMv2ogAUgbQEtDmTIhfqielrG5ExIM9TP4UoYdi90jLF1aTcsWCJNEO0UrgKzP0y3nTSg== dependencies: jake "^10.6.1" @@ -7981,24 +7994,6 @@ es-abstract@^1.17.0, es-abstract@^1.17.0-next.0, es-abstract@^1.17.0-next.1, es- string.prototype.trimend "^1.0.1" string.prototype.trimstart "^1.0.1" -es-abstract@^1.18.0-next.0: - version "1.18.0-next.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.0.tgz#b302834927e624d8e5837ed48224291f2c66e6fc" - integrity sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ== - dependencies: - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.2.0" - is-negative-zero "^2.0.0" - is-regex "^1.1.1" - object-inspect "^1.8.0" - object-keys "^1.1.1" - object.assign "^4.1.0" - string.prototype.trimend "^1.0.1" - string.prototype.trimstart "^1.0.1" - es-array-method-boxes-properly@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" @@ -8261,7 +8256,7 @@ eslint-plugin-react@7.19.0: string.prototype.matchall "^4.0.2" xregexp "^4.3.0" -eslint-plugin-react@^7.20.6: +eslint-plugin-react@^7.20.5: version "7.20.6" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.6.tgz#4d7845311a93c463493ccfa0a19c9c5d0fd69f60" integrity sha512-kidMTE5HAEBSLu23CUDvj8dc3LdBU0ri1scwHBZjI41oDv4tjsWZKU7MQccFzH1QYPYhsnTF2ovh7JlcIcmxgg== @@ -8951,16 +8946,11 @@ eventemitter3@4.0.0: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb" integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg== -eventemitter3@4.0.4: +eventemitter3@4.0.4, eventemitter3@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== -eventemitter3@^4.0.0: - version "4.0.5" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.5.tgz#51d81e4f1ccc8311a04f0c20121ea824377ea6d9" - integrity sha512-QR0rh0YiPuxuDQ6+T9GAO/xWTExXpxIes1Nl9RykNGTnE1HJmkuEfxJH9cubjIOQZ/GH4qNBR4u8VSHaKiWs4g== - events@^3.0.0, events@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" @@ -9049,7 +9039,7 @@ expect@^24.9.0: jest-message-util "^24.9.0" jest-regex-util "^24.9.0" -exponential-backoff@^3.1.0: +exponential-backoff@^3.0.1: version "3.1.0" resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.0.tgz#9409c7e579131f8bd4b32d7d8094a911040f2e68" integrity sha512-oBuz5SYz5zzyuHINoe9ooePwSu0xApKWgeNzok4hZ5YKXFh9zrQBEM15CXqoZkJJPuI2ArvqjPQd8UKJA753XA== @@ -10574,10 +10564,10 @@ immer@1.10.0: resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d" integrity sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg== -immortal-db@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/immortal-db/-/immortal-db-1.1.0.tgz#b0bbff61262bcbc964952954aeb169462e4b6c5c" - integrity sha512-RwtZT+FEdXrLQeHHKvQQx6SKlQelrcH7x1SLh5lQVcOZFtUNYPjc/ZaU52SsFI/T5rey+VdM87pxVOGKhuZLVw== +immortal-db@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/immortal-db/-/immortal-db-1.0.3.tgz#cd88a1e8ba53646ccc8d7363fd1ee4717ad049c3" + integrity sha512-KWmEx/5KZumg++Yrj/+LH0vERDf1mXR5UFKKhLla0pwd7r/FttKz80ccO1sHyd5+eoSK2wb/N2WCFxWz9O6JKw== dependencies: idb-keyval "^3.2.0" js-cookie "^2.2.1" @@ -11074,11 +11064,6 @@ is-natural-number@^4.0.1: resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= -is-negative-zero@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" - integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= - is-npm@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d" @@ -11152,7 +11137,7 @@ is-plain-object@^3.0.0: resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.1.tgz#662d92d24c0aa4302407b0d45d21f2251c85f85b" integrity sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g== -is-regex@^1.0.4, is-regex@^1.1.0, is-regex@^1.1.1: +is-regex@^1.0.4, is-regex@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== @@ -11790,17 +11775,6 @@ jest@24.9.0: import-local "^2.0.0" jest-cli "^24.9.0" -joi@^17.1.1: - version "17.2.1" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.2.1.tgz#e5140fdf07e8fecf9bc977c2832d1bdb1e3f2a0a" - integrity sha512-YT3/4Ln+5YRpacdmfEfrrKh50/kkgX3LgBltjqnlMPIYiZ4hxXZuVJcxmsvxsdeHg9soZfE3qXxHC2tMpCCBOA== - dependencies: - "@hapi/address" "^4.1.0" - "@hapi/formula" "^2.0.0" - "@hapi/hoek" "^9.0.0" - "@hapi/pinpoint" "^2.0.0" - "@hapi/topo" "^5.0.0" - js-base64@^2.1.8: version "2.6.4" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4" @@ -12808,7 +12782,7 @@ matcher@^3.0.0: dependencies: escape-string-regexp "^4.0.0" -material-ui-search-bar@^1.0.0: +material-ui-search-bar@^1.0.0-beta.13: version "1.0.0" resolved "https://registry.yarnpkg.com/material-ui-search-bar/-/material-ui-search-bar-1.0.0.tgz#2652dd5bdc4cb043cffb7144d9c296c120702e62" integrity sha512-lCNuzMLPBVukVAkcnYKLXHneozsuKZREZNOcc8z9S9scXHqxJzhC9hOS3OC3/YJ+NJEB5lZB9zg1gryBaXEu8w== @@ -13247,9 +13221,9 @@ mocha@8.0.1: yargs-unparser "1.6.0" mock-fs@^4.1.0: - version "4.13.0" - resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.13.0.tgz#31c02263673ec3789f90eb7b6963676aa407a598" - integrity sha512-DD0vOdofJdoaRNtnWcrXe6RQbpHkPPmtqGq14uRX0F8ZKJ5nv89CVTYl/BZdppDxBDaV0hl75htg3abpEWlPZA== + version "4.12.0" + resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.12.0.tgz#a5d50b12d2d75e5bec9dac3b67ffe3c41d31ade4" + integrity sha512-/P/HtrlvBxY4o/PzXY9cCNBrdylDNxg7gnrv2sMNxj+UJ2m8jSpl0/A6fuJeNAWr99ZvGWH8XCbE0vmnM5KupQ== moment@2.24.0: version "2.24.0" @@ -13422,9 +13396,9 @@ no-case@^3.0.3: tslib "^1.10.0" node-abi@^2.18.0, node-abi@^2.7.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.19.0.tgz#11614ff22dd64dad3501074bf656e6923539e17a" - integrity sha512-rpKqVe24p9GvMTgtqUXdLR1WQJBGVlkYPU10qHKv9/1i9V/k04MmFLVK2WcHBf1WKKY+ZsdvARPi8F4tfJ4opA== + version "2.18.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.18.0.tgz#1f5486cfd7d38bd4f5392fa44a4ad4d9a0dffbf4" + integrity sha512-yi05ZoiuNNEbyT/xXfSySZE+yVnQW6fxPZuFbLyS1s6b5Kw3HzV2PHOM4XR+nsjzkHxByK+2Wg+yCQbe35l8dw== dependencies: semver "^5.4.1" @@ -13744,7 +13718,7 @@ object-hash@^2.0.1: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.0.3.tgz#d12db044e03cd2ca3d77c0570d87225b02e1e6ea" integrity sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg== -object-inspect@^1.7.0, object-inspect@^1.8.0: +object-inspect@^1.7.0: version "1.8.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== @@ -13905,7 +13879,7 @@ open@^6.3.0: dependencies: is-wsl "^1.1.0" -open@^7.0.0, open@^7.0.2: +open@^7.0.0, open@^7.0.2, open@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/open/-/open-7.1.0.tgz#68865f7d3cb238520fa1225a63cf28bcf8368a1c" integrity sha512-lLPI5KgOwEYCDKXf4np7y1PBEkj7HYIyP2DY8mVDRnx0VIIu6bNrRB0R66TuO7Mack6EnTNLm4uvcl1UoklTpA== @@ -13913,14 +13887,6 @@ open@^7.0.0, open@^7.0.2: is-docker "^2.0.0" is-wsl "^2.1.1" -open@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/open/-/open-7.2.0.tgz#212959bd7b0ce2e8e3676adc76e3cf2f0a2498b4" - integrity sha512-4HeyhxCvBTI5uBePsAdi55C5fmqnWZ2e2MlmvWi5KW5tdH5rxoiv/aMtbeVxKZc3eWkT1GymMnLG8XC4Rq4TDQ== - dependencies: - is-docker "^2.0.0" - is-wsl "^2.1.1" - opencollective-postinstall@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" @@ -15580,9 +15546,9 @@ querystring@0.2.0, querystring@^0.2.0: integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= querystringify@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" - integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + version "2.1.1" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" + integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== quick-lru@^1.0.0: version "1.1.0" @@ -15976,7 +15942,7 @@ react-router@5.2.0: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-scripts@^3.4.3: +react-scripts@^3.4.1: version "3.4.3" resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-3.4.3.tgz#21de5eb93de41ee92cd0b85b0e1298d0bb2e6c51" integrity sha512-oSnoWmii/iKdeQiwaO6map1lUaZLmG0xIUyb/HwCVFLT7gNbj8JZ9RmpvMCZ4fB98ZUMRfNmp/ft8uy/xD1RLA== @@ -17266,12 +17232,12 @@ shellwords@^0.1.1: integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== side-channel@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.3.tgz#cdc46b057550bbab63706210838df5d4c19519c3" - integrity sha512-A6+ByhlLkksFoUepsGxfj5x1gTSrs+OydsRptUxeNCabQpCFUvcwIczgOigI8vhY/OJCnPnyE9rGiwgvr9cS1g== + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.2.tgz#df5d1abadb4e4bf4af1cd8852bf132d2f7876947" + integrity sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA== dependencies: - es-abstract "^1.18.0-next.0" - object-inspect "^1.8.0" + es-abstract "^1.17.0-next.1" + object-inspect "^1.7.0" signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.3" @@ -18587,10 +18553,10 @@ truffle-interface-adapter@^0.2.5: lodash "^4.17.13" web3 "1.2.1" -truffle@5.1.41: - version "5.1.41" - resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.1.41.tgz#662a0f2816c4e5a12bae25c0b68d908478ff4606" - integrity sha512-6vphA82Os7HvrzqkMy0o2kxP0SYsf7glHE8U8jk15lbUNOy76SrBLmTi7at7xFkIq6LMgv03YRf0EFEN/qwAxg== +truffle@5.1.36: + version "5.1.36" + resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.1.36.tgz#d49c9e0c20558bdee76f442663f81367f62c5559" + integrity sha512-BXfDrRJmxECsHFu1ZHeQNDdv3OA3vmwQ6Wp5m9yaE0swKcHS+gd8sBdxQBoliiAI0xvUAsD62PRGowqFfT1CLg== dependencies: app-module-path "^2.2.0" mocha "8.0.1" @@ -18747,9 +18713,9 @@ type@^1.0.1: integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== type@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.1.0.tgz#9bdc22c648cf8cf86dd23d32336a41cfb6475e3f" - integrity sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA== + version "2.0.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3" + integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow== typechain@^2.0.0: version "2.0.0" @@ -19189,13 +19155,13 @@ w3c-xmlserializer@^1.1.2: webidl-conversions "^4.0.2" xml-name-validator "^3.0.0" -wait-on@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-5.2.0.tgz#6711e74422523279714a36d52cf49fb47c9d9597" - integrity sha512-U1D9PBgGw2XFc6iZqn45VBubw02VsLwnZWteQ1au4hUVHasTZuFSKRzlTB2dqgLhji16YVI8fgpEpwUdCr8B6g== +wait-on@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-5.1.0.tgz#b697f21c6fea0908b9c7ad6ed56ace4736768b66" + integrity sha512-JM0kgaE+V0nCDvSl72iM05W8NDt2E2M56WC5mzR7M+T+k6xjt2yYpyom+xA8RasSunFGzbxIpAXbVzXqtweAnA== dependencies: + "@hapi/joi" "^17.1.1" axios "^0.19.2" - joi "^17.1.1" lodash "^4.17.19" minimist "^1.2.5" rxjs "^6.5.5"