From 481e6a37927dd5b5f0c641e2e2752896dfbb5aac Mon Sep 17 00:00:00 2001 From: Michael <30682308+mike10ca@users.noreply.github.com> Date: Wed, 1 Nov 2023 13:14:19 +0100 Subject: [PATCH 1/9] Tests: Update skipped tests (#2723) * Update skipped tests * Fix permissions tests * Fix NFTS tests --- cypress/e2e/pages/dashboard.pages.js | 6 +- cypress/e2e/pages/nfts.pages.js | 6 +- cypress/e2e/pages/safeapps.pages.js | 2 +- .../e2e/safe-apps/browser_permissions.cy.js | 5 +- cypress/e2e/safe-apps/safe_permissions.cy.js | 6 +- cypress/e2e/smoke/dashboard.cy.js | 12 +- cypress/e2e/smoke/nfts.cy.js | 16 +-- cypress/e2e/smoke/tx_history.cy.js | 115 +++--------------- 8 files changed, 42 insertions(+), 126 deletions(-) diff --git a/cypress/e2e/pages/dashboard.pages.js b/cypress/e2e/pages/dashboard.pages.js index 43ad81fa8a..44b0bb4743 100644 --- a/cypress/e2e/pages/dashboard.pages.js +++ b/cypress/e2e/pages/dashboard.pages.js @@ -66,12 +66,8 @@ export function verifyFeaturedAppsSection() { cy.contains(transactionBuilderStr) cy.get(txBuilder).should('exist') - // WalletConnect app - cy.contains(walletConnectStr) - cy.get(walletConnect).should('exist') - // Featured apps have a Safe-specific link - cy.get(safeSpecificLink).should('have.length', 2) + cy.get(safeSpecificLink).should('have.length', 1) }) } diff --git a/cypress/e2e/pages/nfts.pages.js b/cypress/e2e/pages/nfts.pages.js index 0800d2bb9f..85775098cb 100644 --- a/cypress/e2e/pages/nfts.pages.js +++ b/cypress/e2e/pages/nfts.pages.js @@ -32,8 +32,10 @@ export function verifyDataInTable(name, address, tokenID) { cy.get('tbody tr:first-child').contains('td:nth-child(2)', tokenID) } -export function openFirstNFT() { - cy.get('tbody tr:first-child td:nth-child(2)').click() +export function openNFT(index) { + cy.get('tbody').within(() => { + cy.get('tr').eq(index).click() + }) } export function verifyNameInNFTModal(name) { diff --git a/cypress/e2e/pages/safeapps.pages.js b/cypress/e2e/pages/safeapps.pages.js index 6c2dce7dcb..1385761e8b 100644 --- a/cypress/e2e/pages/safeapps.pages.js +++ b/cypress/e2e/pages/safeapps.pages.js @@ -143,7 +143,7 @@ function verifyDisclaimerIsVisible() { } export function clickOnContinueBtn() { - return cy.findByRole('button', { name: continueBtnStr }).click() + return cy.findByRole('button', { name: continueBtnStr }).click().wait(1000) } export function verifyCameraCheckBoxExists() { diff --git a/cypress/e2e/safe-apps/browser_permissions.cy.js b/cypress/e2e/safe-apps/browser_permissions.cy.js index cfd4f8ae41..da34de03ab 100644 --- a/cypress/e2e/safe-apps/browser_permissions.cy.js +++ b/cypress/e2e/safe-apps/browser_permissions.cy.js @@ -14,11 +14,11 @@ describe('Browser permissions tests', () => { safe_apps_permissions: ['camera', 'microphone'], }) }) + cy.visitSafeApp(`${constants.testAppUrl}/app`) + main.acceptCookies(1) }) it('Verify a permissions slide to the user is displayed [C56137]', () => { - cy.visitSafeApp(`${constants.testAppUrl}/app`) - main.acceptCookies() safeapps.clickOnContinueBtn() safeapps.verifyCameraCheckBoxExists() safeapps.verifyMicrofoneCheckBoxExists() @@ -29,6 +29,7 @@ describe('Browser permissions tests', () => { safeapps.clickOnContinueBtn() safeapps.verifyWarningDefaultAppMsgIsDisplayed() safeapps.verifyCameraCheckBoxExists() + safeapps.clickOnContinueBtn() safeapps.clickOnContinueBtn().should(() => { expect(window.localStorage.getItem(constants.BROWSER_PERMISSIONS_KEY)).to.eq(safeapps.localStorageItem) }) diff --git a/cypress/e2e/safe-apps/safe_permissions.cy.js b/cypress/e2e/safe-apps/safe_permissions.cy.js index b93a135b90..771beee30d 100644 --- a/cypress/e2e/safe-apps/safe_permissions.cy.js +++ b/cypress/e2e/safe-apps/safe_permissions.cy.js @@ -3,10 +3,8 @@ import * as safeapps from '../pages/safeapps.pages' import * as main from '../pages/main.page' describe('Safe permissions system tests', () => { - before(() => { - cy.clearLocalStorage() - }) beforeEach(() => { + cy.clearLocalStorage() cy.fixture('safe-app').then((html) => { cy.intercept('GET', `${constants.testAppUrl}/*`, html) cy.intercept('GET', `*/manifest.json`, { @@ -58,7 +56,7 @@ describe('Safe permissions system tests', () => { }) cy.visitSafeApp(constants.testAppUrl + constants.getPermissionsUrl) - main.acceptCookies() + main.acceptCookies(1) safeapps.clickOnContinueBtn() safeapps.verifyWarningDefaultAppMsgIsDisplayed() safeapps.clickOnContinueBtn() diff --git a/cypress/e2e/smoke/dashboard.cy.js b/cypress/e2e/smoke/dashboard.cy.js index fac9d8a91f..ad0ca6d0ee 100644 --- a/cypress/e2e/smoke/dashboard.cy.js +++ b/cypress/e2e/smoke/dashboard.cy.js @@ -3,27 +3,27 @@ import * as dashboard from '../pages/dashboard.pages' import * as main from '../pages/main.page' describe('Dashboard tests', () => { - before(() => { + beforeEach(() => { cy.clearLocalStorage() cy.visit(constants.BALANCE_URL + constants.SEPOLIA_TEST_SAFE_5) - main.acceptCookies() + main.acceptCookies(2) main.clickOnSideMenuItem(constants.mainSideMenuOptions.home) dashboard.verifyConnectTransactStrIsVisible() }) - it.skip('Verify the overview widget is displayed [C56107]', () => { + it('Verify the overview widget is displayed [C56107]', () => { dashboard.verifyOverviewWidgetData() }) - it.skip('Verify the transaction queue widget is displayed [C56108]', () => { + it('Verify the transaction queue widget is displayed [C56108]', () => { dashboard.verifyTxQueueWidget() }) - it.skip('Verify the featured Safe Apps are displayed [C56109]', () => { + it('Verify the featured Safe Apps are displayed [C56109]', () => { dashboard.verifyFeaturedAppsSection() }) - it.skip('Verify the Safe Apps Section is displayed [C56110]', () => { + it('Verify the Safe Apps Section is displayed [C56110]', () => { dashboard.verifySafeAppsSection() }) }) diff --git a/cypress/e2e/smoke/nfts.cy.js b/cypress/e2e/smoke/nfts.cy.js index d6cb124519..e86f1d671a 100644 --- a/cypress/e2e/smoke/nfts.cy.js +++ b/cypress/e2e/smoke/nfts.cy.js @@ -7,34 +7,34 @@ const nftsAddress = '0x373B...866c' const nftsTokenID = 'CF' describe('NFTs tests', () => { - before(() => { + beforeEach(() => { cy.clearLocalStorage() cy.visit(constants.BALANCE_URL + constants.SEPOLIA_TEST_SAFE_5) - main.acceptCookies() + main.acceptCookies(2) nfts.clickOnNftsTab() }) - it.skip('Verify that NFTs exist in the table [C56123]', () => { + it('Verify that NFTs exist in the table [C56123]', () => { nfts.verifyNFTNumber(20) }) - it.skip('Verify NFT row contains data [C56124]', () => { + it('Verify NFT row contains data [C56124]', () => { nfts.verifyDataInTable(nftsName, nftsAddress, nftsTokenID) }) - it.skip('Verify NFT preview window can be opened [C56125]', () => { - nfts.openFirstNFT() + it('Verify NFT preview window can be opened [C56125]', () => { + nfts.openNFT(1) nfts.verifyNameInNFTModal(nftsTokenID) nfts.verifySelectedNetwrokSepolia() nfts.closeNFTModal() }) - it.skip('Verify NFT open does not open if no NFT exits [C56126]', () => { + it('Verify NFT open does not open if no NFT exits [C56126]', () => { nfts.clickOn6thNFT() nfts.verifyNFTModalDoesNotExist() }) - it.skip('Verify multipls NFTs can be selected and reviewed [C56127]', () => { + it('Verify multipls NFTs can be selected and reviewed [C56127]', () => { nfts.verifyInitialNFTData() nfts.selectNFTs(3) nfts.deselectNFTs([2], 3) diff --git a/cypress/e2e/smoke/tx_history.cy.js b/cypress/e2e/smoke/tx_history.cy.js index dc2fd67b26..cbc49612ed 100644 --- a/cypress/e2e/smoke/tx_history.cy.js +++ b/cypress/e2e/smoke/tx_history.cy.js @@ -2,16 +2,14 @@ import * as constants from '../../support/constants' import * as main from '../pages/main.page' import * as createTx from '../pages/create_tx.pages' -const INCOMING = 'Received' const OUTGOING = 'Sent' -const CONTRACT_INTERACTION = 'Contract interaction' const str1 = 'Received' const str2 = 'Executed' const str3 = 'Transaction hash' describe('Transaction history tests', () => { - before(() => { + beforeEach(() => { cy.clearLocalStorage() // Go to the test Safe transaction history cy.visit(constants.transactionsHistoryUrl + constants.SEPOLIA_TEST_SAFE_5) @@ -22,110 +20,31 @@ describe('Transaction history tests', () => { main.acceptCookies(1) }) - //Skipping this due to test data creation - it.skip('Verify October 9th transactions are displayed [C56128]', () => { - const DATE = 'Oct 9, 2023' - const NEXT_DATE_LABEL = 'Oct 11, 2023' - const amount = '0.1 ETH' - const amount2 = '15 TT_A' - const amount3 = '21 TT_B' - const amount4 = '82 DAI' - const amount5 = '73 USDC' - const amount6 = '27 AAVE' - const amount7 = '35.94 LINK' - const amount8 = '< 0.00001 ETH' - const time = '2:56 AM' - const time2 = '12:59 AM' - const time3 = '1:00 AM' - const time4 = '1:01 AM' + it('Verify October 9th transactions are displayed [C56128]', () => { + const DATE = 'Oct 29, 2023' + const NEXT_DATE_LABEL = 'Oct 20, 2023' + const amount = '0.00001 ETH' + const time = '10:39 PM' const success = 'Success' createTx.verifyDateExists(DATE) createTx.verifyDateExists(NEXT_DATE_LABEL) - main.scrollToBottomAndWaitForPageLoad() - // Transaction summaries from October 9th const rows = cy.contains('div', DATE).nextUntil(`div:contains(${NEXT_DATE_LABEL})`) - rows.should('have.length', 3) + rows.should('have.length', 10) - rows - .last() - .prev() - .within(() => { - // Type - createTx.verifyImageAltTxt(0, INCOMING) - createTx.verifyStatus(constants.transactionStatus.received) + rows.eq(0).within(() => { + // Type + createTx.verifyImageAltTxt(0, OUTGOING) + createTx.verifyStatus(constants.transactionStatus.sent) - // Info - createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.sep) - createTx.verifyTransactionStrExists(amount) - createTx.verifyTransactionStrExists(time) - createTx.verifyTransactionStrExists(success) - }) - .prev() - .within(() => { - createTx.verifyImageAltTxt(0, INCOMING) - createTx.verifyStatus(constants.transactionStatus.received) - createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.tta) - createTx.verifyTransactionStrExists(amount2) - createTx.verifyTransactionStrExists(time2) - createTx.verifyTransactionStrExists(success) - }) - .prev() - .within(() => { - createTx.verifyImageAltTxt(0, INCOMING) - createTx.verifyStatus(constants.transactionStatus.received) - createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.ttb) - createTx.verifyTransactionStrExists(amount3) - createTx.verifyTransactionStrExists(time2) - createTx.verifyTransactionStrExists(success) - }) - .prev() - .within(() => { - createTx.verifyImageAltTxt(0, INCOMING) - createTx.verifyStatus(constants.transactionStatus.received) - createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.dai) - createTx.verifyTransactionStrExists(amount4) - createTx.verifyTransactionStrExists(time2) - createTx.verifyTransactionStrExists(success) - }) - .prev() - .within(() => { - createTx.verifyImageAltTxt(0, INCOMING) - createTx.verifyStatus(constants.transactionStatus.received) - createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.usds) - createTx.verifyTransactionStrExists(amount5) - createTx.verifyTransactionStrExists(time3) - createTx.verifyTransactionStrExists(success) - }) - .prev() - .within(() => { - createTx.verifyImageAltTxt(0, INCOMING) - createTx.verifyStatus(constants.transactionStatus.received) - createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.aave) - createTx.verifyTransactionStrExists(amount6) - createTx.verifyTransactionStrExists(time3) - createTx.verifyTransactionStrExists(success) - }) - .prev() - .within(() => { - createTx.verifyImageAltTxt(0, INCOMING) - createTx.verifyStatus(constants.transactionStatus.received) - createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.link) - createTx.verifyTransactionStrExists(amount7) - createTx.verifyTransactionStrExists(time3) - createTx.verifyTransactionStrExists(success) - }) - .prev() - .within(() => { - createTx.verifyImageAltTxt(0, INCOMING) - createTx.verifyStatus(constants.transactionStatus.received) - createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.sep) - createTx.verifyTransactionStrExists(amount8) - createTx.verifyTransactionStrExists(time4) - createTx.verifyTransactionStrExists(success) - }) + // Info + createTx.verifyImageAltTxt(1, constants.tokenAbbreviation.sep) + createTx.verifyTransactionStrExists(amount) + createTx.verifyTransactionStrExists(time) + createTx.verifyTransactionStrExists(success) + }) }) it('Verify transaction can be expanded/collapsed [C56129]', () => { From 391bc56a477881137d549e25a69e5dc31c813aa8 Mon Sep 17 00:00:00 2001 From: katspaugh <381895+katspaugh@users.noreply.github.com> Date: Wed, 1 Nov 2023 14:11:41 +0100 Subject: [PATCH 2/9] Fix: render mobile pairing correctly (#2718) --- src/pages/_app.tsx | 3 + src/services/pairing/QRModal.tsx | 106 ++++++++----------------- src/services/pairing/module.ts | 5 +- src/services/pairing/styles.module.css | 3 - 4 files changed, 38 insertions(+), 79 deletions(-) delete mode 100644 src/services/pairing/styles.module.css diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 6e8cea4cbd..ae4df5aeba 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -41,6 +41,7 @@ import { WalletConnectProvider } from '@/services/walletconnect/WalletConnectCon import useABTesting from '@/services/tracking/useAbTesting' import { AbTest } from '@/services/tracking/abTesting' import { useNotificationTracking } from '@/components/settings/PushNotifications/hooks/useNotificationTracking' +import MobilePairingModal from '@/services/pairing/QRModal' const GATEWAY_URL = IS_PRODUCTION || cgwDebugStorage.get() ? GATEWAY_URL_PRODUCTION : GATEWAY_URL_STAGING @@ -121,6 +122,8 @@ const WebCoreApp = ({ + + diff --git a/src/services/pairing/QRModal.tsx b/src/services/pairing/QRModal.tsx index b363838046..47b2e18b14 100644 --- a/src/services/pairing/QRModal.tsx +++ b/src/services/pairing/QRModal.tsx @@ -1,95 +1,55 @@ -import { useState } from 'react' import { Dialog, DialogContent, DialogTitle, IconButton } from '@mui/material' -import { createRoot } from 'react-dom/client' import CloseIcon from '@mui/icons-material/Close' import PairingQRCode from '@/components/common/PairingDetails/PairingQRCode' import PairingDescription from '@/components/common/PairingDetails/PairingDescription' -import { StoreHydrator } from '@/store' -import { AppProviders } from '@/pages/_app' import { PAIRING_MODULE_LABEL } from '@/services/pairing/module' -import css from './styles.module.css' import PairingDeprecationWarning from '@/components/common/PairingDetails/PairingDeprecationWarning' +import ExternalStore from '@/services/ExternalStore' -const WRAPPER_ID = 'safe-mobile-qr-modal' -const QR_CODE_SIZE = 200 +const { useStore: useCloseCallback, setStore: setCloseCallback } = new ExternalStore<() => void>() -const renderWrapper = () => { - if (typeof document === 'undefined') { - return - } - - const wrapper = document.createElement('div') - wrapper.setAttribute('id', WRAPPER_ID) - - document.body.appendChild(wrapper) - - return wrapper -} - -const open = (uri: string, cb: () => void) => { - const wrapper = renderWrapper() - - if (!wrapper) { - return - } - - const root = createRoot(wrapper) - - root.render() +export const open = (cb: () => void) => { + setCloseCallback(() => cb) } -const close = () => { - if (typeof document === 'undefined') { - return - } - - const wrapper = document.getElementById(WRAPPER_ID) - if (wrapper) { - document.body.removeChild(wrapper) - document.body.style.overflow = '' - } +export const close = () => { + setCloseCallback(undefined) } -const Modal = ({ uri, cb }: { uri: string; cb: () => void }) => { - const [open, setOpen] = useState(true) +const QRModal = () => { + const closeCallback = useCloseCallback() + const open = !!closeCallback const handleClose = () => { - cb() - setOpen(false) + closeCallback?.() + setCloseCallback(undefined) close() } + if (!open) return null + return ( - - - - - {PAIRING_MODULE_LABEL} - - - - - - - -
- -
-
-
-
+ + + {PAIRING_MODULE_LABEL} + + + + + + + +
+ +
+
) } -const QRModal = { - open, - close, -} - export default QRModal diff --git a/src/services/pairing/module.ts b/src/services/pairing/module.ts index fe5eba715c..add033b65c 100644 --- a/src/services/pairing/module.ts +++ b/src/services/pairing/module.ts @@ -5,6 +5,7 @@ import type { ITxData } from '@walletconnect/types' import { getPairingConnector, PAIRING_MODULE_STORAGE_ID } from '@/services/pairing/connector' import local from '@/services/local-storage/local' import { killPairingSession } from '@/services/pairing/utils' +import * as QRModal from '@/services/pairing/QRModal' enum ProviderEvents { ACCOUNTS_CHANGED = 'accountsChanged', @@ -44,8 +45,6 @@ const pairingModule = (): WalletInit => { const { default: WalletConnect } = await import('@walletconnect/client') - const { default: QRModal } = await import('@/services/pairing/QRModal') - const { Subject, fromEvent } = await import('rxjs') const { takeUntil, take } = await import('rxjs/operators') @@ -131,7 +130,7 @@ const pairingModule = (): WalletInit => { return new Promise((resolve, reject) => { if (!this.connector.connected) { this.connector.createSession().then(() => { - QRModal.open(this.connector.uri, () => + QRModal.open(() => reject( new ProviderRpcError({ code: 4001, diff --git a/src/services/pairing/styles.module.css b/src/services/pairing/styles.module.css deleted file mode 100644 index d1e8523d06..0000000000 --- a/src/services/pairing/styles.module.css +++ /dev/null @@ -1,3 +0,0 @@ -.modal { - z-index: var(--onboard-modal-z-index) !important; -} From 236c541d968016dbe44543b71310e2687f526f1e Mon Sep 17 00:00:00 2001 From: katspaugh <381895+katspaugh@users.noreply.github.com> Date: Wed, 1 Nov 2023 15:57:36 +0100 Subject: [PATCH 3/9] Fix: soften fallback handler warning (#2716) * Fix: custom fallback handler warning * Adjust style * Fix unit tests --- .../FallbackHandler/__tests__/index.test.tsx | 54 ++----------------- .../settings/FallbackHandler/index.tsx | 41 +++++--------- src/components/settings/SafeModules/index.tsx | 5 +- .../settings/SafeModules/styles.module.css | 10 ---- .../TransactionGuards/styles.module.css | 2 +- 5 files changed, 19 insertions(+), 93 deletions(-) delete mode 100644 src/components/settings/SafeModules/styles.module.css diff --git a/src/components/settings/FallbackHandler/__tests__/index.test.tsx b/src/components/settings/FallbackHandler/__tests__/index.test.tsx index 4546a74e75..3c7697a661 100644 --- a/src/components/settings/FallbackHandler/__tests__/index.test.tsx +++ b/src/components/settings/FallbackHandler/__tests__/index.test.tsx @@ -1,4 +1,4 @@ -import { act, fireEvent, render, waitFor } from '@/tests/test-utils' +import { render, waitFor } from '@/tests/test-utils' import * as useSafeInfoHook from '@/hooks/useSafeInfo' import * as useTxBuilderHook from '@/hooks/safe-apps/useTxBuilderApp' @@ -104,7 +104,7 @@ describe('FallbackHandler', () => { }) describe('No Fallback Handler', () => { - it('should render the Fallback Handler and warning tooltip when no Fallback Handler is set', async () => { + it('should render a warning when no Fallback Handler is set', async () => { jest.spyOn(useSafeInfoHook, 'default').mockImplementation( () => ({ @@ -117,21 +117,6 @@ describe('FallbackHandler', () => { const fbHandler = render() - await waitFor(() => { - expect(fbHandler.getByText('No fallback handler set')).toBeDefined() - }) - - const icon = fbHandler.getByTestId('fallback-handler-warning') - - await act(() => { - fireEvent( - icon, - new MouseEvent('mouseover', { - bubbles: true, - }), - ) - }) - await waitFor(() => { expect( fbHandler.queryByText( @@ -157,17 +142,6 @@ describe('FallbackHandler', () => { const fbHandler = render() - const icon = fbHandler.getByTestId('fallback-handler-warning') - - await act(() => { - fireEvent( - icon, - new MouseEvent('mouseover', { - bubbles: true, - }), - ) - }) - await waitFor(() => { expect( fbHandler.queryByText( @@ -180,7 +154,7 @@ describe('FallbackHandler', () => { }) describe('Unofficial Fallback Handler', () => { - it('should render placeholder and warning tooltip when an unofficial Fallback Handler is set', async () => { + it('should render placeholder and warning when an unofficial Fallback Handler is set', async () => { jest.spyOn(useSafeInfoHook, 'default').mockImplementation( () => ({ @@ -206,17 +180,6 @@ describe('FallbackHandler', () => { expect(fbHandler.getByText('0x123')).toBeDefined() }) - const icon = fbHandler.getByTestId('fallback-handler-warning') - - await act(() => { - fireEvent( - icon, - new MouseEvent('mouseover', { - bubbles: true, - }), - ) - }) - await waitFor(() => { expect(fbHandler.queryByText(new RegExp('An unofficial fallback handler is currently set.'))) expect(fbHandler.queryByText('Transaction Builder')).toBeInTheDocument() @@ -241,17 +204,6 @@ describe('FallbackHandler', () => { const fbHandler = render() - const icon = fbHandler.getByTestId('fallback-handler-warning') - - await act(() => { - fireEvent( - icon, - new MouseEvent('mouseover', { - bubbles: true, - }), - ) - }) - await waitFor(() => { expect(fbHandler.queryByText(new RegExp('An unofficial fallback handler is currently set.'))) expect(fbHandler.queryByText('Transaction Builder')).not.toBeInTheDocument() diff --git a/src/components/settings/FallbackHandler/index.tsx b/src/components/settings/FallbackHandler/index.tsx index 59b5a4e557..28bd7e09ea 100644 --- a/src/components/settings/FallbackHandler/index.tsx +++ b/src/components/settings/FallbackHandler/index.tsx @@ -1,19 +1,16 @@ import NextLink from 'next/link' -import { Typography, Box, SvgIcon, Tooltip, Grid, Paper, Link } from '@mui/material' +import { Typography, Box, Grid, Paper, Link, Alert } from '@mui/material' import semverSatisfies from 'semver/functions/satisfies' import { useMemo } from 'react' import type { ReactElement } from 'react' import EthHashInfo from '@/components/common/EthHashInfo' -import AlertIcon from '@/public/images/common/alert.svg' import useSafeInfo from '@/hooks/useSafeInfo' import { getFallbackHandlerContractDeployment } from '@/services/contracts/deployments' import { HelpCenterArticle } from '@/config/constants' import ExternalLink from '@/components/common/ExternalLink' import { useTxBuilderApp } from '@/hooks/safe-apps/useTxBuilderApp' -import css from '../SafeModules/styles.module.css' - const FALLBACK_HANDLER_VERSION = '>=1.1.1' export const FallbackHandler = (): ReactElement | null => { @@ -30,10 +27,11 @@ export const FallbackHandler = (): ReactElement | null => { return null } + const hasFallbackHandler = !!safe.fallbackHandler const isOfficial = - !!safe.fallbackHandler && safe.fallbackHandler.value === fallbackHandlerDeployment?.networkAddresses[safe.chainId] + hasFallbackHandler && safe.fallbackHandler?.value === fallbackHandlerDeployment?.networkAddresses[safe.chainId] - const tooltip = !safe.fallbackHandler ? ( + const warning = !hasFallbackHandler ? ( <> The {'Safe{Wallet}'} may not work correctly as no fallback handler is currently set. {txBuilder && ( @@ -49,7 +47,7 @@ export const FallbackHandler = (): ReactElement | null => { ) : !isOfficial ? ( <> - An unofficial fallback handler is currently set. + An unofficial fallback handler is currently set. {txBuilder && ( <> {' '} @@ -69,20 +67,6 @@ export const FallbackHandler = (): ReactElement | null => { Fallback handler - {tooltip && ( - - - - - - )} @@ -93,8 +77,11 @@ export const FallbackHandler = (): ReactElement | null => { contract. Learn more about the fallback handler{' '} here - {safe.fallbackHandler ? ( - + + + {warning && {warning}} + + {safe.fallbackHandler && ( { showCopyButton hasExplorer /> - - ) : ( - palette.primary.light}> - No fallback handler set - - )} + )} + diff --git a/src/components/settings/SafeModules/index.tsx b/src/components/settings/SafeModules/index.tsx index aeb9b99025..3a9d4333b6 100644 --- a/src/components/settings/SafeModules/index.tsx +++ b/src/components/settings/SafeModules/index.tsx @@ -2,13 +2,13 @@ import EthHashInfo from '@/components/common/EthHashInfo' import useSafeInfo from '@/hooks/useSafeInfo' import { Paper, Grid, Typography, Box, IconButton, SvgIcon } from '@mui/material' -import css from './styles.module.css' import ExternalLink from '@/components/common/ExternalLink' import RemoveModuleFlow from '@/components/tx-flow/flows/RemoveModule' import DeleteIcon from '@/public/images/common/delete.svg' import CheckWallet from '@/components/common/CheckWallet' import { useContext } from 'react' import { TxModalContext } from '@/components/tx-flow' +import css from '../TransactionGuards/styles.module.css' const NoModules = () => { return ( @@ -22,7 +22,7 @@ const ModuleDisplay = ({ moduleAddress, chainId, name }: { moduleAddress: string const { setTxFlow } = useContext(TxModalContext) return ( - + diff --git a/src/components/settings/SafeModules/styles.module.css b/src/components/settings/SafeModules/styles.module.css deleted file mode 100644 index 20512922f6..0000000000 --- a/src/components/settings/SafeModules/styles.module.css +++ /dev/null @@ -1,10 +0,0 @@ -.container { - background-color: var(--color-secondary-background); - border: 1px solid var(--color-secondary-main); - padding: var(--space-1); - border-radius: 4px; - margin-top: var(--space-2); - display: flex; - align-items: center; - justify-content: space-between; -} diff --git a/src/components/settings/TransactionGuards/styles.module.css b/src/components/settings/TransactionGuards/styles.module.css index 2c8995abb6..fd3c093e54 100644 --- a/src/components/settings/TransactionGuards/styles.module.css +++ b/src/components/settings/TransactionGuards/styles.module.css @@ -1,6 +1,6 @@ .guardDisplay { background-color: var(--color-secondary-background); - border: 1px solid var(--color-secondary-main); + border: 1px solid var(--color-success-dark); padding: 8px; border-radius: 4px; margin-top: 16px; From 5d7e2dc6c2b35bb2ad7f78201935963a0b332e1d Mon Sep 17 00:00:00 2001 From: katspaugh <381895+katspaugh@users.noreply.github.com> Date: Wed, 1 Nov 2023 15:58:06 +0100 Subject: [PATCH 4/9] Fix: adjust WalletConnect events (#2717) * Fix: adjust WalletConnect events * Cut off error details * Don't swallow chain switch errors * Fix nested p warning * Fix tests * Split errors * Style wc error * Connect/disconnect timer to 1s * Fix: safe logo for WC * Show unsupported chain error * Fix: WC url for the origin field * Redirect WC Safe App to open popup * Fix error overflow * Fix tests * Fix: pass app id to offchain message flow * A better wrong chain message --- src/components/safe-apps/AppFrame/index.tsx | 1 - .../tx-flow/flows/SignMessage/SignMessage.tsx | 2 +- .../ReviewSignMessageOnChain.test.tsx | 1 - .../ReviewSignMessageOnChain.tsx | 1 - .../walletconnect/WcConnectionForm/index.tsx | 10 +++-- .../walletconnect/WcErrorMessage/index.tsx | 14 +++++-- .../WcErrorMessage/styles.module.css | 14 ++++--- .../walletconnect/WcHints/index.tsx | 6 +-- .../walletconnect/WcLogoHeader/index.tsx | 8 ++-- .../WcLogoHeader/styles.module.css | 6 +++ .../WcSessionList/WcNoSessions.tsx | 10 ++--- .../walletconnect/WcSessionList/index.tsx | 7 +++- .../walletconnect/WcSessionMananger/index.tsx | 13 +++--- src/pages/apps/open.tsx | 14 ++++++- .../analytics/events/walletconnect.ts | 9 +++++ src/services/exceptions/ErrorCodes.ts | 2 - src/services/onboard.ts | 2 +- .../safe-wallet-provider/index.test.ts | 1 + src/services/safe-wallet-provider/index.ts | 1 + .../useSafeWalletProvider.test.tsx | 10 ++--- .../useSafeWalletProvider.tsx | 40 +++++-------------- .../walletconnect/WalletConnectContext.tsx | 33 ++++++++++++++- .../walletconnect/WalletConnectWallet.ts | 19 +-------- .../__tests__/WalletConnectContext.test.tsx | 31 +++++++++++--- .../walletconnect/__tests__/utils.test.ts | 19 +++++++++ src/services/walletconnect/utils.ts | 4 ++ 26 files changed, 174 insertions(+), 104 deletions(-) create mode 100644 src/services/walletconnect/__tests__/utils.test.ts diff --git a/src/components/safe-apps/AppFrame/index.tsx b/src/components/safe-apps/AppFrame/index.tsx index fb738f289d..4314f7eab2 100644 --- a/src/components/safe-apps/AppFrame/index.tsx +++ b/src/components/safe-apps/AppFrame/index.tsx @@ -142,7 +142,6 @@ const AppFrame = ({ appUrl, allowedFeaturesList, safeAppFromManifest }: AppFrame {label}: - + diff --git a/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.test.tsx b/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.test.tsx index 69f1a35528..622b4f457e 100644 --- a/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.test.tsx +++ b/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.test.tsx @@ -39,7 +39,6 @@ describe('ReviewSignMessageOnChain', () => { type: SafeAppAccessPolicyTypes.NoRestrictions, }, }} - appId={73} requestId="73" message={{ types: { diff --git a/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.tsx b/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.tsx index 17f68fc3f9..ab535b7ede 100644 --- a/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.tsx +++ b/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.tsx @@ -27,7 +27,6 @@ import { SafeTxContext } from '@/components/tx-flow/SafeTxProvider' import { asError } from '@/services/exceptions/utils' export type SignMessageOnChainProps = { - appId?: number app?: SafeAppData requestId: RequestId message: string | EIP712TypedData diff --git a/src/components/walletconnect/WcConnectionForm/index.tsx b/src/components/walletconnect/WcConnectionForm/index.tsx index d76d24845b..3efda49329 100644 --- a/src/components/walletconnect/WcConnectionForm/index.tsx +++ b/src/components/walletconnect/WcConnectionForm/index.tsx @@ -10,6 +10,8 @@ import WcInput from '../WcInput' import WcLogoHeader from '../WcLogoHeader' import css from './styles.module.css' import useSafeInfo from '@/hooks/useSafeInfo' +import Track from '@/components/common/Track' +import { WALLETCONNECT_EVENTS } from '@/services/analytics/events/walletconnect' const WC_HINTS_KEY = 'wcHints' @@ -44,9 +46,11 @@ export const WcConnectionForm = ({ className={css.infoIcon} > - - - + + + + + diff --git a/src/components/walletconnect/WcErrorMessage/index.tsx b/src/components/walletconnect/WcErrorMessage/index.tsx index dde8e6a657..ccb346a6cb 100644 --- a/src/components/walletconnect/WcErrorMessage/index.tsx +++ b/src/components/walletconnect/WcErrorMessage/index.tsx @@ -1,15 +1,21 @@ +import { splitError } from '@/services/walletconnect/utils' import { Button, Typography } from '@mui/material' import WcLogoHeader from '../WcLogoHeader' import css from './styles.module.css' const WcErrorMessage = ({ error, onClose }: { error: Error; onClose: () => void }) => { + const message = error.message || 'An error occurred' + const [summary, details] = splitError(message) + return (
- + - - {error.message || 'An error occurred'} - + {details && ( + + {details} + + )}