diff --git a/apps/extension/src/ui/apps/dashboard/routes/Settings/ChangePassword.tsx b/apps/extension/src/ui/apps/dashboard/routes/Settings/ChangePassword.tsx index f4dfe0274..0ad278a80 100644 --- a/apps/extension/src/ui/apps/dashboard/routes/Settings/ChangePassword.tsx +++ b/apps/extension/src/ui/apps/dashboard/routes/Settings/ChangePassword.tsx @@ -7,7 +7,7 @@ import { api } from "@ui/api" import Layout from "@ui/apps/dashboard/layout" import { MnemonicModal } from "@ui/domains/Settings/MnemonicModal" import useMnemonicBackup from "@ui/hooks/useMnemonicBackup" -import { useCallback } from "react" +import { useCallback, useEffect, useMemo } from "react" import { useForm } from "react-hook-form" import { useTranslation } from "react-i18next" import { useNavigate } from "react-router-dom" @@ -26,22 +26,27 @@ const ChangePassword = () => { const { isNotConfirmed } = useMnemonicBackup() const { isOpen, open, close } = useOpenClose() - const schema = yup - .object({ - currentPw: yup.string().required(""), - newPw: yup.string().required("").min(6, t("Password must be at least 6 characters long")), - newPwConfirm: yup - .string() - .required("") - .oneOf([yup.ref("newPw")], t("Passwords must match!")), - }) - .required() + const schema = useMemo( + () => + yup + .object({ + currentPw: yup.string().required(""), + newPw: yup.string().required("").min(6, t("Password must be at least 6 characters long")), + newPwConfirm: yup + .string() + .required("") + .oneOf([yup.ref("newPw")], t("Passwords must match!")), + }) + .required(), + [t] + ) const { register, handleSubmit, formState: { errors, isValid, isSubmitting }, setError, + setValue, } = useForm({ mode: "onChange", resolver: yupResolver(schema), @@ -73,6 +78,14 @@ const ChangePassword = () => { [navigate, setError, t] ) + useEffect(() => { + return () => { + setValue("currentPw", "") + setValue("newPw", "") + setValue("newPwConfirm", "") + } + }, [setValue]) + return ( <> diff --git a/apps/extension/src/ui/apps/onboard/context.tsx b/apps/extension/src/ui/apps/onboard/context.tsx index 785857a02..13d5d5aef 100644 --- a/apps/extension/src/ui/apps/onboard/context.tsx +++ b/apps/extension/src/ui/apps/onboard/context.tsx @@ -62,6 +62,12 @@ const useAppOnboardProvider = ({ isResettingWallet = false }: { isResettingWalle }) }, [data.allowTracking]) + useEffect(() => { + return () => { + setData(DEFAULT_DATA) + } + }, []) + return { onboard, reset, diff --git a/apps/extension/src/ui/apps/onboard/routes/ImportSeed.tsx b/apps/extension/src/ui/apps/onboard/routes/ImportSeed.tsx index 0c09c626f..1aa77e956 100644 --- a/apps/extension/src/ui/apps/onboard/routes/ImportSeed.tsx +++ b/apps/extension/src/ui/apps/onboard/routes/ImportSeed.tsx @@ -2,7 +2,7 @@ import { yupResolver } from "@hookform/resolvers/yup" import { api } from "@ui/api" import { AnalyticsPage, sendAnalyticsEvent } from "@ui/api/analytics" import { useAnalyticsPageView } from "@ui/hooks/useAnalyticsPageView" -import { useCallback, useMemo } from "react" +import { useCallback, useEffect, useMemo } from "react" import { useForm } from "react-hook-form" import { Trans, useTranslation } from "react-i18next" import { useNavigate } from "react-router-dom" @@ -61,6 +61,7 @@ export const ImportSeedPage = () => { const { register, handleSubmit, + setValue, formState: { errors, isValid }, } = useForm({ mode: "onChange", @@ -85,6 +86,12 @@ export const ImportSeedPage = () => { [data.importAccountType, data.importMethodType, navigate, updateData] ) + useEffect(() => { + return () => { + setValue("mnemonic", "") + } + }, [setValue]) + return (
diff --git a/apps/extension/src/ui/apps/onboard/routes/Password.tsx b/apps/extension/src/ui/apps/onboard/routes/Password.tsx index 86318c6ab..2e239cce1 100644 --- a/apps/extension/src/ui/apps/onboard/routes/Password.tsx +++ b/apps/extension/src/ui/apps/onboard/routes/Password.tsx @@ -53,6 +53,7 @@ export const PasswordPage = () => { handleSubmit, watch, trigger, + setValue, formState: { errors, isValid, isSubmitting }, } = useForm({ mode: "all", @@ -99,6 +100,13 @@ export const PasswordPage = () => { ] }, [data, t]) + useEffect(() => { + return () => { + setValue("password", "") + setValue("passwordConfirm", "") + } + }, [setValue]) + return (
diff --git a/apps/extension/src/ui/apps/popup/pages/Login.tsx b/apps/extension/src/ui/apps/popup/pages/Login.tsx index ac5b6b5d4..99e804b4e 100644 --- a/apps/extension/src/ui/apps/popup/pages/Login.tsx +++ b/apps/extension/src/ui/apps/popup/pages/Login.tsx @@ -137,6 +137,12 @@ const Login = ({ setShowResetWallet }: { setShowResetWallet: () => void }) => { } }, [handleSubmit, setValue, submit]) + useEffect(() => { + return () => { + setValue("password", "") + } + }, [setValue]) + return ( }> diff --git a/apps/extension/src/ui/domains/Account/AccountExportModal.tsx b/apps/extension/src/ui/domains/Account/AccountExportModal.tsx index 2fb6b040b..588e8972c 100644 --- a/apps/extension/src/ui/domains/Account/AccountExportModal.tsx +++ b/apps/extension/src/ui/domains/Account/AccountExportModal.tsx @@ -77,6 +77,7 @@ const ExportAccountForm = ({ onSuccess }: { onSuccess?: () => void }) => { formState: { errors, isValid, isSubmitting }, watch, setError, + setValue, } = useForm({ mode: "onChange", resolver: yupResolver(schema), @@ -99,6 +100,13 @@ const ExportAccountForm = ({ onSuccess }: { onSuccess?: () => void }) => { [exportAccount, setError, onSuccess, password] ) + useEffect(() => { + return () => { + setValue("newPw", "") + setValue("newPwConfirm", "") + } + }, [setValue]) + if (!canExportAccount || !password) return null return (
diff --git a/apps/extension/src/ui/domains/Account/AccountExportPrivateKeyModal.tsx b/apps/extension/src/ui/domains/Account/AccountExportPrivateKeyModal.tsx index 2526c597d..eff5b747a 100644 --- a/apps/extension/src/ui/domains/Account/AccountExportPrivateKeyModal.tsx +++ b/apps/extension/src/ui/domains/Account/AccountExportPrivateKeyModal.tsx @@ -4,9 +4,8 @@ import { notify } from "@talisman/components/Notifications" import { useOpenClose } from "@talisman/hooks/useOpenClose" import { CopyIcon, LoaderIcon } from "@talisman/theme/icons" import { provideContext } from "@talisman/util/provideContext" -import { useQuery } from "@tanstack/react-query" import { api } from "@ui/api" -import { useCallback, useEffect, useMemo } from "react" +import { useCallback, useEffect, useMemo, useState } from "react" import { useTranslation } from "react-i18next" import { Button } from "talisman-ui" @@ -28,7 +27,7 @@ const useAccountExportPrivateKeyModalProvider = () => { ) const exportAccount = useCallback( - (password: string) => { + async (password: string) => { if (!account) return return api.accountExportPrivateKey(account.address, password) }, @@ -46,19 +45,10 @@ const ExportPrivateKeyResult = ({ onClose }: { onClose?: () => void }) => { const { account, exportAccount } = useAccountExportPrivateKeyModal() const { password } = usePasswordUnlock() - // force password check each time this component is rendered - const { - error, - data: privateKey, - isLoading, - } = useQuery({ - queryKey: ["accountExportPrivateKey", !!password], - queryFn: () => (password ? exportAccount(password) : null), - refetchInterval: false, - refetchOnWindowFocus: false, - refetchOnReconnect: false, - refetchOnMount: true, - }) + // don't use react-query here as we don't want this to be cached + const [privateKey, setPrivateKey] = useState() + const [isLoading, setIsLoading] = useState(false) + const [error, setError] = useState() const copyToClipboard = useCallback(async () => { if (!privateKey) return @@ -88,6 +78,25 @@ const ExportPrivateKeyResult = ({ onClose }: { onClose?: () => void }) => { } }, [privateKey, t]) + useEffect(() => { + if (password) { + setError(undefined) + setIsLoading(true) + exportAccount(password) + .then(setPrivateKey) + .catch(setError) + .finally(() => setIsLoading(false)) + } + }, [exportAccount, password]) + + useEffect(() => { + return () => { + setError(undefined) + setPrivateKey(undefined) + setIsLoading(false) + } + }, []) + if (!account) return null return ( diff --git a/apps/extension/src/ui/domains/Account/MnemonicForm.tsx b/apps/extension/src/ui/domains/Account/MnemonicForm.tsx index 1b1ba66a6..719da3f13 100644 --- a/apps/extension/src/ui/domains/Account/MnemonicForm.tsx +++ b/apps/extension/src/ui/domains/Account/MnemonicForm.tsx @@ -46,9 +46,15 @@ const MnemonicForm = ({ className }: MnemonicFormProps) => { useEffect(() => { if (!password) return - api.mnemonicUnlock(password).then((result) => setMnemonic(result)) + api.mnemonicUnlock(password).then(setMnemonic) }, [password]) + useEffect(() => { + return () => { + setMnemonic(undefined) + } + }, []) + return (
{mnemonic ? ( diff --git a/apps/extension/src/ui/domains/Account/PasswordUnlock.tsx b/apps/extension/src/ui/domains/Account/PasswordUnlock.tsx index 4b4ed5fb9..566213005 100644 --- a/apps/extension/src/ui/domains/Account/PasswordUnlock.tsx +++ b/apps/extension/src/ui/domains/Account/PasswordUnlock.tsx @@ -2,7 +2,7 @@ import { yupResolver } from "@hookform/resolvers/yup" import { KeyIcon } from "@talisman/theme/icons" import { provideContext } from "@talisman/util/provideContext" import { api } from "@ui/api" -import { ReactNode, useCallback, useState } from "react" +import { ReactNode, useCallback, useEffect, useState } from "react" import { useForm } from "react-hook-form" import { useTranslation } from "react-i18next" import { Button, FormFieldContainer, FormFieldInputText } from "talisman-ui" @@ -33,12 +33,15 @@ type PasswordUnlockContext = { function usePasswordUnlockContext(): PasswordUnlockContext { const [password, setPassword] = useState() - const checkPassword = useCallback( - async (password: string) => { - if (await api.checkPassword(password)) setPassword(password) - }, - [setPassword] - ) + const checkPassword = useCallback(async (password: string) => { + if (await api.checkPassword(password)) setPassword(password) + }, []) + + useEffect(() => { + return () => { + setPassword(undefined) + } + }, []) return { checkPassword, @@ -56,6 +59,8 @@ const BasePasswordUnlock = ({ className, children, buttonText, title }: Password register, handleSubmit, setError, + setValue, + setFocus, formState: { errors, isValid, isSubmitting }, } = useForm({ mode: "onChange", @@ -77,6 +82,16 @@ const BasePasswordUnlock = ({ className, children, buttonText, title }: Password [checkPassword, setError] ) + useEffect(() => { + if (!password) setFocus("password") + }, [password, setFocus]) + + useEffect(() => { + return () => { + setValue("password", "") + } + }, [setValue]) + return password ? (
{children}
) : ( @@ -92,8 +107,6 @@ const BasePasswordUnlock = ({ className, children, buttonText, title }: Password placeholder={t("Enter password")} spellCheck={false} data-lpignore - // eslint-disable-next-line jsx-a11y/no-autofocus - autoFocus />
diff --git a/apps/extension/src/ui/domains/Settings/MigratePassword/context.ts b/apps/extension/src/ui/domains/Settings/MigratePassword/context.ts index 96abbfa2b..71bb787d1 100644 --- a/apps/extension/src/ui/domains/Settings/MigratePassword/context.ts +++ b/apps/extension/src/ui/domains/Settings/MigratePassword/context.ts @@ -60,6 +60,14 @@ const useMigratePasswordProvider = ({ onComplete }: { onComplete: () => void }) } }, [hasBackedUpMnemonic, status, migratePassword]) + useEffect(() => { + return () => { + setPassword(undefined) + setMnemonic(undefined) + setNewPassword(undefined) + } + }, []) + return { hasPassword, hasNewPassword,