Skip to content

Commit

Permalink
Merge pull request #31 from CoongCrafts/coong/feature/import-secret-p…
Browse files Browse the repository at this point in the history
…hrase

Restore wallet by importing secret phrase
  • Loading branch information
sinzii authored Apr 14, 2023
2 parents 99915d3 + 2dd1be7 commit fd5fc79
Show file tree
Hide file tree
Showing 20 changed files with 550 additions and 128 deletions.
8 changes: 7 additions & 1 deletion packages/ui/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,27 @@
"Finally, back up your secret recovery phrase": "",
"Finish": "",
"First, choose your wallet password": "",
"First, enter your secret recovery phrase": "",
"I have backed up my recovery phrase": "",
"If you open this page by accident, it's safe to close it now.": "",
"InternalError": "Internal error",
"Invalid Request": "",
"Invalid request": "",
"Invalid secret recovery phrase": "",
"InvalidMessageFormat": "Invalid message format",
"KeypairNotFound": "Keypair not found",
"KeyringLocked": "The keyring is locked, please unlock the wallet first",
"KeyringNotInitialized": "Keyring is not initialized",
"Language": "",
"Lastly, confirm your wallet password": "",
"Light": "",
"Lock the wallet": "",
"Make sure you are in a safe place.": "",
"My first account": "",
"New Account": "",
"New account name": "",
"Next": "",
"Next, choose your wallet password": "",
"Next, confirm your wallet password": "",
"No accounts found in wallet": "",
"No accounts meet search query:": "",
Expand All @@ -61,8 +65,10 @@
"PasswordIncorrect": "Password incorrect",
"PasswordRequired": "Password required",
"Reset wallet": "",
"Restore existing wallet": "",
"Restore Existing Wallet": "",
"Search by name": "",
"Secret recovery phrase": "",
"Secret recovery phrase or password are missing": "",
"Select all": "",
"Select the accounts you'd like to connect": "",
"Set up new wallet": "",
Expand Down
53 changes: 0 additions & 53 deletions packages/ui/src/components/pages/NewWallet/index.tsx

This file was deleted.

5 changes: 0 additions & 5 deletions packages/ui/src/components/pages/NewWallet/types.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import { useDispatch } from 'react-redux';
import { useToggle } from 'react-use';
import { Close } from '@mui/icons-material';
import { AppBar, Button, Container, Dialog, DialogContent, IconButton, Toolbar } from '@mui/material';
import { NewWalletScreenStep } from 'components/pages/NewWallet/types';
import SetupWalletDialogContent from 'components/pages/Request/RequestAccess/SetupWalletDialogContent';
import { setupWalletActions } from 'redux/slices/setup-wallet';
import { Props } from 'types';
import { Props, NewWalletScreenStep, RestoreWalletScreenStep } from 'types';

