Merge branch 'hn.validator-onboarding' of https://github.com/nimbus-gui/nimbus-gui into hn.validator-onboarding

This commit is contained in:
Hristo Nedelkov 2023-08-29 09:34:10 +03:00
commit eb2cca5d9c
9 changed files with 60 additions and 41 deletions

View File

@ -9,3 +9,9 @@ export const BAD_STORAGE_TEXT =
export const BAD_CPU_CLOCK_RATE_TEXT = 'Your CPU clock rate is below the recommended 2.4GHz.' export const BAD_CPU_CLOCK_RATE_TEXT = 'Your CPU clock rate is below the recommended 2.4GHz.'
export const BAD_RAM_MEMORY_TEXT = 'There is insufficient RAM required for selected services.' export const BAD_RAM_MEMORY_TEXT = 'There is insufficient RAM required for selected services.'
export const BAD_NETWORK_TEXT = 'Network Latency is high.' export const BAD_NETWORK_TEXT = 'Network Latency is high.'
/* Validator Onboarding */
export const KEY_FILES = 'Key Files'
export const RECOVERY_PHRASE = 'Recovery Phrase'
export const BOTH_KEY_AND_RECOVERY = 'Both Key Files & Recovery Phrase'

View File

@ -1,16 +1,16 @@
import type { Meta, StoryObj } from '@storybook/react' import type { Meta, StoryObj } from '@storybook/react'
import PasswordFields from './PasswordFields' import KeyFiles from './KeyFiles'
const meta = { const meta = {
title: 'ValidatorOnboarding/PasswordFields', title: 'ValidatorOnboarding/KeyFiles',
component: PasswordFields, component: KeyFiles,
parameters: { parameters: {
layout: 'centered', layout: 'centered',
}, },
tags: ['autodocs'], tags: ['autodocs'],
argTypes: {}, argTypes: {},
} satisfies Meta<typeof PasswordFields> } satisfies Meta<typeof KeyFiles>
export default meta export default meta
type Story = StoryObj<typeof meta> type Story = StoryObj<typeof meta>

View File

@ -1,11 +1,11 @@
import { XStack, YStack } from 'tamagui' import { XStack, YStack } from 'tamagui'
import { Button, Input, Text } from '@status-im/components' import { Button, InformationBox, Input, Text } from '@status-im/components'
import { ClearIcon } from '@status-im/icons' import { ClearIcon, CloseCircleIcon } from '@status-im/icons'
import BorderBox from '../../../components/General/BorderBox'
import { useState } from 'react' import { useState } from 'react'
const PasswordFields = () => { import BorderBox from '../../../components/General/BorderBox'
const KeyFiles = () => {
const [encryptedPassword, setEncryptedPassword] = useState('') const [encryptedPassword, setEncryptedPassword] = useState('')
const [confirmEncryptedPassword, setConfirmEncryptedPassword] = useState('') const [confirmEncryptedPassword, setConfirmEncryptedPassword] = useState('')
@ -75,8 +75,13 @@ const PasswordFields = () => {
</BorderBox> </BorderBox>
</XStack> </XStack>
<Button onPress={generateKeyFilesHandler}>Generate Key files</Button> <Button onPress={generateKeyFilesHandler}>Generate Key files</Button>
<InformationBox
message="You should see that you have one keystore per validator. This keystore contains your signing key, encrypted with your password. Warning: Do not store keys on multiple (backup) validator clients at once"
variant="error"
icon={<CloseCircleIcon size={20} />}
/>
</YStack> </YStack>
) )
} }
export default PasswordFields export default KeyFiles

View File

