Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
it works!
  • Loading branch information
shawntabrizi committed May 22, 2020
commit 70361dfb858f9be812187d1dfec5395d86c8bc80
20 changes: 16 additions & 4 deletions packages/extension-base/src/background/handlers/Extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import { MetadataDef } from '@polkadot/extension-inject/types';
import { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
import { AccountJson, AuthorizeRequest, MessageTypes, MetadataRequest, RequestAccountCreateExternal, RequestAccountCreateSuri, RequestAccountEdit, RequestAccountExport, RequestAccountValidate, RequestAuthorizeApprove, RequestAuthorizeReject, RequestDeriveCreate, ResponseDeriveValidate, RequestMetadataApprove, RequestMetadataReject, RequestSigningApprovePassword, RequestSigningApproveSignature, RequestSigningCancel, RequestSeedCreate, RequestTypes, ResponseAccountExport, RequestAccountForget, ResponseSeedCreate, RequestSeedValidate, RequestDeriveValidate, ResponseSeedValidate, ResponseType, SigningRequest } from '../types';
import { AccountJson, AuthorizeRequest, MessageTypes, MetadataRequest, RequestAccountCreateExternal, RequestAccountCreateSuri, RequestAccountEdit, RequestAccountExport, RequestAccountValidate, RequestAuthorizeApprove, RequestAuthorizeReject, RequestDeriveCreate, ResponseDeriveValidate, RequestMetadataApprove, RequestMetadataReject, RequestSigningApprovePassword, RequestSigningApproveSignature, RequestSigningCancel, RequestSeedCreate, RequestTypes, ResponseAccountExport, RequestAccountForget, ResponseSeedCreate, RequestSeedValidate, RequestDeriveValidate, ResponseSeedValidate, ResponseType, SigningRequest, RequestJsonRestore, ResponseJsonRestore } from '../types';

import chrome from '@polkadot/extension-inject/chrome';
import keyring from '@polkadot/ui-keyring';
Expand Down Expand Up @@ -270,14 +270,23 @@ export default class Extension {
return true;
}

private uploadJson(): boolean {
private jsonUpload(): boolean {
chrome.tabs.create({
url: chrome.extension.getURL('index.html#/account/upload-json')
});

return true;
}

private jsonRestore({json, password}: RequestJsonRestore): ResponseJsonRestore {
const pair = keyring.restoreAccount(json, password);
const { address } = pair;

assert(pair, "Could not recover key pair");

return { address };
}

private windowOpen (): boolean {
chrome.tabs.create({
url: chrome.extension.getURL('index.html')
Expand Down Expand Up @@ -393,8 +402,11 @@ export default class Extension {
case 'pri(signing.requests)':
return this.signingSubscribe(id, port);

case 'pri(upload.json)':
return this.uploadJson();
case 'pri(json.upload)':
return this.jsonUpload();

case 'pri(json.restore)':
return this.jsonRestore(request as RequestJsonRestore);

case 'pri(window.open)':
return this.windowOpen();
Expand Down
14 changes: 12 additions & 2 deletions packages/extension-base/src/background/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { InjectedAccount, MetadataDef, ProviderList, ProviderMeta, InjectedMetadataKnown } from '@polkadot/extension-inject/types';
import { JsonRpcResponse } from '@polkadot/rpc-provider/types';
import { KeypairType } from '@polkadot/util-crypto/types';
import { KeyringPair, KeyringPair$Meta } from '@polkadot/keyring/types';
import { KeyringPair, KeyringPair$Json, KeyringPair$Meta } from '@polkadot/keyring/types';
import { SignerPayloadJSON, SignerPayloadRaw } from '@polkadot/types/types';
import { TypeRegistry } from '@polkadot/types';

Expand Down Expand Up @@ -86,7 +86,8 @@ export interface RequestSignatures {
'pri(signing.approve.signature)': [RequestSigningApproveSignature, boolean];
'pri(signing.cancel)': [RequestSigningCancel, boolean];
'pri(signing.requests)': [RequestSigningSubscribe, boolean, SigningRequest[]];
'pri(upload.json)': [null, boolean];
'pri(json.upload)': [null, boolean];
'pri(json.restore)': [RequestJsonRestore, ResponseJsonRestore];
'pri(window.open)': [null, boolean];
// public/external requests, i.e. from a page
'pub(accounts.list)': [RequestAccountList, InjectedAccount[]];
Expand Down Expand Up @@ -308,3 +309,12 @@ export interface RequestSign {

sign (registry: TypeRegistry, pair: KeyringPair): { signature: string };
}

export interface RequestJsonRestore {
json: KeyringPair$Json;
password: string;
}

export interface ResponseJsonRestore {
address: string;
}
1 change: 1 addition & 0 deletions packages/extension-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@polkadot/util-crypto": "^2.10.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-dropzone": "^11.0.1",
"react-is": "^16.13.1",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/extension-ui/src/Popup/ImportSeed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import styled from 'styled-components';

import { ActionContext, Address, ButtonArea, NextStepButton, TextAreaWithLabel, ValidatedInput, VerticalSpace, ActionText } from '../components';
import { allOf, isNotShorterThan, Result } from '../validators';
import { createAccountSuri, validateSeed, uploadJson } from '../messaging';
import { createAccountSuri, validateSeed, jsonUpload } from '../messaging';
import { Header, Name, Password } from '../partials';
import unlock from '../assets/unlock.svg';

Expand Down Expand Up @@ -93,7 +93,7 @@ export default function Import (): React.ReactElement<Props> {
<ActionText
data-seed-action='upload'
icon={unlock}
onClick={uploadJson}
onClick={jsonUpload}
text='Upload JSON backup'
/>
</ButtonsRow>
Expand Down
105 changes: 101 additions & 4 deletions packages/extension-ui/src/Popup/UploadJson.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.

import React from 'react';
import { KeyringPair$Json } from '@polkadot/keyring/types';
import React, { useCallback, useState, createRef } from 'react';
import Dropzone, { DropzoneRef } from 'react-dropzone';
import { InputWithLabel, Button } from '../components';
import { isHex, u8aToString, hexToU8a, formatNumber } from '@polkadot/util';
import styled from 'styled-components';
import { jsonRestore } from '../messaging';

import { Header } from '../partials';

Expand All @@ -16,13 +21,105 @@ export default function Upload(): React.ReactElement<Props> {
<HeaderWithSmallerMargin
text='Restore JSON'
/>
<div>
Upload File Stuff Here
</div>
<InputFile
accept={acceptedFormats}
//className='full'
help={'Select the JSON key file that was downloaded when you created the account. This JSON file contains your private key encrypted with your password.'}
label={'backup file'}
onChange={_onChangeFile}
withLabel
/>
<InputWithLabel
label='Password for this file'
onChange={_onChangePass}
type='password'
/>
<Button
isDisabled={!json || !password}
onClick={_onSave}
>
Restore
</Button>
</>
);
}

function InputFile({ accept, clearContent, convertHex, help, isDisabled, isError = false, label, onChange, placeholder, withEllipsis, withLabel }: InputFileProps): React.ReactElement<InputFileProps> {
const dropRef = createRef<DropzoneRef>();
const [file, setFile] = useState<FileState | undefined>();

const _onDrop = useCallback(
(files: File[]): void => {
files.forEach((file): void => {
const reader = new FileReader();

reader.onabort = NOOP;
reader.onerror = NOOP;

reader.onload = ({ target }: ProgressEvent<FileReader>): void => {
if (target && target.result) {
const name = file.name;
const data = convertResult(target.result as ArrayBuffer, convertHex);

onChange && onChange(data, name);
dropRef && setFile({
name,
size: data.length
});
}
};

reader.readAsArrayBuffer(file);
});
},
[convertHex, dropRef, onChange]
);

const dropZone = (
<Dropzone
accept={accept}
disabled={isDisabled}
multiple={false}
onDrop={_onDrop}
ref={dropRef}
>
{({ getInputProps, getRootProps }): JSX.Element => (
<div {...getRootProps({ })} >
<input {...getInputProps()} />
<em className='label' >
{
!file || clearContent
? placeholder || 'click to select or drag and drop the file here'
: placeholder || `${ file.name }(${ formatNumber(file.size) } bytes)`
}
</em>
</div>
)}
</Dropzone>
);

return dropZone
}

const NOOP = (): void => undefined;
const BYTE_STR_0 = '0'.charCodeAt(0);
const BYTE_STR_X = 'x'.charCodeAt(0);

function convertResult(result: ArrayBuffer, convertHex?: boolean): Uint8Array {
const data = new Uint8Array(result);

// this converts the input (if detected as hex), vai the hex conversion route
if (convertHex && data[0] === BYTE_STR_0 && data[1] === BYTE_STR_X) {
const hex = u8aToString(data);

if (isHex(hex)) {
return hexToU8a(hex);
}
}

return data;
}

const HeaderWithSmallerMargin = styled(Header)`
margin-bottom: 15px;
`;
9 changes: 7 additions & 2 deletions packages/extension-ui/src/messaging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { KeypairType } from '@polkadot/util-crypto/types';
import { PORT_EXTENSION } from '@polkadot/extension-base/defaults';
import chrome from '@polkadot/extension-inject/chrome';
import { findChain } from '@polkadot/extension-chains';
import { KeyringPair$Json } from '@polkadot/keyring/types';

interface Handler {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down Expand Up @@ -143,8 +144,12 @@ export async function validateSeed (suri: string, type?: KeypairType): Promise<{
return sendMessage('pri(seed.validate)', { suri, type });
}

export async function uploadJson (): Promise<boolean> {
return sendMessage('pri(upload.json)', null);
export async function jsonUpload (): Promise<boolean> {
return sendMessage('pri(json.upload)', null);
}

export async function jsonRestore(json: KeyringPair$Json, password: string): Promise<{ address: string }> {
return sendMessage('pri(json.restore)', { json, password });
}

export async function windowOpen(): Promise<boolean> {
Expand Down
30 changes: 30 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2992,6 +2992,7 @@ __metadata:
enzyme-adapter-react-16: ^1.15.2
react: ^16.13.1
react-dom: ^16.13.1
react-dropzone: ^11.0.1
react-is: ^16.13.1
react-router: ^5.2.0
react-router-dom: ^5.2.0
Expand Down Expand Up @@ -4980,6 +4981,13 @@ __metadata:
languageName: node
linkType: hard

"attr-accept@npm:^2.0.0":
version: 2.1.0
resolution: "attr-accept@npm:2.1.0"
checksum: 3/a31fdf3b37daed32e8f33a46e17b3a85b156900c9b7e564cf9202a4893bf475aeebda41421c0febce65bac02c528cbe603abc18592af907fc4a7b839a181a5e4
languageName: node
linkType: hard

"autocomplete.js@npm:0.36.0":
version: 0.36.0
resolution: "autocomplete.js@npm:0.36.0"
Expand Down Expand Up @@ -9723,6 +9731,15 @@ __metadata:
languageName: node
linkType: hard

"file-selector@npm:^0.1.12":
version: 0.1.12
resolution: "file-selector@npm:0.1.12"
dependencies:
tslib: ^1.9.0
checksum: 3/b1a8287dabc8c239998ecb319c5b4eae156bdeb23130d3b5b6bed349f296d7798d0e5ef43e83dad3550aa2b1d1fd45ab7c5302fe8a9e26196676089de565f4ac
languageName: node
linkType: hard

"file-uri-to-path@npm:1.0.0":
version: 1.0.0
resolution: "file-uri-to-path@npm:1.0.0"
Expand Down Expand Up @@ -17181,6 +17198,19 @@ fsevents@^2.1.2:
languageName: node
linkType: hard

"react-dropzone@npm:^11.0.1":
version: 11.0.1
resolution: "react-dropzone@npm:11.0.1"
dependencies:
attr-accept: ^2.0.0
file-selector: ^0.1.12
prop-types: ^15.7.2
peerDependencies:
react: ">= 16.8"
checksum: 3/c5192e7367df18d77b8b4c219fd9e091d9d63e7a530ec9f983b42e32a738079f0f5f5082057a867ffd7031aa0a703638d7e873476cb6a27b96c0f330e4166523
languageName: node
linkType: hard

"react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.6.0, react-is@npm:^16.7.0, react-is@npm:^16.8.1, react-is@npm:^16.8.6, react-is@npm:^16.9.0":
version: 16.13.1
resolution: "react-is@npm:16.13.1"
Expand Down