From 4c39df6f955daec3bc955c59f9133c0f76ed27cb Mon Sep 17 00:00:00 2001 From: Petr Knetl Date: Fri, 22 Nov 2024 13:42:38 +0100 Subject: [PATCH] feat(suite-native): advanced recipient address validation --- .../src/screens/SendOutputsScreen.tsx | 4 +++ .../module-send/src/sendOutputsFormSchema.ts | 27 +++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/suite-native/module-send/src/screens/SendOutputsScreen.tsx b/suite-native/module-send/src/screens/SendOutputsScreen.tsx index a01d9872051e..da0d6fe52d06 100644 --- a/suite-native/module-send/src/screens/SendOutputsScreen.tsx +++ b/suite-native/module-send/src/screens/SendOutputsScreen.tsx @@ -14,6 +14,7 @@ import { SendRootState, composeSendFormTransactionFeeLevelsThunk, selectAccountByKey, + selectDeviceUnavailableCapabilities, selectNetworkFeeInfo, selectSendFormDraftByKey, sendFormActions, @@ -96,6 +97,8 @@ export const SendOutputsScreen = ({ selectSendFormDraftByKey(state, accountKey, tokenContract), ); + const deviceUnavailableCapabilities = useSelector(selectDeviceUnavailableCapabilities); + const network = account ? getNetwork(account.symbol) : null; const form = useForm({ @@ -111,6 +114,7 @@ export const SendOutputsScreen = ({ isValueInSats: isAmountInSats, feeLevelsMaxAmount, decimals: tokenInfo?.decimals ?? network?.decimals, + isTaprootAvailable: !deviceUnavailableCapabilities?.taproot, }, defaultValues: getDefaultValues({ tokenContract }), }); diff --git a/suite-native/module-send/src/sendOutputsFormSchema.ts b/suite-native/module-send/src/sendOutputsFormSchema.ts index 8f25ea11e00e..b75811ebe109 100644 --- a/suite-native/module-send/src/sendOutputsFormSchema.ts +++ b/suite-native/module-send/src/sendOutputsFormSchema.ts @@ -2,7 +2,14 @@ import { G } from '@mobily/ts-belt'; import { BigNumber } from '@trezor/utils'; import { getNetworkType, NetworkSymbol } from '@suite-common/wallet-config'; -import { formatNetworkAmount, isAddressValid, isDecimalsValid } from '@suite-common/wallet-utils'; +import { + formatNetworkAmount, + isAddressDeprecated, + isAddressValid, + isBech32AddressUppercase, + isDecimalsValid, + isTaprootAddress, +} from '@suite-common/wallet-utils'; import { FeeInfo } from '@suite-common/wallet-types'; import { yup } from '@suite-common/validators'; import { U_INT_32 } from '@suite-common/wallet-constants'; @@ -18,6 +25,7 @@ export type SendFormFormContext = { feeLevelsMaxAmount?: FeeLevelsMaxAmount; decimals?: number; accountDescriptor?: string; + isTaprootAvailable?: boolean; }; const isAmountDust = (amount: string, context?: SendFormFormContext) => { @@ -89,12 +97,21 @@ export const sendOutputsFormValidationSchema = yup.object({ 'is-invalid-address', 'The address format is incorrect.', (value, { options: { context } }: yup.TestContext) => { - const networkSymbol = context?.networkSymbol; + if (!value || !context) { + return false; + } + const { networkSymbol, isTaprootAvailable } = context; + + if (!networkSymbol) return false; + + const isTaprootValid = + isTaprootAvailable || !isTaprootAddress(value, networkSymbol); return ( - G.isNotNullable(value) && - G.isNotNullable(networkSymbol) && - isAddressValid(value, networkSymbol) + isAddressValid(value, networkSymbol) && + !isAddressDeprecated(value, networkSymbol) && + !isBech32AddressUppercase(value) && // bech32 addresses are valid as uppercase but are not accepted by Trezor + isTaprootValid // bech32m/Taproot addresses are valid but may not be supported by older FW ); }, )