@ -1,18 +1,24 @@
import { YStack } from 'tamagui' import { YStack } from 'tamagui'
import KeyGenerationHeader from './KeyGenerationHeader' import KeyGenerationHeader from './KeyGenerationHeader'
import RecoveryMechanism from './RecoveryMechanism' import RecoveryMechanism from './RecoveryMechanism'
import { Button, InformationBox, Text } from '@status-im/components' import { Text } from '@status-im/components'
import { CloseCircleIcon } from '@status-im/icons' import KeyFiles from './KeyFiles'
import PasswordFields from './PasswordFields'
import { useState } from 'react' import { useState } from 'react'
import RecoveryPhrase from './RecoveryPhrase'
import { KEY_FILES, RECOVERY_PHRASE } from '../../../constants'
const KeyGeneration = () => { const KeyGeneration = () => {
const [selectedRecoveryMechanism, setSelectedRecoveryMechanism] = useState('Key Files') const [selectedRecoveryMechanism, setSelectedRecoveryMechanism] = useState(KEY_FILES)
const handleRecoveryMechanismChange = (value: string) => { const handleRecoveryMechanismChange = (value: string) => {
setSelectedRecoveryMechanism(value) setSelectedRecoveryMechanism(value)
} }
const isKeyFiles = recoveryMechanism === KEY_FILES || recoveryMechanism === BOTH_KEY_AND_RECOVERY
const isRecoveryPhrase =
recoveryMechanism === RECOVERY_PHRASE || recoveryMechanism === BOTH_KEY_AND_RECOVERY
return ( return (
<YStack space={'$2'} style={{ width: '100%', padding: '16px 32px', alignItems: 'start' }}> <YStack space={'$2'} style={{ width: '100%', padding: '16px 32px', alignItems: 'start' }}>
<KeyGenerationHeader /> <KeyGenerationHeader />
@ -23,26 +29,8 @@ const KeyGeneration = () => {
<Text size={27} weight={'semibold'}> <Text size={27} weight={'semibold'}>
4 Validators 4 Validators
</Text> </Text>
{selectedRecoveryMechanism === 'Key Files' && ( {isKeyFiles && <KeyFiles />}
<> {isRecoveryPhrase && <RecoveryPhrase />}
<PasswordFields />
<InformationBox
message="You should see that you have one keystore per validator. This keystore contains your signing key, encrypted with your password. Warning: Do not store keys on multiple (backup) validator clients at once"
variant="error"
icon={<CloseCircleIcon size={20} />}
/>
</>
)}
{selectedRecoveryMechanism === 'Recovery Phrase' && (
<>
<Button>Reveal Recovery Phrase</Button>
<InformationBox
message="Write down and keep your Secret Recovery Phrase in a secure place. Make sure no one is looking at your screen."
variant="error"
icon={<CloseCircleIcon size={20} />}
/>
</>
)}
</YStack> </YStack>
) )
} }

View File

@ -1,6 +1,7 @@
import type { Meta, StoryObj } from '@storybook/react' import type { Meta, StoryObj } from '@storybook/react'
import RecoveryMechanism from './RecoveryMechanism' import RecoveryMechanism from './RecoveryMechanism'
import { KEY_FILES } from '../../../constants'
const meta = { const meta = {
title: 'ValidatorOnboarding/RecoveryMechanism', title: 'ValidatorOnboarding/RecoveryMechanism',
@ -17,7 +18,7 @@ type Story = StoryObj<typeof meta>
export const Page: Story = { export const Page: Story = {
args: { args: {
selectedRecoveryMechanism: 'Key Files', selectedRecoveryMechanism: KEY_FILES,
handleRecoveryMechanismChange: () => {}, handleRecoveryMechanismChange: () => {},
}, },
} }

View File

@ -1,6 +1,7 @@
import { Text } from '@status-im/components' import { Text } from '@status-im/components'
import { XStack, YStack } from 'tamagui' import { XStack, YStack } from 'tamagui'
import RecoveryMechanismCard from './RecoveryMechanismCard' import RecoveryMechanismCard from './RecoveryMechanismCard'
import { BOTH_KEY_AND_RECOVERY, KEY_FILES, RECOVERY_PHRASE } from '../../../constants'
type RecoveryMechanismProps = { type RecoveryMechanismProps = {
selectedRecoveryMechanism: string selectedRecoveryMechanism: string
@ -18,17 +19,17 @@ const RecoveryMechanism = ({
</Text> </Text>
<XStack space={'$4'} style={{ justifyContent: 'space-between', marginTop: '40px' }}> <XStack space={'$4'} style={{ justifyContent: 'space-between', marginTop: '40px' }}>
<RecoveryMechanismCard <RecoveryMechanismCard
value="Key Files" value={KEY_FILES}
selectedRecoveryMechanism={selectedRecoveryMechanism} selectedRecoveryMechanism={selectedRecoveryMechanism}
handleRecoveryMechanismChange={handleRecoveryMechanismChange} handleRecoveryMechanismChange={handleRecoveryMechanismChange}
/> />
<RecoveryMechanismCard <RecoveryMechanismCard
value="Recovery Phrase" value={RECOVERY_PHRASE}
selectedRecoveryMechanism={selectedRecoveryMechanism} selectedRecoveryMechanism={selectedRecoveryMechanism}
handleRecoveryMechanismChange={handleRecoveryMechanismChange} handleRecoveryMechanismChange={handleRecoveryMechanismChange}
/> />
<RecoveryMechanismCard <RecoveryMechanismCard
value="Both Key Files & Recovery Phrase" value={BOTH_KEY_AND_RECOVERY}
selectedRecoveryMechanism={selectedRecoveryMechanism} selectedRecoveryMechanism={selectedRecoveryMechanism}
handleRecoveryMechanismChange={handleRecoveryMechanismChange} handleRecoveryMechanismChange={handleRecoveryMechanismChange}
/> />

View File

@ -1,6 +1,7 @@
import type { Meta, StoryObj } from '@storybook/react' import type { Meta, StoryObj } from '@storybook/react'
import RecoveryMechanismCard from './RecoveryMechanismCard' import RecoveryMechanismCard from './RecoveryMechanismCard'
import { KEY_FILES } from '../../../constants'
const meta = { const meta = {
title: 'ValidatorOnboarding/RecoveryMechanismCard', title: 'ValidatorOnboarding/RecoveryMechanismCard',
@ -17,8 +18,8 @@ type Story = StoryObj<typeof meta>
export const Page: Story = { export const Page: Story = {
args: { args: {
value: 'Key Files', value: KEY_FILES,
selectedRecoveryMechanism: 'Key Files', selectedRecoveryMechanism: KEY_FILES,
handleRecoveryMechanismChange: () => {}, handleRecoveryMechanismChange: () => {},
}, },
} }

View File

@ -0,0 +1,18 @@
import { YStack } from 'tamagui'
import { Button, InformationBox } from '@status-im/components'
import { CloseCircleIcon } from '@status-im/icons'
const RecoveryPhrase = () => {
return (
<YStack space={'$2'}>
<Button>Reveal Recovery Phrase</Button>
<InformationBox
message="Write down and keep your Secret Recovery Phrase in a secure place. Make sure no one is looking at your screen."
variant="error"
icon={<CloseCircleIcon size={20} />}
/>
</YStack>
)
}
export default RecoveryPhrase

View File

@ -11,7 +11,6 @@ import ValidatorBoxWrapper from './ValidatorBoxWrapper/ValidatorBoxWrapper'
import { Button } from '@status-im/components' import { Button } from '@status-im/components'
import { useNavigate } from 'react-router-dom' import { useNavigate } from 'react-router-dom'
import ValidatorSetupInstall from './ValidatorSetup/ValidatorInstall' import ValidatorSetupInstall from './ValidatorSetup/ValidatorInstall'
import ValidatorSetup from './ValidatorSetup/ValidatorSetup'
const ValidatorOnboarding = () => { const ValidatorOnboarding = () => {
const [activeStep, setActiveStep] = useState(0) const [activeStep, setActiveStep] = useState(0)