From 6c55d60fd822049b21bb4cb6794e19ea8c91a17d Mon Sep 17 00:00:00 2001 From: William Swanson Date: Mon, 1 Sep 2025 17:25:06 -0700 Subject: [PATCH 1/5] Fix all `prefer-optional-chain` warnings --- eslint.config.mjs | 1 - src/actions/NotificationActions.ts | 2 +- src/components/common/DotsBackground.tsx | 2 +- src/components/modals/CountryListModal.tsx | 2 +- src/components/scenes/Loans/LoanCloseScene.tsx | 6 ++---- src/components/scenes/Staking/StakeOverviewScene.tsx | 2 +- src/components/themed/WalletListCurrencyRow.tsx | 4 ++-- src/controllers/action-queue/push.ts | 5 +---- src/hooks/useAccountSyncRatio.tsx | 3 +-- src/util/DeepLinkParser.ts | 2 +- 10 files changed, 11 insertions(+), 18 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 74ded809cd3..5ced7846b9d 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -574,7 +574,6 @@ export default [ '@typescript-eslint/no-dynamic-delete': 'warn', '@typescript-eslint/no-misused-promises': 'warn', '@typescript-eslint/prefer-nullish-coalescing': 'warn', - '@typescript-eslint/prefer-optional-chain': 'warn', '@typescript-eslint/require-array-sort-compare': 'warn', '@typescript-eslint/restrict-plus-operands': 'warn', '@typescript-eslint/restrict-template-expressions': 'warn', diff --git a/src/actions/NotificationActions.ts b/src/actions/NotificationActions.ts index 89ced97a11b..62f9eae205a 100644 --- a/src/actions/NotificationActions.ts +++ b/src/actions/NotificationActions.ts @@ -362,7 +362,7 @@ async function legacyGet(path: string) { 'X-Api-Key': ENV.EDGE_API_KEY } }) - if (response != null && response.ok) { + if (response.ok) { return await response.json() } else { throw new Error('Error accessing notification server') diff --git a/src/components/common/DotsBackground.tsx b/src/components/common/DotsBackground.tsx index 7bdb9f2ac96..265aba660df 100644 --- a/src/components/common/DotsBackground.tsx +++ b/src/components/common/DotsBackground.tsx @@ -51,7 +51,7 @@ export function DotsBackground(props: Props): React.ReactElement { cy: overrideDot.cy ?? dot.cy } if (mergedDot.accentColor != null) { - const ac = (accentColors ?? {})[mergedDot.accentColor] + const ac = accentColors?.[mergedDot.accentColor] if (ac == null) { throw new Error('Missing accentColors') } diff --git a/src/components/modals/CountryListModal.tsx b/src/components/modals/CountryListModal.tsx index d1a0ec2ee49..ffcd3bde14a 100644 --- a/src/components/modals/CountryListModal.tsx +++ b/src/components/modals/CountryListModal.tsx @@ -48,7 +48,7 @@ export const CountryListModal = ({ const upperCaseText = searchText.toUpperCase() return ( country.name.toLowerCase().includes(lowerCaseText) || - (country.filename != null && country.filename.includes(lowerCaseText)) || + country.filename?.includes(lowerCaseText) === true || country['alpha-2'].includes(upperCaseText) || country['alpha-3'].includes(upperCaseText) ) diff --git a/src/components/scenes/Loans/LoanCloseScene.tsx b/src/components/scenes/Loans/LoanCloseScene.tsx index a8d8d62704d..69c835b900c 100644 --- a/src/components/scenes/Loans/LoanCloseScene.tsx +++ b/src/components/scenes/Loans/LoanCloseScene.tsx @@ -133,11 +133,9 @@ export const LoanCloseSceneComponent = (props: Props) => { actionProgram === undefined || networkFeeMap === undefined // TODO: Pass networkFeeMap to a component which can display fee total for NetworkFeeMap interfaces - const networkFeeAggregate = (networkFeeMap ?? {})[ - borrowEngineWallet.currencyInfo.currencyCode - ] const networkFeeAmountAggregate = - networkFeeAggregate != null ? networkFeeAggregate.nativeAmount : '0' + networkFeeMap?.[borrowEngineWallet.currencyInfo.currencyCode] + ?.nativeAmount ?? '0' // // Handlers diff --git a/src/components/scenes/Staking/StakeOverviewScene.tsx b/src/components/scenes/Staking/StakeOverviewScene.tsx index 2bf4d9744ff..e4efc9570ab 100644 --- a/src/components/scenes/Staking/StakeOverviewScene.tsx +++ b/src/components/scenes/Staking/StakeOverviewScene.tsx @@ -261,7 +261,7 @@ const StakeOverviewSceneComponent = (props: Props) => { diff --git a/src/components/themed/WalletListCurrencyRow.tsx b/src/components/themed/WalletListCurrencyRow.tsx index 27928dc7941..7ae3d4ef53f 100644 --- a/src/components/themed/WalletListCurrencyRow.tsx +++ b/src/components/themed/WalletListCurrencyRow.tsx @@ -42,10 +42,10 @@ const WalletListCurrencyRowComponent = (props: Props) => { } = props const theme = useTheme() const styles = getStyles(theme) - const pausedWallets = useSelector( + const userPausedWalletsSet = useSelector( state => state.ui.settings.userPausedWalletsSet ) - const isPaused = pausedWallets != null && pausedWallets.has(wallet.id) + const isPaused = userPausedWalletsSet?.has(wallet.id) ?? false const isDisabled = isKeysOnlyPlugin(wallet.currencyInfo.pluginId) const { pluginId } = wallet.currencyInfo diff --git a/src/controllers/action-queue/push.ts b/src/controllers/action-queue/push.ts index 98ae98d8fd1..cfe6512f05c 100644 --- a/src/controllers/action-queue/push.ts +++ b/src/controllers/action-queue/push.ts @@ -127,10 +127,7 @@ export async function checkPushEvent( const status: PushEventStatus = eventStatusMap[eventId] const pushEventState: PushEventState = status.state - if ( - status.broadcastTxErrors != null && - status.broadcastTxErrors.some(error => error != null) - ) { + if (status.broadcastTxErrors?.some(error => error != null) === true) { throw new Error( `Broadcast failed for ${eventId} event:\n\t${status.broadcastTxErrors.join( '\n\t' diff --git a/src/hooks/useAccountSyncRatio.tsx b/src/hooks/useAccountSyncRatio.tsx index fd465a6c1de..53e9f1c2ebf 100644 --- a/src/hooks/useAccountSyncRatio.tsx +++ b/src/hooks/useAccountSyncRatio.tsx @@ -23,8 +23,7 @@ export const useAccountSyncRatio = () => { account.activeWalletIds.filter(walletId => { const pluginId = findPluginId(account, walletId) const isKeysOnly = pluginId == null || isKeysOnlyPlugin(pluginId) - const isPaused = - userPausedWalletsSet != null && userPausedWalletsSet.has(walletId) + const isPaused = userPausedWalletsSet?.has(walletId) ?? false return !isKeysOnly && !isPaused }), [account, userPausedWalletsSet] diff --git a/src/util/DeepLinkParser.ts b/src/util/DeepLinkParser.ts index ca79d28cf8b..46305ace95d 100644 --- a/src/util/DeepLinkParser.ts +++ b/src/util/DeepLinkParser.ts @@ -63,7 +63,7 @@ export function parseDeepLink( // besides the specific currency defined in the uri's scheme. // Even if a specific currency is found in the protocol, the payment protocol // does not care what currency the payment steps start with. - if (betterUrl.query.r != null && betterUrl.query.r.includes('http')) { + if (betterUrl.query.r?.includes('http') === true) { // If the URI started with 'bitcoin:', etc. uri = betterUrl.query.r return { type: 'paymentProto', uri } From 84fb58c324a5d111fb0d7c97496ee5f0f635f921 Mon Sep 17 00:00:00 2001 From: William Swanson Date: Mon, 1 Sep 2025 15:40:28 -0700 Subject: [PATCH 2/5] Fix FillLoader warnings --- eslint.config.mjs | 1 - .../progress-indicators/FillLoader.tsx | 37 +++++++------------ 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 5ced7846b9d..a6fb531ba46 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -213,7 +213,6 @@ export default [ 'src/components/progress-indicators/AccountSyncBar.tsx', 'src/components/progress-indicators/CancellableProcessingScene.tsx', 'src/components/progress-indicators/CircleTimer.tsx', - 'src/components/progress-indicators/FillLoader.tsx', 'src/components/progress-indicators/FullScreenLoader.tsx', 'src/components/progress-indicators/LoadingSplashScreen.tsx', 'src/components/progress-indicators/Shimmer.tsx', diff --git a/src/components/progress-indicators/FillLoader.tsx b/src/components/progress-indicators/FillLoader.tsx index 7b2426b0562..5c505afc973 100644 --- a/src/components/progress-indicators/FillLoader.tsx +++ b/src/components/progress-indicators/FillLoader.tsx @@ -1,31 +1,20 @@ import * as React from 'react' -import { - ActivityIndicator, - StyleSheet, - View, - type ViewStyle -} from 'react-native' +import { ActivityIndicator, StyleSheet, View } from 'react-native' -import { THEME } from '../../theme/variables/airbitz' +import { useTheme } from '../services/ThemeContext' -interface Props { - indicatorStyles?: ViewStyle - size?: 'large' | 'small' -} +export const FillLoader: React.FC = props => { + const theme = useTheme() -export class FillLoader extends React.Component { - render() { - const { size, indicatorStyles } = this.props - return ( - - - - ) - } + return ( + + + + ) } const styles = StyleSheet.create({ From 80a196f4f5ebdafee5db3f9d0def7788b6aa4364 Mon Sep 17 00:00:00 2001 From: William Swanson Date: Mon, 1 Sep 2025 15:33:12 -0700 Subject: [PATCH 3/5] Fix WalletSyncCircle warnings --- eslint.config.mjs | 1 - src/components/progress-indicators/WalletSyncCircle.tsx | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index a6fb531ba46..a7e3006d279 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -217,7 +217,6 @@ export default [ 'src/components/progress-indicators/LoadingSplashScreen.tsx', 'src/components/progress-indicators/Shimmer.tsx', 'src/components/progress-indicators/StepProgressBar.tsx', - 'src/components/progress-indicators/WalletSyncCircle.tsx', 'src/components/rows/CoinRankRow.tsx', 'src/components/rows/CryptoFiatAmountRow.tsx', 'src/components/rows/CurrencyRow.tsx', diff --git a/src/components/progress-indicators/WalletSyncCircle.tsx b/src/components/progress-indicators/WalletSyncCircle.tsx index 6d9a5405ec5..03a063d9326 100644 --- a/src/components/progress-indicators/WalletSyncCircle.tsx +++ b/src/components/progress-indicators/WalletSyncCircle.tsx @@ -27,7 +27,7 @@ interface Props { /** * Renders the sync progress ratio as part of the `CryptoIcon` component. */ -export const WalletSyncCircle = (props: Props) => { +export const WalletSyncCircle: React.FC = props => { const theme = useTheme() const { size = theme.rem(2), wallet } = props // Animation shared state @@ -37,7 +37,7 @@ export const WalletSyncCircle = (props: Props) => { // Subscribe to the sync ratio: React.useEffect(() => { - const handler = (ratio: number) => { + const handler = (ratio: number): void => { if (ratio < RESYNC_THRESHOLD) { // Do not animate backwards if a resync happens after the sync is done: if (syncRatio.value > DONE_THRESHOLD) { From 9fd8037893bd89b264d0d1dc33a4ba1335053316 Mon Sep 17 00:00:00 2001 From: William Swanson Date: Mon, 1 Sep 2025 15:21:37 -0700 Subject: [PATCH 4/5] Fix CircleTimer warnings --- eslint.config.mjs | 1 - .../progress-indicators/CircleTimer.tsx | 21 +++++++------------ 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index a7e3006d279..2ac40f67b17 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -212,7 +212,6 @@ export default [ 'src/components/notification/NotificationView.tsx', 'src/components/progress-indicators/AccountSyncBar.tsx', 'src/components/progress-indicators/CancellableProcessingScene.tsx', - 'src/components/progress-indicators/CircleTimer.tsx', 'src/components/progress-indicators/FullScreenLoader.tsx', 'src/components/progress-indicators/LoadingSplashScreen.tsx', 'src/components/progress-indicators/Shimmer.tsx', diff --git a/src/components/progress-indicators/CircleTimer.tsx b/src/components/progress-indicators/CircleTimer.tsx index be4deb3640a..8bf91005822 100644 --- a/src/components/progress-indicators/CircleTimer.tsx +++ b/src/components/progress-indicators/CircleTimer.tsx @@ -9,12 +9,13 @@ interface Props { export const TEN_MINUTES = 600 -export const CircleTimer: React.FC = ({ expiration, timeExpired }) => { +export const CircleTimer: React.FC = props => { + const { expiration, timeExpired } = props const componentMounted = useRef(true) const timeoutId = useRef | null>(null) const isFocused = useIsFocused() - const timerTick = () => { + const timerTick = (): void => { if (!componentMounted.current || !isFocused) { if (timeoutId.current != null) { clearTimeout(timeoutId.current) @@ -24,7 +25,7 @@ export const CircleTimer: React.FC = ({ expiration, timeExpired }) => { const now = new Date() const nowMilli = now.getTime() const expMil = expiration.getTime() - if (expiration && nowMilli >= expMil) { + if (nowMilli >= expMil) { timeExpired() return } @@ -50,18 +51,12 @@ export const CircleTimer: React.FC = ({ expiration, timeExpired }) => { }, []) useEffect(() => { - if (expiration !== null) { - if (timeoutId.current != null) { - clearTimeout(timeoutId.current) - } - timeoutId.current = setTimeout(timerTick, 1000) + if (timeoutId.current != null) { + clearTimeout(timeoutId.current) } + timeoutId.current = setTimeout(timerTick, 1000) // eslint-disable-next-line react-hooks/exhaustive-deps - }, [expiration]) - - if (!expiration) { - return null - } + }, []) return } From f1649f8525a72f4de0b7b8d2d05057c870b4b836 Mon Sep 17 00:00:00 2001 From: William Swanson Date: Thu, 4 Sep 2025 15:03:34 -0700 Subject: [PATCH 5/5] Fix warnings in tests --- eslint.config.mjs | 4 ---- .../components/CreateWalletSelectCryptoRow.test.tsx | 2 +- src/__tests__/components/MenuTabs.test.tsx | 5 +++-- src/__tests__/utils.test.ts | 5 ++--- src/__tests__/utils/parseMarkedText.test.ts | 6 ++++-- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 2ac40f67b17..7a3f84fcd4c 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -57,10 +57,6 @@ export default [ 'scripts/secretFiles.ts', 'scripts/themeServer.ts', 'scripts/updateVersion.ts', - 'src/__tests__/components/CreateWalletSelectCryptoRow.test.tsx', - 'src/__tests__/components/MenuTabs.test.tsx', - 'src/__tests__/utils.test.ts', - 'src/__tests__/utils/parseMarkedText.test.ts', 'src/actions/BackupModalActions.tsx', 'src/actions/CategoriesActions.ts', 'src/actions/CountryListActions.tsx', diff --git a/src/__tests__/components/CreateWalletSelectCryptoRow.test.tsx b/src/__tests__/components/CreateWalletSelectCryptoRow.test.tsx index 51b3327f1e2..4cdbfb1b490 100644 --- a/src/__tests__/components/CreateWalletSelectCryptoRow.test.tsx +++ b/src/__tests__/components/CreateWalletSelectCryptoRow.test.tsx @@ -23,7 +23,7 @@ describe('WalletListRow', () => { it('should render with loading props', () => { const pluginId = 'bitcoin' const walletName = 'My bitcoin wallet' - const onPress = () => undefined + const onPress = (): void => {} const rightSide = ( ) diff --git a/src/__tests__/components/MenuTabs.test.tsx b/src/__tests__/components/MenuTabs.test.tsx index 4124c1a8ad2..eddb888cc6f 100644 --- a/src/__tests__/components/MenuTabs.test.tsx +++ b/src/__tests__/components/MenuTabs.test.tsx @@ -11,9 +11,10 @@ describe('MenuTabs', () => { const rendered = render( diff --git a/src/__tests__/utils.test.ts b/src/__tests__/utils.test.ts index 062ae725189..a8aba13f6f1 100644 --- a/src/__tests__/utils.test.ts +++ b/src/__tests__/utils.test.ts @@ -316,9 +316,8 @@ describe('precisionAdjust', function () { } } - for (const key in tests) { - // @ts-expect-error - const { input, output } = tests[key] + for (const key of Object.keys(tests)) { + const { input, output } = tests[key as keyof typeof tests] const { displayDenominationMultiplier, primaryExchangeMultiplier, diff --git a/src/__tests__/utils/parseMarkedText.test.ts b/src/__tests__/utils/parseMarkedText.test.ts index c7bb5098b6d..e7b8727b37a 100644 --- a/src/__tests__/utils/parseMarkedText.test.ts +++ b/src/__tests__/utils/parseMarkedText.test.ts @@ -1,10 +1,12 @@ import { describe, it } from '@jest/globals' -import { asObject, asTuple, asUnknown, asValue, type Cleaner } from 'cleaners' +import { asObject, asTuple, asValue, type Cleaner } from 'cleaners' import { parseMarkedText } from '../../util/parseMarkedText' describe('parseMarkedText', () => { - const asJsxElement = (asChildren: Cleaner = asUnknown) => + const asJsxElement = ( + asChildren: Cleaner + ): Cleaner<{ props: { children: T } }> => asObject({ props: asObject({ children: asChildren