feature(settings): add export private keys in settings view
This commit is contained in:
parent
3cf4d058f7
commit
b586e7ed7f
|
@ -3,10 +3,12 @@ import React, { PureComponent } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import { Button } from '../components/button';
|
import { Button } from '../components/button';
|
||||||
import { ModalComponent } from '../components/modal';
|
|
||||||
import { ConfirmDialogComponent } from '../components/confirm-dialog';
|
import { ConfirmDialogComponent } from '../components/confirm-dialog';
|
||||||
import { TextComponent } from '../components/text';
|
import { TextComponent } from '../components/text';
|
||||||
import { InputComponent } from '../components/input';
|
import { InputComponent } from '../components/input';
|
||||||
|
import { InputLabelComponent } from '../components/input-label';
|
||||||
|
import { RowComponent } from '../components/row';
|
||||||
|
import { Clipboard } from '../components/clipboard';
|
||||||
|
|
||||||
import rpc from '../../services/api';
|
import rpc from '../../services/api';
|
||||||
|
|
||||||
|
@ -17,10 +19,26 @@ const Wrapper = styled.div`
|
||||||
const ModalContent = styled.div`
|
const ModalContent = styled.div`
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow-x: hidden;
|
max-height: 600px;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
p {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
type ViewKey = {
|
const Btn = styled(Button)`
|
||||||
|
margin-bottom: 10px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ClipboardButton = styled(Clipboard)`
|
||||||
|
width: 50px;
|
||||||
|
border-radius: ${props => props.theme.boxBorderRadius};
|
||||||
|
height: 45px;
|
||||||
|
margin-left: 5px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
type Key = {
|
||||||
zAddress: string,
|
zAddress: string,
|
||||||
key: string,
|
key: string,
|
||||||
};
|
};
|
||||||
|
@ -29,18 +47,20 @@ type Props = {
|
||||||
addresses: string[],
|
addresses: string[],
|
||||||
};
|
};
|
||||||
type State = {
|
type State = {
|
||||||
viewKeys: ViewKey[],
|
viewKeys: Key[],
|
||||||
|
privateKeys: Key[],
|
||||||
isLoading: boolean,
|
isLoading: boolean,
|
||||||
successExportViewKeys: boolean,
|
successExportViewKeys: boolean,
|
||||||
message: string | null,
|
successExportPrivateKeys: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
export class SettingsView extends PureComponent<Props, State> {
|
export class SettingsView extends PureComponent<Props, State> {
|
||||||
state = {
|
state = {
|
||||||
viewKeys: [],
|
viewKeys: [],
|
||||||
|
privateKeys: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
successExportViewKeys: false,
|
successExportViewKeys: false,
|
||||||
message: null,
|
successExportPrivateKeys: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
exportViewKeys = () => {
|
exportViewKeys = () => {
|
||||||
|
@ -48,6 +68,8 @@ export class SettingsView extends PureComponent<Props, State> {
|
||||||
|
|
||||||
const zAddresses = addresses.filter(addr => addr.startsWith('z'));
|
const zAddresses = addresses.filter(addr => addr.startsWith('z'));
|
||||||
|
|
||||||
|
this.setState({ isLoading: true });
|
||||||
|
|
||||||
Promise.all(
|
Promise.all(
|
||||||
zAddresses.map(async (zAddr) => {
|
zAddresses.map(async (zAddr) => {
|
||||||
const viewKey = await rpc.z_exportviewingkey(zAddr);
|
const viewKey = await rpc.z_exportviewingkey(zAddr);
|
||||||
|
@ -57,63 +79,68 @@ export class SettingsView extends PureComponent<Props, State> {
|
||||||
this.setState({
|
this.setState({
|
||||||
viewKeys,
|
viewKeys,
|
||||||
successExportViewKeys: true,
|
successExportViewKeys: true,
|
||||||
|
isLoading: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handleCloseModal = (fn: () => void) => () => {
|
exportPrivateKeys = () => {
|
||||||
this.setState(
|
const { addresses } = this.props;
|
||||||
{
|
|
||||||
message: null,
|
const zAddresses = addresses.filter(addr => addr.startsWith('z'));
|
||||||
},
|
|
||||||
fn,
|
this.setState({ isLoading: true });
|
||||||
);
|
|
||||||
|
Promise.all(
|
||||||
|
zAddresses.map(async (zAddr) => {
|
||||||
|
const privateKey = await rpc.z_exportkey(zAddr);
|
||||||
|
return { zAddress: zAddr, key: privateKey };
|
||||||
|
}),
|
||||||
|
).then((privateKeys) => {
|
||||||
|
this.setState({
|
||||||
|
privateKeys,
|
||||||
|
successExportPrivateKeys: true,
|
||||||
|
isLoading: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
render = () => {
|
render = () => {
|
||||||
const {
|
const {
|
||||||
viewKeys, isLoading, successExportViewKeys, message,
|
viewKeys,
|
||||||
|
isLoading,
|
||||||
|
successExportViewKeys,
|
||||||
|
privateKeys,
|
||||||
|
successExportPrivateKeys,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<ModalComponent
|
|
||||||
renderTrigger={toggleVisibility => (
|
|
||||||
<Button label='Export view keys' onClick={toggleVisibility} />
|
|
||||||
)}
|
|
||||||
closeOnBackdropClick={false}
|
|
||||||
closeOnEsc={false}
|
|
||||||
>
|
|
||||||
{toggleVisibility => (
|
|
||||||
<ConfirmDialogComponent
|
<ConfirmDialogComponent
|
||||||
title='Export view keys'
|
title='Export view keys'
|
||||||
handleClose={this.handleCloseModal(toggleVisibility)}
|
renderTrigger={toggleVisibility => (
|
||||||
|
<Btn label='Export view keys' onClick={toggleVisibility} />
|
||||||
|
)}
|
||||||
onConfirm={this.exportViewKeys}
|
onConfirm={this.exportViewKeys}
|
||||||
showButtons={!successExportViewKeys}
|
showButtons={!successExportViewKeys}
|
||||||
width={750}
|
width={750}
|
||||||
>
|
>
|
||||||
<ModalContent>
|
<ModalContent>
|
||||||
{successExportViewKeys ? (
|
{successExportViewKeys ? (
|
||||||
|
viewKeys.map(({ zAddress, key }) => (
|
||||||
<>
|
<>
|
||||||
|
<InputLabelComponent value={zAddress} />
|
||||||
|
<RowComponent alignItems='center'>
|
||||||
<InputComponent
|
<InputComponent
|
||||||
inputType='textarea'
|
value={key}
|
||||||
rows={10}
|
|
||||||
value={viewKeys.reduce(
|
|
||||||
(acc, cur, idx) => `${acc}${cur.key} ${
|
|
||||||
idx === viewKeys.length - 1 ? '' : '\n\n'
|
|
||||||
}`,
|
|
||||||
'',
|
|
||||||
)}
|
|
||||||
onFocus={(event) => {
|
onFocus={(event) => {
|
||||||
event.currentTarget.select();
|
event.currentTarget.select();
|
||||||
document.execCommand('copy');
|
|
||||||
this.setState({ message: 'Copied to clipboard!' });
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{message && (
|
<ClipboardButton text={key} />
|
||||||
<TextComponent value={message} align='center' />
|
</RowComponent>
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
|
))
|
||||||
) : (
|
) : (
|
||||||
<TextComponent
|
<TextComponent
|
||||||
value={
|
value={
|
||||||
|
@ -125,8 +152,43 @@ export class SettingsView extends PureComponent<Props, State> {
|
||||||
)}
|
)}
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
</ConfirmDialogComponent>
|
</ConfirmDialogComponent>
|
||||||
|
|
||||||
|
<ConfirmDialogComponent
|
||||||
|
title='Export private keys'
|
||||||
|
renderTrigger={toggleVisibility => (
|
||||||
|
<Btn label='Export private keys' onClick={toggleVisibility} />
|
||||||
)}
|
)}
|
||||||
</ModalComponent>
|
onConfirm={this.exportPrivateKeys}
|
||||||
|
showButtons={!successExportPrivateKeys}
|
||||||
|
width={750}
|
||||||
|
>
|
||||||
|
<ModalContent>
|
||||||
|
{successExportPrivateKeys ? (
|
||||||
|
privateKeys.map(({ zAddress, key }) => (
|
||||||
|
<>
|
||||||
|
<InputLabelComponent value={zAddress} />
|
||||||
|
<RowComponent alignItems='center'>
|
||||||
|
<InputComponent
|
||||||
|
value={key}
|
||||||
|
onFocus={(event) => {
|
||||||
|
event.currentTarget.select();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ClipboardButton text={key} />
|
||||||
|
</RowComponent>
|
||||||
|
</>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<TextComponent
|
||||||
|
value={
|
||||||
|
isLoading
|
||||||
|
? 'Loading...'
|
||||||
|
: 'Ut id vulputate arcu. Curabitur mattis aliquam magna sollicitudin vulputate. Morbi tempus bibendum porttitor. Quisque dictum ac ipsum a luctus. Donec et lacus ac erat consectetur molestie a id erat.'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</ModalContent>
|
||||||
|
</ConfirmDialogComponent>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue