@@ -117,131 +123,120 @@ export default class SelectHardware extends Component {
);
}
- getAffiliateLinks() {
- const links = {
- trezor: `
Trezor`,
- ledger: `
Ledger`,
- };
-
- const text = this.context.t('orderOneHere');
- const response = text
- .replace('Trezor', links.trezor)
- .replace('Ledger', links.ledger);
-
- return (
-
- );
- }
-
- renderTrezorAffiliateLink() {
- return (
-
-
- {this.context.t('dontHaveAHardwareWallet')}
-
- {this.getAffiliateLinks()}
-
- );
+ renderTutorialsteps() {
+ switch (this.state.selectedDevice) {
+ case 'ledger':
+ return this.renderLedgerTutorialSteps();
+ case 'trezor':
+ return this.renderTrezorTutorialSteps();
+ default:
+ return '';
+ }
}
- scrollToTutorial = () => {
- if (this.referenceNode) {
- this.referenceNode.scrollIntoView({ behavior: 'smooth' });
+ renderLedgerTutorialSteps() {
+ const steps = [];
+ if (this.props.useLedgerLive) {
+ steps.push({
+ title: this.context.t('step1LedgerWallet'),
+ message: this.context.t('step1LedgerWalletMsg', [
+
+ {this.context.t('ledgerLiveApp')}
+ ,
+ ]),
+ });
}
- };
- renderLearnMore() {
+ steps.push({
+ asset: 'plug-in-wallet',
+ dimensions: { width: '225px', height: '75px' },
+ title: this.context.t('step2LedgerWallet'),
+ message: this.context.t('step2LedgerWalletMsg', [
+
+ {this.context.t('hardwareWalletSupportLinkConversion')}
+ ,
+ ]),
+ });
+
return (
-
- {this.context.t('learnMore')}
-
-
+
+ {steps.map((step, index) => (
+
+
{step.title}
+
{step.message}
+ {step.asset && (
+
+ )}
+
+ ))}
+
);
}
- renderTutorialSteps() {
+ renderTrezorTutorialSteps() {
const steps = [
{
- asset: 'hardware-wallet-step-1',
+ asset: 'plug-in-wallet',
dimensions: { width: '225px', height: '75px' },
- title: this.context.t('step1HardwareWallet'),
- message: this.context.t('step1HardwareWalletMsg'),
- },
- {
- asset: 'hardware-wallet-step-2',
- dimensions: { width: '300px', height: '100px' },
- title: this.context.t('step2HardwareWallet'),
- message: this.context.t('step2HardwareWalletMsg'),
- },
- {
- asset: 'hardware-wallet-step-3',
- dimensions: { width: '120px', height: '90px' },
- title: this.context.t('step3HardwareWallet'),
- message: this.context.t('step3HardwareWalletMsg'),
+ title: this.context.t('step1TrezorWallet'),
+ message: this.context.t('step1TrezorWalletMsg', [
+
+ {this.context.t('hardwareWalletSupportLinkConversion')}
+ ,
+ ]),
},
];
return (
-
{
- this.referenceNode = node;
- }}
- >
+
{steps.map((step, index) => (
{step.title}
{step.message}
-
+ {step.asset && (
+
+ )}
))}
);
}
- renderFooter() {
- return (
-
- );
- }
-
renderConnectScreen() {
return (
{this.renderHeader()}
{this.renderButtons()}
- {this.renderTrezorAffiliateLink()}
- {this.renderLearnMore()}
- {this.renderTutorialSteps()}
- {this.renderFooter()}
+ {this.state.selectedDevice && this.renderTutorialsteps()}
+ {this.renderContinueButton()}
);
}
diff --git a/ui/app/pages/create-account/create-account.component.js b/ui/app/pages/create-account/create-account.component.js
index 4eaefce52..4cba7b261 100644
--- a/ui/app/pages/create-account/create-account.component.js
+++ b/ui/app/pages/create-account/create-account.component.js
@@ -1,7 +1,6 @@
import React, { Component } from 'react';
-import { Switch, Route, matchPath } from 'react-router-dom';
-import PropTypes from 'prop-types';
-import classnames from 'classnames';
+import { Switch, Route } from 'react-router-dom';
+
import {
NEW_ACCOUNT_ROUTE,
IMPORT_ACCOUNT_ROUTE,
@@ -12,53 +11,9 @@ import NewAccountImportForm from './import-account';
import ConnectHardwareForm from './connect-hardware';
export default class CreateAccountPage extends Component {
- renderTabs() {
- const {
- history,
- location: { pathname },
- } = this.props;
- const getClassNames = (path) =>
- classnames('new-account__tabs__tab', {
- 'new-account__tabs__selected': matchPath(pathname, {
- path,
- exact: true,
- }),
- });
-
- return (
-
-
history.push(NEW_ACCOUNT_ROUTE)}
- >
- {this.context.t('create')}
-
-
history.push(IMPORT_ACCOUNT_ROUTE)}
- >
- {this.context.t('import')}
-
-
history.push(CONNECT_HARDWARE_ROUTE)}
- >
- {this.context.t('hardware')}
-
-
- );
- }
-
render() {
return (
-
-
- {this.renderTabs()}
-
-
{
- let wrapper;
-
- const props = {
- history: {
- push: sinon.spy(),
- },
- location: {
- pathname: '/new-account',
- },
- };
-
- beforeAll(() => {
- wrapper = mountWithRouter();
- });
-
- afterEach(() => {
- props.history.push.resetHistory();
- });
-
- it('clicks create account and routes to new-account path', () => {
- const createAccount = wrapper.find('.new-account__tabs__tab').at(0);
- createAccount.simulate('click');
- expect(props.history.push.getCall(0).args[0]).toStrictEqual('/new-account');
- });
-
- it('clicks import account and routes to import new account path', () => {
- const importAccount = wrapper.find('.new-account__tabs__tab').at(1);
- importAccount.simulate('click');
- expect(props.history.push.getCall(0).args[0]).toStrictEqual(
- '/new-account/import',
- );
- });
-
- it('clicks connect HD Wallet and routes to connect new account path', () => {
- const connectHdWallet = wrapper.find('.new-account__tabs__tab').at(2);
- connectHdWallet.simulate('click');
- expect(props.history.push.getCall(0).args[0]).toStrictEqual(
- '/new-account/connect',
- );
- });
-});
diff --git a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js b/ui/app/pages/settings/advanced-tab/advanced-tab.component.js
index 742d1c233..ef95e84f2 100644
--- a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js
+++ b/ui/app/pages/settings/advanced-tab/advanced-tab.component.js
@@ -7,6 +7,9 @@ import TextField from '../../../components/ui/text-field';
import Button from '../../../components/ui/button';
import { MOBILE_SYNC_ROUTE } from '../../../helpers/constants/routes';
+import { getPlatform } from '../../../../../app/scripts/lib/util';
+import { PLATFORM_FIREFOX } from '../../../../../shared/constants/app';
+
export default class AdvancedTab extends PureComponent {
static contextTypes = {
t: PropTypes.func,
@@ -33,6 +36,8 @@ export default class AdvancedTab extends PureComponent {
threeBoxDisabled: PropTypes.bool.isRequired,
setIpfsGateway: PropTypes.func.isRequired,
ipfsGateway: PropTypes.string.isRequired,
+ useLedgerLive: PropTypes.bool.isRequired,
+ setLedgerLivePreference: PropTypes.func.isRequired,
};
state = {
@@ -384,6 +389,33 @@ export default class AdvancedTab extends PureComponent {
);
}
+ renderLedgerLiveControl() {
+ const { t } = this.context;
+ const { useLedgerLive, setLedgerLivePreference } = this.props;
+
+ return (
+
+
+
{t('ledgerLiveAdvancedSetting')}
+
+ {t('ledgerLiveAdvancedSettingDescription')}
+
+
+
+
+ setLedgerLivePreference(!value)}
+ offLabel={t('off')}
+ onLabel={t('on')}
+ disabled={getPlatform() === PLATFORM_FIREFOX}
+ />
+
+
+
+ );
+ }
+
handleIpfsGatewayChange(url) {
const { t } = this.context;
@@ -478,6 +510,7 @@ export default class AdvancedTab extends PureComponent {
{this.renderAutoLockTimeLimit()}
{this.renderThreeBoxControl()}
{this.renderIpfsGatewayControl()}
+ {this.renderLedgerLiveControl()}
);
}
diff --git a/ui/app/pages/settings/advanced-tab/advanced-tab.component.test.js b/ui/app/pages/settings/advanced-tab/advanced-tab.component.test.js
index fc133a5d1..b73b90212 100644
--- a/ui/app/pages/settings/advanced-tab/advanced-tab.component.test.js
+++ b/ui/app/pages/settings/advanced-tab/advanced-tab.component.test.js
@@ -23,7 +23,7 @@ describe('AdvancedTab Component', () => {
},
);
- expect(root.find('.settings-page__content-row')).toHaveLength(10);
+ expect(root.find('.settings-page__content-row')).toHaveLength(11);
});
it('should update autoLockTimeLimit', () => {
diff --git a/ui/app/pages/settings/advanced-tab/advanced-tab.container.js b/ui/app/pages/settings/advanced-tab/advanced-tab.container.js
index 1bfa82f30..2fe9eaf39 100644
--- a/ui/app/pages/settings/advanced-tab/advanced-tab.container.js
+++ b/ui/app/pages/settings/advanced-tab/advanced-tab.container.js
@@ -11,6 +11,7 @@ import {
turnThreeBoxSyncingOnAndInitialize,
setUseNonceField,
setIpfsGateway,
+ setLedgerLivePreference,
} from '../../../store/actions';
import { getPreferences } from '../../../selectors';
import AdvancedTab from './advanced-tab.component';
@@ -26,6 +27,7 @@ export const mapStateToProps = (state) => {
threeBoxDisabled,
useNonceField,
ipfsGateway,
+ useLedgerLive,
} = metamask;
const { showFiatInTestnets, autoLockTimeLimit } = getPreferences(state);
@@ -39,6 +41,7 @@ export const mapStateToProps = (state) => {
threeBoxDisabled,
useNonceField,
ipfsGateway,
+ useLedgerLive,
};
};
@@ -68,6 +71,8 @@ export const mapDispatchToProps = (dispatch) => {
setIpfsGateway: (value) => {
return dispatch(setIpfsGateway(value));
},
+ setLedgerLivePreference: (value) =>
+ dispatch(setLedgerLivePreference(value)),
};
};
diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js
index cbd90fe84..f3c2c03ea 100644
--- a/ui/app/store/actions.js
+++ b/ui/app/store/actions.js
@@ -2845,6 +2845,14 @@ export function getCurrentWindowTab() {
};
}
+export function setLedgerLivePreference(value) {
+ return async (dispatch) => {
+ dispatch(showLoadingIndication());
+ await promisifiedBackground.setLedgerLivePreference(value);
+ dispatch(hideLoadingIndication());
+ };
+}
+
// MetaMetrics
/**
* @typedef {import('../../../shared/constants/metametrics').MetaMetricsEventPayload} MetaMetricsEventPayload
diff --git a/yarn.lock b/yarn.lock
index c40f5432a..f72b8435e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2704,14 +2704,14 @@
resolved "https://registry.yarnpkg.com/@metamask/eslint-config/-/eslint-config-6.0.0.tgz#ec53e8ab278073e882411ed89705bc7d06b78c81"
integrity sha512-LyakGYGwM8UQOGhwWa+5erAI1hXuiTgf/y7USzOomX6H9KiuY09IAUYnPh7ToPG2sedD2F48UF1bUm8yvCoZOw==
-"@metamask/eth-ledger-bridge-keyring@^0.3.0":
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/@metamask/eth-ledger-bridge-keyring/-/eth-ledger-bridge-keyring-0.3.0.tgz#4fc2a6345199e18f94c098d8c632d3d55add5c36"
- integrity sha512-Iv9fmxPClBohIK6ciy0ZVYNTUodlmrdQt19cZDAicSfFdR2Gcgbq2FDA75o63+fW8TwPEohhDRV/vWQ0MU5esw==
+"@metamask/eth-ledger-bridge-keyring@^0.4.0":
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/@metamask/eth-ledger-bridge-keyring/-/eth-ledger-bridge-keyring-0.4.0.tgz#764834adf146fc86ab7688a6c8f1e08708ed0d71"
+ integrity sha512-FkoAsP19YMKHNQzfPL5l9QJwp4YsEaN8d5pbJc+VcMzoC5rkt1iyDQdderERUV9DQlS3flBjxECCZ+QX54HD5w==
dependencies:
eth-sig-util "^1.4.2"
ethereumjs-tx "^1.3.4"
- ethereumjs-util "^5.1.5"
+ ethereumjs-util "^7.0.9"
events "^2.0.0"
hdkey "0.8.0"