Skip to content

Commit

Permalink
feat: add token autodetect modal (MetaMask#24281)
Browse files Browse the repository at this point in the history
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Add in recommended auto token enablement button in new Extension app
update, once we enable auto token detection by default for new users,
for existing users, we need to get them to turn on auto token detection
as well.

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/24281?quickstart=1)

## **Related issues**

Fixes:

## **Manual testing steps**

1. you are an existing user and you have token autodetection off
2. once the upgrade will be done , you should see the modal below right
after what's new pop up
3. if you have it of and you decide to disable , you should see the pop
up once

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

No Modal was displayed

### **After**
Existing users with toggle off


https://github.com/MetaMask/metamask-extension/assets/26223211/2ff49f38-e652-4287-9b0a-a7092b8a1812

Users with toggle on and want to disable it ( the modal should be
displayed once )




https://github.com/MetaMask/metamask-extension/assets/26223211/4438312f-cbb3-47f1-bc80-d1158b73e66a



## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
  • Loading branch information
salimtb authored May 31, 2024
1 parent 5f22357 commit b560fdc
Show file tree
Hide file tree
Showing 30 changed files with 448 additions and 7 deletions.
18 changes: 18 additions & 0 deletions app/_locales/en/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added app/images/wallet-alpha.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions app/scripts/controllers/app-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type AppMetadataControllerState = {
previousAppVersion: string;
previousMigrationVersion: number;
currentMigrationVersion: number;
showTokenAutodetectModalOnUpgrade: boolean | null;
};

