diff --git a/.yarnrc.yml b/.yarnrc.yml index 252333917781..1522080c0561 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -43,6 +43,16 @@ npmAuditIgnoreAdvisories: # not appear to be used. - 1092461 + # Issue: path-to-regexp outputs backtracking regular expressions + # URL: https://github.com/advisories/GHSA-9wv6-86v2-598j + # path-to-regexp is used in react-router v5.1.2, which we use. However, the + # vulnerability in path-to-regexp could only be exploited within react-router + # if malicious properties were passed to react-router components or methods + # explicitly from our code. As such, this vulneratibility cannot be exploited + # by an external / malicious actor. Meanwhile, once we update to v6+, + # path-to-regexp will no longer be used. + - 1099499 + # Temp fix for https://github.com/MetaMask/metamask-extension/pull/16920 for the sake of 11.7.1 hotfix # This will be removed in this ticket https://github.com/MetaMask/metamask-extension/issues/22299 - 'ts-custom-error (deprecation)' diff --git a/test/integration/confirmations/transactions/alerts.test.tsx b/test/integration/confirmations/transactions/alerts.test.tsx index e2897976128b..1e07ddcdd68d 100644 --- a/test/integration/confirmations/transactions/alerts.test.tsx +++ b/test/integration/confirmations/transactions/alerts.test.tsx @@ -347,4 +347,52 @@ describe('Contract Interaction Confirmation', () => { 'This transaction won’t go through until a previous transaction is complete. Learn how to cancel or speed up a transaction.', ); }); + + it('displays the alert for gas fees too', async () => { + const account = + mockMetaMaskState.internalAccounts.accounts[ + mockMetaMaskState.internalAccounts + .selectedAccount as keyof typeof mockMetaMaskState.internalAccounts.accounts + ]; + + const mockedMetaMaskState = + getMetaMaskStateWithUnapprovedApproveTransaction(account.address); + + const transaction = mockedMetaMaskState.transactions[0]; + transaction.defaultGasEstimates.estimateType = 'low'; + transaction.userFeeLevel = 'low'; + + await act(async () => { + await integrationTestRender({ + preloadedState: { + ...mockedMetaMaskState, + transactions: [transaction], + }, + backgroundConnection: backgroundConnectionMocked, + }); + }); + + act(() => { + fireEvent.click(screen.getByTestId('inline-alert')); + }); + + expect(await screen.findByTestId('alert-modal')).toBeInTheDocument(); + + expect( + await screen.findByTestId('alert-modal__selected-alert'), + ).toBeInTheDocument(); + + expect( + await screen.findByTestId('alert-modal__selected-alert'), + ).toHaveTextContent( + 'When choosing a low fee, expect slower transactions and longer wait times. For faster transactions, choose Market or Aggressive fee options.', + ); + + expect( + await screen.findByTestId('alert-modal-action-showGasFeeModal'), + ).toBeInTheDocument(); + expect( + await screen.findByTestId('alert-modal-action-showGasFeeModal'), + ).toHaveTextContent('Update gas options'); + }); }); diff --git a/ui/components/app/connected-sites-list/connected-snaps.js b/ui/components/app/connected-sites-list/connected-snaps.js index 9d723cf1a43e..83de2cc2fc96 100644 --- a/ui/components/app/connected-sites-list/connected-snaps.js +++ b/ui/components/app/connected-sites-list/connected-snaps.js @@ -5,7 +5,6 @@ import { useDispatch, useSelector } from 'react-redux'; import { Box, IconName, IconSize, Text } from '../../component-library'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { MenuItem } from '../../ui/menu'; -import SnapAvatar from '../snaps/snap-avatar'; import { AlignItems, BlockSize, @@ -18,6 +17,7 @@ import ConnectedAccountsListOptions from '../connected-accounts-list/connected-a import { getOriginOfCurrentTab } from '../../../selectors'; import { disconnectOriginFromSnap } from '../../../store/actions'; import { getSnapRoute } from '../../../helpers/utils/util'; +import { SnapIcon } from '../snaps/snap-icon'; export default function ConnectedSnaps({ connectedSubjects }) { const [showOptions, setShowOptions] = useState(); @@ -74,11 +74,7 @@ export default function ConnectedSnaps({ connectedSubjects }) { display={Display.Flex} alignItems={AlignItems.center} > - + { const t = useI18nContext(); const [isModalOpen, setIsModalOpen] = useState(false); - // We're using optional chaining with snapId, because with the current implementation - // of snap update in the snap controller, we do not have reference to snapId when an - // update request is rejected because the reference comes from the request itself and not subject metadata - // like it is done with snap install - const packageName = snapId && stripSnapPrefix(snapId); const { name: snapName } = useSelector((state) => getSnapMetadata(state, snapId), @@ -57,13 +50,15 @@ const SnapAuthorshipHeader = ({ return ( {snapId && ( @@ -87,7 +82,8 @@ const SnapAuthorshipHeader = ({ marginLeft={4} marginRight={4} display={Display.Flex} - flexDirection={FlexDirection.Column} + justifyContent={JustifyContent.center} + alignItems={AlignItems.center} style={{ overflow: 'hidden' }} width={BlockSize.Full} > @@ -96,11 +92,7 @@ const SnapAuthorshipHeader = ({ justifyContent={JustifyContent.center} alignItems={AlignItems.center} > - + - - - {packageName} - - {showInfo && ( diff --git a/ui/components/app/snaps/snap-avatar/index.js b/ui/components/app/snaps/snap-avatar/index.js deleted file mode 100644 index 2c17e12d55b7..000000000000 --- a/ui/components/app/snaps/snap-avatar/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './snap-avatar'; diff --git a/ui/components/app/snaps/snap-avatar/snap-avatar.js b/ui/components/app/snaps/snap-avatar/snap-avatar.js deleted file mode 100644 index 97b6fa90de5b..000000000000 --- a/ui/components/app/snaps/snap-avatar/snap-avatar.js +++ /dev/null @@ -1,67 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import classnames from 'classnames'; - -import { - IconColor, - BackgroundColor, -} from '../../../../helpers/constants/design-system'; -import { - BadgeWrapper, - BadgeWrapperPosition, - AvatarIcon, - IconName, - IconSize, -} from '../../../component-library'; - -import { SnapIcon } from '../snap-icon'; - -const SnapAvatar = ({ - snapId, - badgeSize = IconSize.Sm, - avatarSize = IconSize.Lg, - borderWidth = 2, - className, - badgeBackgroundColor = BackgroundColor.backgroundAlternative, -}) => { - return ( - - } - position={BadgeWrapperPosition.bottomRight} - > - - - ); -}; - -SnapAvatar.propTypes = { - /** - * The id of the snap - */ - snapId: PropTypes.string, - badgeSize: PropTypes.string, - avatarSize: PropTypes.string, - borderWidth: PropTypes.number, - /** - * The color of the badge background - */ - badgeBackgroundColor: PropTypes.string, - /** - * The className of the SnapAvatar - */ - className: PropTypes.string, -}; - -export default SnapAvatar; diff --git a/ui/components/app/snaps/snap-avatar/snap-avatar.stories.js b/ui/components/app/snaps/snap-avatar/snap-avatar.stories.js deleted file mode 100644 index 4f1e88b99640..000000000000 --- a/ui/components/app/snaps/snap-avatar/snap-avatar.stories.js +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; -import SnapAvatar from '.'; - -export default { - title: 'Components/App/Snaps/SnapAvatar', - - component: SnapAvatar, - argTypes: { - snapId: { - control: 'text', - }, - }, -}; - -export const DefaultStory = (args) => ; - -DefaultStory.storyName = 'Default'; - -DefaultStory.args = { - snapId: 'npm:@metamask/test-snap-bip44', -}; diff --git a/ui/components/app/snaps/snap-connect-cell/snap-connect-cell.js b/ui/components/app/snaps/snap-connect-cell/snap-connect-cell.js index ede8bc796a46..a587e422719c 100644 --- a/ui/components/app/snaps/snap-connect-cell/snap-connect-cell.js +++ b/ui/components/app/snaps/snap-connect-cell/snap-connect-cell.js @@ -17,8 +17,8 @@ import { } from '../../../component-library'; import Tooltip from '../../../ui/tooltip/tooltip'; import { useI18nContext } from '../../../../hooks/useI18nContext'; -import SnapAvatar from '../snap-avatar/snap-avatar'; import { getSnapMetadata } from '../../../../selectors'; +import { SnapIcon } from '../snap-icon'; export default function SnapConnectCell({ origin, snapId }) { const t = useI18nContext(); @@ -33,7 +33,7 @@ export default function SnapConnectCell({ origin, snapId }) { paddingTop={2} paddingBottom={2} > - + {t('connectSnap', [ diff --git a/ui/components/app/snaps/snap-home-page/snap-home-renderer.js b/ui/components/app/snaps/snap-home-page/snap-home-renderer.js index 305dd28ae2ff..d0acd2060f9b 100644 --- a/ui/components/app/snaps/snap-home-page/snap-home-renderer.js +++ b/ui/components/app/snaps/snap-home-page/snap-home-renderer.js @@ -12,6 +12,7 @@ import { import { SnapDelineator } from '../snap-delineator'; import { DelineatorType } from '../../../../helpers/constants/snaps'; import { + BackgroundColor, BlockSize, TextVariant, } from '../../../../helpers/constants/design-system'; @@ -64,7 +65,14 @@ export const SnapHomeRenderer = ({ snapId }) => { }, [unapprovedTemplatedConfirmations, unapprovedConfirmations, history]); return ( - + {error && ( @@ -82,6 +90,7 @@ export const SnapHomeRenderer = ({ snapId }) => { isLoading={loading} useDelineator={false} useFooter + contentBackgroundColor={BackgroundColor.backgroundAlternative} /> )} diff --git a/ui/components/app/snaps/snap-legacy-authorship-header/snap-legacy-authorship-header.js b/ui/components/app/snaps/snap-legacy-authorship-header/snap-legacy-authorship-header.js index 346bcd3dcf2b..3b514e2c19ea 100644 --- a/ui/components/app/snaps/snap-legacy-authorship-header/snap-legacy-authorship-header.js +++ b/ui/components/app/snaps/snap-legacy-authorship-header/snap-legacy-authorship-header.js @@ -18,7 +18,7 @@ import { import { Box, Text } from '../../../component-library'; import { getSnapMetadata } from '../../../../selectors'; -import SnapAvatar from '../snap-avatar'; +import { SnapIcon } from '../snap-icon'; const SnapLegacyAuthorshipHeader = ({ snapId, @@ -45,7 +45,7 @@ const SnapLegacyAuthorshipHeader = ({ marginRight={marginRight} > - + - + { const t = useI18nContext(); @@ -101,7 +101,7 @@ export const SnapMetadataModal = ({ snapId, isOpen, onClose }) => { }} > - + {snapName} diff --git a/ui/components/app/snaps/snap-ui-checkbox/snap-ui-checkbox.tsx b/ui/components/app/snaps/snap-ui-checkbox/snap-ui-checkbox.tsx index a5f769bbef80..0d85f8ef60dc 100644 --- a/ui/components/app/snaps/snap-ui-checkbox/snap-ui-checkbox.tsx +++ b/ui/components/app/snaps/snap-ui-checkbox/snap-ui-checkbox.tsx @@ -1,6 +1,7 @@ import React, { FunctionComponent, useEffect, useState } from 'react'; import { useSnapInterfaceContext } from '../../../../contexts/snaps'; import { + BorderColor, Display, FlexDirection, } from '../../../../helpers/constants/design-system'; @@ -68,6 +69,9 @@ export const SnapUICheckbox: FunctionComponent = ({ onChange={handleChange} isChecked={value} label={label} + inputProps={{ + borderColor: BorderColor.borderMuted, + }} {...props} /> )} diff --git a/ui/components/app/snaps/snap-ui-dropdown/snap-ui-dropdown.tsx b/ui/components/app/snaps/snap-ui-dropdown/snap-ui-dropdown.tsx index 46a5d6e35ef6..c9000c13839b 100644 --- a/ui/components/app/snaps/snap-ui-dropdown/snap-ui-dropdown.tsx +++ b/ui/components/app/snaps/snap-ui-dropdown/snap-ui-dropdown.tsx @@ -55,6 +55,9 @@ export const SnapUIDropdown: FunctionComponent = ({ data-testid="snaps-dropdown" selectedOption={value} onChange={handleChange} + style={{ + border: '1px solid var(--color-border-muted)', + }} {...props} /> {error && ( diff --git a/ui/components/app/snaps/snap-ui-file-input/snap-ui-file-input.tsx b/ui/components/app/snaps/snap-ui-file-input/snap-ui-file-input.tsx index 9508dae3e0d3..1d254ccaa2e3 100644 --- a/ui/components/app/snaps/snap-ui-file-input/snap-ui-file-input.tsx +++ b/ui/components/app/snaps/snap-ui-file-input/snap-ui-file-input.tsx @@ -187,8 +187,8 @@ export const SnapUIFileInput: FunctionComponent = ({ style={{ cursor: 'pointer', backgroundColor: active - ? 'var(--color-background-alternative-hover)' - : undefined, + ? 'var(--color-background-default-hover)' + : 'var(--color-background-default)', }} onClick={handleClick} onDragOver={handleDragOver} diff --git a/ui/components/app/snaps/snap-ui-renderer/components/container.ts b/ui/components/app/snaps/snap-ui-renderer/components/container.ts index 152a01eb652d..07557c6d7a01 100644 --- a/ui/components/app/snaps/snap-ui-renderer/components/container.ts +++ b/ui/components/app/snaps/snap-ui-renderer/components/container.ts @@ -80,6 +80,10 @@ export const container: UIComponentFactory = ({ flexDirection: FlexDirection.Column, height: BlockSize.Full, className: 'snap-ui-renderer__container', + style: { + overflowY: 'auto', + paddingBottom: useFooter ? '74px' : 'initial', + }, }, }; }; diff --git a/ui/components/app/snaps/snap-ui-renderer/components/footer.ts b/ui/components/app/snaps/snap-ui-renderer/components/footer.ts index 3d400c4fa918..4fc3b2108f2b 100644 --- a/ui/components/app/snaps/snap-ui-renderer/components/footer.ts +++ b/ui/components/app/snaps/snap-ui-renderer/components/footer.ts @@ -21,7 +21,10 @@ export const DEFAULT_FOOTER = { className: 'snap-ui-renderer__footer', backgroundColor: BackgroundColor.backgroundDefault, style: { - boxShadow: 'var(--shadow-size-lg) var(--color-shadow-default)', + boxShadow: 'var(--shadow-size-md) var(--color-shadow-default)', + height: '74px', + position: 'fixed', + bottom: 0, }, }, }; diff --git a/ui/components/app/snaps/snap-ui-renderer/index.scss b/ui/components/app/snaps/snap-ui-renderer/index.scss index 9df749ce1019..63109f4f7ba9 100644 --- a/ui/components/app/snaps/snap-ui-renderer/index.scss +++ b/ui/components/app/snaps/snap-ui-renderer/index.scss @@ -22,6 +22,10 @@ height: 1px; } + &__input > .mm-text-field { + border-color: var(--color-border-muted); + } + &__panel { gap: 8px; } diff --git a/ui/components/app/snaps/snap-ui-renderer/snap-ui-renderer.js b/ui/components/app/snaps/snap-ui-renderer/snap-ui-renderer.js index 5bde7fba7aa8..332fab99308d 100644 --- a/ui/components/app/snaps/snap-ui-renderer/snap-ui-renderer.js +++ b/ui/components/app/snaps/snap-ui-renderer/snap-ui-renderer.js @@ -39,6 +39,7 @@ const SnapUIRendererComponent = ({ useDelineator = true, useFooter = false, onCancel, + contentBackgroundColor, }) => { const t = useI18nContext(); @@ -126,7 +127,11 @@ const SnapUIRendererComponent = ({ initialState={initialState} context={context} > - + @@ -155,4 +160,5 @@ SnapUIRendererComponent.propTypes = { useDelineator: PropTypes.bool, useFooter: PropTypes.bool, onCancel: PropTypes.func, + contentBackgroundColor: PropTypes.string, }; diff --git a/ui/components/multichain/notification-list-item-snap/notification-list-item-snap.tsx b/ui/components/multichain/notification-list-item-snap/notification-list-item-snap.tsx index fbe021861b91..ea290e8478d4 100644 --- a/ui/components/multichain/notification-list-item-snap/notification-list-item-snap.tsx +++ b/ui/components/multichain/notification-list-item-snap/notification-list-item-snap.tsx @@ -18,7 +18,7 @@ import type { NotificationListItemTextProps } from '../notification-list-item-te import { NotificationListItemText } from '../notification-list-item-text'; import { formatMenuItemDate } from '../../../helpers/utils/notification.util'; import { SnapUIMarkdown } from '../../app/snaps/snap-ui-markdown'; -import SnapAvatar from '../../app/snaps/snap-avatar'; +import { SnapIcon } from '../../app/snaps/snap-icon'; export type NotificationListItemSnapProps = { id: string; @@ -107,11 +107,7 @@ export const NotificationListItemSnap = ({ )} - + { @@ -54,12 +54,10 @@ export const ConnectionListItem = ({ connection, onClick }) => { style={{ alignSelf: 'center' }} > {isSnap ? ( - ) : (

