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

641 Validate Mnemonic Words on Wallet Import #739

Merged
4 changes: 2 additions & 2 deletions src/components/MnemonicPhraseInput.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect, useRef, useState } from 'react'
import MnemonicWordInput from './MnemonicWordInput'
import { Bip39MnemonicWordInput } from './MnemonicWordInput'

interface MnemonicPhraseInputProps {
columns?: number
Expand Down Expand Up @@ -44,7 +44,7 @@ export default function MnemonicPhraseInput({
const isCurrentActive = wordIndex === activeIndex
return (
<div className="col" key={wordIndex}>
<MnemonicWordInput
<Bip39MnemonicWordInput
forwardRef={(el: HTMLInputElement) => (inputRefs.current[wordIndex] = el)}
index={wordIndex}
value={givenWord}
Expand Down
37 changes: 37 additions & 0 deletions src/components/MnemonicWordInput.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { render, screen } from '../testUtils'
import { Bip39MnemonicWordInput, MnemonicWordInputProps } from './MnemonicWordInput'

const NOOP = () => {}

describe('<Bip39MnemonicWordInput />', () => {
const validBip39MnemonicWord = 'abandon'
const invalidBip39MnemonicWord = 'not a bip39 word!'

const setup = (props: MnemonicWordInputProps) => {
render(<Bip39MnemonicWordInput {...props} />)
}

it('should render without errors', async () => {
setup({ index: 0, value: '', setValue: NOOP })

expect(await screen.findByTestId('mnemonic-word-input')).toBeVisible()
})

it('should report if input is NOT included in the BIP-39 wordlist', async () => {
setup({ index: 0, value: invalidBip39MnemonicWord, setValue: NOOP })

const input = await screen.findByTestId('mnemonic-word-input')
expect(input).toBeVisible()
expect(input).toHaveClass('is-invalid')
expect(input).not.toHaveClass('is-valid')
})

it('should report if input IS INCLUDED in the BIP-39 wordlist', async () => {
setup({ index: 0, value: validBip39MnemonicWord, setValue: NOOP })

const input = await screen.findByTestId('mnemonic-word-input')
expect(input).toBeVisible()
expect(input).toHaveClass('is-valid')
expect(input).not.toHaveClass('is-invalid')
})
})
13 changes: 10 additions & 3 deletions src/components/MnemonicWordInput.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { useMemo } from 'react'
import * as rb from 'react-bootstrap'
import { useTranslation } from 'react-i18next'
import { MNEMONIC_WORDS } from '../constants/bip39words'
import styles from './MnemonicWordInput.module.css'

interface MnemonicWordInputProps {
forwardRef: (el: HTMLInputElement) => void
export interface MnemonicWordInputProps {
forwardRef?: (el: HTMLInputElement) => void
index: number
value: string
setValue: (value: string, index: number) => void
Expand All @@ -28,6 +30,7 @@ const MnemonicWordInput = ({
<rb.InputGroup>
<rb.InputGroup.Text className={styles.seedwordIndexBackup}>{index + 1}.</rb.InputGroup.Text>
<rb.Form.Control
data-testid="mnemonic-word-input"
ref={forwardRef}
type="text"
placeholder={`${t('create_wallet.placeholder_seed_word_input')} ${index + 1}`}
Expand All @@ -45,4 +48,8 @@ const MnemonicWordInput = ({
)
}

export default MnemonicWordInput
export const Bip39MnemonicWordInput = ({ value, ...props }: MnemonicWordInputProps) => {
const isBip39Value = useMemo(() => MNEMONIC_WORDS.includes(value), [value])

return <MnemonicWordInput {...props} value={value} isValid={isBip39Value && (props.isValid ?? true)} />
}
Loading
Loading