From eb6b82eb7513dac3e91dec4d0ab8af9adabb307c Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Thu, 24 Sep 2020 16:05:18 +0200 Subject: [PATCH] Import via new createFromJSON (#3758) --- package.json | 6 +- packages/page-accounts/src/modals/Import.tsx | 72 +++++----------- packages/react-components/package.json | 14 ++-- yarn.lock | 88 ++++++++++---------- 4 files changed, 75 insertions(+), 105 deletions(-) diff --git a/package.json b/package.json index bbf9a8387c..62465c9ec2 100644 --- a/package.json +++ b/package.json @@ -35,10 +35,10 @@ "resolutions": { "@polkadot/api": "^1.35.0-beta.7", "@polkadot/api-contract": "^1.35.0-beta.7", - "@polkadot/keyring": "^3.5.0-beta.12", + "@polkadot/keyring": "^3.5.0-beta.13", "@polkadot/types": "^1.35.0-beta.7", - "@polkadot/util": "^3.5.0-beta.12", - "@polkadot/util-crypto": "^3.5.0-beta.12", + "@polkadot/util": "^3.5.0-beta.13", + "@polkadot/util-crypto": "^3.5.0-beta.13", "@polkadot/wasm-crypto": "^1.4.1", "babel-core": "^7.0.0-bridge.0", "typescript": "^4.0.3" diff --git a/packages/page-accounts/src/modals/Import.tsx b/packages/page-accounts/src/modals/Import.tsx index 46ec56bf50..859f0e3840 100644 --- a/packages/page-accounts/src/modals/Import.tsx +++ b/packages/page-accounts/src/modals/Import.tsx @@ -1,15 +1,14 @@ // Copyright 2017-2020 @polkadot/app-accounts authors & contributors // SPDX-License-Identifier: Apache-2.0 -import { KeyringPair$Json } from '@polkadot/keyring/types'; +import { KeyringPair, KeyringPair$Json } from '@polkadot/keyring/types'; import { ActionStatus } from '@polkadot/react-components/Status/types'; import { ModalProps } from '../types'; import React, { useCallback, useMemo, useState } from 'react'; import { AddressRow, Button, InputAddress, InputFile, Modal, Password } from '@polkadot/react-components'; import { useApi } from '@polkadot/react-hooks'; -import { hexToU8a, isHex, isObject, u8aToString } from '@polkadot/util'; -import { blake2AsU8a } from '@polkadot/util-crypto'; +import { u8aToString } from '@polkadot/util'; import keyring from '@polkadot/ui-keyring'; import { useTranslation } from '../translate'; @@ -21,12 +20,6 @@ interface Props extends ModalProps { onStatusChange: (status: ActionStatus) => void; } -interface FileState { - address: string | null; - isFileValid: boolean; - json: KeyringPair$Json | null; -} - interface PassState { isPassValid: boolean; password: string; @@ -34,46 +27,28 @@ interface PassState { const acceptedFormats = ['application/json', 'text/plain'].join(', '); -function parseFile (file: Uint8Array): FileState { +function parseFile (file: Uint8Array, genesisHash?: string | null): KeyringPair | null { try { - const json = JSON.parse(u8aToString(file)) as KeyringPair$Json; - const publicKey = isHex(json.address) - ? hexToU8a(json.address) - : keyring.decodeAddress(json.address, true); - const address = keyring.encodeAddress( - isHex(json.address) && Array.isArray(json.encoding.content) && publicKey.length !== 32 - ? json.encoding.content[1] === 'ecdsa' - ? blake2AsU8a(publicKey) - // FIXME Handle Ethereum - : publicKey - : publicKey - ); - const isFileValid = [32, 33].includes(publicKey.length) && !!json.encoded && isObject(json.meta) && ( - Array.isArray(json.encoding.content) - ? json.encoding.content[0] === 'pkcs8' - : json.encoding.content === 'pkcs8' - ); - - return { address, isFileValid, json }; + return keyring.createFromJSON(JSON.parse(u8aToString(file)) as KeyringPair$Json, { genesisHash }); } catch (error) { console.error(error); } - return { address: null, isFileValid: false, json: null }; + return null; } function Import ({ className = '', onClose, onStatusChange }: Props): React.ReactElement { const { t } = useTranslation(); - const { api } = useApi(); + const { api, isDevelopment } = useApi(); const [isBusy, setIsBusy] = useState(false); - const [{ address, isFileValid, json }, setFile] = useState({ address: null, isFileValid: false, json: null }); + const [pair, setPair] = useState(null); const [{ isPassValid, password }, setPass] = useState({ isPassValid: false, password: '' }); - const apiGenesisHash = useMemo(() => api.genesisHash.toHex(), [api]); - const differentGenesis = useMemo(() => json?.meta.genesisHash && json.meta.genesisHash !== apiGenesisHash, [apiGenesisHash, json]); + const apiGenesisHash = useMemo(() => isDevelopment ? null : api.genesisHash.toHex(), [api, isDevelopment]); + const differentGenesis = useMemo(() => pair?.meta.genesisHash && pair.meta.genesisHash !== apiGenesisHash, [apiGenesisHash, pair]); const _onChangeFile = useCallback( - (file: Uint8Array) => setFile(parseFile(file)), - [] + (file: Uint8Array) => setPair(parseFile(file, apiGenesisHash)), + [apiGenesisHash] ); const _onChangePass = useCallback( @@ -83,7 +58,7 @@ function Import ({ className = '', onClose, onStatusChange }: Props): React.Reac const _onSave = useCallback( (): void => { - if (!json) { + if (!pair) { return; } @@ -92,18 +67,13 @@ function Import ({ className = '', onClose, onStatusChange }: Props): React.Reac const status: Partial = { action: 'restore' }; try { - const pair = keyring.restoreAccount({ - ...json, - // forcing the use of current genesis hash - meta: { ...json.meta, genesisHash: apiGenesisHash } - }, password); - const { address } = pair; + keyring.addPair(pair, password); - status.status = pair ? 'success' : 'error'; - status.account = address; + status.status = 'success'; + status.account = pair.address; status.message = t('account restored'); - InputAddress.setLastValue('account', address); + InputAddress.setLastValue('account', pair.address); } catch (error) { setPass((state: PassState) => ({ ...state, isPassValid: false })); @@ -120,7 +90,7 @@ function Import ({ className = '', onClose, onStatusChange }: Props): React.Reac } }, 0); }, - [apiGenesisHash, json, onClose, onStatusChange, password, t] + [onClose, onStatusChange, pair, password, t] ); return ( @@ -133,9 +103,9 @@ function Import ({ className = '', onClose, onStatusChange }: Props): React.Reac @@ -145,7 +115,7 @@ function Import ({ className = '', onClose, onStatusChange }: Props): React.Reac accept={acceptedFormats} className='full' help={t('Select the JSON key file that was downloaded when you created the account. This JSON file contains your private key encrypted with your password.')} - isError={!isFileValid} + isError={!pair} label={t('backup file')} onChange={_onChangeFile} withLabel @@ -183,7 +153,7 @@ function Import ({ className = '', onClose, onStatusChange }: Props): React.Reac