Discourage private keys (pt. 1) (#780)
* Insecure wallet blocker warning before unlocking insecure wallet. * Wrap in quotes to avoid prettier error. * Make account the homepage. Add a link to generate on the wallet unlock component. * Fix send routing weirdness.
This commit is contained in:
parent
2ac3015ad8
commit
4fb342a757
|
@ -59,16 +59,15 @@ export default class Root extends Component<Props, State> {
|
||||||
const routes = (
|
const routes = (
|
||||||
<CaptureRouteNotFound>
|
<CaptureRouteNotFound>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact={true} path="/" component={GenerateWallet} />
|
<Redirect exact={true} from="/" to="/account" />
|
||||||
<Route path="/generate" component={GenerateWallet} />
|
|
||||||
<Route path="/account" component={SendTransaction} />
|
<Route path="/account" component={SendTransaction} />
|
||||||
|
<Route path="/generate" component={GenerateWallet} />
|
||||||
<Route path="/swap" component={Swap} />
|
<Route path="/swap" component={Swap} />
|
||||||
<Route path="/contracts" component={Contracts} />
|
<Route path="/contracts" component={Contracts} />
|
||||||
<Route path="/ens" component={ENS} />
|
<Route path="/ens" component={ENS} />
|
||||||
<Route path="/help" component={Help} />
|
<Route path="/help" component={Help} />
|
||||||
<Route path="/sign-and-verify-message" component={SignAndVerifyMessage} />
|
<Route path="/sign-and-verify-message" component={SignAndVerifyMessage} />
|
||||||
<Route path="/pushTx" component={BroadcastTx} />
|
<Route path="/pushTx" component={BroadcastTx} />
|
||||||
<Route path="/send-transaction" component={SendTransaction} />
|
|
||||||
<RouteNotFound />
|
<RouteNotFound />
|
||||||
</Switch>
|
</Switch>
|
||||||
</CaptureRouteNotFound>
|
</CaptureRouteNotFound>
|
||||||
|
|
|
@ -10,15 +10,14 @@ export interface TabLink {
|
||||||
}
|
}
|
||||||
|
|
||||||
const tabs: TabLink[] = [
|
const tabs: TabLink[] = [
|
||||||
{
|
|
||||||
name: 'NAV_GenerateWallet',
|
|
||||||
to: '/generate'
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
name: 'Account View & Send',
|
name: 'Account View & Send',
|
||||||
to: '/account'
|
to: '/account'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'NAV_GenerateWallet',
|
||||||
|
to: '/generate'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'NAV_Swap',
|
name: 'NAV_Swap',
|
||||||
to: '/swap'
|
to: '/swap'
|
||||||
|
|
|
@ -45,6 +45,12 @@ $speed: 500ms;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-generate {
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 300;
|
||||||
|
margin-top: $space;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-decrypt {
|
&-decrypt {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
import isEmpty from 'lodash/isEmpty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
import { TransitionGroup, CSSTransition } from 'react-transition-group';
|
import { TransitionGroup, CSSTransition } from 'react-transition-group';
|
||||||
import {
|
import {
|
||||||
|
@ -27,7 +28,8 @@ import {
|
||||||
TrezorDecrypt,
|
TrezorDecrypt,
|
||||||
ViewOnlyDecrypt,
|
ViewOnlyDecrypt,
|
||||||
Web3Decrypt,
|
Web3Decrypt,
|
||||||
WalletButton
|
WalletButton,
|
||||||
|
InsecureWalletWarning
|
||||||
} from './components';
|
} from './components';
|
||||||
import { AppState } from 'reducers';
|
import { AppState } from 'reducers';
|
||||||
import DISABLES from './disables';
|
import DISABLES from './disables';
|
||||||
|
@ -52,6 +54,7 @@ import { getNetworkConfig } from '../../selectors/config';
|
||||||
interface OwnProps {
|
interface OwnProps {
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
disabledWallets?: WalletName[];
|
disabledWallets?: WalletName[];
|
||||||
|
showGenerateLink?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DispatchProps {
|
interface DispatchProps {
|
||||||
|
@ -78,6 +81,7 @@ type UnlockParams = {} | PrivateKeyValue;
|
||||||
interface State {
|
interface State {
|
||||||
selectedWalletKey: WalletName | null;
|
selectedWalletKey: WalletName | null;
|
||||||
value: UnlockParams | null;
|
value: UnlockParams | null;
|
||||||
|
hasAcknowledgedInsecure: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BaseWalletInfo {
|
interface BaseWalletInfo {
|
||||||
|
@ -121,6 +125,10 @@ type Wallets = SecureWallets & InsecureWallets & MiscWallet;
|
||||||
const WEB3_TYPE: string | false =
|
const WEB3_TYPE: string | false =
|
||||||
(window as any).web3 && (window as any).web3.currentProvider.constructor.name;
|
(window as any).web3 && (window as any).web3.currentProvider.constructor.name;
|
||||||
|
|
||||||
|
const SECURE_WALLETS = Object.values(SecureWalletName);
|
||||||
|
const INSECURE_WALLETS = Object.values(InsecureWalletName);
|
||||||
|
const MISC_WALLETS = Object.values(MiscWalletName);
|
||||||
|
|
||||||
export class WalletDecrypt extends Component<Props, State> {
|
export class WalletDecrypt extends Component<Props, State> {
|
||||||
// https://github.com/Microsoft/TypeScript/issues/13042
|
// https://github.com/Microsoft/TypeScript/issues/13042
|
||||||
// index signature should become [key: Wallets] (from config) once typescript bug is fixed
|
// index signature should become [key: Wallets] (from config) once typescript bug is fixed
|
||||||
|
@ -197,7 +205,8 @@ export class WalletDecrypt extends Component<Props, State> {
|
||||||
|
|
||||||
public state: State = {
|
public state: State = {
|
||||||
selectedWalletKey: null,
|
selectedWalletKey: null,
|
||||||
value: null
|
value: null,
|
||||||
|
hasAcknowledgedInsecure: false
|
||||||
};
|
};
|
||||||
|
|
||||||
public componentWillReceiveProps(nextProps: Props) {
|
public componentWillReceiveProps(nextProps: Props) {
|
||||||
|
@ -220,36 +229,59 @@ export class WalletDecrypt extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public getDecryptionComponent() {
|
public getDecryptionComponent() {
|
||||||
|
const { selectedWalletKey, hasAcknowledgedInsecure } = this.state;
|
||||||
const selectedWallet = this.getSelectedWallet();
|
const selectedWallet = this.getSelectedWallet();
|
||||||
if (!selectedWallet) {
|
if (!selectedWalletKey || !selectedWallet) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (INSECURE_WALLETS.includes(selectedWalletKey) && !hasAcknowledgedInsecure) {
|
||||||
|
return (
|
||||||
|
<div className="WalletDecrypt-decrypt">
|
||||||
|
<InsecureWalletWarning
|
||||||
|
walletType={translate(selectedWallet.lid)}
|
||||||
|
onContinue={this.handleAcknowledgeInsecure}
|
||||||
|
onCancel={this.clearWalletChoice}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<selectedWallet.component
|
<div className="WalletDecrypt-decrypt">
|
||||||
value={this.state.value}
|
<button className="WalletDecrypt-decrypt-back" onClick={this.clearWalletChoice}>
|
||||||
onChange={this.onChange}
|
<i className="fa fa-arrow-left" /> {translate('Change Wallet')}
|
||||||
onUnlock={this.onUnlock}
|
</button>
|
||||||
showNotification={this.props.showNotification}
|
<h2 className="WalletDecrypt-decrypt-title">
|
||||||
isWalletPending={
|
{!selectedWallet.isReadOnly && 'Unlock your'} {translate(selectedWallet.lid)}
|
||||||
this.state.selectedWalletKey === InsecureWalletName.KEYSTORE_FILE
|
</h2>
|
||||||
? this.props.isWalletPending
|
<section className="WalletDecrypt-decrypt-form">
|
||||||
: undefined
|
<selectedWallet.component
|
||||||
}
|
value={this.state.value}
|
||||||
isPasswordPending={
|
onChange={this.onChange}
|
||||||
this.state.selectedWalletKey === InsecureWalletName.KEYSTORE_FILE
|
onUnlock={this.onUnlock}
|
||||||
? this.props.isPasswordPending
|
showNotification={this.props.showNotification}
|
||||||
: undefined
|
isWalletPending={
|
||||||
}
|
this.state.selectedWalletKey === InsecureWalletName.KEYSTORE_FILE
|
||||||
/>
|
? this.props.isWalletPending
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
isPasswordPending={
|
||||||
|
this.state.selectedWalletKey === InsecureWalletName.KEYSTORE_FILE
|
||||||
|
? this.props.isPasswordPending
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public buildWalletOptions() {
|
public handleAcknowledgeInsecure = () => {
|
||||||
const SECURE_WALLETS = Object.values(SecureWalletName);
|
this.setState({ hasAcknowledgedInsecure: true });
|
||||||
const INSECURE_WALLETS = Object.values(InsecureWalletName);
|
};
|
||||||
const MISC_WALLETS = Object.values(MiscWalletName);
|
|
||||||
|
|
||||||
|
public buildWalletOptions() {
|
||||||
return (
|
return (
|
||||||
<div className="WalletDecrypt-wallets">
|
<div className="WalletDecrypt-wallets">
|
||||||
<h2 className="WalletDecrypt-wallets-title">{translate('decrypt_Access')}</h2>
|
<h2 className="WalletDecrypt-wallets-title">{translate('decrypt_Access')}</h2>
|
||||||
|
@ -305,6 +337,12 @@ export class WalletDecrypt extends Component<Props, State> {
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{this.props.showGenerateLink && (
|
||||||
|
<div className="WalletDecrypt-wallets-generate">
|
||||||
|
Don’t have a wallet? <Link to="/generate">Click here to get one</Link>.
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -328,7 +366,8 @@ export class WalletDecrypt extends Component<Props, State> {
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedWalletKey: walletType,
|
selectedWalletKey: walletType,
|
||||||
value: wallet.initialParams
|
value: wallet.initialParams,
|
||||||
|
hasAcknowledgedInsecure: false
|
||||||
});
|
});
|
||||||
}, timeout);
|
}, timeout);
|
||||||
};
|
};
|
||||||
|
@ -336,7 +375,8 @@ export class WalletDecrypt extends Component<Props, State> {
|
||||||
public clearWalletChoice = () => {
|
public clearWalletChoice = () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedWalletKey: null,
|
selectedWalletKey: null,
|
||||||
value: null
|
value: null,
|
||||||
|
hasAcknowledgedInsecure: false
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -352,21 +392,7 @@ export class WalletDecrypt extends Component<Props, State> {
|
||||||
<TransitionGroup>
|
<TransitionGroup>
|
||||||
{decryptionComponent && selectedWallet ? (
|
{decryptionComponent && selectedWallet ? (
|
||||||
<CSSTransition classNames="DecryptContent" timeout={500} key="decrypt">
|
<CSSTransition classNames="DecryptContent" timeout={500} key="decrypt">
|
||||||
<div className="WalletDecrypt-decrypt">
|
{decryptionComponent}
|
||||||
<button
|
|
||||||
className="WalletDecrypt-decrypt-back"
|
|
||||||
onClick={this.clearWalletChoice}
|
|
||||||
>
|
|
||||||
<i className="fa fa-arrow-left" /> {translate('Change Wallet')}
|
|
||||||
</button>
|
|
||||||
<h2 className="WalletDecrypt-decrypt-title">
|
|
||||||
{!selectedWallet.isReadOnly && 'Unlock your'}{' '}
|
|
||||||
{translate(selectedWallet.lid)}
|
|
||||||
</h2>
|
|
||||||
<section className="WalletDecrypt-decrypt-form">
|
|
||||||
{decryptionComponent}
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</CSSTransition>
|
</CSSTransition>
|
||||||
) : (
|
) : (
|
||||||
<CSSTransition classNames="DecryptContent" timeout={500} key="wallets">
|
<CSSTransition classNames="DecryptContent" timeout={500} key="wallets">
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
@import 'common/sass/variables';
|
||||||
|
|
||||||
|
.WalletWarning {
|
||||||
|
max-width: 780px;
|
||||||
|
margin: 0 auto;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
&-title {
|
||||||
|
color: $brand-danger;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-desc {
|
||||||
|
margin-bottom: $space;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-check {
|
||||||
|
margin-bottom: $space * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-checkboxes {
|
||||||
|
margin-bottom: $space * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-bottom: -$space-sm;
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 280px;
|
||||||
|
margin: 0 $space-sm $space-sm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.AcknowledgeCheckbox {
|
||||||
|
margin-bottom: $space-sm;
|
||||||
|
|
||||||
|
&-checkbox[type="checkbox"] {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: $space-sm;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-label {
|
||||||
|
font-size: $font-size-bump-more;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,138 @@
|
||||||
|
import React from 'react';
|
||||||
|
import './InsecureWalletWarning.scss';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
walletType: string | React.ReactElement<string>;
|
||||||
|
onContinue(): void;
|
||||||
|
onCancel(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
hasConfirmedSite: boolean;
|
||||||
|
hasAcknowledgedDownload: boolean;
|
||||||
|
hasAcknowledgedWallets: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Checkbox {
|
||||||
|
name: keyof State;
|
||||||
|
label: string | React.ReactElement<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class InsecureWalletWarning extends React.Component<Props, State> {
|
||||||
|
public state: State = {
|
||||||
|
hasConfirmedSite: false,
|
||||||
|
hasAcknowledgedDownload: false,
|
||||||
|
hasAcknowledgedWallets: false
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
if (process.env.BUILD_DOWNLOADABLE) {
|
||||||
|
props.onContinue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
if (process.env.BUILD_DOWNLOADABLE) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { walletType, onContinue, onCancel } = this.props;
|
||||||
|
const checkboxes: Checkbox[] = [
|
||||||
|
{
|
||||||
|
name: 'hasAcknowledgedWallets',
|
||||||
|
label: 'I acknowledge that I can and should use MetaMask or a Hardware Wallet'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'hasAcknowledgedDownload',
|
||||||
|
label: 'I acknowledge that I can and should download and run MyEtherWallet locally'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'hasConfirmedSite',
|
||||||
|
label:
|
||||||
|
'I have checked the URL and SSL certificate to make sure this is the real MyEtherWallet'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const canContinue = checkboxes.reduce(
|
||||||
|
(prev, checkbox) => prev && this.state[checkbox.name],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="WalletWarning">
|
||||||
|
<h2 className="WalletWarning-title">
|
||||||
|
This is <u>not</u> a recommended way to access your wallet
|
||||||
|
</h2>
|
||||||
|
<p className="WalletWarning-desc">
|
||||||
|
Entering your {walletType} on a website is <strong>dangerous</strong>. If our website is
|
||||||
|
compromised, or you accidentally visit a phishing website, you could{' '}
|
||||||
|
<strong>lose all of your funds</strong>. Before you continue, please consider:
|
||||||
|
</p>
|
||||||
|
<ul className="WalletWarning-bullets">
|
||||||
|
<li>
|
||||||
|
Using{' '}
|
||||||
|
<a href="https://myetherwallet.github.io/knowledge-base/migration/moving-from-private-key-to-metamask.html">
|
||||||
|
MetaMask
|
||||||
|
</a>{' '}
|
||||||
|
or a{' '}
|
||||||
|
<a href="https://myetherwallet.github.io/knowledge-base/hardware-wallets/hardware-wallet-recommendations.html">
|
||||||
|
Hardware Wallet
|
||||||
|
</a>{' '}
|
||||||
|
to access your wallet
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://myetherwallet.github.io/knowledge-base/offline/running-myetherwallet-locally.html">
|
||||||
|
Downloading MEW and running it offline & locally
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Reading{' '}
|
||||||
|
<a href="https://myetherwallet.github.io/knowledge-base/security/securing-your-ethereum.html">
|
||||||
|
How to Protect Yourself and Your Funds
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p className="WalletWarning-check">
|
||||||
|
If you must use your {walletType} online, please double-check the URL & SSL certificate.
|
||||||
|
It should say <code>{'https://www.myetherwallet.com'}</code>
|
||||||
|
& <code>MYETHERWALLET LLC [US]</code> in your URL bar.
|
||||||
|
</p>
|
||||||
|
<div className="WalletWarning-checkboxes">{checkboxes.map(this.makeCheckbox)}</div>
|
||||||
|
|
||||||
|
<div className="WalletWarning-buttons">
|
||||||
|
<button className="WalletWarning-cancel btn btn-lg btn-default" onClick={onCancel}>
|
||||||
|
Go Back
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="WalletWarning-continue btn btn-lg btn-primary"
|
||||||
|
onClick={onContinue}
|
||||||
|
disabled={!canContinue}
|
||||||
|
>
|
||||||
|
Continue
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private makeCheckbox = (checkbox: Checkbox) => {
|
||||||
|
return (
|
||||||
|
<label className="AcknowledgeCheckbox">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
name={checkbox.name}
|
||||||
|
className="AcknowledgeCheckbox-checkbox"
|
||||||
|
onChange={this.handleCheckboxChange}
|
||||||
|
checked={this.state[checkbox.name]}
|
||||||
|
/>
|
||||||
|
<span className="AcknowledgeCheckbox-label">{checkbox.label}</span>
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
private handleCheckboxChange = (ev: React.FormEvent<HTMLInputElement>) => {
|
||||||
|
this.setState({
|
||||||
|
[ev.currentTarget.name as any]: !!ev.currentTarget.checked
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
|
@ -93,6 +93,8 @@ export class PrivateKeyDecrypt extends Component<Props> {
|
||||||
};
|
};
|
||||||
|
|
||||||
public onPasswordChange = (e: React.FormEvent<HTMLInputElement>) => {
|
public onPasswordChange = (e: React.FormEvent<HTMLInputElement>) => {
|
||||||
|
// NOTE: Textareas don't support password type, so we replace the value
|
||||||
|
// with an equal length number of dots. On change, we replace
|
||||||
const pkey = this.props.value.key;
|
const pkey = this.props.value.key;
|
||||||
const pass = e.currentTarget.value;
|
const pass = e.currentTarget.value;
|
||||||
const { valid } = validatePkeyAndPass(pkey, pass);
|
const { valid } = validatePkeyAndPass(pkey, pass);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
export * from './DeterministicWalletsModal';
|
export * from './DeterministicWalletsModal';
|
||||||
export * from './DigitalBitbox';
|
export * from './DigitalBitbox';
|
||||||
|
export * from './InsecureWalletWarning';
|
||||||
export * from './Keystore';
|
export * from './Keystore';
|
||||||
export * from './LedgerNano';
|
export * from './LedgerNano';
|
||||||
export * from './Mnemonic';
|
export * from './Mnemonic';
|
||||||
|
|
|
@ -11,6 +11,7 @@ interface Props {
|
||||||
title: TranslateType;
|
title: TranslateType;
|
||||||
wallet: IWallet;
|
wallet: IWallet;
|
||||||
disabledWallets?: WalletName[];
|
disabledWallets?: WalletName[];
|
||||||
|
showGenerateLink?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
|
@ -29,7 +30,7 @@ export class UnlockHeader extends React.PureComponent<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const { title, wallet, disabledWallets } = this.props;
|
const { title, wallet, disabledWallets, showGenerateLink } = this.props;
|
||||||
const { isExpanded } = this.state;
|
const { isExpanded } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -55,7 +56,11 @@ export class UnlockHeader extends React.PureComponent<Props, State> {
|
||||||
<i className="fa fa-times" />
|
<i className="fa fa-times" />
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<WalletDecrypt hidden={!this.state.isExpanded} disabledWallets={disabledWallets} />
|
<WalletDecrypt
|
||||||
|
hidden={!this.state.isExpanded}
|
||||||
|
disabledWallets={disabledWallets}
|
||||||
|
showGenerateLink={showGenerateLink}
|
||||||
|
/>
|
||||||
</article>
|
</article>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,39 +56,41 @@ class SendTransaction extends React.Component<Props> {
|
||||||
return (
|
return (
|
||||||
<TabSection>
|
<TabSection>
|
||||||
<section className="Tab-content">
|
<section className="Tab-content">
|
||||||
<UnlockHeader title={translate('Account')} />
|
<UnlockHeader title={translate('Account')} showGenerateLink={true} />
|
||||||
<div className="SubTabs row">
|
{wallet && (
|
||||||
<div className="col-sm-8">{wallet && <SubTabs tabs={tabs} match={match} />}</div>
|
<div className="SubTabs row">
|
||||||
<div className="col-sm-8">
|
<div className="col-sm-8">
|
||||||
<Switch>
|
<SubTabs tabs={tabs} match={match} />
|
||||||
<Route
|
</div>
|
||||||
exact={true}
|
<div className="col-sm-8">
|
||||||
path={currentPath}
|
<Switch>
|
||||||
render={() => (
|
<Route
|
||||||
<Redirect
|
exact={true}
|
||||||
from={`${currentPath}`}
|
path={currentPath}
|
||||||
to={`${
|
render={() => (
|
||||||
wallet && wallet.isReadOnly ? currentPath + '/info' : currentPath + '/send'
|
<Redirect
|
||||||
}`}
|
from={`${currentPath}`}
|
||||||
/>
|
to={`${wallet.isReadOnly ? `${currentPath}/info` : `${currentPath}/send`}`}
|
||||||
)}
|
/>
|
||||||
/>
|
)}
|
||||||
<Route exact={true} path={`${currentPath}/send`} component={Send} />
|
/>
|
||||||
<Route
|
<Route exact={true} path={`${currentPath}/send`} component={Send} />
|
||||||
path={`${currentPath}/info`}
|
<Route
|
||||||
exact={true}
|
path={`${currentPath}/info`}
|
||||||
render={() => wallet && <WalletInfo wallet={wallet} />}
|
exact={true}
|
||||||
/>
|
render={() => <WalletInfo wallet={wallet} />}
|
||||||
<Route
|
/>
|
||||||
path={`${currentPath}/request`}
|
<Route
|
||||||
exact={true}
|
path={`${currentPath}/request`}
|
||||||
render={() => <RequestPayment wallet={wallet} />}
|
exact={true}
|
||||||
/>
|
render={() => <RequestPayment wallet={wallet} />}
|
||||||
<RouteNotFound />
|
/>
|
||||||
</Switch>
|
<RouteNotFound />
|
||||||
|
</Switch>
|
||||||
|
</div>
|
||||||
|
<SideBar />
|
||||||
</div>
|
</div>
|
||||||
<SideBar />
|
)}
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
</TabSection>
|
</TabSection>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue