Skip to content
AccountImportOptions.js 4.39 KiB
Newer Older
YJ's avatar
YJ committed
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
//
// SPDX-License-Identifier: BSD-3-Clause

YJ's avatar
YJ committed
import React, { Component } from 'react';
import { Card, Form as FetherForm } from 'fether-ui';
import { accountsInfo$, withoutLoading } from '@parity/light.js';
import light from '@parity/light.js-react';
YJ's avatar
YJ committed
import { inject, observer } from 'mobx-react';

@light({
  accountsInfo: () => accountsInfo$().pipe(withoutLoading())
})
YJ's avatar
YJ committed
@inject('createAccountStore')
@observer
class AccountImportOptions extends Component {
  state = {
YJ's avatar
YJ committed
    isLoading: false,
YJ's avatar
YJ committed
  };

  handleNextStep = async () => {
    const {
      history,
YJ's avatar
YJ committed
    } = this.props;
    const currentStep = pathname.slice(-1);
    history.push(`/accounts/new/${+currentStep + 1}`);
  };

  handlePhraseChange = ({ target: { value: phrase } }) => {
    this.setState({ phrase });
YJ's avatar
YJ committed
  };

  handleSubmitPhrase = async () => {
    const phrase = this.state.phrase.trim();
YJ's avatar
YJ committed
    const {
      createAccountStore: { setPhrase }
YJ's avatar
YJ committed
    } = this.props;

    this.setState({ isLoading: true, phrase });
YJ's avatar
YJ committed
    try {

      const addressForPhrase = createAccountStore.address.toLowerCase();

      if (this.hasExistingAddressForImport(addressForPhrase)) {
        return;
      }

      this.setState({
        isLoading: false,
        error:
          'The passphrase was not recognized. Please verify that you entered your passphrase correctly.'
      });
  handleChangeFile = async jsonString => {
    const {
      createAccountStore: { setJsonString }
    } = this.props;
YJ's avatar
YJ committed

    this.setState({ isLoading: true });
Luke Schoen's avatar
Luke Schoen committed
      const json = JSON.parse(jsonString);
      const jsonAddress = `0x${json['address'].toLowerCase()}`;
      if (this.hasExistingAddressForImport(jsonAddress)) {
      await setJsonString(jsonString);
      this.handleNextStep();
YJ's avatar
YJ committed
    } catch (error) {
      this.setState({
        error:
          'Invalid file. Please check this is your actual Parity backup JSON keyfile and try again.'
      });
YJ's avatar
YJ committed
    }
  };

  hasExistingAddressForImport = addressForImport => {
    const { accountsInfo } = this.props;
    const isExistingAddress = Object.keys(accountsInfo)
      .map(address => address && address.toLowerCase())
      .includes(addressForImport);

    if (isExistingAddress) {
      this.setState({
        isLoading: false,
        error: `Account already loaded. Address ${addressForImport} is already in the account list`
      });
    }

    return isExistingAddress;
  };

YJ's avatar
YJ committed
  render () {
    const {
      history,
      location: { pathname }
    } = this.props;
    const { error, phrase } = this.state;
YJ's avatar
YJ committed
    const currentStep = pathname.slice(-1);

YJ's avatar
YJ committed
    const jsonCard = (
YJ's avatar
YJ committed
      <div key='createAccount'>
        <div className='text -centered'>
          <p> Recover from JSON Keyfile </p>

          <FetherForm.InputFile
            label='JSON Backup Keyfile'
            onChangeFile={this.handleChangeFile}
            required
          />
        </div>
      </div>
YJ's avatar
YJ committed
    );
YJ's avatar
YJ committed

YJ's avatar
YJ committed
    const phraseCard = (
YJ's avatar
YJ committed
      <div key='importBackup'>
        <div className='text -centered'>
          <p>Recover from Seed Phrase</p>

YJ's avatar
YJ committed
          <FetherForm.Field
            as='textarea'
            label='Recovery phrase'
            onChange={this.handlePhraseChange}
YJ's avatar
YJ committed
            required
YJ's avatar
YJ committed
          />

          {this.renderButton()}
        </div>
YJ's avatar
YJ committed
      </div>
YJ's avatar
YJ committed
    );
YJ's avatar
YJ committed

    return (
      <div className='center-md'>
        <Card> {jsonCard} </Card>
        <br />
        <Card> {phraseCard} </Card>
        <br />
YJ's avatar
YJ committed
        <p>{error}</p>
YJ's avatar
YJ committed
        <nav className='form-nav -space-around'>
          {currentStep > 1 && (
            <button className='button -cancel' onClick={history.goBack}>
              Back
            </button>
          )}
        </nav>
      </div>
    );
  }

  renderButton = () => {
    const { isLoading, json, phrase } = this.state;

YJ's avatar
YJ committed
    // If we are importing an existing account, the button goes to the next step
    return (
      <button
        className='button'
        disabled={(!json && !phrase) || isLoading}
        onClick={this.handleSubmitPhrase}
YJ's avatar
YJ committed
      >
        Next
      </button>
    );
  };
}

export default AccountImportOptions;