diff --git a/@shared/api/internal.ts b/@shared/api/internal.ts index 4e55ef718f..44f0368855 100644 --- a/@shared/api/internal.ts +++ b/@shared/api/internal.ts @@ -670,8 +670,8 @@ export const signOut = async (): Promise<{ export const showBackupPhrase = async ( password: string, -): Promise<{ error: string }> => { - let response = { error: "" }; +): Promise<{ mnemonicPhrase: string; error: string }> => { + let response = { mnemonicPhrase: "", error: "" }; try { response = await sendMessageToBackground({ password, diff --git a/extension/package.json b/extension/package.json index 9545a5819a..04946170b8 100755 --- a/extension/package.json +++ b/extension/package.json @@ -1,6 +1,6 @@ { "name": "extension", - "version": "5.3.0", + "version": "5.3.1", "license": "Apache-2.0", "prettier": "@stellar/prettier-config", "scripts": { diff --git a/extension/public/static/manifest/v2.json b/extension/public/static/manifest/v2.json index 1179b0a4ad..206ec4bcd4 100644 --- a/extension/public/static/manifest/v2.json +++ b/extension/public/static/manifest/v2.json @@ -1,7 +1,7 @@ { "name": "Freighter", - "version": "5.3.0", - "version_name": "5.3.0", + "version": "5.3.1", + "version_name": "5.3.1", "description": "Freighter is a non-custodial wallet extension that enables you to sign Stellar transactions via your browser.", "browser_specific_settings": { "gecko": { diff --git a/extension/public/static/manifest/v3.json b/extension/public/static/manifest/v3.json index 0c7622f1b2..3985a30f17 100644 --- a/extension/public/static/manifest/v3.json +++ b/extension/public/static/manifest/v3.json @@ -1,7 +1,7 @@ { "name": "Freighter", - "version": "5.3.0", - "version_name": "5.3.0", + "version": "5.3.1", + "version_name": "5.3.1", "description": "Freighter is a non-custodial wallet extension that enables you to sign Stellar transactions via your browser.", "background": { "service_worker": "background.min.js" diff --git a/extension/src/background/messageListener/popupMessageListener.ts b/extension/src/background/messageListener/popupMessageListener.ts index cebb21e4c9..905fa4f9c6 100644 --- a/extension/src/background/messageListener/popupMessageListener.ts +++ b/extension/src/background/messageListener/popupMessageListener.ts @@ -583,9 +583,23 @@ export const popupMessageListener = (request: Request, sessionStore: Store) => { }; }; - const getMnemonicPhrase = () => ({ - mnemonicPhrase: mnemonicPhraseSelector(sessionStore.getState()), - }); + const getMnemonicPhrase = async () => { + const { password } = request; + + const keyID = (await getIsHardwareWalletActive()) + ? await _getNonHwKeyID() + : (await localStore.getItem(KEY_ID)) || ""; + + try { + await _unlockKeystore({ keyID, password }); + } catch (e) { + console.error(e); + return { error: "Incorrect password" }; + } + return { + mnemonicPhrase: mnemonicPhraseSelector(sessionStore.getState()), + }; + }; const confirmMnemonicPhrase = async () => { const isCorrectPhrase = @@ -698,10 +712,13 @@ export const popupMessageListener = (request: Request, sessionStore: Store) => { keyID: (await localStore.getItem(KEY_ID)) || "", password, }); - return {}; } catch (e) { return { error: "Incorrect Password" }; } + + return { + mnemonicPhrase: mnemonicPhraseSelector(sessionStore.getState()), + }; }; const _getLocalStorageAccounts = async (password: string) => { diff --git a/extension/src/popup/Router.tsx b/extension/src/popup/Router.tsx index c14598dfe7..3a3c1c49f3 100644 --- a/extension/src/popup/Router.tsx +++ b/extension/src/popup/Router.tsx @@ -283,7 +283,7 @@ export const Router = () => { - + diff --git a/extension/src/popup/components/Onboarding/index.tsx b/extension/src/popup/components/Onboarding/index.tsx index 543cbe5db7..8a9359a425 100644 --- a/extension/src/popup/components/Onboarding/index.tsx +++ b/extension/src/popup/components/Onboarding/index.tsx @@ -6,9 +6,11 @@ import { BackButton } from "popup/basics/buttons/BackButton"; import "./styles.scss"; export const Onboarding = ({ + customBackAction, hasGoBackBtn, children, }: { + customBackAction?: () => void; hasGoBackBtn?: boolean; children: React.ReactNode; }) => { @@ -19,7 +21,7 @@ export const Onboarding = ({
{hasGoBackBtn && !isNewTabSession ? (
- +
) : null} {children} diff --git a/extension/src/popup/components/mnemonicPhrase/DisplayMnemonicPhrase/index.tsx b/extension/src/popup/components/mnemonicPhrase/DisplayMnemonicPhrase/index.tsx index e2578e1edd..303d3c5437 100644 --- a/extension/src/popup/components/mnemonicPhrase/DisplayMnemonicPhrase/index.tsx +++ b/extension/src/popup/components/mnemonicPhrase/DisplayMnemonicPhrase/index.tsx @@ -3,8 +3,6 @@ import { useTranslation } from "react-i18next"; import { InfoBlock } from "popup/basics/InfoBlock"; import { Button } from "popup/basics/buttons/Button"; -import { ROUTES } from "popup/constants/routes"; -import { navigateTo } from "popup/helpers/navigate"; import { OnboardingScreen, @@ -18,8 +16,10 @@ import "./styles.scss"; export const DisplayMnemonicPhrase = ({ mnemonicPhrase, + setIsConfirmed, }: { mnemonicPhrase: string; + setIsConfirmed: (confirmed: boolean) => void; }) => { const { t } = useTranslation(); @@ -60,7 +60,7 @@ export const DisplayMnemonicPhrase = ({ data-testid="display-mnemonic-phrase-next-btn" fullWidth onClick={() => { - navigateTo(ROUTES.mnemonicPhraseConfirm); + setIsConfirmed(true); }} > {t("Next")} diff --git a/extension/src/popup/components/mnemonicPhrase/MnemonicDisplay/index.tsx b/extension/src/popup/components/mnemonicPhrase/MnemonicDisplay/index.tsx index a145adb2a6..8b6d47e013 100644 --- a/extension/src/popup/components/mnemonicPhrase/MnemonicDisplay/index.tsx +++ b/extension/src/popup/components/mnemonicPhrase/MnemonicDisplay/index.tsx @@ -11,7 +11,7 @@ interface generateMnemonicPhraseDisplayProps { } export const generateMnemonicPhraseDisplay = ({ - mnemonicPhrase, + mnemonicPhrase = "", }: generateMnemonicPhraseDisplayProps) => mnemonicPhrase.split(" ").map((word: string) => { /* diff --git a/extension/src/popup/helpers/useMnemonicPhrase.ts b/extension/src/popup/helpers/useMnemonicPhrase.ts deleted file mode 100644 index 33cb92b8aa..0000000000 --- a/extension/src/popup/helpers/useMnemonicPhrase.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { useEffect, useState } from "react"; -import { getMnemonicPhrase } from "@shared/api/internal"; - -export const useMnemonicPhrase = () => { - const [mnemonicPhrase, setMnemonicPhrase] = useState(""); - - useEffect(() => { - let res = { mnemonicPhrase: "" }; - - const fetchMnemonicPhrase = async () => { - try { - res = await getMnemonicPhrase(); - } catch (e) { - console.error(e); - } - - const { mnemonicPhrase: fetchedMnemonicPhrase } = res; - setMnemonicPhrase(fetchedMnemonicPhrase); - }; - - fetchMnemonicPhrase(); - - return () => { - setMnemonicPhrase(""); - }; - }, []); - - return mnemonicPhrase; -}; diff --git a/extension/src/popup/views/AccountCreator/index.tsx b/extension/src/popup/views/AccountCreator/index.tsx index 5c3489d083..d35380d43c 100644 --- a/extension/src/popup/views/AccountCreator/index.tsx +++ b/extension/src/popup/views/AccountCreator/index.tsx @@ -1,13 +1,12 @@ -import React, { useEffect } from "react"; +import React, { useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { Input, Checkbox, TextLink } from "@stellar/design-system"; import { Field, FieldProps, Formik, Form } from "formik"; import { object as YupObject } from "yup"; import { useTranslation } from "react-i18next"; +import { showBackupPhrase } from "@shared/api/internal"; import { Button } from "popup/basics/buttons/Button"; -import { ROUTES } from "popup/constants/routes"; -import { navigateTo } from "popup/helpers/navigate"; import { password as passwordValidator, confirmPassword as confirmPasswordValidator, @@ -30,6 +29,8 @@ import { import { Header } from "popup/components/Header"; import { PasswordRequirements } from "popup/components/PasswordRequirements"; +import { MnemonicPhrase } from "popup/views/MnemonicPhrase"; + import "./styles.scss"; export const AccountCreator = () => { @@ -37,6 +38,7 @@ export const AccountCreator = () => { const dispatch = useDispatch(); const authError = useSelector(authErrorSelector); const { t } = useTranslation(); + const [mnemonicPhrase, setMnemonicPhrase] = useState(""); interface FormValues { password: string; @@ -52,6 +54,9 @@ export const AccountCreator = () => { const handleSubmit = async (values: FormValues) => { await dispatch(createAccount(values.password)); + const res = await showBackupPhrase(values.password); + + setMnemonicPhrase(res.mnemonicPhrase); }; const AccountCreatorSchema = YupObject().shape({ @@ -60,13 +65,9 @@ export const AccountCreator = () => { termsOfUse: termsofUseValidator, }); - useEffect(() => { - if (publicKey) { - navigateTo(ROUTES.mnemonicPhrase); - } - }, [publicKey]); - - return ( + return mnemonicPhrase && publicKey ? ( + + ) : ( <>
diff --git a/extension/src/popup/views/DisplayBackupPhrase/index.tsx b/extension/src/popup/views/DisplayBackupPhrase/index.tsx index 486dcf5af3..d77d4abdf3 100644 --- a/extension/src/popup/views/DisplayBackupPhrase/index.tsx +++ b/extension/src/popup/views/DisplayBackupPhrase/index.tsx @@ -9,7 +9,6 @@ import { ROUTES } from "popup/constants/routes"; import { Button } from "popup/basics/buttons/Button"; import { navigateTo } from "popup/helpers/navigate"; import { emitMetric } from "helpers/metrics"; -import { useMnemonicPhrase } from "popup/helpers/useMnemonicPhrase"; import { METRIC_NAMES } from "popup/constants/metricsNames"; @@ -24,7 +23,7 @@ export const DisplayBackupPhrase = () => { const { t } = useTranslation(); const [errorMessage, setErrorMessage] = useState(""); const [isPhraseUnlocked, setIsPhraseUnlocked] = useState(false); - const mnemonicPhrase = useMnemonicPhrase(); + const [mnemonicPhrase, setMnemonicPhrase] = useState(""); useEffect(() => { emitMetric( @@ -51,6 +50,7 @@ export const DisplayBackupPhrase = () => { error_type: res.error, }); } else { + setMnemonicPhrase(res.mnemonicPhrase); setIsPhraseUnlocked(true); setErrorMessage(""); emitMetric(METRIC_NAMES.backupPhraseSuccess); diff --git a/extension/src/popup/views/MnemonicPhrase.tsx b/extension/src/popup/views/MnemonicPhrase.tsx index aee2d8f86c..b75934ce40 100644 --- a/extension/src/popup/views/MnemonicPhrase.tsx +++ b/extension/src/popup/views/MnemonicPhrase.tsx @@ -1,46 +1,52 @@ -import React from "react"; +import React, { useState } from "react"; import { useSelector } from "react-redux"; import shuffle from "lodash/shuffle"; -import { Switch, Redirect } from "react-router-dom"; +import { Redirect } from "react-router-dom"; import { APPLICATION_STATE } from "@shared/constants/applicationState"; -import { PublicKeyRoute } from "popup/Router"; import { ROUTES } from "popup/constants/routes"; import { FullscreenStyle } from "popup/components/FullscreenStyle"; -import { useMnemonicPhrase } from "popup/helpers/useMnemonicPhrase"; import { Header } from "popup/components/Header"; import { Onboarding } from "popup/components/Onboarding"; import { ConfirmMnemonicPhrase } from "popup/components/mnemonicPhrase/ConfirmMnemonicPhrase"; import { DisplayMnemonicPhrase } from "popup/components/mnemonicPhrase/DisplayMnemonicPhrase"; import { applicationStateSelector } from "popup/ducks/accountServices"; -export const MnemonicPhrase = () => { - const mnemonicPhrase = useMnemonicPhrase(); +interface MnemonicPhraseProps { + mnemonicPhrase: string; +} + +export const MnemonicPhrase = ({ + mnemonicPhrase = "", +}: MnemonicPhraseProps) => { const applicationState = useSelector(applicationStateSelector); + const [isConfirmed, setIsConfirmed] = useState(false); if (applicationState === APPLICATION_STATE.MNEMONIC_PHRASE_CONFIRMED) { return ; } if (mnemonicPhrase) { - return ( - - -
- - - - - - -
- - - - - - + return isConfirmed ? ( + <> +
+ + setIsConfirmed(false)} hasGoBackBtn> + + + + ) : ( + <> +
+ + + + + ); } diff --git a/extension/src/popup/views/__tests__/MnemonicPhrase.test.tsx b/extension/src/popup/views/__tests__/MnemonicPhrase.test.tsx index dc468d316f..afcb43cfca 100644 --- a/extension/src/popup/views/__tests__/MnemonicPhrase.test.tsx +++ b/extension/src/popup/views/__tests__/MnemonicPhrase.test.tsx @@ -27,9 +27,6 @@ jest.mock("popup/constants/history", () => ({ }, })); -jest.mock("popup/helpers/useMnemonicPhrase", () => ({ - useMnemonicPhrase: () => "dummy mnemonic", -})); jest.mock("react-router-dom", () => { const ReactRouter = jest.requireActual("react-router-dom"); return { @@ -68,7 +65,7 @@ describe.skip("MnemonicPhrase", () => { }, }} > - + , ); await waitFor(() => screen.getByTestId("display-mnemonic-phrase")); @@ -96,7 +93,7 @@ describe.skip("MnemonicPhrase", () => { }, }} > - + , );