Fix Ledger DPaths, Improve Error Messaging (#1517)

This commit is contained in:
William O'Beirne 2018-04-16 19:07:00 -04:00 committed by Daniel Ternyak
parent 8ce45a0c83
commit 2ddd5df7dc
7 changed files with 68 additions and 47 deletions

View File

@ -199,15 +199,19 @@ class DeterministicWalletsModalClass extends React.PureComponent<Props, State> {
private getAddresses(props: Props = this.props) {
const { dPath, publicKey, chainCode, seed } = props;
if (dPath && ((publicKey && chainCode) || seed) && isValidPath(dPath)) {
this.props.getDeterministicWallets({
seed,
dPath,
publicKey,
chainCode,
limit: WALLETS_PER_PAGE,
offset: WALLETS_PER_PAGE * this.state.page
});
if (dPath && ((publicKey && chainCode) || seed)) {
if (isValidPath(dPath)) {
this.props.getDeterministicWallets({
seed,
dPath,
publicKey,
chainCode,
limit: WALLETS_PER_PAGE,
offset: WALLETS_PER_PAGE * this.state.page
});
} else {
console.error('Invalid dPath provided', dPath);
}
}
}

View File

@ -9,6 +9,8 @@ import { connect } from 'react-redux';
import { AppState } from 'reducers';
import { SecureWalletName, ledgerReferralURL } from 'config';
import { getPaths, getSingleDPath } from 'selectors/config/wallet';
import { getNetworkConfig } from 'selectors/config';
import { NetworkConfig } from 'types/network';
import './LedgerNano.scss';
interface OwnProps {
@ -18,6 +20,7 @@ interface OwnProps {
interface StateProps {
dPath: DPath | undefined;
dPaths: DPath[];
network: NetworkConfig;
}
interface State {
@ -54,6 +57,7 @@ class LedgerNanoSDecryptClass extends PureComponent<Props, State> {
}
public render() {
const { network } = this.props;
const { dPath, publicKey, chainCode, error, isLoading, showTip } = this.state;
const showErr = error ? 'is-showing' : '';
@ -74,12 +78,6 @@ class LedgerNanoSDecryptClass extends PureComponent<Props, State> {
return (
<div className="LedgerDecrypt">
{showTip && (
<p>
<strong>Tip: </strong>Make sure you're logged into the ethereum app on your hardware
wallet
</p>
)}
<button
className="LedgerDecrypt-decrypt btn btn-primary btn-lg btn-block"
onClick={this.handleNullConnect}
@ -101,6 +99,10 @@ class LedgerNanoSDecryptClass extends PureComponent<Props, State> {
<div className={`LedgerDecrypt-error alert alert-danger ${showErr}`}>{error || '-'}</div>
{showTip && (
<p className="LedgerDecrypt-tip">{translate('LEDGER_TIP', { $network: network.unit })}</p>
)}
<div className="LedgerDecrypt-help">
<NewTabLink href="https://support.ledgerwallet.com/hc/en-us/articles/115005200009">
{translate('HELP_ARTICLE_1')}
@ -143,13 +145,34 @@ class LedgerNanoSDecryptClass extends PureComponent<Props, State> {
});
})
.catch((err: any) => {
let showTip;
let errMsg;
// Timeout
if (err && err.metaData && err.metaData.code === 5) {
this.showTip();
showTip = true;
errMsg = translateRaw('LEDGER_TIMEOUT');
}
// Wrong app logged into
if (err && err.includes && err.includes('6804')) {
showTip = true;
errMsg = translateRaw('LEDGER_WRONG_APP');
}
// Ledger locked
if (err && err.includes && err.includes('6801')) {
errMsg = translateRaw('LEDGER_LOCKED');
}
// Other
if (!errMsg) {
errMsg = err && err.metaData ? err.metaData.type : err.toString();
}
this.setState({
error: err && err.metaData ? err.metaData.type : err.toString(),
error: errMsg,
isLoading: false
});
if (showTip) {
this.showTip();
}
});
});
};
@ -179,7 +202,8 @@ class LedgerNanoSDecryptClass extends PureComponent<Props, State> {
function mapStateToProps(state: AppState): StateProps {
return {
dPath: getSingleDPath(state, SecureWalletName.LEDGER_NANO_S),
dPaths: getPaths(state, SecureWalletName.LEDGER_NANO_S)
dPaths: getPaths(state, SecureWalletName.LEDGER_NANO_S),
network: getNetworkConfig(state)
};
}

View File

@ -15,7 +15,7 @@ export const ETH_LEDGER: DPath = {
export const ETC_LEDGER: DPath = {
label: 'Ledger (ETC)',
value: "m/44'/60'/160720'/0"
value: "m/44'/60'/160720'/0'"
};
export const ETC_TREZOR: DPath = {
@ -86,5 +86,5 @@ export const EXTRA_PATHS = [ETH_SINGULAR];
// whitespace strings are evaluated the same way as nospace strings, except they allow optional spaces between each portion of the string
// ie. "m / 44' / 0' / 0'" is valid, "m / 4 4' / 0' / 0'" is invalid
export const dPathRegex = /m\/(44|0)'\/[0-9]+\'\/[0-9]+(\'+$|\'+(\/[0-1]+$))/;
export const dPathRegex = /m\/44'\/[0-9]+\'\/[0-9]+(\'+$|\'+(\/[0-1]+$))/;
// export const whitespaceDPathRegex = /m\s*\/\s*44'\s*\/\s*[0-9]+\'\s*\/\s*[0-9]+(\'+$|\'+\s*(\/\s*[0-1]+$))/;

View File

@ -11,7 +11,7 @@ import {
GAS_PRICE_GWEI_LOWER_BOUND,
GAS_PRICE_GWEI_UPPER_BOUND
} from 'config/constants';
import { dPathRegex } from 'config/dpaths';
import { dPathRegex, ETC_LEDGER, ETH_SINGULAR } from 'config/dpaths';
import { EAC_SCHEDULING_CONFIG } from './scheduling';
import BN from 'bn.js';
@ -126,6 +126,16 @@ export function isPositiveIntegerOrZero(num: number): boolean {
}
export function isValidPath(dPath: string) {
// ETC Ledger is incorrect up due to an extra ' at the end of it
if (dPath === ETC_LEDGER.value) {
return true;
}
// SingularDTV is incorrect due to using a 0 instead of a 44 as the purpose
if (dPath === ETH_SINGULAR.value) {
return true;
}
return dPathRegex.test(dPath);
}

View File

@ -68,7 +68,7 @@ export const INITIAL_STATE: State = {
isTestnet: true,
dPathFormats: {
[SecureWalletName.TREZOR]: ETH_TESTNET,
[SecureWalletName.LEDGER_NANO_S]: ETH_TESTNET,
[SecureWalletName.LEDGER_NANO_S]: ETH_LEDGER,
[InsecureWalletName.MNEMONIC_PHRASE]: ETH_TESTNET
},
gasPriceSettings: testnetDefaultGasPrice
@ -88,7 +88,7 @@ export const INITIAL_STATE: State = {
isTestnet: true,
dPathFormats: {
[SecureWalletName.TREZOR]: ETH_TESTNET,
[SecureWalletName.LEDGER_NANO_S]: ETH_TESTNET,
[SecureWalletName.LEDGER_NANO_S]: ETH_LEDGER,
[InsecureWalletName.MNEMONIC_PHRASE]: ETH_TESTNET
},
gasPriceSettings: testnetDefaultGasPrice
@ -108,7 +108,7 @@ export const INITIAL_STATE: State = {
isTestnet: true,
dPathFormats: {
[SecureWalletName.TREZOR]: ETH_TESTNET,
[SecureWalletName.LEDGER_NANO_S]: ETH_TESTNET,
[SecureWalletName.LEDGER_NANO_S]: ETH_LEDGER,
[InsecureWalletName.MNEMONIC_PHRASE]: ETH_TESTNET
},
gasPriceSettings: testnetDefaultGasPrice
@ -199,7 +199,7 @@ export const INITIAL_STATE: State = {
contracts: [],
dPathFormats: {
[SecureWalletName.TREZOR]: POA_DEFAULT,
[SecureWalletName.LEDGER_NANO_S]: POA_DEFAULT,
[SecureWalletName.LEDGER_NANO_S]: ETH_LEDGER,
[InsecureWalletName.MNEMONIC_PHRASE]: POA_DEFAULT
},
gasPriceSettings: {
@ -221,6 +221,7 @@ export const INITIAL_STATE: State = {
tokens: [],
contracts: [],
dPathFormats: {
[SecureWalletName.LEDGER_NANO_S]: ETH_LEDGER,
[SecureWalletName.TREZOR]: ETH_TREZOR,
[SecureWalletName.LEDGER_NANO_S]: TOMO_DEFAULT,
[InsecureWalletName.MNEMONIC_PHRASE]: TOMO_DEFAULT

View File

@ -25,28 +25,6 @@
}
}
// Alert icons
.alert:after {
content: '';
background-position: 50%;
background-repeat: no-repeat;
background-size: contain;
display: block;
color: #fff;
position: absolute;
top: 0;
bottom: 0;
left: 1%;
width: $space * 2;
@media screen and (max-width: $screen-sm) {
left: 3%;
}
@media screen and (max-width: $screen-xs) {
left: 1%;
}
}
.alert,
.alert-info {
@include alert-variant($alert-info-bg, $alert-info-border, $alert-info-text);

View File

@ -384,6 +384,10 @@
"ETHER_ADDRESS_LOOKUP": "Ether Address Lookup",
"LEDGER_REFERRAL_1": "Buy a Ledger Wallet",
"LEDGER_REFERRAL_2": "Dont have a Ledger? Order one now!",
"LEDGER_TIP": "**Tip:** Make sure you're logged into the $network app on your hardware wallet, and have enabled browser support in the settings",
"LEDGER_TIMEOUT": "The request timed out",
"LEDGER_WRONG_APP": "Wrong application selected on your device",
"LEDGER_LOCKED": "Your Ledger device is locked",
"TREZOR_REFERAL": "Buy a TREZOR",
"ETHERCARD_REFERAL": "Get an ether.card",
"DISCLAIMER": "Disclaimer",