diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index e0caae301..f5ec58369 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -871,6 +871,12 @@
"expandView": {
"message": "Expand view"
},
+ "experimental": {
+ "message": "Experimental"
+ },
+ "experimentalSettingsDescription": {
+ "message": "Token detection & more"
+ },
"exportPrivateKey": {
"message": "Export Private Key"
},
@@ -2733,7 +2739,7 @@
"message": "Use Token Detection"
},
"useTokenDetectionDescription": {
- "message": "We use third-party APIs to detect and display new tokens sent to your wallet. Turn this off if you don’t want MetaMask to pull data from those those services."
+ "message": "We use third-party APIs to detect and display new tokens sent to your wallet. Turn off if you don’t want MetaMask to pull data from those services."
},
"usedByClients": {
"message": "Used by a variety of different clients"
diff --git a/ui/helpers/constants/routes.js b/ui/helpers/constants/routes.js
index 579b33585..800a4badb 100644
--- a/ui/helpers/constants/routes.js
+++ b/ui/helpers/constants/routes.js
@@ -5,6 +5,7 @@ const ASSET_ROUTE = '/asset';
const SETTINGS_ROUTE = '/settings';
const GENERAL_ROUTE = '/settings/general';
const ADVANCED_ROUTE = '/settings/advanced';
+const EXPERIMENTAL_ROUTE = '/settings/experimental';
const SECURITY_ROUTE = '/settings/security';
const ABOUT_US_ROUTE = '/settings/about-us';
const ALERTS_ROUTE = '/settings/alerts';
@@ -73,6 +74,7 @@ const PATH_NAME_MAP = {
[SETTINGS_ROUTE]: 'Settings Page',
[GENERAL_ROUTE]: 'General Settings Page',
[ADVANCED_ROUTE]: 'Advanced Settings Page',
+ [EXPERIMENTAL_ROUTE]: 'Experimental Settings Page',
[SECURITY_ROUTE]: 'Security Settings Page',
[ABOUT_US_ROUTE]: 'About Us Page',
[ALERTS_ROUTE]: 'Alerts Settings Page',
@@ -172,6 +174,7 @@ export {
CONFIRMATION_V_NEXT_ROUTE,
INITIALIZE_METAMETRICS_OPT_IN_ROUTE,
ADVANCED_ROUTE,
+ EXPERIMENTAL_ROUTE,
SECURITY_ROUTE,
GENERAL_ROUTE,
ABOUT_US_ROUTE,
diff --git a/ui/pages/settings/experimental-tab/experimental-tab.component.js b/ui/pages/settings/experimental-tab/experimental-tab.component.js
new file mode 100644
index 000000000..db41d008a
--- /dev/null
+++ b/ui/pages/settings/experimental-tab/experimental-tab.component.js
@@ -0,0 +1,58 @@
+import React, { PureComponent } from 'react';
+import PropTypes from 'prop-types';
+import ToggleButton from '../../../components/ui/toggle-button';
+
+export default class ExperimentalTab extends PureComponent {
+ static contextTypes = {
+ t: PropTypes.func,
+ metricsEvent: PropTypes.func,
+ };
+
+ static propTypes = {
+ useTokenDetection: PropTypes.bool,
+ setUseTokenDetection: PropTypes.func,
+ };
+
+ renderTokenDetectionToggle() {
+ const { t } = this.context;
+ const { useTokenDetection, setUseTokenDetection } = this.props;
+
+ return (
+
+
+
{t('useTokenDetection')}
+
+ {t('useTokenDetectionDescription')}
+
+
+
+
+ {
+ this.context.metricsEvent({
+ eventOpts: {
+ category: 'Settings',
+ action: 'Token Detection',
+ name: 'Token Detection',
+ },
+ });
+ setUseTokenDetection(!value);
+ }}
+ offLabel={t('off')}
+ onLabel={t('on')}
+ />
+
+
+
+ );
+ }
+
+ render() {
+ return (
+
+ {this.renderTokenDetectionToggle()}
+
+ );
+ }
+}
diff --git a/ui/pages/settings/experimental-tab/experimental-tab.component.test.js b/ui/pages/settings/experimental-tab/experimental-tab.component.test.js
new file mode 100644
index 000000000..158e6f76e
--- /dev/null
+++ b/ui/pages/settings/experimental-tab/experimental-tab.component.test.js
@@ -0,0 +1,28 @@
+import React from 'react';
+import sinon from 'sinon';
+import { mount } from 'enzyme';
+import ExperimentalTab from './experimental-tab.container';
+
+describe('Experimental Tab', () => {
+ let wrapper;
+
+ const props = {
+ useTokenDetection: true,
+ setUseTokenDetection: sinon.spy(),
+ };
+
+ beforeEach(() => {
+ wrapper = mount(, {
+ context: {
+ t: (str) => str,
+ metricsEvent: () => undefined,
+ },
+ });
+ });
+
+ it('toggles Use Token detection', () => {
+ const useTokenDetection = wrapper.find({ type: 'checkbox' }).at(0);
+ useTokenDetection.simulate('click');
+ expect(props.setUseTokenDetection.calledOnce).toStrictEqual(true);
+ });
+});
diff --git a/ui/pages/settings/experimental-tab/experimental-tab.container.js b/ui/pages/settings/experimental-tab/experimental-tab.container.js
new file mode 100644
index 000000000..6af85154d
--- /dev/null
+++ b/ui/pages/settings/experimental-tab/experimental-tab.container.js
@@ -0,0 +1,23 @@
+import { compose } from 'redux';
+import { connect } from 'react-redux';
+import { withRouter } from 'react-router-dom';
+import { setUseTokenDetection } from '../../../store/actions';
+import { getUseTokenDetection } from '../../../selectors';
+import ExperimentalTab from './experimental-tab.component';
+
+const mapStateToProps = (state) => {
+ return {
+ useTokenDetection: getUseTokenDetection(state),
+ };
+};
+
+const mapDispatchToProps = (dispatch) => {
+ return {
+ setUseTokenDetection: (val) => dispatch(setUseTokenDetection(val)),
+ };
+};
+
+export default compose(
+ withRouter,
+ connect(mapStateToProps, mapDispatchToProps),
+)(ExperimentalTab);
diff --git a/ui/pages/settings/experimental-tab/index.js b/ui/pages/settings/experimental-tab/index.js
new file mode 100644
index 000000000..ca614580f
--- /dev/null
+++ b/ui/pages/settings/experimental-tab/index.js
@@ -0,0 +1 @@
+export { default } from './experimental-tab.container';
diff --git a/ui/pages/settings/security-tab/security-tab.component.js b/ui/pages/settings/security-tab/security-tab.component.js
index 5cb75f454..8eab40ec2 100644
--- a/ui/pages/settings/security-tab/security-tab.component.js
+++ b/ui/pages/settings/security-tab/security-tab.component.js
@@ -19,8 +19,6 @@ export default class SecurityTab extends PureComponent {
setShowIncomingTransactionsFeatureFlag: PropTypes.func.isRequired,
setUsePhishDetect: PropTypes.func.isRequired,
usePhishDetect: PropTypes.bool.isRequired,
- useTokenDetection: PropTypes.bool.isRequired,
- setUseTokenDetection: PropTypes.func.isRequired,
};
renderSeedWords() {
@@ -143,32 +141,6 @@ export default class SecurityTab extends PureComponent {
);
}
- renderTokenDetectionToggle() {
- const { t } = this.context;
- const { useTokenDetection, setUseTokenDetection } = this.props;
-
- return (
-
-
-
{t('useTokenDetection')}
-
- {t('useTokenDetectionDescription')}
-
-
-
-
- setUseTokenDetection(!value)}
- offLabel={t('off')}
- onLabel={t('on')}
- />
-
-
-
- );
- }
-
render() {
const { warning } = this.props;
@@ -179,7 +151,6 @@ export default class SecurityTab extends PureComponent {
{this.renderIncomingTransactionsOptIn()}
{this.renderPhishingDetectionToggle()}
{this.renderMetaMetricsOptIn()}
- {this.renderTokenDetectionToggle()}
);
}
diff --git a/ui/pages/settings/security-tab/security-tab.container.js b/ui/pages/settings/security-tab/security-tab.container.js
index 61c7e63ee..e6060f45b 100644
--- a/ui/pages/settings/security-tab/security-tab.container.js
+++ b/ui/pages/settings/security-tab/security-tab.container.js
@@ -5,7 +5,6 @@ import {
setFeatureFlag,
setParticipateInMetaMetrics,
setUsePhishDetect,
- setUseTokenDetection,
} from '../../../store/actions';
import SecurityTab from './security-tab.component';
@@ -18,7 +17,6 @@ const mapStateToProps = (state) => {
featureFlags: { showIncomingTransactions } = {},
participateInMetaMetrics,
usePhishDetect,
- useTokenDetection,
} = metamask;
return {
@@ -26,7 +24,6 @@ const mapStateToProps = (state) => {
showIncomingTransactions,
participateInMetaMetrics,
usePhishDetect,
- useTokenDetection,
};
};
@@ -37,7 +34,6 @@ const mapDispatchToProps = (dispatch) => {
setShowIncomingTransactionsFeatureFlag: (shouldShow) =>
dispatch(setFeatureFlag('showIncomingTransactions', shouldShow)),
setUsePhishDetect: (val) => dispatch(setUsePhishDetect(val)),
- setUseTokenDetection: (val) => dispatch(setUseTokenDetection(val)),
};
};
diff --git a/ui/pages/settings/settings.component.js b/ui/pages/settings/settings.component.js
index 6efe49b05..c9f694c1c 100644
--- a/ui/pages/settings/settings.component.js
+++ b/ui/pages/settings/settings.component.js
@@ -15,6 +15,7 @@ import {
CONTACT_ADD_ROUTE,
CONTACT_EDIT_ROUTE,
CONTACT_VIEW_ROUTE,
+ EXPERIMENTAL_ROUTE,
} from '../../helpers/constants/routes';
import SettingsTab from './settings-tab';
import AlertsTab from './alerts-tab';
@@ -23,6 +24,7 @@ import AdvancedTab from './advanced-tab';
import InfoTab from './info-tab';
import SecurityTab from './security-tab';
import ContactListTab from './contact-list-tab';
+import ExperimentalTab from './experimental-tab';
class SettingsPage extends PureComponent {
static propTypes = {
@@ -191,6 +193,11 @@ class SettingsPage extends PureComponent {
description: t('networkSettingsDescription'),
key: NETWORKS_ROUTE,
},
+ {
+ content: t('experimental'),
+ description: t('experimentalSettingsDescription'),
+ key: EXPERIMENTAL_ROUTE,
+ },
{
content: t('about'),
description: t('aboutSettingsDescription'),
@@ -217,6 +224,7 @@ class SettingsPage extends PureComponent {
+
{