mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-10-22 11:22:43 +02:00
18566 firefox ledger u2f message (#18570)
* check for user agent * fix regex * fix lint * update link * add test * update message * update coverage * fix test names * update text * add whats new notification for firefox and ledger users * update action button link * update notification text * update viewed notification * update coverage * update coverage
This commit is contained in:
parent
34c1e5a2a1
commit
fa6e26744d
29
app/_locales/en/messages.json
generated
29
app/_locales/en/messages.json
generated
@ -2537,6 +2537,19 @@
|
|||||||
"message": "Swapping on mobile is here!",
|
"message": "Swapping on mobile is here!",
|
||||||
"description": "Title for a notification in the 'See What's New' popup. Tells users that they can now use MetaMask Swaps on Mobile."
|
"description": "Title for a notification in the 'See What's New' popup. Tells users that they can now use MetaMask Swaps on Mobile."
|
||||||
},
|
},
|
||||||
|
"notifications20ActionText": {
|
||||||
|
"message": "Learn more",
|
||||||
|
"description": "The 'call to action' on the button, or link, of the 'Stay secure' notification. Upon clicking, users will be taken to a ledger page to resolve the U2F connection issue."
|
||||||
|
},
|
||||||
|
|
||||||
|
"notifications20Description": {
|
||||||
|
"message": "If you're on the latest version of Firefox, you might be experiencing an issue related to Firefox dropping U2F support.",
|
||||||
|
"description": "Description of a notification in the 'See What's New' popup. Describes the U2F support being dropped by firefox and that it affects ledger users."
|
||||||
|
},
|
||||||
|
"notifications20Title": {
|
||||||
|
"message": "Ledger and Firefox Users Experiencing Connection Issues",
|
||||||
|
"description": "Title for a notification in the 'See What's New' popup. Tells users that latest firefox users using U2F may experience connection issues."
|
||||||
|
},
|
||||||
"notifications3ActionText": {
|
"notifications3ActionText": {
|
||||||
"message": "Read more",
|
"message": "Read more",
|
||||||
"description": "The 'call to action' on the button, or link, of the 'Stay secure' notification. Upon clicking, users will be taken to a page about security on the metamask support website."
|
"description": "The 'call to action' on the button, or link, of the 'Stay secure' notification. Upon clicking, users will be taken to a page about security on the metamask support website."
|
||||||
@ -4541,6 +4554,22 @@
|
|||||||
"transferFrom": {
|
"transferFrom": {
|
||||||
"message": "Transfer from"
|
"message": "Transfer from"
|
||||||
},
|
},
|
||||||
|
"troubleConnectingToLedgerU2FOnFirefox": {
|
||||||
|
"message": "We're having trouble connecting your Ledger. $1",
|
||||||
|
"description": "$1 is a link to the wallet connection guide;"
|
||||||
|
},
|
||||||
|
"troubleConnectingToLedgerU2FOnFirefox2": {
|
||||||
|
"message": "Review our hardware wallet connection guide and try again.",
|
||||||
|
"description": "$1 of the ledger wallet connection guide"
|
||||||
|
},
|
||||||
|
"troubleConnectingToLedgerU2FOnFirefoxLedgerSolution": {
|
||||||
|
"message": "If you're on the latest version of Firefox, you might be experiencing an issue related to Firefox dropping U2F support. Learn how to fix this issue $1.",
|
||||||
|
"description": "It is a link to the ledger website for the workaround."
|
||||||
|
},
|
||||||
|
"troubleConnectingToLedgerU2FOnFirefoxLedgerSolution2": {
|
||||||
|
"message": "here",
|
||||||
|
"description": "Second part of the error message; It is a link to the ledger website for the workaround."
|
||||||
|
},
|
||||||
"troubleConnectingToWallet": {
|
"troubleConnectingToWallet": {
|
||||||
"message": "We had trouble connecting to your $1, try reviewing $2 and try again.",
|
"message": "We had trouble connecting to your $1, try reviewing $2 and try again.",
|
||||||
"description": "$1 is the wallet device name; $2 is a link to wallet connection guide"
|
"description": "$1 is the wallet device name; $2 is a link to wallet connection guide"
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
// subset of files to check against these targets.
|
// subset of files to check against these targets.
|
||||||
module.exports = {
|
module.exports = {
|
||||||
global: {
|
global: {
|
||||||
lines: 67.8,
|
lines: 68.5,
|
||||||
branches: 55.84,
|
branches: 56.34,
|
||||||
statements: 67.13,
|
statements: 67.86,
|
||||||
functions: 59.66,
|
functions: 60.69,
|
||||||
},
|
},
|
||||||
transforms: {
|
transforms: {
|
||||||
branches: 100,
|
branches: 100,
|
||||||
|
@ -102,6 +102,10 @@ export const UI_NOTIFICATIONS = {
|
|||||||
width: '100%',
|
width: '100%',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
20: {
|
||||||
|
id: 20,
|
||||||
|
date: null,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTranslatedUINotifications = (t, locale) => {
|
export const getTranslatedUINotifications = (t, locale) => {
|
||||||
@ -279,5 +283,16 @@ export const getTranslatedUINotifications = (t, locale) => {
|
|||||||
)
|
)
|
||||||
: '',
|
: '',
|
||||||
},
|
},
|
||||||
|
20: {
|
||||||
|
...UI_NOTIFICATIONS[20],
|
||||||
|
title: t('notifications20Title'),
|
||||||
|
description: [t('notifications20Description')],
|
||||||
|
actionText: t('notifications20ActionText'),
|
||||||
|
date: UI_NOTIFICATIONS[20].date
|
||||||
|
? new Intl.DateTimeFormat(formattedLocale).format(
|
||||||
|
new Date(UI_NOTIFICATIONS[20].date),
|
||||||
|
)
|
||||||
|
: '',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -73,6 +73,12 @@ function getActionFunctionById(id, history) {
|
|||||||
updateViewedNotifications({ 19: true });
|
updateViewedNotifications({ 19: true });
|
||||||
history.push(`${EXPERIMENTAL_ROUTE}#autodetect-nfts`);
|
history.push(`${EXPERIMENTAL_ROUTE}#autodetect-nfts`);
|
||||||
},
|
},
|
||||||
|
20: () => {
|
||||||
|
updateViewedNotifications({ 20: true });
|
||||||
|
global.platform.openTab({
|
||||||
|
url: ZENDESK_URLS.LEDGER_FIREFOX_U2F_GUIDE,
|
||||||
|
});
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return actionFunctions[id];
|
return actionFunctions[id];
|
||||||
|
@ -15,6 +15,8 @@ const ZENDESK_URLS = {
|
|||||||
'https://metamask.zendesk.com/hc/en-us/articles/360015289932',
|
'https://metamask.zendesk.com/hc/en-us/articles/360015289932',
|
||||||
INFURA_BLOCKAGE:
|
INFURA_BLOCKAGE:
|
||||||
'https://metamask.zendesk.com/hc/en-us/articles/360059386712',
|
'https://metamask.zendesk.com/hc/en-us/articles/360059386712',
|
||||||
|
LEDGER_FIREFOX_U2F_GUIDE:
|
||||||
|
'https://support.ledger.com/hc/en-us/articles/10371387758493-MetaMask-Firefox-Ledger-Integration-Issue?support=true',
|
||||||
LEGACY_WEB3: 'https://metamask.zendesk.com/hc/en-us/articles/360053147012',
|
LEGACY_WEB3: 'https://metamask.zendesk.com/hc/en-us/articles/360053147012',
|
||||||
NFT_TOKENS:
|
NFT_TOKENS:
|
||||||
'https://metamask.zendesk.com/hc/en-us/articles/360058238591-NFT-tokens-in-MetaMask-wallet',
|
'https://metamask.zendesk.com/hc/en-us/articles/360058238591-NFT-tokens-in-MetaMask-wallet',
|
||||||
|
File diff suppressed because one or more lines are too long
@ -20,7 +20,14 @@ import {
|
|||||||
HardwareDeviceNames,
|
HardwareDeviceNames,
|
||||||
LedgerTransportTypes,
|
LedgerTransportTypes,
|
||||||
} from '../../../../shared/constants/hardware-wallets';
|
} from '../../../../shared/constants/hardware-wallets';
|
||||||
|
import {
|
||||||
|
BUTTON_TYPES,
|
||||||
|
BUTTON_SIZES,
|
||||||
|
Button,
|
||||||
|
Text,
|
||||||
|
} from '../../../components/component-library';
|
||||||
import ZENDESK_URLS from '../../../helpers/constants/zendesk-url';
|
import ZENDESK_URLS from '../../../helpers/constants/zendesk-url';
|
||||||
|
import { TextColor } from '../../../helpers/constants/design-system';
|
||||||
import SelectHardware from './select-hardware';
|
import SelectHardware from './select-hardware';
|
||||||
import AccountList from './account-list';
|
import AccountList from './account-list';
|
||||||
|
|
||||||
@ -74,6 +81,7 @@ class ConnectHardwareForm extends Component {
|
|||||||
browserSupported: true,
|
browserSupported: true,
|
||||||
unlocked: false,
|
unlocked: false,
|
||||||
device: null,
|
device: null,
|
||||||
|
isFirefox: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||||
@ -89,6 +97,10 @@ class ConnectHardwareForm extends Component {
|
|||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.checkIfUnlocked();
|
this.checkIfUnlocked();
|
||||||
|
const useAgent = window.navigator.userAgent;
|
||||||
|
if (/Firefox/u.test(useAgent)) {
|
||||||
|
this.setState({ isFirefox: true });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkIfUnlocked() {
|
async checkIfUnlocked() {
|
||||||
@ -287,23 +299,64 @@ class ConnectHardwareForm extends Component {
|
|||||||
|
|
||||||
renderError() {
|
renderError() {
|
||||||
if (this.state.error === U2F_ERROR) {
|
if (this.state.error === U2F_ERROR) {
|
||||||
|
if (this.state.device === 'ledger' && this.state.isFirefox) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Text color={TextColor.warningDefault} margin={[5, 5, 2]}>
|
||||||
|
{this.context.t('troubleConnectingToLedgerU2FOnFirefox', [
|
||||||
|
// eslint-disable-next-line react/jsx-key
|
||||||
|
<Button
|
||||||
|
type={BUTTON_TYPES.LINK}
|
||||||
|
href={ZENDESK_URLS.HARDWARE_CONNECTION}
|
||||||
|
size={BUTTON_SIZES.INHERIT}
|
||||||
|
key="u2f-error-1"
|
||||||
|
as="a"
|
||||||
|
block={false}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{this.context.t('troubleConnectingToLedgerU2FOnFirefox2')}
|
||||||
|
</Button>,
|
||||||
|
])}
|
||||||
|
</Text>
|
||||||
|
<Text color={TextColor.warningDefault} margin={[5, 5, 2]}>
|
||||||
|
{this.context.t(
|
||||||
|
'troubleConnectingToLedgerU2FOnFirefoxLedgerSolution',
|
||||||
|
[
|
||||||
|
// eslint-disable-next-line react/jsx-key
|
||||||
|
<Button
|
||||||
|
type={BUTTON_TYPES.LINK}
|
||||||
|
href={ZENDESK_URLS.LEDGER_FIREFOX_U2F_GUIDE}
|
||||||
|
size={BUTTON_SIZES.INHERIT}
|
||||||
|
key="u2f-error-1"
|
||||||
|
as="a"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{this.context.t(
|
||||||
|
'troubleConnectingToLedgerU2FOnFirefoxLedgerSolution2',
|
||||||
|
)}
|
||||||
|
</Button>,
|
||||||
|
],
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<p className="hw-connect__error">
|
<Text color={TextColor.warningDefault} margin={[5, 5, 2]}>
|
||||||
{this.context.t('troubleConnectingToWallet', [
|
{this.context.t('troubleConnectingToWallet', [
|
||||||
this.state.device,
|
this.state.device,
|
||||||
// eslint-disable-next-line react/jsx-key
|
// eslint-disable-next-line react/jsx-key
|
||||||
<a
|
<Button
|
||||||
|
type={BUTTON_TYPES.LINK}
|
||||||
href={ZENDESK_URLS.HARDWARE_CONNECTION}
|
href={ZENDESK_URLS.HARDWARE_CONNECTION}
|
||||||
key="hardware-connection-guide"
|
key="u2f-error-1"
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="hw-connect__link"
|
|
||||||
style={{ marginLeft: '5px', marginRight: '5px' }}
|
|
||||||
>
|
>
|
||||||
{this.context.t('walletConnectionGuide')}
|
{this.context.t('walletConnectionGuide')}
|
||||||
</a>,
|
</Button>,
|
||||||
])}
|
])}
|
||||||
</p>
|
</Text>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return this.state.error ? (
|
return this.state.error ? (
|
||||||
|
151
ui/pages/create-account/connect-hardware/index.test.tsx
Normal file
151
ui/pages/create-account/connect-hardware/index.test.tsx
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
import configureMockStore from 'redux-mock-store';
|
||||||
|
import { fireEvent, waitFor } from '@testing-library/react';
|
||||||
|
import thunk from 'redux-thunk';
|
||||||
|
import React from 'react';
|
||||||
|
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||||
|
import {
|
||||||
|
LedgerTransportTypes,
|
||||||
|
HardwareDeviceNames,
|
||||||
|
} from '../../../../shared/constants/hardware-wallets';
|
||||||
|
import ConnectHardwareForm from '.';
|
||||||
|
|
||||||
|
const mockConnectHardware = jest.fn();
|
||||||
|
const mockCheckHardwareStatus = jest.fn().mockResolvedValue(false);
|
||||||
|
|
||||||
|
jest.mock('../../../store/actions', () => ({
|
||||||
|
connectHardware: () => mockConnectHardware,
|
||||||
|
checkHardwareStatus: () => mockCheckHardwareStatus,
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('../../../selectors', () => ({
|
||||||
|
getCurrentChainId: () => jest.fn().mockResolvedValue('0x1'),
|
||||||
|
getRpcPrefsForCurrentProvider: () => jest.fn().mockResolvedValue({}),
|
||||||
|
getMetaMaskAccountsConnected: () => jest.fn().mockResolvedValue([]),
|
||||||
|
getMetaMaskAccounts: () => jest.fn().mockResolvedValue([]),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('../../../ducks/history/history', () => ({
|
||||||
|
getMostRecentOverviewPage: () => jest.fn().mockResolvedValue('/'),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const mockProps = {
|
||||||
|
forgetDevice: jest.fn(),
|
||||||
|
showAlert: jest.fn(),
|
||||||
|
hideAlert: jest.fn(),
|
||||||
|
unlockHardwareWalletAccount: jest.fn(),
|
||||||
|
setHardwareWalletDefaultHdPath: jest.fn(),
|
||||||
|
history: {},
|
||||||
|
defaultHdPath: "m/44'/60'/0'/0",
|
||||||
|
mostRecentOverviewPage: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockState = {
|
||||||
|
metamask: {
|
||||||
|
provider: {
|
||||||
|
chainId: '0x1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
appState: {
|
||||||
|
networkDropdownOpen: false,
|
||||||
|
gasIsLoading: false,
|
||||||
|
isLoading: false,
|
||||||
|
modal: {
|
||||||
|
open: false,
|
||||||
|
modalState: {
|
||||||
|
name: null,
|
||||||
|
props: {},
|
||||||
|
},
|
||||||
|
previousModalState: {
|
||||||
|
name: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
warning: null,
|
||||||
|
chainId: '0x1',
|
||||||
|
rpcPrefs: null,
|
||||||
|
accounts: [],
|
||||||
|
connectedAccounts: [],
|
||||||
|
defaultHdPaths: {
|
||||||
|
[HardwareDeviceNames.lattice]: "m/44'/60'/0'/0",
|
||||||
|
[HardwareDeviceNames.ledger]: "m/44'/60'/0'/0",
|
||||||
|
[HardwareDeviceNames.trezor]: "m/44'/60'/0'/0",
|
||||||
|
},
|
||||||
|
mostRecentOverviewPage: '',
|
||||||
|
ledgerTransportType: LedgerTransportTypes.webhid,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('ConnectHardwareForm', () => {
|
||||||
|
const mockStore = configureMockStore([thunk])(mockState);
|
||||||
|
it('should match snapshot', () => {
|
||||||
|
const { container } = renderWithProvider(
|
||||||
|
<ConnectHardwareForm {...mockProps} />,
|
||||||
|
mockStore,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('U2F Error', () => {
|
||||||
|
it('should render a U2F error', async () => {
|
||||||
|
mockConnectHardware.mockRejectedValue(new Error('U2F Error'));
|
||||||
|
const mockStateWithU2F = Object.assign(mockState, {});
|
||||||
|
mockStateWithU2F.appState.ledgerTransportType = LedgerTransportTypes.u2f;
|
||||||
|
const mockStoreWithU2F = configureMockStore([thunk])(mockStateWithU2F);
|
||||||
|
const { getByText, getByLabelText, queryByText } = renderWithProvider(
|
||||||
|
<ConnectHardwareForm {...mockProps} />,
|
||||||
|
mockStoreWithU2F,
|
||||||
|
);
|
||||||
|
|
||||||
|
const ledgerButton = getByLabelText('Ledger');
|
||||||
|
const continueButton = getByText('Continue');
|
||||||
|
|
||||||
|
fireEvent.click(ledgerButton);
|
||||||
|
fireEvent.click(continueButton);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(
|
||||||
|
getByText('We had trouble connecting to your ledger, try reviewing', {
|
||||||
|
exact: false,
|
||||||
|
}),
|
||||||
|
).toBeInTheDocument();
|
||||||
|
const firefoxError = queryByText(
|
||||||
|
"If you're on the latest version of Firefox, you might be experiencing an issue related to Firefox dropping U2F support. Learn how to fix this issue",
|
||||||
|
{ exact: false },
|
||||||
|
);
|
||||||
|
expect(firefoxError).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render a different U2F error for firefox', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(window.navigator, 'userAgent', 'get')
|
||||||
|
.mockReturnValue(
|
||||||
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:95.0) Gecko/20100101 Firefox/95.0',
|
||||||
|
);
|
||||||
|
|
||||||
|
mockConnectHardware.mockRejectedValue(new Error('U2F Error'));
|
||||||
|
const mockStateWithU2F = Object.assign(mockState, {});
|
||||||
|
mockStateWithU2F.appState.ledgerTransportType = LedgerTransportTypes.u2f;
|
||||||
|
const mockStoreWithU2F = configureMockStore([thunk])(mockStateWithU2F);
|
||||||
|
const { getByText, getByLabelText } = renderWithProvider(
|
||||||
|
<ConnectHardwareForm {...mockProps} />,
|
||||||
|
mockStoreWithU2F,
|
||||||
|
);
|
||||||
|
|
||||||
|
const ledgerButton = getByLabelText('Ledger');
|
||||||
|
const continueButton = getByText('Continue');
|
||||||
|
|
||||||
|
fireEvent.click(ledgerButton);
|
||||||
|
fireEvent.click(continueButton);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(
|
||||||
|
getByText(
|
||||||
|
"If you're on the latest version of Firefox, you might be experiencing an issue related to Firefox dropping U2F support. Learn how to fix this issue",
|
||||||
|
{ exact: false },
|
||||||
|
),
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -935,6 +935,7 @@ function getAllowedAnnouncementIds(state) {
|
|||||||
const supportsWebHid = window.navigator.hid !== undefined;
|
const supportsWebHid = window.navigator.hid !== undefined;
|
||||||
const currentlyUsingLedgerLive =
|
const currentlyUsingLedgerLive =
|
||||||
getLedgerTransportType(state) === LedgerTransportTypes.live;
|
getLedgerTransportType(state) === LedgerTransportTypes.live;
|
||||||
|
const isFirefox = window.navigator.userAgent.includes('Firefox');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
1: false,
|
1: false,
|
||||||
@ -956,6 +957,7 @@ function getAllowedAnnouncementIds(state) {
|
|||||||
17: false,
|
17: false,
|
||||||
18: true,
|
18: true,
|
||||||
19: true,
|
19: true,
|
||||||
|
20: currentKeyringIsLedger && isFirefox,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user