/**
Expand All @@ -25,6 +26,7 @@ const defaultState: AppMetadataControllerState = {
previousAppVersion: '',
previousMigrationVersion: 0,
currentMigrationVersion: 0,
showTokenAutodetectModalOnUpgrade: false,
};

/**
Expand Down Expand Up @@ -76,6 +78,7 @@ export default class AppMetadataController extends EventEmitter {
this.store.updateState({
currentAppVersion: maybeNewAppVersion,
previousAppVersion: oldCurrentAppVersion,
showTokenAutodetectModalOnUpgrade: null,
});
}
}
Expand All @@ -96,4 +99,13 @@ export default class AppMetadataController extends EventEmitter {
});
}
}

/**
* Setter for the `showTokenAutodetectModalOnUpgrade` property
*
* @param val - Indicates the value of showTokenAutodetectModalOnUpgrade
*/
setShowTokenAutodetectModalOnUpgrade(val: boolean): void {
this.store.updateState({ showTokenAutodetectModalOnUpgrade: val });
}
}
1 change: 1 addition & 0 deletions app/scripts/controllers/preferences.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export default class PreferencesController {
petnamesEnabled: true,
redesignedConfirmationsEnabled: true,
featureNotificationsEnabled: false,
showTokenAutodetectModal: null,
},
// ENS decentralized website resolution
ipfsGateway: IPFS_DEFAULT_GATEWAY_URL,
Expand Down
1 change: 1 addition & 0 deletions app/scripts/lib/backup.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ const jsonData = JSON.stringify({
showTestNetworks: true,
smartTransactionsOptInStatus: false,
useNativeCurrencyAsPrimaryCurrency: true,
showTokenAutodetectModal: false,
},
ipfsGateway: 'dweb.link',
ledgerTransportType: 'webhid',
Expand Down
2 changes: 2 additions & 0 deletions app/scripts/lib/setupSentry.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export const SENTRY_BACKGROUND_STATE = {
currentMigrationVersion: true,
previousAppVersion: true,
previousMigrationVersion: true,
showTokenAutodetectModalOnUpgrade: false,
},
ApprovalController: {
approvalFlows: false,
Expand Down Expand Up @@ -240,6 +241,7 @@ export const SENTRY_BACKGROUND_STATE = {
smartTransactionsOptInStatus: true,
useNativeCurrencyAsPrimaryCurrency: true,
petnamesEnabled: true,
showTokenAutodetectModal: false,
},
useExternalServices: false,
selectedAddress: false,
Expand Down
7 changes: 7 additions & 0 deletions app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -2961,6 +2961,7 @@ export default class MetamaskController extends EventEmitter {
networkController,
announcementController,
onboardingController,
appMetadataController,
permissionController,
preferencesController,
swapsController,
Expand Down Expand Up @@ -3394,6 +3395,12 @@ export default class MetamaskController extends EventEmitter {
this.encryptionPublicKeyController,
),

// AppMetadataController
setShowTokenAutodetectModalOnUpgrade:
appMetadataController.setShowTokenAutodetectModalOnUpgrade.bind(
appMetadataController,
),

// onboarding controller
setSeedPhraseBackedUp:
onboardingController.setSeedPhraseBackedUp.bind(onboardingController),
Expand Down
2 changes: 2 additions & 0 deletions shared/constants/metametrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,8 @@ export enum MetaMetricsEventName {
SnapAccountTransactionFinalizeRedirectGoToSiteClicked = 'Snap Account Transaction Finalize Redirect "Go To Site" Clicked',
SnapAccountTransactionFinalizeRedirectSnapUrlClicked = 'Snap Account Transaction Finalize Redirect "Snap URL" Clicked',
SnapAccountTransactionFinalizeClosed = 'Snap Account Transaction Finalize Closed',
TokenAutoDetectionEnableModal = 'Token Autodetection Enabled from modal',
TokenAutoDetectionDisableModal = 'Token Autodetection Disabled from modal',
///: END:ONLY_INCLUDE_IF
TurnOffProfileSyncing = 'Turn Off Profile Syncing',
TurnOnProfileSyncing = 'Turn On Profile Syncing',
Expand Down
9 changes: 9 additions & 0 deletions shared/modules/selectors/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ describe('Selectors', () => {
metamask: {
preferences: {
smartTransactionsOptInStatus: true,
showTokenAutodetectModal: true,
},
internalAccounts: {
selectedAccount: 'account1',
Expand Down Expand Up @@ -68,6 +69,14 @@ describe('Selectors', () => {
});
});

describe('getShowTokenAutodetectModal', () => {
it('should return show autodetection token modal status', () => {
const state = createMockState();
const result = getSmartTransactionsOptInStatus(state);
expect(result).toBe(true);
});
});

describe('getCurrentChainSupportsSmartTransactions', () => {
it('should return true if the chain ID is allowed for smart transactions', () => {
const state = createMockState();
Expand Down
1 change: 1 addition & 0 deletions shared/modules/selectors/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './smart-transactions';
export * from './feature-flags';
export * from './token-auto-detect';
32 changes: 32 additions & 0 deletions shared/modules/selectors/token-auto-detect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { getUseTokenDetection } from '../../../ui/selectors/selectors';

type TokenAutoDetectionMetaMaskState = {
metamask: {
preferences: {
showTokenAutodetectModal: boolean | null;
};
showTokenAutodetectModalOnUpgrade: boolean | null;
};
};

export const getShowTokenAutodetectModal = (
state: TokenAutoDetectionMetaMaskState,
): boolean | null => {
return state.metamask.preferences?.showTokenAutodetectModal;
};

export const getIsShowTokenAutodetectModal = (
state: TokenAutoDetectionMetaMaskState,
) => {
// Upgrade case
if (state.metamask.showTokenAutodetectModalOnUpgrade === null) {
return (
!getUseTokenDetection(state) &&
state.metamask.showTokenAutodetectModalOnUpgrade === null
);
}

return (
!getUseTokenDetection(state) && getShowTokenAutodetectModal(state) === null
);
};
1 change: 1 addition & 0 deletions test/e2e/default-fixture.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ function defaultFixture(inputChainId = CHAIN_IDS.LOCALHOST) {
smartTransactionsOptInStatus: false,
useNativeCurrencyAsPrimaryCurrency: true,
petnamesEnabled: true,
showTokenAutodetectModal: false,
},
selectedAddress: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
theme: 'light',
Expand Down
1 change: 1 addition & 0 deletions test/e2e/fixture-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ function onboardingFixture() {
smartTransactionsOptInStatus: false,
useNativeCurrencyAsPrimaryCurrency: true,
petnamesEnabled: true,
showTokenAutodetectModal: false,
},
useExternalServices: true,
theme: 'light',
Expand Down
3 changes: 2 additions & 1 deletion test/e2e/restore/MetaMaskUserData.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"showFiatInTestnets": false,
"showTestNetworks": false,
"smartTransactionsOptInStatus": false,
"useNativeCurrencyAsPrimaryCurrency": true
"useNativeCurrencyAsPrimaryCurrency": true,
"showTokenAutodetectModal": "boolean"
},
"theme": "light",
"useBlockie": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"currentAppVersion": "string",
"previousAppVersion": "",
"previousMigrationVersion": 0,
"currentMigrationVersion": "number"
"currentMigrationVersion": "number",
"showTokenAutodetectModalOnUpgrade": "object"
},
"AppStateController": {
"connectedStatusPopoverHasBeenShown": true,
Expand Down Expand Up @@ -187,7 +188,8 @@
"showTestNetworks": false,
"smartTransactionsOptInStatus": false,
"useNativeCurrencyAsPrimaryCurrency": true,
"petnamesEnabled": true
"petnamesEnabled": true,
"showTokenAutodetectModal": "boolean"
},
"ipfsGateway": "string",
"isIpfsGatewayEnabled": "boolean",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
"showTestNetworks": false,
"smartTransactionsOptInStatus": false,
"useNativeCurrencyAsPrimaryCurrency": true,
"petnamesEnabled": true
"petnamesEnabled": true,
"showTokenAutodetectModal": "boolean"
},
"firstTimeFlowType": "import",
"completedOnboarding": true,
Expand Down Expand Up @@ -91,6 +92,7 @@
"previousMigrationVersion": 0,
"currentMigrationVersion": "number",
"selectedNetworkClientId": "string",
"showTokenAutodetectModalOnUpgrade": "object",
"networksMetadata": {
"networkConfigurationId": {
"EIPS": { "1559": false },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@
"showTestNetworks": false,
"smartTransactionsOptInStatus": false,
"useNativeCurrencyAsPrimaryCurrency": true,
"petnamesEnabled": true
"petnamesEnabled": true,
"showTokenAutodetectModal": "boolean"
},
"selectedAddress": "string",
"theme": "light",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@
"showTestNetworks": false,
"smartTransactionsOptInStatus": false,
"useNativeCurrencyAsPrimaryCurrency": true,
"petnamesEnabled": true
"petnamesEnabled": true,
"showTokenAutodetectModal": "boolean"
},
"selectedAddress": "string",
"theme": "light",
Expand Down
1 change: 1 addition & 0 deletions test/jest/mock-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ export const createSwapsMockStore = () => {
preferences: {
showFiatInTestnets: true,
smartTransactionsOptInStatus: true,
showTokenAutodetectModal: false,
},
transactions: [
{
Expand Down
1 change: 1 addition & 0 deletions ui/components/app/app-components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
@import 'recovery-phrase-reminder/index';
@import 'step-progress-bar/index.scss';
@import 'selected-account/index';
@import 'auto-detect-token/index';
@import 'smart-transactions/index';
@import 'srp-input/srp-input';
@import 'snaps/snap-privacy-warning/index';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from 'react';
import { Provider } from 'react-redux';
import testData from '../../../../.storybook/test-data';
import configureStore from '../../../store/store';
import AutoDetectTokenModal from './auto-detect-token-modal';

const customData = {
...testData,
metamask: {
...testData.metamask,
currentCurrency: 'USD',
intlLocale: 'en-US',
},
};
const customStore = configureStore(customData);

export default {
title: 'Components/App/AutoDetectTokenModal',
component: AutoDetectTokenModal,
decorators: [
(Story) => (
<Provider store={customStore}>
<Story />
</Provider>
),
],
argTypes: {
isOpen: {
control: 'boolean',
},
onClose: { action: 'onClose' },
},
args: {
isOpen: true,
},
};

const Template = (args) => <AutoDetectTokenModal {...args} />;

export const ModalOpen = Template.bind({});
ModalOpen.args = {
isOpen: true,
};

export const ModalClosed = Template.bind({});
ModalClosed.args = {
isOpen: false,
};
Loading

0 comments on commit b560fdc

Please sign in to comment.