diff --git a/.eslintrc.js b/.eslintrc.js index be4cf89c8e..a75ca6fdc7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -11,7 +11,6 @@ module.exports = { }, rules: { ...base.rules, - '@typescript-eslint/no-explicit-any': 'off', - 'react-hooks/exhaustive-deps': 'warn' + '@typescript-eslint/no-explicit-any': 'off' } }; diff --git a/packages/page-accounts/src/Accounts/modals/Identity.tsx b/packages/page-accounts/src/Accounts/modals/Identity.tsx index 5eda7c2ecb..8af0499ff5 100644 --- a/packages/page-accounts/src/Accounts/modals/Identity.tsx +++ b/packages/page-accounts/src/Accounts/modals/Identity.tsx @@ -75,7 +75,7 @@ function Identity ({ address, className, onClose }: Props): React.ReactElement

{ - if (identityOpt?.isSome) { + if (identityOpt && identityOpt.isSome) { const { info } = identityOpt.unwrap(); setData(info.display, null, setValDisplay); diff --git a/packages/page-contracts/src/Contracts/ValidateAddr.tsx b/packages/page-contracts/src/Contracts/ValidateAddr.tsx index 89e713f4cf..aeb5f32e90 100644 --- a/packages/page-contracts/src/Contracts/ValidateAddr.tsx +++ b/packages/page-contracts/src/Contracts/ValidateAddr.tsx @@ -35,7 +35,7 @@ function ValidateAddr ({ address, onChange }: Props): React.ReactElement useEffect((): void => { setIsStored(!!contractInfo?.isSome); - }, [contractInfo]); + }, [contractInfo?.isSome]); useEffect((): void => { onChange(isAddress && isStored); diff --git a/packages/page-council/src/Motions/Slashing.tsx b/packages/page-council/src/Motions/Slashing.tsx index a094b8418f..95a5ac49b7 100644 --- a/packages/page-council/src/Motions/Slashing.tsx +++ b/packages/page-council/src/Motions/Slashing.tsx @@ -48,7 +48,7 @@ function Slashing ({ className, isMember, members }: Props): React.ReactElement< }, [slashes, t]); useEffect((): void => { - const actioned = selectedEra && slashes?.find(([era]): boolean => era.eqn(selectedEra)); + const actioned = selectedEra && slashes && slashes.find(([era]): boolean => era.eqn(selectedEra)); setProposal((): any => actioned diff --git a/packages/page-council/src/Motions/useAvailableSlashes.ts b/packages/page-council/src/Motions/useAvailableSlashes.ts index d137617b45..5afc2738a4 100644 --- a/packages/page-council/src/Motions/useAvailableSlashes.ts +++ b/packages/page-council/src/Motions/useAvailableSlashes.ts @@ -22,7 +22,7 @@ export default function useAvailableSlashes (): [BN, UnappliedSlash[]][] { useEffect((): Unsub => { let unsub: Unsub | undefined; - if (mountedRef.current && indexes && earliestSlash?.isSome) { + if (mountedRef.current && indexes && earliestSlash && earliestSlash.isSome) { const from = earliestSlash.unwrap(); const range: BN[] = []; let start = new BN(from); diff --git a/packages/page-democracy/src/Overview/Fasttrack.tsx b/packages/page-democracy/src/Overview/Fasttrack.tsx index b5bd4c401e..b585467615 100644 --- a/packages/page-democracy/src/Overview/Fasttrack.tsx +++ b/packages/page-democracy/src/Overview/Fasttrack.tsx @@ -42,7 +42,7 @@ function Fasttrack ({ imageHash, threshold }: Props): React.ReactElement useEffect((): void => { setProposal( - () => delayBlocks?.gtn(0) && votingBlocks?.gtn(0) + () => delayBlocks && delayBlocks.gtn(0) && votingBlocks && votingBlocks.gtn(0) ? api.tx.democracy.fastTrack(imageHash, votingBlocks, delayBlocks) : null ); diff --git a/packages/page-democracy/src/useCounter.ts b/packages/page-democracy/src/useCounter.ts index 2913045141..9ea951c8d0 100644 --- a/packages/page-democracy/src/useCounter.ts +++ b/packages/page-democracy/src/useCounter.ts @@ -18,7 +18,7 @@ export default function useCounter (): number { (proposals?.length || 0) + (referenda?.length || 0) ); - }, [mountedRef, proposals, referenda]); + }, [mountedRef, proposals?.length, referenda?.length]); return counter; } diff --git a/packages/page-explorer/src/SummarySession.tsx b/packages/page-explorer/src/SummarySession.tsx index ea90d4806c..cad8c0f3b4 100644 --- a/packages/page-explorer/src/SummarySession.tsx +++ b/packages/page-explorer/src/SummarySession.tsx @@ -27,7 +27,7 @@ function SummarySession ({ withEra = true, withSession = true }: Props): React.R sessionInfo?.isEpoch ? t('epoch') : t('session') - , [sessionInfo, t]); + , [sessionInfo?.isEpoch, t]); return ( <> diff --git a/packages/page-parachains/src/index.tsx b/packages/page-parachains/src/index.tsx index 9d67e3f353..c86540cbc6 100644 --- a/packages/page-parachains/src/index.tsx +++ b/packages/page-parachains/src/index.tsx @@ -32,7 +32,7 @@ function ParachainsApp ({ basePath }: Props): React.ReactElement { text: t('Parachains overview') }, ...( - match?.params.id + match && match.params.id ? [{ name: match.params.id, text: `${match.params.id}: ${parachainName(t, paraInfoRef.current)}` diff --git a/packages/page-society/src/Overview/Summary.tsx b/packages/page-society/src/Overview/Summary.tsx index 338c783abd..734966445d 100644 --- a/packages/page-society/src/Overview/Summary.tsx +++ b/packages/page-society/src/Overview/Summary.tsx @@ -25,7 +25,7 @@ function Summary ({ className, info }: Props): React.ReactElement { const bestNumber = useCall(api.derive.chain.bestNumber, []); const pot = useMemo((): string | null => { - return info?.pot.gtn(0) + return info && info.pot.gtn(0) ? info.pot.toString() : null; }, [info]); diff --git a/packages/page-staking/src/Actions/useInactives.ts b/packages/page-staking/src/Actions/useInactives.ts index b8c2cfcb71..98f22c8e37 100644 --- a/packages/page-staking/src/Actions/useInactives.ts +++ b/packages/page-staking/src/Actions/useInactives.ts @@ -56,7 +56,7 @@ export default function useInactives (stashId: string, nominees?: string[]): Ina useEffect((): () => void => { let unsub: (() => void) | undefined; - if (mountedRef.current && nominees?.length && indexes) { + if (mountedRef.current && nominees && nominees.length && indexes) { api .queryMulti( [[api.query.staking.nominators, stashId] as any].concat( diff --git a/packages/page-staking/src/Actions/useUnbondDuration.ts b/packages/page-staking/src/Actions/useUnbondDuration.ts index 6ba53160e1..5e9f9a8a40 100644 --- a/packages/page-staking/src/Actions/useUnbondDuration.ts +++ b/packages/page-staking/src/Actions/useUnbondDuration.ts @@ -18,7 +18,7 @@ export default function useUnbondDuration (): BN | undefined { useEffect((): void => { // We check sessionLength, for aura this is not properly calculated (not exposed), // so the actual real block value would be invalid here - sessionInfo?.sessionLength.gt(ONE) && setDuration( + sessionInfo && sessionInfo.sessionLength.gt(ONE) && setDuration( sessionInfo.eraLength.mul(api.consts.staking.bondingDuration) ); }, [api, sessionInfo]); diff --git a/packages/page-staking/src/Payouts/useEraBlocks.ts b/packages/page-staking/src/Payouts/useEraBlocks.ts index 2aaf4ffcba..1bb442e048 100644 --- a/packages/page-staking/src/Payouts/useEraBlocks.ts +++ b/packages/page-staking/src/Payouts/useEraBlocks.ts @@ -17,7 +17,7 @@ export default function useEraBlocks (era?: BN): BN | undefined { const [duration, setDuration] = useState(); useEffect((): void => { - depth && era && progress?.sessionLength.gt(ONE) && setDuration( + depth && era && progress && progress.sessionLength.gt(ONE) && setDuration( progress.eraLength .mul( depth diff --git a/packages/page-staking/src/Payouts/useStakerPayouts.ts b/packages/page-staking/src/Payouts/useStakerPayouts.ts index c568a7b848..47424adbaa 100644 --- a/packages/page-staking/src/Payouts/useStakerPayouts.ts +++ b/packages/page-staking/src/Payouts/useStakerPayouts.ts @@ -20,7 +20,7 @@ export default function useStakerPayouts (): BN { const migrateEraOpt = useCall>(api.query.staking?.migrateEra, []); useEffect((): void => { - migrateEraOpt?.isSome && setState(migrateEraOpt.unwrap()); + migrateEraOpt && migrateEraOpt.isSome && setState(migrateEraOpt.unwrap()); }, [migrateEraOpt]); return stakerPayoutAfter; diff --git a/packages/page-staking/src/Query/useBlockCounts.tsx b/packages/page-staking/src/Query/useBlockCounts.tsx index e4001385c1..b2436bc05a 100644 --- a/packages/page-staking/src/Query/useBlockCounts.tsx +++ b/packages/page-staking/src/Query/useBlockCounts.tsx @@ -8,6 +8,7 @@ import { SessionRewards } from '../types'; import { useEffect, useState } from 'react'; import { useApi, useCall, useIsMountedRef } from '@polkadot/react-hooks'; import { u32 } from '@polkadot/types'; +import { isFunction } from '@polkadot/util'; export default function useBlockCounts (accountId: string, sessionRewards: SessionRewards[]): u32[] { const { api } = useApi(); @@ -18,7 +19,7 @@ export default function useBlockCounts (accountId: string, sessionRewards: Sessi const [historic, setHistoric] = useState([]); useEffect((): void => { - if (api.query.imOnline?.authoredBlocks && sessionRewards?.length) { + if (isFunction(api.query.imOnline?.authoredBlocks) && sessionRewards && sessionRewards.length) { const filtered = sessionRewards.filter(({ sessionIndex }): boolean => sessionIndex.gtn(0)); if (filtered.length) { diff --git a/packages/page-staking/src/Targets/Nominate.tsx b/packages/page-staking/src/Targets/Nominate.tsx index 120a199ed5..8cb88375ba 100644 --- a/packages/page-staking/src/Targets/Nominate.tsx +++ b/packages/page-staking/src/Targets/Nominate.tsx @@ -31,7 +31,7 @@ function Nominate ({ className, ownNominators, targets }: Props): React.ReactEle const _onChangeStash = useCallback( (accountId?: string | null): void => { - const acc = ownNominators?.find(({ stashId }) => stashId === accountId); + const acc = ownNominators && ownNominators.find(({ stashId }) => stashId === accountId); setIds( acc diff --git a/packages/page-staking/src/Targets/Summary.tsx b/packages/page-staking/src/Targets/Summary.tsx index 61a6527f0f..6fe622bb55 100644 --- a/packages/page-staking/src/Targets/Summary.tsx +++ b/packages/page-staking/src/Targets/Summary.tsx @@ -26,7 +26,7 @@ function Summary ({ lastReward, numNominators, numValidators, totalStaked }: Pro const [percentage, setPercentage] = useState(); useEffect((): void => { - totalIssuance && totalStaked?.gtn(0) && setPercentage( + totalIssuance && totalStaked && totalStaked.gtn(0) && setPercentage( `${(totalStaked.muln(10000).div(totalIssuance).toNumber() / 100).toFixed(2)}%` ); }, [totalIssuance, totalStaked]); diff --git a/packages/page-toolbox/src/Sign.tsx b/packages/page-toolbox/src/Sign.tsx index 255e5972c7..a9fe252df8 100644 --- a/packages/page-toolbox/src/Sign.tsx +++ b/packages/page-toolbox/src/Sign.tsx @@ -41,9 +41,10 @@ function Sign ({ className }: Props): React.ReactElement { const [isUnlockVisible, toggleUnlock] = useToggle(); useEffect((): void => { - const isExternal = currentPair?.meta.isExternal || false; - const isHardware = currentPair?.meta.isHardware || false; - const isInjected = currentPair?.meta.isInjected || false; + const meta = (currentPair && currentPair.meta) || {}; + const isExternal = meta.isExternal || false; + const isHardware = meta.isHardware || false; + const isInjected = meta.isInjected || false; const isUsable = !(isExternal || isHardware || isInjected); setAccountState({ @@ -54,18 +55,16 @@ function Sign ({ className }: Props): React.ReactElement { setIsLocked( isInjected ? false - : currentPair?.isLocked || false + : (currentPair && currentPair.isLocked) || false ); setSignature(''); setSigner({ isUsable, signer: null }); // for injected, retrieve the signer - if (currentPair && isInjected) { - const { meta: { source } } = currentPair; - - web3FromSource(source) + if (meta.source && isInjected) { + web3FromSource(meta.source) .catch((): null => null) - .then((injected): void => setSigner({ + .then((injected) => setSigner({ isUsable: isFunction(injected?.signer?.signRaw), signer: injected?.signer || null })); @@ -88,7 +87,7 @@ function Sign ({ className }: Props): React.ReactElement { return; } - if (signer?.signRaw) { + if (signer && isFunction(signer.signRaw)) { setSignature(''); signer @@ -99,7 +98,7 @@ function Sign ({ className }: Props): React.ReactElement { : stringToHex(data), type: 'bytes' }) - .then(({ signature }): void => setSignature(signature)); + .then(({ signature }) => setSignature(signature)); } else { setSignature(u8aToHex( currentPair.sign( diff --git a/packages/page-toolbox/src/Unlock.tsx b/packages/page-toolbox/src/Unlock.tsx index 2de5ba2274..cca3f67fbd 100644 --- a/packages/page-toolbox/src/Unlock.tsx +++ b/packages/page-toolbox/src/Unlock.tsx @@ -23,7 +23,7 @@ function Unlock ({ onClose, onUnlock, pair }: Props): React.ReactElement useEffect((): void => { setAddress(pair?.address || ''); - }, [pair]); + }, [pair?.address]); useEffect((): void => { setUnlockError(null); diff --git a/packages/page-treasury/src/useCounter.ts b/packages/page-treasury/src/useCounter.ts index fc689e2bfd..0e553e03f9 100644 --- a/packages/page-treasury/src/useCounter.ts +++ b/packages/page-treasury/src/useCounter.ts @@ -15,7 +15,7 @@ export default function useCounter (): number { useEffect((): void => { setCounter(proposals?.proposals.length || 0); - }, [proposals]); + }, [proposals?.proposals.length]); return counter; } diff --git a/packages/react-components/src/VoteValue.tsx b/packages/react-components/src/VoteValue.tsx index aa84fa1d0d..0691a355b5 100644 --- a/packages/react-components/src/VoteValue.tsx +++ b/packages/react-components/src/VoteValue.tsx @@ -32,7 +32,7 @@ function VoteValue ({ accountId, autoFocus, onChange }: Props): React.ReactEleme useEffect((): void => { // if the set accountId changes and the new balances is for that id, set it - (accountId !== selectedId) && allBalances?.accountId.eq(accountId) && setValue({ + (accountId !== selectedId) && allBalances && allBalances.accountId.eq(accountId) && setValue({ selectedId: accountId, value: allBalances.lockedBalance }); diff --git a/packages/react-hooks/src/useAccountInfo.ts b/packages/react-hooks/src/useAccountInfo.ts index 34159c92ca..f229703a86 100644 --- a/packages/react-hooks/src/useAccountInfo.ts +++ b/packages/react-hooks/src/useAccountInfo.ts @@ -111,7 +111,7 @@ export default function useAccountInfo (value: string): UseAccountInfo { setMeta(accountOrAddress?.meta); setName(accountOrAddress?.meta.name || ''); setSortedTags(accountOrAddress?.meta.tags ? accountOrAddress.meta.tags.sort() : []); - }, [identity, isAccount, isAddress, value]); + }, [identity?.display, isAccount, isAddress, value]); const onSaveName = useCallback( (): void => { diff --git a/packages/react-params/src/Param/DispatchError.tsx b/packages/react-params/src/Param/DispatchError.tsx index 4d53871e8b..6aa8f47923 100644 --- a/packages/react-params/src/Param/DispatchError.tsx +++ b/packages/react-params/src/Param/DispatchError.tsx @@ -18,27 +18,35 @@ interface Details { type?: string; } +interface RawModuleError { + value: DispatchError; +} + +function isModuleError (defaultValue?: { value: any }): defaultValue is RawModuleError { + return !!defaultValue?.value?.isModule; +} + function ErrorDisplay (props: Props): React.ReactElement { const { t } = useTranslation(); const [{ details, type }, setDetails] = useState

({}); useEffect((): void => { - if (details !== null && props.defaultValue?.value?.isModule) { + if (isModuleError(props.defaultValue)) { try { - const { documentation, name, section } = registry.findMetaError((props.defaultValue.value as DispatchError).asModule); + const { documentation, name, section } = registry.findMetaError(props.defaultValue.value.asModule); - setDetails({ + return setDetails({ details: documentation.join(', '), type: `${section}.${name}` }); } catch (error) { // Errors may not actually be exposed, in this case, just return the default representation console.error(error); - - setDetails({ details: null }); } } - }, [details, props.defaultValue]); + + setDetails({ details: null }); + }, [props.defaultValue]); if (!props.isDisabled || !details) { return ; diff --git a/packages/react-query/src/BlockToTime.tsx b/packages/react-query/src/BlockToTime.tsx index 9eaa9438dc..73de8af11c 100644 --- a/packages/react-query/src/BlockToTime.tsx +++ b/packages/react-query/src/BlockToTime.tsx @@ -63,7 +63,7 @@ function BlockToTime ({ blocks, children, className, label, style }: Props): Rea api.consts.timestamp?.minimumPeriod.muln(2) || DEFAULT_TIME ).divn(1000); - const time = extractTime(blocks?.mul(blockTime).toNumber()); + const time = extractTime(blocks && blocks.mul(blockTime).toNumber()); return [ time[0] ? (time[0] > 1) ? t('{{d}} days', { replace: { d: time[0] } }) : t('1 day') : null, diff --git a/packages/react-signer/src/Checks/index.tsx b/packages/react-signer/src/Checks/index.tsx index d1f3b8d8dd..6b0401b3a5 100644 --- a/packages/react-signer/src/Checks/index.tsx +++ b/packages/react-signer/src/Checks/index.tsx @@ -10,7 +10,7 @@ import React, { useState, useEffect } from 'react'; import { Trans } from 'react-i18next'; import { Expander } from '@polkadot/react-components'; import { useApi } from '@polkadot/react-hooks'; -import { formatBalance } from '@polkadot/util'; +import { formatBalance, isFunction } from '@polkadot/util'; interface Props { accountId?: string | null; @@ -26,7 +26,7 @@ function Checks ({ accountId, className, extrinsic }: Props): React.ReactElement const [dispatchInfo, setDispatchInfo] = useState(null); useEffect((): void => { - accountId && extrinsic?.paymentInfo && api.rpc.payment?.queryInfo && + accountId && extrinsic && isFunction(api.rpc.payment?.queryInfo) && extrinsic .paymentInfo(accountId) .then(setDispatchInfo);