From 5f5ab27a56b99212d969121cbe524407798a3373 Mon Sep 17 00:00:00 2001 From: Sid Vishnoi <8426945+sidvishnoi@users.noreply.github.com> Date: Thu, 3 Oct 2024 18:10:01 +0530 Subject: [PATCH 1/3] refactor(ConnectWalletForm): preserve key in errors --- src/popup/components/ConnectWalletForm.tsx | 106 ++++++++++----------- 1 file changed, 49 insertions(+), 57 deletions(-) diff --git a/src/popup/components/ConnectWalletForm.tsx b/src/popup/components/ConnectWalletForm.tsx index ece16642..10805535 100644 --- a/src/popup/components/ConnectWalletForm.tsx +++ b/src/popup/components/ConnectWalletForm.tsx @@ -18,7 +18,6 @@ import { isErrorWithKey, sleep, type ErrorWithKeyLike, - type ErrorKeys, } from '@/shared/helpers'; import type { WalletAddress } from '@interledger/open-payments'; import type { ConnectWalletPayload, Response } from '@/shared/messages'; @@ -28,8 +27,13 @@ interface Inputs { walletAddressUrl: string; amount: string; recurring: boolean; + autoKeyAddConsent: boolean; } +type ErrorInfo = { message: string; info?: ErrorWithKeyLike }; +type ErrorsParams = 'walletAddressUrl' | 'amount' | 'keyPair' | 'connect'; +type Errors = Record; + interface ConnectWalletFormProps { publicKey: string; defaultValues: Partial; @@ -62,34 +66,34 @@ export const ConnectWalletForm = ({ const [recurring, setRecurring] = React.useState( defaultValues.recurring || false, ); + const [autoKeyShareFailed, setAutoKeyShareFailed] = React.useState( isAutoKeyAddFailed(state), ); const resetState = React.useCallback(async () => { await clearConnectState(); - setErrors((_) => ({ ..._, keyPair: '', connect: '' })); + setErrors((_) => ({ ..._, keyPair: null, connect: null })); setAutoKeyShareFailed(false); }, [clearConnectState]); + const toErrorInfo = React.useCallback( + (err?: string | ErrorWithKeyLike | null): ErrorInfo | null => { + if (!err) return null; + if (typeof err === 'string') return { message: err }; + return { message: t(err), info: err }; + }, + [t], + ); + const [walletAddressInfo, setWalletAddressInfo] = React.useState(null); - const [errors, setErrors] = React.useState({ - walletAddressUrl: '', - amount: '', - keyPair: - state?.status === 'error:key' - ? isErrorWithKey(state.error) - ? t(state.error) - : state.error - : '', - connect: - state?.status === 'error' - ? isErrorWithKey(state.error) - ? t(state.error) - : state.error - : '', + const [errors, setErrors] = React.useState({ + walletAddressUrl: null, + amount: null, + keyPair: state?.status === 'error:key' ? toErrorInfo(state.error) : null, + connect: state?.status === 'error' ? toErrorInfo(state.error) : null, }); const [isValidating, setIsValidating] = React.useState({ walletAddressUrl: false, @@ -106,7 +110,7 @@ export const ConnectWalletForm = ({ const getWalletInformation = React.useCallback( async (walletAddressUrl: string): Promise => { - setErrors((_) => ({ ..._, walletAddressUrl: '' })); + setErrors((_) => ({ ..._, walletAddressUrl: null })); if (!walletAddressUrl) return false; try { setIsValidating((_) => ({ ..._, walletAddressUrl: true })); @@ -114,14 +118,17 @@ export const ConnectWalletForm = ({ const walletAddress = await getWalletInfo(url.toString()); setWalletAddressInfo(walletAddress); } catch (error) { - setErrors((_) => ({ ..._, walletAddressUrl: error.message })); + setErrors((_) => ({ + ..._, + walletAddressUrl: toErrorInfo(error.message), + })); return false; } finally { setIsValidating((_) => ({ ..._, walletAddressUrl: false })); } return true; }, - [getWalletInfo], + [getWalletInfo, toErrorInfo], ); const handleWalletAddressUrlChange = React.useCallback( @@ -130,7 +137,7 @@ export const ConnectWalletForm = ({ setWalletAddressUrl(value); const error = validateWalletAddressUrl(value); - setErrors((_) => ({ ..._, walletAddressUrl: error ? t(error) : '' })); + setErrors((_) => ({ ..._, walletAddressUrl: toErrorInfo(error) })); saveValue('walletAddressUrl', value); if (!error) { const ok = await getWalletInformation(value); @@ -138,13 +145,13 @@ export const ConnectWalletForm = ({ } return false; }, - [saveValue, getWalletInformation, t], + [saveValue, getWalletInformation, toErrorInfo], ); const handleAmountChange = React.useCallback( (value: string, input: HTMLInputElement) => { const error = validateAmount(value, currencySymbol.symbol); - setErrors((_) => ({ ..._, amount: error ? t(error) : '' })); + setErrors((_) => ({ ..._, amount: toErrorInfo(error) })); const amountValue = formatNumber(+value, currencySymbol.scale); if (!error) { @@ -153,23 +160,19 @@ export const ConnectWalletForm = ({ } saveValue('amount', error ? value : amountValue); }, - [saveValue, currencySymbol, t], + [saveValue, currencySymbol, toErrorInfo], ); - const handleSubmit = async (ev: React.FormEvent) => { - ev.preventDefault(); - if (!walletAddressInfo) { - setErrors((_) => ({ ..._, walletAddressUrl: 'Not fetched yet?!' })); - return; - } + const handleSubmit = async (ev?: React.FormEvent) => { + ev?.preventDefault(); const errWalletAddressUrl = validateWalletAddressUrl(walletAddressUrl); const errAmount = validateAmount(amount, currencySymbol.symbol); if (errAmount || errWalletAddressUrl) { setErrors((_) => ({ ..._, - walletAddressUrl: errWalletAddressUrl ? t(errWalletAddressUrl) : '', - amount: errAmount && t(errAmount), + walletAddressUrl: toErrorInfo(errWalletAddressUrl), + amount: toErrorInfo(errAmount), })); return; } @@ -181,7 +184,7 @@ export const ConnectWalletForm = ({ skipAutoKeyShare = true; setAutoKeyShareFailed(true); } - setErrors((_) => ({ ..._, keyPair: '', connect: '' })); + setErrors((_) => ({ ..._, keyPair: null, connect: null })); const res = await connectWallet({ walletAddressUrl: toWalletAddressUrl(walletAddressUrl), amount, @@ -194,9 +197,9 @@ export const ConnectWalletForm = ({ if (isErrorWithKey(res.error)) { const error = res.error; if (error.key.startsWith('connectWalletKeyService_error_')) { - setErrors((_) => ({ ..._, keyPair: t(error) })); + setErrors((_) => ({ ..._, keyPair: toErrorInfo(error) })); } else { - setErrors((_) => ({ ..._, connect: t(error) })); + setErrors((_) => ({ ..._, connect: toErrorInfo(error) })); } } else { throw new Error(res.message); @@ -239,7 +242,7 @@ export const ConnectWalletForm = ({ {errors.connect && ( - + )} {currencySymbol.symbol}} aria-invalid={!!errors.amount} - aria-describedby={errors.amount} + aria-describedby={errors.amount?.message} required={true} onKeyDown={allowOnlyNumericInput} onBlur={(ev) => { @@ -337,7 +340,7 @@ export const ConnectWalletForm = ({ {errors.amount && ( -

{errors.amount}

+

{errors.amount.message}

)} @@ -390,20 +393,20 @@ export const ConnectWalletForm = ({ }; const ManualKeyPairNeeded: React.FC<{ - error: { message: string; details: string; whyText: string }; + error: { message: string; details: null | ErrorInfo; whyText: string }; hideError?: boolean; text: string; learnMoreText: string; publicKey: string; }> = ({ error, hideError, text, learnMoreText, publicKey }) => { const ErrorDetails = () => { - if (!error) return null; + if (!error || !error.details) return null; return (
{error.whyText} - {error.details} + {error.details.message}
); }; @@ -465,18 +468,7 @@ const Footer: React.FC<{ ); }; -type ErrorCodeWalletAddressUrl = Extract< - ErrorKeys, - `connectWallet_error_url${string}` ->; -type ErrorCodeAmount = Extract< - ErrorKeys, - `connectWallet_error_amount${string}` ->; - -function validateWalletAddressUrl( - value: string, -): '' | ErrorWithKeyLike { +function validateWalletAddressUrl(value: string): null | ErrorWithKeyLike { if (!value) { return errorWithKey('connectWallet_error_urlRequired'); } @@ -491,13 +483,13 @@ function validateWalletAddressUrl( return errorWithKey('connectWallet_error_urlInvalidNotHttps'); } - return ''; + return null; } function validateAmount( value: string, currencySymbol: string, -): '' | ErrorWithKeyLike { +): null | ErrorWithKeyLike { if (!value) { return errorWithKey('connectWallet_error_amountRequired'); } @@ -510,7 +502,7 @@ function validateAmount( if (val <= 0) { return errorWithKey('connectWallet_error_amountMinimum'); } - return ''; + return null; } function allowOnlyNumericInput(ev: React.KeyboardEvent) { From dbe6ba83c76fab8a023ecbd19e0dc43f345ab79f Mon Sep 17 00:00:00 2001 From: Sid Vishnoi <8426945+sidvishnoi@users.noreply.github.com> Date: Thu, 3 Oct 2024 18:13:44 +0530 Subject: [PATCH 2/3] remove changes from other branch --- src/popup/components/ConnectWalletForm.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/popup/components/ConnectWalletForm.tsx b/src/popup/components/ConnectWalletForm.tsx index 10805535..734a61f4 100644 --- a/src/popup/components/ConnectWalletForm.tsx +++ b/src/popup/components/ConnectWalletForm.tsx @@ -27,7 +27,6 @@ interface Inputs { walletAddressUrl: string; amount: string; recurring: boolean; - autoKeyAddConsent: boolean; } type ErrorInfo = { message: string; info?: ErrorWithKeyLike }; From a012ce4ec04def3ee3a9400eab2f3b2411246f72 Mon Sep 17 00:00:00 2001 From: Sid Vishnoi <8426945+sidvishnoi@users.noreply.github.com> Date: Thu, 3 Oct 2024 18:19:27 +0530 Subject: [PATCH 3/3] missed one (thanks to 'any') --- src/popup/components/ConnectWalletForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/popup/components/ConnectWalletForm.tsx b/src/popup/components/ConnectWalletForm.tsx index 734a61f4..3fd1c2b8 100644 --- a/src/popup/components/ConnectWalletForm.tsx +++ b/src/popup/components/ConnectWalletForm.tsx @@ -205,7 +205,7 @@ export const ConnectWalletForm = ({ } } } catch (error) { - setErrors((_) => ({ ..._, connect: error.message })); + setErrors((_) => ({ ..._, connect: toErrorInfo(error.message) })); } finally { setIsSubmitting(false); }