Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: avoid regenerating mnemonics on back button hit #8885

Merged
merged 12 commits into from
Feb 19, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,12 @@ export const NativeCreate = () => {
revealedOnce.current = true
setRevealed(!revealed)
}, [revealed])

const [vault, setVault] = useState<Vault | null>(null)
const [words, setWords] = useState<ReactNode[] | null>(null)
const [revoker] = useState(new (Revocable(class {}))())
const revokerRef = useRef(new (Revocable(class {}))())

const isLegacyWallet = !!location.state?.vault
const isLegacyWallet = location.state?.isLegacyWallet

const placeholders = useMemo(() => {
return range(1, 13).map(i => (
Expand Down Expand Up @@ -83,36 +84,40 @@ export const NativeCreate = () => {
}, [history, isLegacyWallet, mixpanel, vault])

useEffect(() => {
if (vault) return
;(async () => {
try {
// If the vault is already passed from the legacy wallet flow, use it.
const vault = isLegacyWallet ? location.state.vault : await getVault()
const vault = location.state?.vault ?? (await getVault())
setVault(vault)
} catch (e) {
console.error(e)
}
})()
}, [setVault, location.state?.vault, isLegacyWallet])
}, [setVault, vault, location.state?.vault])

useEffect(() => {
if (!vault) return
;(async () => {
try {
revokerRef.current.revoke()
revokerRef.current = new (Revocable(class {}))()

const mnemonic = await vault.unwrap().get('#mnemonic')
setWords(
(await vault.unwrap().get('#mnemonic')).split(' ').map((word: string, index: number) =>
mnemonic.split(' ').map((word: string, index: number) =>
revocable(
<Tag
p={2}
flexBasis='31%'
justifyContent='flex-start'
fontSize='md'
key={word}
key={`${word}-${index}`}
colorScheme='blue'
>
<Code mr={2}>{index + 1}</Code>
{word}
</Tag>,
revoker.addRevoker.bind(revocable),
revokerRef.current.addRevoker.bind(revocable),
),
),
)
Expand All @@ -123,9 +128,9 @@ export const NativeCreate = () => {
})()

return () => {
revoker.revoke()
revokerRef.current.revoke()
}
}, [setWords, vault, revoker])
}, [setWords, vault])

return (
<>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import type { Vault } from '@shapeshiftoss/hdwallet-native-vault'
import { useCallback } from 'react'
import { useHistory, useLocation } from 'react-router-dom'
import { NativeWalletRoutes } from 'context/WalletProvider/types'

import type { LocationState } from '../types'
import { LegacyLoginSuccess } from './LegacyMigration/LegacyLoginSuccess'

export const NativeLegacySuccess = () => {
const history = useHistory<{ vault: Vault }>()
const location = useLocation<{ vault: Vault }>()
const history = useHistory<LocationState>()
const location = useLocation<LocationState>()

const handleContinue = useCallback(() => {
history.push(NativeWalletRoutes.Create, location.state)
history.push(NativeWalletRoutes.Create, {
vault: location.state.vault,
isLegacyWallet: true,
})
}, [history, location.state])

return <LegacyLoginSuccess onContinue={handleContinue} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { FaCheck } from 'react-icons/fa'
import { useTranslate } from 'react-polyglot'
import { Text } from 'components/Text'
<<<<<<< HEAD
import { NativeWalletRoutes } from 'context/WalletProvider/types'
=======
>>>>>>> origin/develop

import type { NativeSetupProps } from '../types'

Expand Down Expand Up @@ -117,7 +121,7 @@ export const NativeTestPhrase = ({ history, location }: NativeSetupProps) => {

const handleBackupComplete = useCallback(() => {
vault.seal()
history.replace('/native/password', { vault })
history.replace('/native/password', { vault, from: NativeWalletRoutes.CreateTest })
setTimeout(() => revoker.revoke(), 250)
}, [history, revoker, vault])

Expand All @@ -136,7 +140,7 @@ export const NativeTestPhrase = ({ history, location }: NativeSetupProps) => {
}

const handleSkipClick = useCallback(
() => history.push('/native/password', { vault }),
() => history.push('/native/password', { vault, from: NativeWalletRoutes.CreateTest }),
[history, vault],
)

Expand Down
1 change: 1 addition & 0 deletions src/context/WalletProvider/NativeWallet/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface LocationState {
error?: {
message: string
}
from?: string
}

export type NativeSetupProps = RouteComponentProps<{}, any, LocationState>
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ import { useTranslate } from 'react-polyglot'
import { reactQueries } from 'react-queries'
import type { StaticContext } from 'react-router'
import type { RouteComponentProps } from 'react-router-dom'
import { Route, Switch, useHistory } from 'react-router-dom'
import { Route, Switch, useHistory, useLocation } from 'react-router-dom'
import { Text } from 'components/Text'
import { WalletActions } from 'context/WalletProvider/actions'
import { KeepKeyRoutes as KeepKeyRoutesEnum } from 'context/WalletProvider/routes'
import { useWallet } from 'hooks/useWallet/useWallet'

import type { KeyManager } from '../KeyManager'
import type { LocationState } from '../NativeWallet/types'
import { NativeWalletRoutes } from '../types'
import { RDNS_TO_FIRST_CLASS_KEYMANAGER } from './constants'
import { KeepKeyRoutes } from './routes/KeepKeyRoutes'
Expand Down Expand Up @@ -96,6 +97,7 @@ export const NewWalletViewsSwitch = () => {
const [selectedWalletId, setSelectedWalletId] = useState<string | null>(null)

const history = useHistory()
const location = useLocation<LocationState>()
const toast = useToast()
const translate = useTranslate()
const {
Expand Down Expand Up @@ -129,15 +131,29 @@ export const NewWalletViewsSwitch = () => {
}, [toast, translate, wallet])

const handleBack = useCallback(async () => {
history.goBack()
const { pathname } = history.location

if (location.state?.vault && pathname === NativeWalletRoutes.CreateTest) {
history.replace({
pathname: NativeWalletRoutes.Create,
state: { vault: location.state.vault },
})

// Add this at the end of the callstack so we can store the vault in the state
setTimeout(() => {
history.goBack()
}, 250)
} else {
history.goBack()
}

// If we're back at the select wallet modal, remove the initial route
// otherwise clicking the button for the same wallet doesn't do anything
const { pathname } = history.location
if ([INITIAL_WALLET_MODAL_ROUTE, NativeWalletRoutes.Load].includes(pathname)) {
dispatch({ type: WalletActions.SET_INITIAL_ROUTE, payload: '' })
}
await cancelWalletRequests()
}, [cancelWalletRequests, dispatch, history])
}, [cancelWalletRequests, dispatch, history, location.state])

const handleRouteReset = useCallback(() => {
history.replace(INITIAL_WALLET_MODAL_ROUTE)
Expand Down
Loading