Import via new createFromJSON (#3758)

This commit is contained in:
Jaco Greeff 2020-09-24 16:05:18 +02:00 committed by GitHub
parent 63f8c07d6c
commit eb6b82eb75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 105 deletions

View File

@ -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"

View File

@ -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<Props> {
const { t } = useTranslation();
const { api } = useApi();
const { api, isDevelopment } = useApi();
const [isBusy, setIsBusy] = useState(false);
const [{ address, isFileValid, json }, setFile] = useState<FileState>({ address: null, isFileValid: false, json: null });
const [pair, setPair] = useState<KeyringPair | null>(null);
const [{ isPassValid, password }, setPass] = useState<PassState>({ 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<ActionStatus> = { 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<string>('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
<Modal.Columns>
<Modal.Column>
<AddressRow
defaultName={(isFileValid && json?.meta.name as string) || null}
defaultName={(pair?.meta.name as string) || null}
noDefaultNameOpacity
value={isFileValid && address ? address : null}
value={pair?.address || null}
/>
</Modal.Column>
</Modal.Columns>
@ -145,7 +115,7 @@ function Import ({ className = '', onClose, onStatusChange }: Props): React.Reac
accept={acceptedFormats}
className='full'
help={t<string>('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<string>('backup file')}
onChange={_onChangeFile}
withLabel
@ -183,7 +153,7 @@ function Import ({ className = '', onClose, onStatusChange }: Props): React.Reac
<Button
icon='sync'
isBusy={isBusy}
isDisabled={!isFileValid || !isPassValid}
isDisabled={!pair || !isPassValid}
label={t<string>('Restore')}
onClick={_onSave}
/>

View File

@ -14,15 +14,15 @@
"@fortawesome/fontawesome-svg-core": "^1.2.30",
"@fortawesome/free-solid-svg-icons": "^5.14.0",
"@fortawesome/react-fontawesome": "^0.1.11",
"@polkadot/keyring": "^3.5.0-beta.12",
"@polkadot/keyring": "^3.5.0-beta.13",
"@polkadot/react-api": "0.60.0-beta.18",
"@polkadot/react-identicon": "^0.59.0-beta.8",
"@polkadot/react-qr": "^0.59.0-beta.8",
"@polkadot/react-identicon": "^0.59.0-beta.10",
"@polkadot/react-qr": "^0.59.0-beta.10",
"@polkadot/react-query": "0.60.0-beta.18",
"@polkadot/ui-keyring": "^0.59.0-beta.8",
"@polkadot/ui-settings": "^0.59.0-beta.8",
"@polkadot/util": "^3.5.0-beta.12",
"@polkadot/util-crypto": "^3.5.0-beta.12",
"@polkadot/ui-keyring": "^0.59.0-beta.10",
"@polkadot/ui-settings": "^0.59.0-beta.10",
"@polkadot/util": "^3.5.0-beta.13",
"@polkadot/util-crypto": "^3.5.0-beta.13",
"chart.js": "^2.9.3",
"codeflask": "^1.4.1",
"i18next": "^19.7.0",

View File

@ -3542,14 +3542,14 @@ __metadata:
languageName: node
linkType: hard
"@polkadot/keyring@npm:^3.5.0-beta.12":
version: 3.5.0-beta.12
resolution: "@polkadot/keyring@npm:3.5.0-beta.12"
"@polkadot/keyring@npm:^3.5.0-beta.13":
version: 3.5.0-beta.13
resolution: "@polkadot/keyring@npm:3.5.0-beta.13"
dependencies:
"@babel/runtime": ^7.11.2
"@polkadot/util": 3.5.0-beta.12
"@polkadot/util-crypto": 3.5.0-beta.12
checksum: 63a1d8cff1f982b4936e6bfb1d8b98920f6f47924f0b231de63d419d3974f31dd8a34716f444837647564bde44a332495ae66b806f4439fc661ff7ac72f8b47c
"@polkadot/util": 3.5.0-beta.13
"@polkadot/util-crypto": 3.5.0-beta.13
checksum: bbdeaa9e334d271c882e14368403b9e460a37d34e7f086ed104d7df0c8fdd10eb152223f4e43e761cd0e63b058bf616b4e37fd25284c66a39fd7a23686b773ca
languageName: node
linkType: hard
@ -3586,15 +3586,15 @@ __metadata:
"@fortawesome/fontawesome-svg-core": ^1.2.30
"@fortawesome/free-solid-svg-icons": ^5.14.0
"@fortawesome/react-fontawesome": ^0.1.11
"@polkadot/keyring": ^3.5.0-beta.12
"@polkadot/keyring": ^3.5.0-beta.13
"@polkadot/react-api": 0.60.0-beta.18
"@polkadot/react-identicon": ^0.59.0-beta.8
"@polkadot/react-qr": ^0.59.0-beta.8
"@polkadot/react-identicon": ^0.59.0-beta.10
"@polkadot/react-qr": ^0.59.0-beta.10
"@polkadot/react-query": 0.60.0-beta.18
"@polkadot/ui-keyring": ^0.59.0-beta.8
"@polkadot/ui-settings": ^0.59.0-beta.8
"@polkadot/util": ^3.5.0-beta.12
"@polkadot/util-crypto": ^3.5.0-beta.12
"@polkadot/ui-keyring": ^0.59.0-beta.10
"@polkadot/ui-settings": ^0.59.0-beta.10
"@polkadot/util": ^3.5.0-beta.13
"@polkadot/util-crypto": ^3.5.0-beta.13
"@types/codeflask": ^1.4.2
chart.js: ^2.9.3
codeflask: ^1.4.1
@ -3630,13 +3630,13 @@ __metadata:
languageName: unknown
linkType: soft
"@polkadot/react-identicon@npm:^0.59.0-beta.8":
version: 0.59.0-beta.8
resolution: "@polkadot/react-identicon@npm:0.59.0-beta.8"
"@polkadot/react-identicon@npm:^0.59.0-beta.10":
version: 0.59.0-beta.10
resolution: "@polkadot/react-identicon@npm:0.59.0-beta.10"
dependencies:
"@babel/runtime": ^7.11.2
"@polkadot/ui-settings": 0.59.0-beta.8
"@polkadot/ui-shared": 0.59.0-beta.8
"@polkadot/ui-settings": 0.59.0-beta.10
"@polkadot/ui-shared": 0.59.0-beta.10
color: ^3.1.2
jdenticon: 2.2.0
react-copy-to-clipboard: ^5.0.2
@ -3648,7 +3648,7 @@ __metadata:
react-dom: "*"
react-is: "*"
styled-components: "*"
checksum: 527c2e8beea0ea175ba92bdf91e0e12914bc2372a495df7c4caeb44d533077a10a153e616ec848ec9c18e31eae36c1b5115a7c7abd0c4364c1dd6e3f1211e60f
checksum: 1a494df73b881bef846089a7eeed508c6f6f17b774655dd9018d19a5dbca488691c723cbbc0a39a942575f7309ea6f5d2645122a65e5e86e39c333be058dd2d0
languageName: node
linkType: hard
@ -3661,9 +3661,9 @@ __metadata:
languageName: unknown
linkType: soft
"@polkadot/react-qr@npm:^0.59.0-beta.8":
version: 0.59.0-beta.8
resolution: "@polkadot/react-qr@npm:0.59.0-beta.8"
"@polkadot/react-qr@npm:^0.59.0-beta.10":
version: 0.59.0-beta.10
resolution: "@polkadot/react-qr@npm:0.59.0-beta.10"
dependencies:
"@babel/runtime": ^7.11.2
qrcode-generator: ^1.4.4
@ -3674,7 +3674,7 @@ __metadata:
react: "*"
react-dom: "*"
styled-components: "*"
checksum: 6a4beba3476c44c2e7a32f56b3dfa67e2f9ba6c0b53da668cb821fb269e75a0b2504dc4cb4c3e107052ebac1acaba58d34fdb1cd0ea0386757032115b1b1092f
checksum: 6ed7875739925871fe1433532311857540ef8c9a4a04b026f2a38d3b4d9c91d0436ac1ba3d978e194b517d709430bb47eed18d172bc7d0c3bd3525064f2f0d75
languageName: node
linkType: hard
@ -3764,9 +3764,9 @@ __metadata:
languageName: node
linkType: hard
"@polkadot/ui-keyring@npm:^0.59.0-beta.8":
version: 0.59.0-beta.8
resolution: "@polkadot/ui-keyring@npm:0.59.0-beta.8"
"@polkadot/ui-keyring@npm:^0.59.0-beta.10":
version: 0.59.0-beta.10
resolution: "@polkadot/ui-keyring@npm:0.59.0-beta.10"
dependencies:
"@babel/runtime": ^7.11.2
"@ledgerhq/hw-transport-node-hid": ^5.23.2
@ -3782,42 +3782,42 @@ __metadata:
dependenciesMeta:
"@ledgerhq/hw-transport-node-hid":
optional: true
checksum: a6803ba057c521d85c477e19207dda758205227beacf6aa14e046c4daa51d94a9afff7a45d9a0fba83733bc0327ea6a5d50083872197a3008e4620229fecdf3b
checksum: 4ef2da3ea9e48d4a06918aca431e4593f858260f47bff1dc14a5da86514c05dc9f7fe3871ec129485f88af450a401ee4fce9042364a8d856f252f71bd4b23f6a
languageName: node
linkType: hard
"@polkadot/ui-settings@npm:0.59.0-beta.8, @polkadot/ui-settings@npm:^0.59.0-beta.8":
version: 0.59.0-beta.8
resolution: "@polkadot/ui-settings@npm:0.59.0-beta.8"
"@polkadot/ui-settings@npm:0.59.0-beta.10, @polkadot/ui-settings@npm:^0.59.0-beta.10":
version: 0.59.0-beta.10
resolution: "@polkadot/ui-settings@npm:0.59.0-beta.10"
dependencies:
"@babel/runtime": ^7.11.2
eventemitter3: ^4.0.7
store: ^2.0.12
peerDependencies:
"@polkadot/util": "*"
checksum: f32afe3045dd66af81ab4ad2acefdb876deba5df3a52e57d6bc1a43f3765a63cce7ad3e320f019b460b6763055d906cb659d753db6379f918d6d30e1f02fc861
checksum: 66456e3e6bf9fab5693ddef59bd3ebeef0ca838319d25b660b1186498150367fc6025af8a7b5e7df0c5e0c7437d4d20296dd4408ed1a44e5ee5effcbc844e54b
languageName: node
linkType: hard
"@polkadot/ui-shared@npm:0.59.0-beta.8":
version: 0.59.0-beta.8
resolution: "@polkadot/ui-shared@npm:0.59.0-beta.8"
"@polkadot/ui-shared@npm:0.59.0-beta.10":
version: 0.59.0-beta.10
resolution: "@polkadot/ui-shared@npm:0.59.0-beta.10"
dependencies:
"@babel/runtime": ^7.11.2
color: ^3.1.2
peerDependencies:
"@polkadot/util": "*"
"@polkadot/util-crypto": "*"
checksum: 100320146e8355a4b1b617758bf11ea0602b504108f195254218a0388849d463cd79669c91f40345c693f5f2342237a044d8b803d99f26be897f07e79d988cda
checksum: b59025a03d6f3daba1dce320e832f4201099ad3c5d387d7bdbfef94883114216f97dffc884c45fa4fd9499dc372a83de888cd083e657a8c822600d96b28e802a
languageName: node
linkType: hard
"@polkadot/util-crypto@npm:^3.5.0-beta.12":
version: 3.5.0-beta.12
resolution: "@polkadot/util-crypto@npm:3.5.0-beta.12"
"@polkadot/util-crypto@npm:^3.5.0-beta.13":
version: 3.5.0-beta.13
resolution: "@polkadot/util-crypto@npm:3.5.0-beta.13"
dependencies:
"@babel/runtime": ^7.11.2
"@polkadot/util": 3.5.0-beta.12
"@polkadot/util": 3.5.0-beta.13
"@polkadot/wasm-crypto": ^1.4.1
base-x: ^3.0.8
bip39: ^3.0.2
@ -3829,13 +3829,13 @@ __metadata:
scryptsy: ^2.1.0
tweetnacl: ^1.0.3
xxhashjs: ^0.2.2
checksum: f366a1826fd05e4396e1adb97353b0bf18a26cb94c7786115c7096f735e528db56fa83b106e3785cd1672c6c44cda3bb4d1c03046d8416c7ee1a7196be6e8800
checksum: db9222d3b067f349ec9ee711af115be5e035c4b7a30e9b11f9f2a26b0ecc17d38f79f15896ec9f7445475c7cfa0a8b78170f1d8bd55bdfaadfa03c8ada4f778c
languageName: node
linkType: hard
"@polkadot/util@npm:^3.5.0-beta.12":
version: 3.5.0-beta.12
resolution: "@polkadot/util@npm:3.5.0-beta.12"
"@polkadot/util@npm:^3.5.0-beta.13":
version: 3.5.0-beta.13
resolution: "@polkadot/util@npm:3.5.0-beta.13"
dependencies:
"@babel/runtime": ^7.11.2
"@polkadot/x-textdecoder": ^0.3.2
@ -3845,7 +3845,7 @@ __metadata:
camelcase: ^5.3.1
chalk: ^4.1.0
ip-regex: ^4.1.0
checksum: ad4513479c9b9ed20cb06eae999663c98b1fddf7c2116d7c57d02d722264cb8be100561aa9a2bd6c12cde1f464e4c410f9f1a3d8a1a4c7c1696e35e68c9f7b4d
checksum: c720fa6410a8b7e8771bb12f39eab703f49b207fc19a8c654d455381594f6bd22151d7193fc74a6177622f47bfc6a20122823d94a3ea10ed2606b6d42f0ba88b
languageName: node
linkType: hard