1) { - contentMargin += 32; + contentMargin += NAVIGATION_CONTROLS_HEIGHT; } if (isSnapCustomUIDialog) { - contentMargin += 80; + contentMargin += SNAP_DIALOG_HEADER_HEIGHT; } return ( @@ -552,6 +559,7 @@ export default function ConfirmationPage({ useDelineator={false} onCancel={handleSnapDialogCancel} useFooter={isSnapDefaultDialog} + contentBackgroundColor={BackgroundColor.backgroundAlternative} /> ) : ( diff --git a/ui/pages/confirmations/confirmation/templates/__snapshots__/create-snap-account.test.js.snap b/ui/pages/confirmations/confirmation/templates/__snapshots__/create-snap-account.test.js.snap index f87429326b6e..d85bbe7bb4ed 100644 --- a/ui/pages/confirmations/confirmation/templates/__snapshots__/create-snap-account.test.js.snap +++ b/ui/pages/confirmations/confirmation/templates/__snapshots__/create-snap-account.test.js.snap @@ -13,8 +13,8 @@ exports[`create-snap-account confirmation should match snapshot 1`] = ` class="mm-box create-snap-account-page mm-box--margin-bottom-0 mm-box--display-flex mm-box--flex-direction-column mm-box--align-items-center mm-box--width-full mm-box--height-full mm-box--border-style-none" >

-
- T -
-
-
- -
-
+ T

-
-

- @metamask/snap-test -

-
-
- T -
-
-
- -
-
+ T

-
-

- @metamask/snap-test -

-
-
- ? -
-
-
- -
-
+ ?

-
-

-

- + {t('connectionRequest')} diff --git a/ui/pages/snap-account-redirect/__snapshots__/create-snap-redirect.test.tsx.snap b/ui/pages/snap-account-redirect/__snapshots__/create-snap-redirect.test.tsx.snap index 440f05d43033..a971dd30faba 100644 --- a/ui/pages/snap-account-redirect/__snapshots__/create-snap-redirect.test.tsx.snap +++ b/ui/pages/snap-account-redirect/__snapshots__/create-snap-redirect.test.tsx.snap @@ -6,37 +6,21 @@ exports[` renders the url and message when provided and i class="mm-box create-snap-account-page mm-box--flex-direction-column mm-box--align-items-center mm-box--width-full mm-box--height-full mm-box--border-style-none" >
-
- m -
-
-
- -
-
+ m

renders the url and message when provided and i @metamask/snap-simple-keyring

-
-

- @metamask/snap-simple-keyring -

-
+ ); diff --git a/ui/pages/snaps/snap-view/snap-view.js b/ui/pages/snaps/snap-view/snap-view.js index a913a1387527..5ef406fe9123 100644 --- a/ui/pages/snaps/snap-view/snap-view.js +++ b/ui/pages/snaps/snap-view/snap-view.js @@ -92,7 +92,12 @@ function SnapView() { }; return ( -
+