From 932282e638902621fd40d297c840dbf175ca8885 Mon Sep 17 00:00:00 2001 From: Filip Sekulic Date: Mon, 27 Feb 2023 17:20:22 +0100 Subject: [PATCH] What's new - OpenSea security provider (#16831) --- app/_locales/en/messages.json | 21 +++ app/images/open-sea-security-provider.svg | 91 +++++++++++++ app/scripts/controllers/preferences.js | 11 ++ app/scripts/controllers/preferences.test.js | 24 ++++ app/scripts/metamask-controller.js | 4 + test/e2e/fixture-builder.js | 2 + .../app/open-sea-whats-new-popover/index.js | 1 + .../app/open-sea-whats-new-popover/index.scss | 6 + .../open-sea-whats-new-popover.js | 124 ++++++++++++++++++ ui/pages/home/home.component.js | 2 + ui/selectors/selectors.js | 6 + ui/store/actions.ts | 16 ++- 12 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 app/images/open-sea-security-provider.svg create mode 100644 ui/components/app/open-sea-whats-new-popover/index.js create mode 100644 ui/components/app/open-sea-whats-new-popover/index.scss create mode 100644 ui/components/app/open-sea-whats-new-popover/open-sea-whats-new-popover.js diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 3cd6aa772..f7845b79b 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -329,6 +329,9 @@ "message": "Allow $1 to withdraw and spend up to the following amount:", "description": "The url of the site that requested permission to 'withdraw and spend'" }, + "alwaysBeSureTo": { + "message": "Always be sure to do your own due diligence before approving any requests." + }, "amount": { "message": "Amount" }, @@ -1266,6 +1269,9 @@ "enableOpenSeaAPIDescription": { "message": "Use OpenSea's API to fetch NFT data. NFT auto-detection relies on OpenSea's API, and will not be available when this is turned off." }, + "enableOpenSeaSecurityProvider": { + "message": "Enable security provider" + }, "enableSmartTransactions": { "message": "Enable smart transactions" }, @@ -1567,6 +1573,9 @@ "message": "Get Ether from a faucet for the $1 network.", "description": "Displays network name for Ether faucet" }, + "getWarningsFromOpenSea": { + "message": "Get warnings from OpenSea whenever you receive a known malicious request." + }, "goBack": { "message": "Go back" }, @@ -2327,6 +2336,9 @@ "notEnoughGas": { "message": "Not enough gas" }, + "notNow": { + "message": "Not now" + }, "notifications": { "message": "Notifications" }, @@ -2660,6 +2672,12 @@ "openSea": { "message": "OpenSea (Beta)" }, + "openSeaAltText": { + "message": "OpenSea security provider" + }, + "openSeaDescription": { + "message": "OpenSea is the first security provider for this feature. More providers coming soon!" + }, "openSeaNew": { "message": "OpenSea" }, @@ -3561,6 +3579,9 @@ "statusNotConnected": { "message": "Not connected" }, + "staySafeWithOpenSea": { + "message": "Stay safe with OpenSea" + }, "step1LatticeWallet": { "message": "Connect your Lattice1" }, diff --git a/app/images/open-sea-security-provider.svg b/app/images/open-sea-security-provider.svg new file mode 100644 index 000000000..ac79c0026 --- /dev/null +++ b/app/images/open-sea-security-provider.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index ab51bb0c5..b0afa083b 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -70,6 +70,7 @@ export default class PreferencesController { : LedgerTransportTypes.u2f, transactionSecurityCheckEnabled: false, theme: ThemeType.os, + openSeaTransactionSecurityProviderPopoverHasBeenShown: false, ...opts.initState, }; @@ -206,6 +207,16 @@ export default class PreferencesController { }); } + /** + * Setter for the `openSeaTransactionSecurityProviderPopoverHasBeenShown` property + * + */ + setOpenSeaTransactionSecurityProviderPopoverHasBeenShown() { + this.store.updateState({ + openSeaTransactionSecurityProviderPopoverHasBeenShown: true, + }); + } + /** * Add new methodData to state, to avoid requesting this information again through Infura * diff --git a/app/scripts/controllers/preferences.test.js b/app/scripts/controllers/preferences.test.js index 7c4e2d110..1679cab45 100644 --- a/app/scripts/controllers/preferences.test.js +++ b/app/scripts/controllers/preferences.test.js @@ -390,4 +390,28 @@ describe('preferences controller', function () { ); }); }); + + describe('setOpenSeaTransactionSecurityProviderPopoverHasBeenShown', function () { + it('should default to value "false"', function () { + const state = preferencesController.store.getState(); + assert.equal( + state.openSeaTransactionSecurityProviderPopoverHasBeenShown, + false, + ); + }); + + it('should set the openSeaTransactionSecurityProviderPopoverHasBeenShown to true', function () { + const state = preferencesController.store.getState(); + assert.equal( + state.openSeaTransactionSecurityProviderPopoverHasBeenShown, + false, + ); + preferencesController.setOpenSeaTransactionSecurityProviderPopoverHasBeenShown(); + assert.equal( + preferencesController.store.getState() + .openSeaTransactionSecurityProviderPopoverHasBeenShown, + true, + ); + }); + }); }); diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 9309d1eb8..73578b834 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1865,6 +1865,10 @@ export default class MetamaskController extends EventEmitter { preferencesController.setTransactionSecurityCheckEnabled.bind( preferencesController, ), + setOpenSeaTransactionSecurityProviderPopoverHasBeenShown: + preferencesController.setOpenSeaTransactionSecurityProviderPopoverHasBeenShown.bind( + preferencesController, + ), // AssetsContractController getTokenStandardAndDetails: this.getTokenStandardAndDetails.bind(this), diff --git a/test/e2e/fixture-builder.js b/test/e2e/fixture-builder.js index 7ec760bcf..3e0c6921f 100644 --- a/test/e2e/fixture-builder.js +++ b/test/e2e/fixture-builder.js @@ -234,6 +234,7 @@ function defaultFixture() { useTokenDetection: false, useCurrencyRateCheck: true, useMultiAccountBalanceChecker: true, + openSeaTransactionSecurityProviderPopoverHasBeenShown: true, }, SmartTransactionsController: { smartTransactionsState: { @@ -346,6 +347,7 @@ function onboardingFixture() { useTokenDetection: false, useCurrencyRateCheck: true, useMultiAccountBalanceChecker: true, + openSeaTransactionSecurityProviderPopoverHasBeenShown: true, }, SmartTransactionsController: { smartTransactionsState: { diff --git a/ui/components/app/open-sea-whats-new-popover/index.js b/ui/components/app/open-sea-whats-new-popover/index.js new file mode 100644 index 000000000..abd91185e --- /dev/null +++ b/ui/components/app/open-sea-whats-new-popover/index.js @@ -0,0 +1 @@ +export { default } from './open-sea-whats-new-popover'; diff --git a/ui/components/app/open-sea-whats-new-popover/index.scss b/ui/components/app/open-sea-whats-new-popover/index.scss new file mode 100644 index 000000000..ff307b957 --- /dev/null +++ b/ui/components/app/open-sea-whats-new-popover/index.scss @@ -0,0 +1,6 @@ +.open-sea-whats-new-popover { + &__enable-security-provider-button { + width: fit-content; + font-weight: 400; + } +} diff --git a/ui/components/app/open-sea-whats-new-popover/open-sea-whats-new-popover.js b/ui/components/app/open-sea-whats-new-popover/open-sea-whats-new-popover.js new file mode 100644 index 000000000..30bfda33a --- /dev/null +++ b/ui/components/app/open-sea-whats-new-popover/open-sea-whats-new-popover.js @@ -0,0 +1,124 @@ +import React, { useContext } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { useHistory } from 'react-router-dom'; +import { I18nContext } from '../../../contexts/i18n'; +import Popover from '../../ui/popover'; +import { + DISPLAY, + FLEX_DIRECTION, + FONT_WEIGHT, + TextColor, + TextVariant, +} from '../../../helpers/constants/design-system'; +import Button from '../../ui/button'; +import Box from '../../ui/box'; +import { + setOpenSeaTransactionSecurityProviderPopoverHasBeenShown, + setTransactionSecurityCheckEnabled, +} from '../../../store/actions'; +import { getHasTheOpenSeaTransactionSecurityProviderPopoverBeenShown } from '../../../selectors'; +import { Text } from '../../component-library'; +import { EXPERIMENTAL_ROUTE } from '../../../helpers/constants/routes'; + +export default function OpenSeaWhatsNewPopover() { + const t = useContext(I18nContext); + const dispatch = useDispatch(); + const history = useHistory(); + + const hasThePopoverBeenShown = useSelector( + getHasTheOpenSeaTransactionSecurityProviderPopoverBeenShown, + ); + + return ( + process.env.TRANSACTION_SECURITY_PROVIDER && + !hasThePopoverBeenShown && ( + + {t('staySafeWithOpenSea')} + + } + footer={ + <> + + + + + + + + } + footerClassName="smart-transactions-popover__footer" + className="smart-transactions-popover" + onClose={() => + dispatch(setOpenSeaTransactionSecurityProviderPopoverHasBeenShown()) + } + > + + + {t('openSeaAltText')} + + + {t('getWarningsFromOpenSea')} + + + {t('openSeaDescription')} + + + {t('alwaysBeSureTo')} + + + + ) + ); +} diff --git a/ui/pages/home/home.component.js b/ui/pages/home/home.component.js index b0b7c23f2..3b5f62170 100644 --- a/ui/pages/home/home.component.js +++ b/ui/pages/home/home.component.js @@ -49,6 +49,7 @@ import { ONBOARDING_SECURE_YOUR_WALLET_ROUTE, } from '../../helpers/constants/routes'; import ZENDESK_URLS from '../../helpers/constants/zendesk-url'; +import OpenSeaWhatsNewPopover from '../../components/app/open-sea-whats-new-popover/open-sea-whats-new-popover'; ///: BEGIN:ONLY_INCLUDE_IN(main) import { SUPPORT_LINK } from '../../../shared/lib/ui-utils'; ///: END:ONLY_INCLUDE_IN @@ -638,6 +639,7 @@ export default class Home extends PureComponent { />
{showWhatsNew ? : null} + {showWhatsNew ? : null} {!showWhatsNew && showRecoveryPhraseReminder ? ( { - return async () => { + return async (dispatch) => { try { await submitRequestToBackground('setTransactionSecurityCheckEnabled', [ transactionSecurityCheckEnabled, ]); + await forceUpdateMetamaskState(dispatch); } catch (error) { logErrorWithMessage(error); } @@ -4511,6 +4512,19 @@ export function setFirstTimeUsedNetwork(chainId: string) { return submitRequestToBackground('setFirstTimeUsedNetwork', [chainId]); } +export function setOpenSeaTransactionSecurityProviderPopoverHasBeenShown(): ThunkAction< + void, + MetaMaskReduxState, + unknown, + AnyAction +> { + return async () => { + await submitRequestToBackground( + 'setOpenSeaTransactionSecurityProviderPopoverHasBeenShown', + ); + }; +} + // QR Hardware Wallets export async function submitQRHardwareCryptoHDKey(cbor: Hex) { await submitRequestToBackground('submitQRHardwareCryptoHDKey', [cbor]);