mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-22 17:33:23 +01:00
Allow user to turn off ENS DNS resolution (#20102)
* Allow user to turn off IPFS gateway resolution * Add end to end test for toggle on and off * Fix jest tests and snapshots * Change variable name * Implement provided content * Use MetaMask eth instead * Allow searching for ENS setting * Fix jest --------- Co-authored-by: Brad Decker <bhdecker84@gmail.com>
This commit is contained in:
parent
05b1b19c6f
commit
99c709ff8f
18
app/_locales/en/messages.json
generated
18
app/_locales/en/messages.json
generated
@ -1426,6 +1426,24 @@
|
||||
"enhancedTokenDetectionAlertMessage": {
|
||||
"message": "Enhanced token detection is currently available on $1. $2"
|
||||
},
|
||||
"ensDomainsSettingDescriptionIntro": {
|
||||
"message": "MetaMask lets you see ENS domains like \"https://metamask.eth\" right in your browser's address bar. Here's how it works:"
|
||||
},
|
||||
"ensDomainsSettingDescriptionOutro": {
|
||||
"message": "Regular browsers don't usually handle ENS or IPFS addresses, but MetaMask helps with that. Using this feature might share your IP address with IPFS third-party services."
|
||||
},
|
||||
"ensDomainsSettingDescriptionPoint1": {
|
||||
"message": "MetaMask checks with Ethereum's ENS contract to find the code connected to the ENS name."
|
||||
},
|
||||
"ensDomainsSettingDescriptionPoint2": {
|
||||
"message": "If the code is linked to IPFS, it gets the content from the IPFS network."
|
||||
},
|
||||
"ensDomainsSettingDescriptionPoint3": {
|
||||
"message": "Then, you can see the content, usually a website or something similar."
|
||||
},
|
||||
"ensDomainsSettingTitle": {
|
||||
"message": "Show ENS domains in address bar"
|
||||
},
|
||||
"ensIllegalCharacter": {
|
||||
"message": "Illegal character for ENS."
|
||||
},
|
||||
|
@ -466,6 +466,9 @@ export function setupController(
|
||||
getIpfsGateway: controller.preferencesController.getIpfsGateway.bind(
|
||||
controller.preferencesController,
|
||||
),
|
||||
getUseAddressBarEnsResolution: () =>
|
||||
controller.preferencesController.store.getState()
|
||||
.useAddressBarEnsResolution,
|
||||
provider: controller.provider,
|
||||
});
|
||||
|
||||
|
@ -67,6 +67,7 @@ export default class PreferencesController {
|
||||
},
|
||||
// ENS decentralized website resolution
|
||||
ipfsGateway: IPFS_DEFAULT_GATEWAY_URL,
|
||||
useAddressBarEnsResolution: true,
|
||||
infuraBlocked: null,
|
||||
ledgerTransportType: window.navigator.hid
|
||||
? LedgerTransportTypes.webhid
|
||||
@ -480,6 +481,15 @@ export default class PreferencesController {
|
||||
return domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* A setter for the `useAddressBarEnsResolution` property
|
||||
*
|
||||
* @param {boolean} useAddressBarEnsResolution - Whether or not user prefers IPFS resolution for domains
|
||||
*/
|
||||
async setUseAddressBarEnsResolution(useAddressBarEnsResolution) {
|
||||
this.store.updateState({ useAddressBarEnsResolution });
|
||||
}
|
||||
|
||||
/**
|
||||
* A setter for the `ledgerTransportType` property.
|
||||
*
|
||||
|
@ -13,6 +13,7 @@ export default function setupEnsIpfsResolver({
|
||||
provider,
|
||||
getCurrentChainId,
|
||||
getIpfsGateway,
|
||||
getUseAddressBarEnsResolution,
|
||||
}) {
|
||||
// install listener
|
||||
const urlPatterns = supportedTopLevelDomains.map((tld) => `*://*.${tld}/*`);
|
||||
@ -33,7 +34,12 @@ export default function setupEnsIpfsResolver({
|
||||
const { tabId, url } = details;
|
||||
// ignore requests that are not associated with tabs
|
||||
// only attempt ENS resolution on mainnet
|
||||
if (tabId === -1 || getCurrentChainId() !== '0x1') {
|
||||
if (
|
||||
(tabId === -1 || getCurrentChainId() !== '0x1') &&
|
||||
// E2E tests use a chain other than 0x1, so for testing,
|
||||
// allow the reuqest to pass through
|
||||
!process.env.IN_TEST
|
||||
) {
|
||||
return;
|
||||
}
|
||||
// parse ens name
|
||||
@ -50,9 +56,23 @@ export default function setupEnsIpfsResolver({
|
||||
|
||||
async function attemptResolve({ tabId, name, pathname, search, fragment }) {
|
||||
const ipfsGateway = getIpfsGateway();
|
||||
const useAddressBarEnsResolution = getUseAddressBarEnsResolution();
|
||||
|
||||
if (!useAddressBarEnsResolution || ipfsGateway === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
browser.tabs.update(tabId, { url: `loading.html` });
|
||||
|
||||
let url = `https://app.ens.domains/name/${name}`;
|
||||
|
||||
// If we're testing ENS domain resolution support,
|
||||
// we assume the ENS domains URL
|
||||
if (process.env.IN_TEST) {
|
||||
browser.tabs.update(tabId, { url });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { type, hash } = await resolveEnsToIpfsContentId({
|
||||
provider,
|
||||
|
@ -2233,6 +2233,10 @@ export default class MetamaskController extends EventEmitter {
|
||||
setIpfsGateway: preferencesController.setIpfsGateway.bind(
|
||||
preferencesController,
|
||||
),
|
||||
setUseAddressBarEnsResolution:
|
||||
preferencesController.setUseAddressBarEnsResolution.bind(
|
||||
preferencesController,
|
||||
),
|
||||
setParticipateInMetaMetrics:
|
||||
metaMetricsController.setParticipateInMetaMetrics.bind(
|
||||
metaMetricsController,
|
||||
|
@ -190,7 +190,14 @@ async function withFixtures(options, testSuite) {
|
||||
if (phishingPageServer.isRunning()) {
|
||||
await phishingPageServer.quit();
|
||||
}
|
||||
await mockServer.stop();
|
||||
|
||||
// Since mockServer could be stop'd at another location,
|
||||
// use a try/catch to avoid an error
|
||||
try {
|
||||
await mockServer.stop();
|
||||
} catch (e) {
|
||||
console.log('mockServer already stopped');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
79
test/e2e/tests/ipfs-ens-resolution.spec.js
Normal file
79
test/e2e/tests/ipfs-ens-resolution.spec.js
Normal file
@ -0,0 +1,79 @@
|
||||
const { strict: assert } = require('assert');
|
||||
const { buildWebDriver } = require('../webdriver');
|
||||
const { withFixtures } = require('../helpers');
|
||||
const FixtureBuilder = require('../fixture-builder');
|
||||
|
||||
describe('Settings', function () {
|
||||
const ENS_NAME = 'metamask.eth';
|
||||
const ENS_NAME_URL = `https://${ENS_NAME}/`;
|
||||
const ENS_DESTINATION_URL = `https://app.ens.domains/name/${ENS_NAME}`;
|
||||
|
||||
it('Redirects to ENS domains when user inputs ENS into address bar', async function () {
|
||||
// Using proxy port that doesn't resolve so that the browser can error out properly
|
||||
// on the ".eth" hostname. The proxy does too much interference with 8000.
|
||||
const { driver } = await buildWebDriver({ proxyUrl: '127.0.0.1:8001' });
|
||||
await driver.navigate();
|
||||
|
||||
// The setting defaults to "on" so we can simply enter an ENS address
|
||||
// into the address bar and listen for address change
|
||||
try {
|
||||
await driver.openNewPage(ENS_NAME_URL);
|
||||
} catch (e) {
|
||||
// Ignore ERR_PROXY_CONNECTION_FAILED error
|
||||
// since all we care about is getting to the correct URL
|
||||
}
|
||||
|
||||
// Ensure that the redirect to ENS Domains has happened
|
||||
const currentUrl = await driver.getCurrentUrl();
|
||||
assert.equal(currentUrl, ENS_DESTINATION_URL);
|
||||
|
||||
await driver.quit();
|
||||
});
|
||||
|
||||
it('Does not lookup IPFS data for ENS Domain when switched off', async function () {
|
||||
let server;
|
||||
|
||||
await withFixtures(
|
||||
{
|
||||
fixtures: new FixtureBuilder().build(),
|
||||
title: this.test.title,
|
||||
testSpecificMock: (mockServer) => {
|
||||
server = mockServer;
|
||||
},
|
||||
},
|
||||
async ({ driver }) => {
|
||||
await driver.navigate();
|
||||
await driver.fill('#password', 'correct horse battery staple');
|
||||
await driver.press('#password', driver.Key.ENTER);
|
||||
|
||||
// goes to the settings screen
|
||||
await driver.clickElement(
|
||||
'[data-testid="account-options-menu-button"]',
|
||||
);
|
||||
await driver.clickElement({ text: 'Settings', tag: 'div' });
|
||||
await driver.clickElement({ text: 'Security & privacy', tag: 'div' });
|
||||
|
||||
// turns off IPFS domain resolution
|
||||
await driver.clickElement(
|
||||
'[data-testid="ipfs-gateway-resolution-container"] .toggle-button',
|
||||
);
|
||||
|
||||
// Now that we no longer need the MetaMask UI, and want the browser
|
||||
// to handle the request error, we need to stop the server
|
||||
await server.stop();
|
||||
|
||||
try {
|
||||
await driver.openNewPage(ENS_NAME_URL);
|
||||
} catch (e) {
|
||||
// Ignore ERR_PROXY_CONNECTION_FAILED error
|
||||
// since all we care about is getting to the correct URL
|
||||
}
|
||||
|
||||
// Ensure that the redirect to ENS Domains does not happen
|
||||
// Instead, the domain will be kept which is a 404
|
||||
const currentUrl = await driver.getCurrentUrl();
|
||||
assert.equal(currentUrl, ENS_NAME_URL);
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
@ -205,6 +205,13 @@ export const SETTINGS_CONSTANTS = [
|
||||
route: `${SECURITY_ROUTE}#price-checker`,
|
||||
icon: 'fa fa-lock',
|
||||
},
|
||||
{
|
||||
tabMessage: (t) => t('securityAndPrivacy'),
|
||||
sectionMessage: (t) => t('ensDomainsSettingTitle'),
|
||||
descriptionMessage: (t) => t('ensDomainsSettingDescriptionIntro'),
|
||||
route: `${SECURITY_ROUTE}#ens-domains`,
|
||||
icon: 'fa fa-lock',
|
||||
},
|
||||
{
|
||||
tabMessage: (t) => t('alerts'),
|
||||
sectionMessage: (t) => t('alertSettingsUnconnectedAccount'),
|
||||
|
@ -165,7 +165,7 @@ describe('Settings Search Utils', () => {
|
||||
it('should get good security & privacy section number', () => {
|
||||
expect(
|
||||
getNumberOfSettingsInSection(t, t('securityAndPrivacy')),
|
||||
).toStrictEqual(9);
|
||||
).toStrictEqual(10);
|
||||
});
|
||||
|
||||
it('should get good alerts section number', () => {
|
||||
|
@ -13,6 +13,7 @@ import {
|
||||
} from '../../../../shared/lib/ui-utils';
|
||||
import {
|
||||
PickerNetwork,
|
||||
Text,
|
||||
TextField,
|
||||
} from '../../../components/component-library';
|
||||
import Box from '../../../components/ui/box/box';
|
||||
@ -22,6 +23,7 @@ import { MetaMetricsContext } from '../../../contexts/metametrics';
|
||||
import {
|
||||
FONT_WEIGHT,
|
||||
TextColor,
|
||||
TextVariant,
|
||||
TypographyVariant,
|
||||
} from '../../../helpers/constants/design-system';
|
||||
import { ONBOARDING_PIN_EXTENSION_ROUTE } from '../../../helpers/constants/routes';
|
||||
@ -35,6 +37,7 @@ import {
|
||||
setUseMultiAccountBalanceChecker,
|
||||
setUsePhishDetect,
|
||||
setUseTokenDetection,
|
||||
setUseAddressBarEnsResolution,
|
||||
showModal,
|
||||
toggleNetworkMenu,
|
||||
} from '../../../store/actions';
|
||||
@ -54,6 +57,7 @@ export default function PrivacySettings() {
|
||||
setMultiAccountBalanceCheckerEnabled,
|
||||
] = useState(true);
|
||||
const [ipfsURL, setIPFSURL] = useState('');
|
||||
const [addressBarResolution, setAddressBarResolution] = useState(true);
|
||||
const [ipfsError, setIPFSError] = useState(null);
|
||||
const trackEvent = useContext(MetaMetricsContext);
|
||||
|
||||
@ -70,6 +74,7 @@ export default function PrivacySettings() {
|
||||
);
|
||||
dispatch(setUseCurrencyRateCheck(turnOnCurrencyRateCheck));
|
||||
dispatch(setCompletedOnboarding());
|
||||
dispatch(setUseAddressBarEnsResolution(addressBarResolution));
|
||||
|
||||
if (ipfsURL && !ipfsError) {
|
||||
const { host } = new URL(addUrlProtocolPrefix(ipfsURL));
|
||||
@ -252,6 +257,38 @@ export default function PrivacySettings() {
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<Setting
|
||||
value={addressBarResolution}
|
||||
setValue={setAddressBarResolution}
|
||||
title={t('ensDomainsSettingTitle')}
|
||||
description={
|
||||
<>
|
||||
<Text variant={TextVariant.inherit}>
|
||||
{t('ensDomainsSettingDescriptionIntro')}
|
||||
</Text>
|
||||
<Box
|
||||
as="ul"
|
||||
marginTop={4}
|
||||
marginBottom={4}
|
||||
paddingInlineStart={4}
|
||||
style={{ listStyleType: 'circle' }}
|
||||
>
|
||||
<Text variant={TextVariant.inherit} as="li">
|
||||
{t('ensDomainsSettingDescriptionPoint1')}
|
||||
</Text>
|
||||
<Text variant={TextVariant.inherit} as="li">
|
||||
{t('ensDomainsSettingDescriptionPoint2')}
|
||||
</Text>
|
||||
<Text variant={TextVariant.inherit} as="li">
|
||||
{t('ensDomainsSettingDescriptionPoint3')}
|
||||
</Text>
|
||||
</Box>
|
||||
<Text variant={TextVariant.inherit}>
|
||||
{t('ensDomainsSettingDescriptionOutro')}
|
||||
</Text>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<Setting
|
||||
value={turnOnCurrencyRateCheck}
|
||||
setValue={setTurnOnCurrencyRateCheck}
|
||||
|
@ -28,6 +28,7 @@ describe('Privacy Settings Onboarding View', () => {
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve());
|
||||
const setUseMultiAccountBalanceCheckerStub = jest.fn();
|
||||
const setUseAddressBarEnsResolutionStub = jest.fn();
|
||||
|
||||
setBackgroundConnection({
|
||||
setFeatureFlag: setFeatureFlagStub,
|
||||
@ -37,6 +38,7 @@ describe('Privacy Settings Onboarding View', () => {
|
||||
setIpfsGateway: setIpfsGatewayStub,
|
||||
completeOnboarding: completeOnboardingStub,
|
||||
setUseMultiAccountBalanceChecker: setUseMultiAccountBalanceCheckerStub,
|
||||
setUseAddressBarEnsResolution: setUseAddressBarEnsResolutionStub,
|
||||
});
|
||||
|
||||
it('should update preferences', () => {
|
||||
@ -50,6 +52,7 @@ describe('Privacy Settings Onboarding View', () => {
|
||||
expect(setUseTokenDetectionStub).toHaveBeenCalledTimes(0);
|
||||
expect(setUseMultiAccountBalanceCheckerStub).toHaveBeenCalledTimes(0);
|
||||
expect(setUseCurrencyRateCheckStub).toHaveBeenCalledTimes(0);
|
||||
expect(setUseAddressBarEnsResolutionStub).toHaveBeenCalledTimes(0);
|
||||
|
||||
const toggles = container.querySelectorAll('input[type=checkbox]');
|
||||
const submitButton = getByText('Done');
|
||||
@ -60,6 +63,7 @@ describe('Privacy Settings Onboarding View', () => {
|
||||
fireEvent.click(toggles[2]);
|
||||
fireEvent.click(toggles[3]);
|
||||
fireEvent.click(toggles[4]);
|
||||
fireEvent.click(toggles[5]);
|
||||
fireEvent.click(submitButton);
|
||||
|
||||
expect(setFeatureFlagStub).toHaveBeenCalledTimes(1);
|
||||
@ -67,6 +71,7 @@ describe('Privacy Settings Onboarding View', () => {
|
||||
expect(setUseTokenDetectionStub).toHaveBeenCalledTimes(1);
|
||||
expect(setUseMultiAccountBalanceCheckerStub).toHaveBeenCalledTimes(1);
|
||||
expect(setUseCurrencyRateCheckStub).toHaveBeenCalledTimes(1);
|
||||
expect(setUseAddressBarEnsResolutionStub).toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(setFeatureFlagStub.mock.calls[0][1]).toStrictEqual(false);
|
||||
expect(setUsePhishDetectStub.mock.calls[0][0]).toStrictEqual(false);
|
||||
@ -75,6 +80,9 @@ describe('Privacy Settings Onboarding View', () => {
|
||||
false,
|
||||
);
|
||||
expect(setUseCurrencyRateCheckStub.mock.calls[0][0]).toStrictEqual(false);
|
||||
expect(setUseAddressBarEnsResolutionStub.mock.calls[0][0]).toStrictEqual(
|
||||
false,
|
||||
);
|
||||
|
||||
// toggle back to true
|
||||
fireEvent.click(toggles[0]);
|
||||
@ -82,12 +90,14 @@ describe('Privacy Settings Onboarding View', () => {
|
||||
fireEvent.click(toggles[2]);
|
||||
fireEvent.click(toggles[3]);
|
||||
fireEvent.click(toggles[4]);
|
||||
fireEvent.click(toggles[5]);
|
||||
fireEvent.click(submitButton);
|
||||
expect(setFeatureFlagStub).toHaveBeenCalledTimes(2);
|
||||
expect(setUsePhishDetectStub).toHaveBeenCalledTimes(2);
|
||||
expect(setUseTokenDetectionStub).toHaveBeenCalledTimes(2);
|
||||
expect(setUseMultiAccountBalanceCheckerStub).toHaveBeenCalledTimes(2);
|
||||
expect(setUseCurrencyRateCheckStub).toHaveBeenCalledTimes(2);
|
||||
expect(setUseAddressBarEnsResolutionStub).toHaveBeenCalledTimes(2);
|
||||
|
||||
expect(setFeatureFlagStub.mock.calls[1][1]).toStrictEqual(true);
|
||||
expect(setUsePhishDetectStub.mock.calls[1][0]).toStrictEqual(true);
|
||||
@ -96,6 +106,9 @@ describe('Privacy Settings Onboarding View', () => {
|
||||
true,
|
||||
);
|
||||
expect(setUseCurrencyRateCheckStub.mock.calls[1][0]).toStrictEqual(true);
|
||||
expect(setUseAddressBarEnsResolutionStub.mock.calls[1][0]).toStrictEqual(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
describe('IPFS', () => {
|
||||
|
@ -405,6 +405,100 @@ exports[`Security Tab should match snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
id="ens-domains"
|
||||
>
|
||||
Show ENS domains in address bar
|
||||
<div
|
||||
class="settings-page__content-description"
|
||||
>
|
||||
<span
|
||||
class="mm-box mm-text mm-text--inherit mm-box--color-inherit"
|
||||
>
|
||||
MetaMask lets you see ENS domains like "https://metamask.eth" right in your browser's address bar. Here's how it works:
|
||||
</span>
|
||||
<ul
|
||||
class="mm-box mm-box--margin-top-4 mm-box--margin-bottom-4 mm-box--padding-inline-start-4"
|
||||
style="list-style-type: circle;"
|
||||
>
|
||||
<li
|
||||
class="mm-box mm-text mm-text--inherit mm-box--color-inherit"
|
||||
>
|
||||
MetaMask checks with Ethereum's ENS contract to find the code connected to the ENS name.
|
||||
</li>
|
||||
<li
|
||||
class="mm-box mm-text mm-text--inherit mm-box--color-inherit"
|
||||
>
|
||||
If the code is linked to IPFS, it gets the content from the IPFS network.
|
||||
</li>
|
||||
<li
|
||||
class="mm-box mm-text mm-text--inherit mm-box--color-inherit"
|
||||
>
|
||||
Then, you can see the content, usually a website or something similar.
|
||||
</li>
|
||||
</ul>
|
||||
<span
|
||||
class="mm-box mm-text mm-text--inherit mm-box--color-inherit"
|
||||
>
|
||||
Regular browsers don't usually handle ENS or IPFS addresses, but MetaMask helps with that. Using this feature might share your IP address with IPFS third-party services.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item-col"
|
||||
data-testid="ipfs-gateway-resolution-container"
|
||||
>
|
||||
<label
|
||||
class="toggle-button toggle-button--off"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;"
|
||||
>
|
||||
<div
|
||||
style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(242, 244, 246);"
|
||||
>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;"
|
||||
/>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgba(255, 255, 255, 0.6); bottom: 0px; margin-top: auto; margin-bottom: auto; padding-right: 5px; line-height: 0; width: 26px; height: 20px; opacity: 1;"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style="position: absolute; height: 100%; top: 0px; left: 0px; display: flex; flex: 1; align-self: stretch; align-items: center; justify-content: flex-start;"
|
||||
>
|
||||
<div
|
||||
style="width: 18px; height: 18px; display: flex; align-self: center; box-shadow: none; border-radius: 50%; box-sizing: border-box; position: relative; background-color: rgb(106, 115, 125); left: 3px;"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px;"
|
||||
type="checkbox"
|
||||
value="false"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="toggle-button__status"
|
||||
>
|
||||
<span
|
||||
class="toggle-button__label-off"
|
||||
>
|
||||
Off
|
||||
</span>
|
||||
<span
|
||||
class="toggle-button__label-on"
|
||||
>
|
||||
On
|
||||
</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
|
@ -31,6 +31,11 @@ import {
|
||||
getNumberOfSettingsInSection,
|
||||
handleSettingsRefs,
|
||||
} from '../../../helpers/utils/settings-search';
|
||||
import { Box, Text } from '../../../components/component-library';
|
||||
import {
|
||||
TextColor,
|
||||
TextVariant,
|
||||
} from '../../../helpers/constants/design-system';
|
||||
|
||||
export default class SecurityTab extends PureComponent {
|
||||
static contextTypes = {
|
||||
@ -55,6 +60,8 @@ export default class SecurityTab extends PureComponent {
|
||||
setUseMultiAccountBalanceChecker: PropTypes.func.isRequired,
|
||||
useCurrencyRateCheck: PropTypes.bool.isRequired,
|
||||
setUseCurrencyRateCheck: PropTypes.func.isRequired,
|
||||
useAddressBarEnsResolution: PropTypes.bool.isRequired,
|
||||
setUseAddressBarEnsResolution: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
state = {
|
||||
@ -309,6 +316,8 @@ export default class SecurityTab extends PureComponent {
|
||||
renderIpfsGatewayControl() {
|
||||
const { t } = this.context;
|
||||
const { ipfsGatewayError } = this.state;
|
||||
const { useAddressBarEnsResolution, setUseAddressBarEnsResolution } =
|
||||
this.props;
|
||||
|
||||
const handleIpfsGatewaySave = (gateway) => {
|
||||
const url = new URL(addUrlProtocolPrefix(gateway));
|
||||
@ -370,6 +379,63 @@ export default class SecurityTab extends PureComponent {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="settings-page__content-item"
|
||||
ref={this.settingsRefs[9]}
|
||||
id="ens-domains"
|
||||
>
|
||||
{t('ensDomainsSettingTitle')}
|
||||
<div className="settings-page__content-description">
|
||||
<Text color={TextColor.inherit} variant={TextVariant.inherit}>
|
||||
{t('ensDomainsSettingDescriptionIntro')}
|
||||
</Text>
|
||||
<Box
|
||||
as="ul"
|
||||
marginTop={4}
|
||||
marginBottom={4}
|
||||
paddingInlineStart={4}
|
||||
style={{ listStyleType: 'circle' }}
|
||||
>
|
||||
<Text
|
||||
as="li"
|
||||
color={TextColor.inherit}
|
||||
variant={TextVariant.inherit}
|
||||
>
|
||||
{t('ensDomainsSettingDescriptionPoint1')}
|
||||
</Text>
|
||||
<Text
|
||||
as="li"
|
||||
color={TextColor.inherit}
|
||||
variant={TextVariant.inherit}
|
||||
>
|
||||
{t('ensDomainsSettingDescriptionPoint2')}
|
||||
</Text>
|
||||
<Text
|
||||
as="li"
|
||||
color={TextColor.inherit}
|
||||
variant={TextVariant.inherit}
|
||||
>
|
||||
{t('ensDomainsSettingDescriptionPoint3')}
|
||||
</Text>
|
||||
</Box>
|
||||
<Text color={TextColor.inherit} variant={TextVariant.inherit}>
|
||||
{t('ensDomainsSettingDescriptionOutro')}
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-page__content-item">
|
||||
<div
|
||||
className="settings-page__content-item-col"
|
||||
data-testid="ipfs-gateway-resolution-container"
|
||||
>
|
||||
<ToggleButton
|
||||
value={useAddressBarEnsResolution}
|
||||
onToggle={(value) => setUseAddressBarEnsResolution(!value)}
|
||||
offLabel={t('off')}
|
||||
onLabel={t('on')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
setUseMultiAccountBalanceChecker,
|
||||
setUsePhishDetect,
|
||||
setUseTokenDetection,
|
||||
setUseAddressBarEnsResolution,
|
||||
} from '../../../store/actions';
|
||||
import SecurityTab from './security-tab.component';
|
||||
|
||||
@ -25,6 +26,7 @@ const mapStateToProps = (state) => {
|
||||
ipfsGateway,
|
||||
useMultiAccountBalanceChecker,
|
||||
useCurrencyRateCheck,
|
||||
useAddressBarEnsResolution,
|
||||
} = metamask;
|
||||
|
||||
return {
|
||||
@ -36,6 +38,7 @@ const mapStateToProps = (state) => {
|
||||
ipfsGateway,
|
||||
useMultiAccountBalanceChecker,
|
||||
useCurrencyRateCheck,
|
||||
useAddressBarEnsResolution,
|
||||
};
|
||||
};
|
||||
|
||||
@ -56,6 +59,8 @@ const mapDispatchToProps = (dispatch) => {
|
||||
setUseMultiAccountBalanceChecker: (value) => {
|
||||
return dispatch(setUseMultiAccountBalanceChecker(value));
|
||||
},
|
||||
setUseAddressBarEnsResolution: (value) =>
|
||||
dispatch(setUseAddressBarEnsResolution(value)),
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -3095,6 +3095,19 @@ export function setIpfsGateway(
|
||||
};
|
||||
}
|
||||
|
||||
export function setUseAddressBarEnsResolution(
|
||||
val: string,
|
||||
): ThunkAction<void, MetaMaskReduxState, unknown, AnyAction> {
|
||||
return (dispatch: MetaMaskReduxDispatch) => {
|
||||
log.debug(`background.setUseAddressBarEnsResolution`);
|
||||
callBackgroundMethod('setUseAddressBarEnsResolution', [val], (err) => {
|
||||
if (err) {
|
||||
dispatch(displayWarning(err));
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function updateCurrentLocale(
|
||||
key: string,
|
||||
): ThunkAction<void, MetaMaskReduxState, unknown, AnyAction> {
|
||||
|
Loading…
Reference in New Issue
Block a user