From 1c091ca09a78b615b018ae5f9766cc7293402a5f Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Thu, 3 Oct 2019 10:50:26 +0200 Subject: [PATCH] Create dialog func. conversion (#1675) * Create dialog func. conversion * Fix linting issues * Small testing updates * adapt soft checks --- packages/app-accounts/src/modals/Create.tsx | 479 +++++++----------- .../src/modals/CreateConfirmation.tsx | 6 +- 2 files changed, 199 insertions(+), 286 deletions(-) diff --git a/packages/app-accounts/src/modals/Create.tsx b/packages/app-accounts/src/modals/Create.tsx index 4e6bd4c350..4b3d4e548a 100644 --- a/packages/app-accounts/src/modals/Create.tsx +++ b/packages/app-accounts/src/modals/Create.tsx @@ -3,17 +3,16 @@ // of the Apache-2.0 license. See the LICENSE file for details. import { I18nProps } from '@polkadot/react-components/types'; -import { ApiProps } from '@polkadot/react-api/types'; import { ActionStatus } from '@polkadot/react-components/Status/types'; import { KeypairType } from '@polkadot/util-crypto/types'; import { ModalProps } from '../types'; import FileSaver from 'file-saver'; -import React from 'react'; +import React, { useContext, useState } from 'react'; import styled from 'styled-components'; import { DEV_PHRASE } from '@polkadot/keyring/defaults'; -import { withApi, withMulti } from '@polkadot/react-api'; -import { AddressRow, Button, Dropdown, Input, InputAddress, Labelled, Modal, Password } from '@polkadot/react-components'; +import { ApiContext } from '@polkadot/react-api'; +import { AddressRow, Button, Dropdown, Input, InputAddress, Modal, Password } from '@polkadot/react-components'; import keyring from '@polkadot/ui-keyring'; import uiSettings from '@polkadot/ui-settings'; import { isHex, u8aToHex } from '@polkadot/util'; @@ -22,20 +21,15 @@ import { keyExtractSuri, mnemonicGenerate, mnemonicValidate, randomAsU8a } from import translate from '../translate'; import CreateConfirmation from './CreateConfirmation'; -interface Props extends ModalProps, ApiProps, I18nProps { +interface Props extends ModalProps, I18nProps { seed?: string; type?: KeypairType; } type SeedType = 'bip' | 'raw' | 'dev'; -interface SeedOption { - text: string; - value: SeedType; -} - interface AddressState { - address: string; + address: string | null; deriveError: string | null; derivePath: string; isSeedValid: boolean; @@ -44,30 +38,15 @@ interface AddressState { seedType: SeedType; } -interface State extends AddressState { - isNameValid: boolean; - isPassValid: boolean; - isValid: boolean; - name: string; - password: string; - seedOptions: SeedOption[]; - showWarning: boolean; - tags: string[]; -} - -const DEFAULT_TYPE = 'sr25519'; +const DEFAULT_PAIR_TYPE = 'sr25519'; function deriveValidate (seed: string, derivePath: string, pairType: KeypairType): string | null { try { const { path } = keyExtractSuri(`${seed}${derivePath}`); // we don't allow soft for ed25519 - if (pairType === 'ed25519') { - const firstSoft = path.find(({ isSoft }): boolean => isSoft); - - if (firstSoft) { - return 'Soft derivation paths are not allowed on ed25519'; - } + if (pairType === 'ed25519' && path.some(({ isSoft }): boolean => isSoft)) { + return 'Soft derivation paths are not allowed on ed25519'; } } catch (error) { return error.message; @@ -90,17 +69,19 @@ function addressFromSeed (phrase: string, derivePath: string, pairType: KeypairT .address; } -function generateSeed (_seed: string | null, derivePath: string, seedType: SeedType, pairType: KeypairType): AddressState { - const seed = ((): string => { - switch (seedType) { - case 'bip': - return mnemonicGenerate(); - case 'dev': - return DEV_PHRASE; - default: - return _seed || u8aToHex(randomAsU8a()); - } - })(); +function newSeed (seed: string | undefined | null, seedType: SeedType): string { + switch (seedType) { + case 'bip': + return mnemonicGenerate(); + case 'dev': + return DEV_PHRASE; + default: + return seed || u8aToHex(randomAsU8a()); + } +} + +function generateSeed (_seed: string | undefined | null, derivePath: string, seedType: SeedType, pairType: KeypairType = DEFAULT_PAIR_TYPE): AddressState { + const seed = newSeed(_seed, seedType); const address = addressFromSeed(seed, derivePath, pairType); return { @@ -114,239 +95,70 @@ function generateSeed (_seed: string | null, derivePath: string, seedType: SeedT }; } -class Create extends React.PureComponent { - public state: State; +function updateAddress (seed: string, derivePath: string, seedType: SeedType, pairType: KeypairType): AddressState { + const deriveError = deriveValidate(seed, derivePath, pairType); + let isSeedValid = seedType === 'raw' + ? rawValidate(seed) + : mnemonicValidate(seed); + let address: string | null = null; - public constructor (props: Props) { - super(props); - - const { isDevelopment, seed, t, type } = this.props; - const seedOptions: SeedOption[] = [ - { value: 'bip', text: t('Mnemonic') }, - { value: 'raw', text: t('Raw seed') } - ]; - - if (isDevelopment) { - seedOptions.push({ value: 'dev', text: t('Development') }); + if (!deriveError && isSeedValid) { + try { + address = addressFromSeed(seed, derivePath, pairType); + } catch (error) { + isSeedValid = false; } - - const pairType = type || DEFAULT_TYPE; - const seedType = seed ? 'raw' : 'bip'; - - this.state = { - ...generateSeed(seed || null, '', seedType, pairType), - isNameValid: true, - isPassValid: false, - isValid: false, - name: 'new account', - password: '', - seedOptions, - showWarning: false, - tags: [] - }; } - public render (): React.ReactNode { - const { className, t } = this.props; - const { address, deriveError, derivePath, isNameValid, isPassValid, isSeedValid, isValid, name, pairType, password, seed, seedOptions, seedType, showWarning } = this.state; - const isDevSeed = seedType === 'dev'; - const seedLabel = ((): string => { - switch (seedType) { - case 'bip': - return t('mnemonic seed'); - case 'dev': - return t('development seed'); - default: - return t('seed (hex or string)'); - } - })(); + return { + address, + deriveError, + derivePath, + isSeedValid, + pairType, + seedType, + seed + }; +} - return ( - - {t('Add an account via seed')} - {showWarning && ( - - )} - - - - - - - -
- {t('Advanced creation options')} - - //". The "/" and "//" may be repeated and mixed`.')} - isError={!!deriveError} - label={t('secret derivation path')} - onChange={this.onChangeDerive} - onEnter={this.onCommit} - value={derivePath} - /> - {deriveError && ( -
{deriveError}
- )} -
-
-
- - -