diff --git a/common/containers/Tabs/GenerateWallet/components/DownloadWallet.jsx b/common/containers/Tabs/GenerateWallet/components/DownloadWallet.jsx index eefc6f6b..528deca6 100644 --- a/common/containers/Tabs/GenerateWallet/components/DownloadWallet.jsx +++ b/common/containers/Tabs/GenerateWallet/components/DownloadWallet.jsx @@ -4,6 +4,7 @@ import translate from 'translations'; import type PrivKeyWallet from 'libs/wallet/privkey'; import { makeBlob } from 'utils/blob'; import { getV3Filename } from 'libs/keystore'; +import type { UtcKeystore } from 'libs/keystore'; type Props = { wallet: PrivKeyWallet, @@ -11,32 +12,43 @@ type Props = { continueToPaper: Function }; +type State = { + hasDownloadedWallet: boolean, + address: string, + keystore: UtcKeystore | null +}; + export default class DownloadWallet extends Component { props: Props; - keystore: Object; - state = { + state: State = { hasDownloadedWallet: false, - address: '' + address: '', + keystore: null }; componentDidMount() { - if (!this.props.wallet) return; this.props.wallet.getAddress().then(addr => { this.setState({ address: addr }); }); } componentWillMount() { - this.keystore = this.props.wallet.toKeystore(this.props.password); + this.props.wallet.toKeystore(this.props.password).then(utcKeystore => { + this.setState({ keystore: utcKeystore }); + }); } componentWillUpdate(nextProps: Props) { if (this.props.wallet !== nextProps.wallet) { - this.keystore = nextProps.wallet.toKeystore(nextProps.password); + nextProps.wallet.toKeystore(nextProps.password).then(utcKeystore => { + this.setState({ keystore: utcKeystore }); + }); } } _markDownloaded = () => { - this.setState({ hasDownloadedWallet: true }); + if (this.state.keystore) { + this.setState({ hasDownloadedWallet: true }); + } }; _handleContinue = () => { @@ -72,6 +84,7 @@ export default class DownloadWallet extends Component { className="btn btn-primary btn-block" aria-label="Download Keystore File (UTC / JSON · Recommended · Encrypted)" aria-describedby="x_KeystoreDesc" + disabled={!this.state.keystore} download={this.getFilename()} href={this.getBlob()} onClick={this._markDownloaded} @@ -115,7 +128,9 @@ export default class DownloadWallet extends Component { } getBlob() { - return makeBlob('text/json;charset=UTF-8', this.keystore); + if (this.state.keystore) { + return makeBlob('text/json;charset=UTF-8', this.state.keystore); + } } getFilename() { diff --git a/common/libs/keystore.js b/common/libs/keystore.js index 42b5ddb2..d650190b 100644 --- a/common/libs/keystore.js +++ b/common/libs/keystore.js @@ -10,6 +10,13 @@ import { sha3, privateToAddress } from 'ethereumjs-util'; import scrypt from 'scryptsy'; import uuid from 'uuid'; +export type UtcKeystore = { + version: number, + id: string, + address: string, + Crypto: Object +}; + //adapted from https://github.com/kvhnuke/etherwallet/blob/de536ffebb4f2d1af892a32697e89d1a0d906b01/app/scripts/myetherwallet.js#L342 export function determineKeystoreType(file: string): string { const parsed = JSON.parse(file); @@ -106,7 +113,7 @@ export function pkeyToKeystore( pkey: Buffer, address: string, password: string -) { +): UtcKeystore { const salt = randomBytes(32); const iv = randomBytes(16); let derivedKey; diff --git a/common/libs/wallet/privkey.js b/common/libs/wallet/privkey.js index 05ca39a2..62404f14 100644 --- a/common/libs/wallet/privkey.js +++ b/common/libs/wallet/privkey.js @@ -11,6 +11,7 @@ import { signRawTxWithPrivKey, signMessageWithPrivKey } from 'libs/signing'; import { isValidPrivKey } from 'libs/validators'; import type { RawTransaction } from 'libs/transaction'; +import type { UtcKeystore } from 'libs/keystore'; export default class PrivKeyWallet extends BaseWallet { privKey: Buffer; @@ -40,7 +41,7 @@ export default class PrivKeyWallet extends BaseWallet { return new PrivKeyWallet(randomBytes(32)); } - toKeystore(password: string): Promise { + toKeystore(password: string): Promise { return new Promise(resolve => { this.getNakedAddress().then(address => { resolve(pkeyToKeystore(this.privKey, address, password));