const SetupWalletButton: FC<Props> = ({ className = '' }) => {
const [open, toggleOpen] = useToggle(false);
Expand All @@ -20,7 +19,7 @@ const SetupWalletButton: FC<Props> = ({ className = '' }) => {

const doClose = () => {
toggleOpen(false);
dispatch(setupWalletActions.setStep(NewWalletScreenStep.ChooseWalletPassword));
dispatch(setupWalletActions.resetState());
};

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { FC, useState } from 'react';
import NewWallet from 'components/pages/NewWallet';
import NewWallet from 'components/pages/SetupWallet/NewWallet';
import RestoreWallet from 'components/pages/SetupWallet/RestoreWallet';
import Welcome from 'components/pages/Welcome';
import { Props } from 'types';

Expand All @@ -12,11 +13,20 @@ enum ViewStep {
const SetupWalletDialogContent: FC<Props> = () => {
const [viewStep, setViewStep] = useState<ViewStep>(ViewStep.WELCOME);

const onWalletSetup = () => {};

switch (viewStep) {
case ViewStep.CREATE_NEW_WALLET:
return <NewWallet onWalletSetup={() => {}} />;
return <NewWallet onWalletSetup={onWalletSetup} />;
case ViewStep.RESTORE_WALLET:
return <RestoreWallet onWalletSetup={onWalletSetup} />;
default:
return <Welcome onCreateNewWallet={() => setViewStep(ViewStep.CREATE_NEW_WALLET)} />;
return (
<Welcome
onCreateNewWallet={() => setViewStep(ViewStep.CREATE_NEW_WALLET)}
onRestoreExistingWallet={() => setViewStep(ViewStep.RESTORE_WALLET)}
/>
);
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,8 @@ describe('RequestAccess', () => {

expect(await screen.findByRole('dialog')).toBeVisible();
expect(await screen.findByText(/Set up new wallet/)).toBeVisible();
expect(await screen.findByRole('button', { name: /Create New Wallet/ })).toBeVisible();
expect(await screen.findByRole('button', { name: /Restore Existing Wallet/ })).toBeDisabled();
expect(await screen.findByRole('button', { name: /Create New Wallet/ })).toBeEnabled();
expect(await screen.findByRole('button', { name: /Restore Existing Wallet/ })).toBeEnabled();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import EmptySpace from 'components/shared/misc/EmptySpace';
import { setupWalletActions } from 'redux/slices/setup-wallet';
import { Props } from 'types';

const ChooseWalletPassword: FC<Props> = ({ className = '' }: Props) => {
interface ChooseWalletPasswordProps extends Props {
nextStep: () => void;
prevStep?: () => void;
}

const ChooseWalletPassword: FC<ChooseWalletPasswordProps> = ({ className = '', nextStep, prevStep }) => {
const dispatch = useDispatch();
const [password, setPassword] = useState('');
const [validation, setValidation] = useState('');
Expand All @@ -28,6 +33,8 @@ const ChooseWalletPassword: FC<Props> = ({ className = '' }: Props) => {
}

dispatch(setupWalletActions.setPassword(password));

nextStep && nextStep();
};

const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
Expand All @@ -36,7 +43,9 @@ const ChooseWalletPassword: FC<Props> = ({ className = '' }: Props) => {

return (
<div className={className}>
<h3>{t('First, choose your wallet password')}</h3>
<h3>
{!prevStep ? t<string>('First, choose your wallet password') : t<string>('Next, choose your wallet password')}
</h3>
<p className='mb-6'>
<Trans>
Your password will be used to encrypt accounts as well as unlock the wallet, make sure to pick a strong &
Expand All @@ -55,9 +64,16 @@ const ChooseWalletPassword: FC<Props> = ({ className = '' }: Props) => {
error={!!validation}
helperText={validation || <EmptySpace />}
/>
<Button type='submit' fullWidth disabled={!password || !!validation} size='large'>
{t<string>('Next')}
</Button>
<div className='flex flex-row gap-4'>
{prevStep && (
<Button variant='text' onClick={prevStep}>
{t<string>('Back')}
</Button>
)}
<Button type='submit' fullWidth disabled={!password || !!validation} size='large'>
{t<string>('Next')}
</Button>
</div>
</form>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
import { ChangeEvent, FC, FormEvent, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
import { LoadingButton } from '@mui/lab';
import { Button, TextField } from '@mui/material';
import { NewWalletScreenStep } from 'components/pages/NewWallet/types';
import EmptySpace from 'components/shared/misc/EmptySpace';
import { setupWalletActions } from 'redux/slices/setup-wallet';
import { RootState } from 'redux/store';
import { Props } from 'types';

const ConfirmWalletPassword: FC<Props> = ({ className = '' }: Props) => {
const dispatch = useDispatch();
interface ConfirmWalletPasswordProps extends Props {
nextStep: () => void;
nextStepLabel?: string;
nextStepLoading?: boolean;
prevStep: () => void;
}

const ConfirmWalletPassword: FC<ConfirmWalletPasswordProps> = ({
className = '',
nextStep,
nextStepLabel = 'Next',
nextStepLoading,
prevStep,
}) => {
const { password } = useSelector((state: RootState) => state.setupWallet);
const [passwordConfirmation, setPasswordConfirmation] = useState('');
const [notMatch, setNotMatch] = useState<boolean>(true);
Expand All @@ -26,11 +37,7 @@ const ConfirmWalletPassword: FC<Props> = ({ className = '' }: Props) => {
return;
}

dispatch(setupWalletActions.setStep(NewWalletScreenStep.BackupSecretRecoveryPhrase));
};

const back = () => {
dispatch(setupWalletActions.setStep(NewWalletScreenStep.ChooseWalletPassword));
nextStep && nextStep();
};

const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
Expand All @@ -39,7 +46,11 @@ const ConfirmWalletPassword: FC<Props> = ({ className = '' }: Props) => {

return (
<div className={className}>
<h3>{t<string>('Next, confirm your wallet password')}</h3>
<h3>
{nextStepLabel === 'Next'
? t<string>('Next, confirm your wallet password')
: t<string>('Lastly, confirm your wallet password')}
</h3>
<p className='mb-6'>{t<string>('Type again your chosen password to ensure you remember it.')}</p>

<form className='flex flex-col gap-2' noValidate autoComplete='off' onSubmit={next}>
Expand All @@ -54,12 +65,18 @@ const ConfirmWalletPassword: FC<Props> = ({ className = '' }: Props) => {
helperText={!!passwordConfirmation && notMatch ? t<string>('Password does not match') : <EmptySpace />}
/>
<div className='flex flex-row gap-4'>
<Button variant='text' onClick={back}>
<Button variant='text' onClick={prevStep}>
{t<string>('Back')}
</Button>
<Button type='submit' fullWidth disabled={notMatch} size='large'>
{t<string>('Next')}
</Button>
<LoadingButton
type='submit'
fullWidth
disabled={notMatch}
loading={nextStepLoading}
size='large'
variant='contained'>
{t<string>(nextStepLabel)}
</LoadingButton>
</div>
</form>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,26 @@
import { ChangeEvent, FC, FormEvent, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
import { useNavigate } from 'react-router-dom';
import { useEffectOnce } from 'react-use';
import { generateMnemonic } from '@polkadot/util-crypto/mnemonic/bip39';
import { LoadingButton } from '@mui/lab';
import { Button, Checkbox, FormControlLabel, FormGroup, styled } from '@mui/material';
import { NewWalletScreenStep } from 'components/pages/NewWallet/types';
import { useWalletState } from 'providers/WalletStateProvider';
import { appActions } from 'redux/slices/app';
import { Button, Checkbox, FormControlLabel, FormGroup } from '@mui/material';
import useSetupWallet from 'hooks/wallet/useSetupWallet';
import { setupWalletActions } from 'redux/slices/setup-wallet';
import { RootState } from 'redux/store';
import { Props } from 'types';
import { Props, NewWalletScreenStep } from 'types';

interface BackupSecretRecoveryPhraseProps extends Props {
onWalletSetup?: () => void;
}

const BackupSecretRecoveryPhrase: FC<BackupSecretRecoveryPhraseProps> = ({ className = '', onWalletSetup }) => {
const { keyring } = useWalletState();
const dispatch = useDispatch();
const navigate = useNavigate();
const { password } = useSelector((state: RootState) => state.setupWallet);
const [checked, setChecked] = useState<boolean>(false);
const [loading, setLoading] = useState<boolean>();
const [secretPhrase, setSecretPhrase] = useState<string>();
const { t } = useTranslation();
const { setup, loading } = useSetupWallet({ secretPhrase, password, onWalletSetup });

useEffectOnce(() => {
setSecretPhrase(generateMnemonic(12));
Expand All @@ -34,29 +29,11 @@ const BackupSecretRecoveryPhrase: FC<BackupSecretRecoveryPhraseProps> = ({ class
const doSetupWallet = (e: FormEvent) => {
e.preventDefault();

setLoading(true);

setTimeout(async () => {
if (!password) {
return;
}

await keyring.initialize(secretPhrase!, password);
await keyring.createNewAccount(t<string>('My first account'), password);

dispatch(appActions.seedReady());
dispatch(appActions.unlock());

if (onWalletSetup) {
onWalletSetup();
} else {
navigate('/');
}
}, 500); // intentionally!
setup();
};

const back = () => {
dispatch(setupWalletActions.setStep(NewWalletScreenStep.ChooseWalletPassword));
dispatch(setupWalletActions.setNewWalletScreenStep(NewWalletScreenStep.ChooseWalletPassword));
};

const handleCheckbox = (event: ChangeEvent<HTMLInputElement>) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { UserEvent } from '@testing-library/user-event/setup/setup';
import { initializeKeyring, newUser, render, screen, waitFor } from '__tests__/testUtils';
import { NewWalletScreenStep } from 'types';
import NewWallet from '../index';
import { NewWalletScreenStep } from '../types';

const navigate = vi.fn();

Expand Down
Loading

0 comments on commit fd5fc79

Please sign in to comment.