123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- // Copyright 2017-2019 @polkadot/app-accounts authors & contributors
- // This software may be modified and distributed under the terms
- // of the Apache-2.0 license. See the LICENSE file for details.
- import { I18nProps } from '@polkadot/react-components/types';
- import FileSaver from 'file-saver';
- import React from 'react';
- import { AddressRow, Button, Modal, Password, TxComponent } from '@polkadot/react-components';
- import { ActionStatus } from '@polkadot/react-components/Status/types';
- import keyring from '@polkadot/ui-keyring';
- import { isPasswordValid } from '@polkadot/joy-utils/accounts';
- import translate from '../translate';
- interface Props extends I18nProps {
- onClose: () => void;
- address: string;
- }
- interface State {
- isPassValid: boolean;
- password: string;
- }
- class Backup extends TxComponent<Props, State> {
- public state: State = {
- isPassValid: true,
- password: ''
- };
- public render (): React.ReactNode {
- const { t } = this.props;
- return (
- <Modal
- className='app--accounts-Modal'
- dimmer='inverted'
- open
- >
- <Modal.Header>{t('Backup account')}</Modal.Header>
- {this.renderContent()}
- {this.renderButtons()}
- </Modal>
- );
- }
- private renderButtons (): React.ReactNode {
- const { onClose, t } = this.props;
- const { isPassValid } = this.state;
- return (
- <Modal.Actions>
- <Button.Group>
- <Button
- icon='cancel'
- isNegative
- label={t('Cancel')}
- onClick={onClose}
- />
- <Button.Or />
- <Button
- icon='download'
- isDisabled={!isPassValid}
- label={t('Download')}
- onClick={this.doBackup}
- ref={this.button}
- />
- </Button.Group>
- </Modal.Actions>
- );
- }
- private renderContent (): React.ReactNode {
- const { address, t } = this.props;
- const { isPassValid, password } = this.state;
- return (
- <Modal.Content>
- <AddressRow
- isInline
- value={address}
- >
- <p>{t('An encrypted backup file will be created once you have pressed the "Download" button. This can be used to re-import your account on any other machine.')}</p>
- <p>{t('Save this backup file in a secure location. Additionally, the password associated with this account is needed together with this backup file in order to restore your account.')}</p>
- <div>
- <Password
- help={t('The account password as specified when creating the account. This is used to encrypt the backup file and subsequently decrypt it when restoring the account.')}
- isError={!isPassValid}
- label={t('password')}
- onChange={this.onChangePass}
- onEnter={this.submit}
- tabIndex={0}
- value={password}
- />
- </div>
- </AddressRow>
- </Modal.Content>
- );
- }
- private doBackup = (): void => {
- const { onClose, address, t } = this.props;
- const { password } = this.state;
- if (!address) {
- return;
- }
- const status: Partial<ActionStatus> = {
- action: 'backup'
- };
- try {
- const addressKeyring = address && keyring.getPair(address);
- const json = addressKeyring && keyring.backupAccount(addressKeyring, password);
- const blob = new Blob([JSON.stringify(json)], { type: 'application/json; charset=utf-8' });
- status.account = address;
- status.status = blob ? 'success' : 'error';
- status.message = t('account backed up');
- FileSaver.saveAs(blob, `${address}.json`);
- } catch (error) {
- this.setState({ isPassValid: true });
- console.error(error);
- status.status = 'error';
- status.message = error.message;
- return;
- }
- onClose();
- }
- private onChangePass = (password: string): void => {
- this.setState({
- isPassValid: isPasswordValid(password),
- password
- });
- }
- }
- export default translate(Backup);
|