From c88e96d603863abb477919a6865b5a0a6a8db857 Mon Sep 17 00:00:00 2001 From: skubakdj Date: Fri, 15 Sep 2017 15:29:38 -0400 Subject: [PATCH] Wallet Decrypt - Mnemonic (#180) * add 'bip39' package * add mnemonic decrypt, wallet wrapper * add mnemonic path config * add mnemonic support to deterministic components * add mnemonic support * accomodate for ledger ETH path * remove comments * update comments regarding path length * rename modal open handler * make several props optional * add basic tests for mnemonic decrypt * make flow happy, add user error notifications * convert dpaths to js file, update references * add ledger path to test * Trezor DPath Fix (#196) * Match v3 more closely. * Require wallet index on deterministic wallets, update trezor to send index. * remove redundent stripAndLower function and rename existing stripHex to stripHexPrefixAndLower --- common/actions/deterministicWallets.js | 13 +- common/actions/wallet.js | 22 +++ .../DeterministicWalletsModal.jsx | 31 +++-- common/components/WalletDecrypt/Mnemonic.jsx | 130 ++++++++++++++++-- common/components/WalletDecrypt/Trezor.jsx | 6 +- common/components/WalletDecrypt/index.jsx | 10 +- common/config/dpaths.js | 50 +++++++ common/config/dpaths.json | 16 --- common/libs/decrypt.js | 30 ++++ common/libs/transaction.js | 6 +- common/libs/validators.js | 9 +- common/libs/values.js | 2 +- common/libs/wallet/deterministic.js | 6 +- common/libs/wallet/index.js | 1 + common/libs/wallet/mnemonic.js | 9 ++ common/libs/wallet/privkey.js | 4 +- common/libs/wallet/trezor.js | 16 +-- common/sagas/deterministicWallets.js | 83 +++++++---- common/sagas/wallet.js | 24 +++- package.json | 1 + spec/libs/decrypt.spec.js | 120 +++++++++++++++- 21 files changed, 488 insertions(+), 101 deletions(-) create mode 100644 common/config/dpaths.js delete mode 100644 common/config/dpaths.json create mode 100644 common/libs/wallet/mnemonic.js diff --git a/common/actions/deterministicWallets.js b/common/actions/deterministicWallets.js index c6f277f2..ee30d31c 100644 --- a/common/actions/deterministicWallets.js +++ b/common/actions/deterministicWallets.js @@ -14,18 +14,20 @@ export type DeterministicWalletData = { export type GetDeterministicWalletsAction = { type: 'DW_GET_WALLETS', payload: { + seed: ?string, dPath: string, - publicKey: string, - chainCode: string, + publicKey: ?string, + chainCode: ?string, limit: number, offset: number } }; export type GetDeterministicWalletsArgs = { + seed: ?string, dPath: string, - publicKey: string, - chainCode: string, + publicKey: ?string, + chainCode: ?string, limit?: number, offset?: number }; @@ -33,10 +35,11 @@ export type GetDeterministicWalletsArgs = { export function getDeterministicWallets( args: GetDeterministicWalletsArgs ): GetDeterministicWalletsAction { - const { dPath, publicKey, chainCode, limit, offset } = args; + const { seed, dPath, publicKey, chainCode, limit, offset } = args; return { type: 'DW_GET_WALLETS', payload: { + seed, dPath, publicKey, chainCode, diff --git a/common/actions/wallet.js b/common/actions/wallet.js index 39a9b6b9..aafe9131 100644 --- a/common/actions/wallet.js +++ b/common/actions/wallet.js @@ -43,6 +43,28 @@ export function unlockKeystore( }; } +/*** Unlock Mnemonic ***/ +export type MnemonicUnlockParams = { + phrase: string, + pass: string, + path: string, + address: string +}; + +export type UnlockMnemonicAction = { + type: 'WALLET_UNLOCK_MNEMONIC', + payload: MnemonicUnlockParams +}; + +export function unlockMnemonic( + value: MnemonicUnlockParams +): UnlockMnemonicAction { + return { + type: 'WALLET_UNLOCK_MNEMONIC', + payload: value + }; +} + /*** Set Wallet ***/ export type SetWalletAction = { type: 'WALLET_SET', diff --git a/common/components/WalletDecrypt/DeterministicWalletsModal.jsx b/common/components/WalletDecrypt/DeterministicWalletsModal.jsx index 3fd7b6eb..032441ff 100644 --- a/common/components/WalletDecrypt/DeterministicWalletsModal.jsx +++ b/common/components/WalletDecrypt/DeterministicWalletsModal.jsx @@ -36,15 +36,17 @@ type Props = { walletType: ?string, dPath: string, dPaths: { label: string, value: string }[], - publicKey: string, - chainCode: string, + publicKey: ?string, + chainCode: ?string, + seed: ?string, onCancel: () => void, - onConfirmAddress: string => void, + onConfirmAddress: (string, number) => void, onPathChange: string => void }; type State = { selectedAddress: string, + selectedAddrIndex: number, isCustomPath: boolean, customPath: string, page: number @@ -54,6 +56,7 @@ class DeterministicWalletsModal extends React.Component { props: Props; state: State = { selectedAddress: '', + selectedAddrIndex: 0, isCustomPath: false, customPath: '', page: 0 @@ -64,20 +67,23 @@ class DeterministicWalletsModal extends React.Component { } componentWillReceiveProps(nextProps) { - const { publicKey, chainCode } = this.props; + const { publicKey, chainCode, seed, dPath } = this.props; if ( nextProps.publicKey !== publicKey || - nextProps.chainCode !== chainCode + nextProps.chainCode !== chainCode || + nextProps.dPath !== dPath || + nextProps.seed !== seed ) { this._getAddresses(nextProps); } } _getAddresses(props: Props = this.props) { - const { dPath, publicKey, chainCode } = props; + const { dPath, publicKey, chainCode, seed } = props; - if (dPath && publicKey && chainCode && isValidPath(dPath)) { + if (dPath && ((publicKey && chainCode) || seed) && isValidPath(dPath)) { this.props.getDeterministicWallets({ + seed, dPath, publicKey, chainCode, @@ -116,12 +122,15 @@ class DeterministicWalletsModal extends React.Component { _handleConfirmAddress = () => { if (this.state.selectedAddress) { - this.props.onConfirmAddress(this.state.selectedAddress); + this.props.onConfirmAddress( + this.state.selectedAddress, + this.state.selectedAddrIndex + ); } }; - _selectAddress(selectedAddress) { - this.setState({ selectedAddress }); + _selectAddress(selectedAddress, selectedAddrIndex) { + this.setState({ selectedAddress, selectedAddrIndex }); } _nextPage = () => { @@ -148,7 +157,7 @@ class DeterministicWalletsModal extends React.Component { return ( {wallet.index + 1} diff --git a/common/components/WalletDecrypt/Mnemonic.jsx b/common/components/WalletDecrypt/Mnemonic.jsx index 2c6bb22a..98cc58ce 100644 --- a/common/components/WalletDecrypt/Mnemonic.jsx +++ b/common/components/WalletDecrypt/Mnemonic.jsx @@ -1,27 +1,129 @@ import React, { Component } from 'react'; -import translate from 'translations'; +import translate, { translateRaw } from 'translations'; +import { validateMnemonic, mnemonicToSeed } from 'bip39'; + +import DeterministicWalletsModal from './DeterministicWalletsModal'; + +import DPATHS from 'config/dpaths.js'; +const DEFAULT_PATH = DPATHS.MNEMONIC[0].value; + +type State = { + phrase: string, + pass: string, + seed: string, + dPath: string +}; export default class MnemonicDecrypt extends Component { + props: { onUnlock: any => void }; + state: State = { + phrase: '', + pass: '', + seed: '', + dPath: DEFAULT_PATH + }; + render() { + const { phrase, seed, dPath, pass } = this.state; + const isValidMnemonic = validateMnemonic(phrase); + return (
-
-

{translate('ADD_Radio_2_alt')}

- +
+

+ {translate('ADD_Radio_5')} +

- - - - {translate('ADD_Radio_2_short')} - +