Skip to content

Commit

Permalink
fix(setup wallet): wallet plate hardcode issue, redirects and mnemoni…
Browse files Browse the repository at this point in the history
…c button (#3203)
  • Loading branch information
banklesss committed Apr 16, 2024
1 parent b4c9dca commit ae5ac71
Show file tree
Hide file tree
Showing 9 changed files with 520 additions and 459 deletions.
Expand Up @@ -72,7 +72,8 @@ export const useStrings = () => {
walletPasswordModalCardSecondItem: intl.formatMessage(messages.walletPasswordModalCardSecondItem),
walletChecksumModalCardTitle: intl.formatMessage(messages.walletChecksumModalCardTitle),
walletChecksumModalCardFirstItem: intl.formatMessage(messages.walletChecksumModalCardFirstItem),
walletChecksumModalCardSecondItem: intl.formatMessage(messages.walletChecksumModalCardSecondItem),
walletChecksumModalCardSecondItem: (checksum: string) =>
intl.formatMessage(messages.walletChecksumModalCardSecondItem, {checksum}),
walletChecksumModalCardThirdItem: intl.formatMessage(messages.walletChecksumModalCardThirdItem),
stepWalletDetails: intl.formatMessage(messages.stepWalletDetails),
walletDetailsTitle: (options: {b: (content: React.ReactNode[]) => React.ReactNode}) =>
Expand Down Expand Up @@ -320,7 +321,7 @@ export const messages = Object.freeze(
},
walletChecksumModalCardSecondItem: {
id: 'components.walletinit.walletDetails.walletChecksumModalCardItem.second',
defaultMessage: '!!!Plate number BONE-0770 is a auto-generated sign of four letters and four digits.',
defaultMessage: '!!!Plate number {checksum} is a auto-generated sign of four letters and four digits.',
},
walletChecksumModalCardThirdItem: {
id: 'components.walletinit.walletDetails.walletChecksumModalCardItem.third',
Expand Down
Expand Up @@ -198,46 +198,44 @@ const MnemonicInput = ({defaultMnemonic, userEntries, onPress}: MnemonicInputPro
const recoveryWordError = !isLastWordValid() && lastUserEntry?.id === entry.id

return (
<Animated.View
<TouchableOpacity
key={entry.id}
style={styles.wordBadgeView}
layout={Layout}
entering={FadeIn}
exiting={FadeOut}
activeOpacity={0.5}
onPress={onPress}
disabled={!isLast || !recoveryWordError}
style={styles.wordBadge}
>
<WordBadge
word={`${(index + 1).toString()}.`}
used
disabled={!isLast || !recoveryWordError}
onPress={onPress}
recoveryWordError={recoveryWordError}
defaultMnemonic={defaultMnemonic}
/>

<Animated.View
layout={Layout}
entering={FadeIn}
exiting={FadeOut}
style={[styles.wordBadgeContainerOutline, recoveryWordError && styles.errorBadgeBackground]}
>
{!recoveryWordError && (
<LinearGradient
style={[StyleSheet.absoluteFill, {opacity: 1}]}
start={isPhraseComplete && isPhraseValid ? {x: 0, y: 0} : {x: 1, y: 0}}
end={isPhraseComplete && isPhraseValid ? {x: 0, y: 1} : {x: 0, y: 0}}
colors={isPhraseComplete && isPhraseValid ? colors.gradientGreen : colors.gradientBlueGreen}
/>
)}

<Animated.View style={styles.wordBadgeView} layout={Layout} entering={FadeIn} exiting={FadeOut}>
<WordBadge
word={entry.word}
disabled={!isLast || !recoveryWordError}
onPress={onPress}
word={`${(index + 1).toString()}.`}
used
recoveryWordError={recoveryWordError}
defaultMnemonic={defaultMnemonic}
/>

<Animated.View
layout={Layout}
entering={FadeIn}
exiting={FadeOut}
style={[styles.wordBadgeContainerOutline, recoveryWordError && styles.errorBadgeBackground]}
>
{!recoveryWordError && (
<LinearGradient
style={[StyleSheet.absoluteFill, {opacity: 1}]}
start={isPhraseComplete && isPhraseValid ? {x: 0, y: 0} : {x: 1, y: 0}}
end={isPhraseComplete && isPhraseValid ? {x: 0, y: 1} : {x: 0, y: 0}}
colors={isPhraseComplete && isPhraseValid ? colors.gradientGreen : colors.gradientBlueGreen}
/>
)}

<WordBadge
word={entry.word}
recoveryWordError={recoveryWordError}
defaultMnemonic={defaultMnemonic}
/>
</Animated.View>
</Animated.View>
</Animated.View>
</TouchableOpacity>
)
})}
</View>
Expand Down Expand Up @@ -293,32 +291,26 @@ const WordBadges = ({
const usedError = isUsed && !isLastWordValid() && lastUserEntry?.id === entry.id

return (
<Animated.View
<TouchableOpacity
testID={isUsed ? `wordBadgeTapped-${entry.word}` : `wordBadgeNonTapped-${entry.word}`}
key={entry.id}
layout={Layout}
entering={FadeIn}
exiting={FadeOut}
style={[styles.wordBadgeContainer]}
activeOpacity={0.5}
disabled={isUsed}
onPress={() => selectWord(entry)}
>
<LinearGradient
style={[StyleSheet.absoluteFill, {opacity: 1}]}
start={{x: 1, y: 0}}
end={{x: 0, y: 0}}
colors={!usedError ? colors.gradientBlueGreen : [colors.error, colors.error]}
/>

{isUsed && <View style={styles.usedWordBackground} />}

<WordBadge
word={entry.word}
onPress={() => selectWord(entry)}
disabled={isUsed}
used={isUsed}
usedError={usedError}
testID={isUsed ? `wordBadgeTapped-${entry.word}` : `wordBadgeNonTapped-${entry.word}`}
defaultMnemonic={defaultMnemonic}
/>
</Animated.View>
<Animated.View layout={Layout} entering={FadeIn} exiting={FadeOut} style={[styles.wordBadgeContainer]}>
<LinearGradient
style={[StyleSheet.absoluteFill, {opacity: 1}]}
start={{x: 1, y: 0}}
end={{x: 0, y: 0}}
colors={!usedError ? colors.gradientBlueGreen : [colors.error, colors.error]}
/>

{isUsed && <View style={styles.usedWordBackground} />}

<WordBadge word={entry.word} used={isUsed} usedError={usedError} defaultMnemonic={defaultMnemonic} />
</Animated.View>
</TouchableOpacity>
)
})}
</Animated.View>
Expand All @@ -327,34 +319,23 @@ const WordBadges = ({

type WordBadgeProps = {
word: string
disabled?: boolean
used?: boolean
usedError?: boolean
recoveryWordError?: boolean
onPress?: () => void
testID?: string
defaultMnemonic: Array<Entry>
}
const WordBadge = ({word, onPress, disabled, testID, used, usedError, recoveryWordError}: WordBadgeProps) => {
const WordBadge = ({word, used, usedError, recoveryWordError}: WordBadgeProps) => {
const {styles} = useStyles()
return (
<Animated.View layout={Layout} entering={FadeIn} exiting={FadeOut}>
<TouchableOpacity
testID={testID}
activeOpacity={0.5}
onPress={onPress}
disabled={disabled}
style={styles.wordBadge}
<Animated.View layout={Layout} entering={FadeIn} exiting={FadeOut} style={styles.wordBadge}>
<Animated.Text
layout={Layout}
entering={FadeIn}
exiting={FadeOut}
style={[styles.wordBadgeText, used && !usedError && styles.usedWord, recoveryWordError && styles.errorBadge]}
>
<Animated.Text
layout={Layout}
entering={FadeIn}
exiting={FadeOut}
style={[styles.wordBadgeText, used && !usedError && styles.usedWord, recoveryWordError && styles.errorBadge]}
>
{word}
</Animated.Text>
</TouchableOpacity>
{word}
</Animated.Text>
</Animated.View>
)
}
Expand Down
@@ -1,5 +1,5 @@
import {useFocusEffect} from '@react-navigation/native'
import {NetworkError} from '@yoroi/common'
import {NetworkError, useAsyncStorage} from '@yoroi/common'
import {useSetupWallet} from '@yoroi/setup-wallet'
import {useTheme} from '@yoroi/theme'
import * as React from 'react'
Expand All @@ -26,8 +26,10 @@ import {useMetrics} from '../../../../metrics/metricsManager'
import {useWalletNavigation} from '../../../../navigation'
import {isEmptyString} from '../../../../utils'
import {AddressMode} from '../../../../wallet-manager/types'
import {parseWalletMeta} from '../../../../wallet-manager/validators'
import {useWalletManager} from '../../../../wallet-manager/WalletManagerContext'
import {useCreateWallet, usePlate, useWalletNames} from '../../../../yoroi-wallets/hooks'
import {InvalidState} from '../../../../yoroi-wallets/cardano/errors'
import {useCreateWallet, useOpenWallet, usePlate, useWalletNames} from '../../../../yoroi-wallets/hooks'
import {WalletImplementationId} from '../../../../yoroi-wallets/types'
import {
getWalletNameError,
Expand All @@ -36,6 +38,7 @@ import {
validateWalletName,
} from '../../../../yoroi-wallets/utils'
import {debugWalletInfo, features} from '../../..'
import {useSetSelectedWallet, useSetSelectedWalletMeta} from '../../../WalletManager/Context'
import {CardAboutPhrase} from '../../common/CardAboutPhrase/CardAboutPhrase'
import {YoroiZendeskLink} from '../../common/contants'
import {LearnMoreButton} from '../../common/LearnMoreButton/LearnMoreButton'
Expand Down Expand Up @@ -63,32 +66,27 @@ export const WalletDetailsScreen = () => {
const {styles} = useStyles()
const {HEIGHT_MODAL_NAME_PASSWORD, HEIGHT_MODAL_CHECKSUM} = useSizeModal()
const {openModal, closeModal} = useModal()
const {resetToWalletSelection} = useWalletNavigation()
const {navigateToTxHistory} = useWalletNavigation()
const strings = useStrings()
const walletManager = useWalletManager()
const {walletNames} = useWalletNames(walletManager)
const {track} = useMetrics()
const intl = useIntl()
const selectWalletMeta = useSetSelectedWalletMeta()
const selectWallet = useSetSelectedWallet()
const storage = useAsyncStorage()
const {mnemonic, networkId, publicKeyHex, walletImplementationId} = useSetupWallet()
const plate = usePlate({networkId, publicKeyHex})
const [name, setName] = React.useState(features.prefillWalletInfo ? debugWalletInfo.WALLET_NAME : '')
const passwordRef = React.useRef<RNTextInput>(null)
const [password, setPassword] = React.useState(features.prefillWalletInfo ? debugWalletInfo.PASSWORD : '')

useFocusEffect(
React.useCallback(() => {
track.createWalletDetailsStepViewed()
}, [track]),
)

const {mnemonic, networkId, publicKeyHex, walletImplementationId} = useSetupWallet()
const plate = usePlate({networkId, publicKeyHex})

const [name, setName] = React.useState(features.prefillWalletInfo ? debugWalletInfo.WALLET_NAME : '')

const nameErrors = validateWalletName(name, null, walletNames ?? [])
const walletNameErrorText = getWalletNameError(
{tooLong: strings.tooLong, nameAlreadyTaken: strings.nameAlreadyTaken, mustBeFilled: strings.mustBeFilled},
nameErrors,
)

const passwordRef = React.useRef<RNTextInput>(null)
const [password, setPassword] = React.useState(features.prefillWalletInfo ? debugWalletInfo.PASSWORD : '')

const passwordConfirmationRef = React.useRef<RNTextInput>(null)
const [passwordConfirmation, setPasswordConfirmation] = React.useState(
features.prefillWalletInfo ? debugWalletInfo.PASSWORD : '',
Expand All @@ -101,11 +99,40 @@ export const WalletDetailsScreen = () => {
? strings.repeatPasswordInputError
: undefined

const intl = useIntl()
const {createWallet, isLoading, isSuccess} = useCreateWallet({
onSuccess: () => {
const {
openWallet,
isLoading: isOpenWalletLoading,
isSuccess: isOpenWalletSuccess,
} = useOpenWallet({
onSuccess: ([wallet, walletMeta]) => {
selectWalletMeta(walletMeta)
selectWallet(wallet)
navigateToTxHistory()
},
onError: (error) => {
InteractionManager.runAfterInteractions(() => {
return error instanceof InvalidState
? showErrorDialog(errorMessages.walletStateInvalid, intl)
: error instanceof NetworkError
? showErrorDialog(errorMessages.networkError, intl)
: showErrorDialog(errorMessages.generalError, intl, {message: error.message})
})
},
})

const {
createWallet,
isLoading: isCreateWalletLoading,
isSuccess: isCreateWalletSuccess,
} = useCreateWallet({
onSuccess: async (wallet) => {
const walletStorage = storage.join('wallet/')
const walletMeta = await walletStorage.getItem(wallet.id, parseWalletMeta)

if (!walletMeta) throw new Error('invalid wallet meta')

openWallet(walletMeta)
track.createWalletDetailsSettled()
resetToWalletSelection()
},
onError: (error) => {
InteractionManager.runAfterInteractions(() => {
Expand All @@ -116,6 +143,14 @@ export const WalletDetailsScreen = () => {
},
})

const nameErrors = validateWalletName(name, null, walletNames && !isCreateWalletSuccess ? walletNames : [])
const walletNameErrorText = getWalletNameError(
{tooLong: strings.tooLong, nameAlreadyTaken: strings.nameAlreadyTaken, mustBeFilled: strings.mustBeFilled},
nameErrors,
)

const isLoading = isCreateWalletLoading || isOpenWalletLoading

const handleCreateWallet = React.useCallback(() => {
track.createWalletDetailsSubmitted()

Expand Down Expand Up @@ -181,7 +216,7 @@ export const WalletDetailsScreen = () => {
checksumLine={1}
linesOfText={[
strings.walletChecksumModalCardFirstItem,
strings.walletChecksumModalCardSecondItem,
strings.walletChecksumModalCardSecondItem(plate.accountPlate.TextPart),
strings.walletChecksumModalCardThirdItem,
]}
/>
Expand Down Expand Up @@ -233,6 +268,7 @@ export const WalletDetailsScreen = () => {
onSubmitEditing={() => passwordRef.current?.focus()}
testID="walletNameInput"
autoComplete="off"
disabled={isLoading}
showErrorOnBlur
/>

Expand All @@ -249,6 +285,7 @@ export const WalletDetailsScreen = () => {
onSubmitEditing={() => passwordConfirmationRef.current?.focus()}
testID="walletPasswordInput"
autoComplete="off"
disabled={isLoading}
showErrorOnBlur
/>

Expand All @@ -265,6 +302,7 @@ export const WalletDetailsScreen = () => {
errorText={passwordConfirmationErrorText}
testID="walletRepeatPasswordInput"
autoComplete="off"
disabled={isLoading}
showErrorOnBlur
/>

Expand All @@ -289,8 +327,8 @@ export const WalletDetailsScreen = () => {
<Button
title={strings.next}
style={styles.button}
onPress={isLoading || isSuccess ? NOOP : () => handleCreateWallet()}
disabled={Object.keys(passwordErrors).length > 0 || Object.keys(nameErrors).length > 0}
onPress={isLoading || isOpenWalletSuccess ? NOOP : () => handleCreateWallet()}
disabled={isLoading || Object.keys(passwordErrors).length > 0 || Object.keys(nameErrors).length > 0}
/>

<Space height="s" />
Expand Down

0 comments on commit ae5ac71

Please sign in to comment.