From 08e46815143559e66a960f7770697a88d760a3f3 Mon Sep 17 00:00:00 2001
From: Brian Bergeron
$1.00
$1.00
128Lkh3...Mp8p6
128Lkh3...Mp8p6
cosmos1...6hdc0
cosmos1...6hdc0
0xab16a...Bfcdb
0xab16a...Bfcdb
0.0.123...zbhlt
0.0.123...zbhlt
5hmuyxw...egmfy
5hmuyxw...egmfy
0x02dd1...0ab57
0x02dd1...0ab57
0xab16a...Bfcdb
+ No changes
+
- No changes predicted for your wallet
-
- You send
-
- - 4
-
- ETH
-
- 1
-
- 0x2e0D7...5d09B
-
- You send
-
- - 4
-
- ETH
-
### **After**
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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.
---
ui/ducks/app/app.test.js | 19 ++++++
ui/ducks/app/app.ts | 33 +++++++++++
.../advanced-tab.component.test.js.snap | 1 +
.../advanced-tab/advanced-tab.component.js | 34 +++++++----
.../advanced-tab.component.test.js | 59 ++++++++++++++++++-
.../advanced-tab/advanced-tab.container.js | 13 ++--
.../advanced-tab/advanced-tab.stories.js | 3 +-
ui/store/actionConstants.ts | 2 +
8 files changed, 146 insertions(+), 18 deletions(-)
diff --git a/ui/ducks/app/app.test.js b/ui/ducks/app/app.test.js
index 9a7a93ea958b..27b20a5841b3 100644
--- a/ui/ducks/app/app.test.js
+++ b/ui/ducks/app/app.test.js
@@ -339,4 +339,23 @@ describe('App State', () => {
expect(state.showDataDeletionErrorModal).toStrictEqual(false);
});
+
+ it('displays error in settings', () => {
+ const state = reduceApp(metamaskState, {
+ type: actions.SHOW_SETTINGS_PAGE_ERROR,
+ payload: 'settings page error',
+ });
+
+ expect(state.errorInSettings).toStrictEqual('settings page error');
+ });
+
+ it('hides error in settings', () => {
+ const displayErrorInSettings = { errorInSettings: 'settings page error' };
+ const oldState = { ...metamaskState, ...displayErrorInSettings };
+ const state = reduceApp(oldState, {
+ type: actions.HIDE_SETTINGS_PAGE_ERROR,
+ });
+
+ expect(state.errorInSettings).toBeNull();
+ });
});
diff --git a/ui/ducks/app/app.ts b/ui/ducks/app/app.ts
index e6a7855ce7a5..81f875446f1e 100644
--- a/ui/ducks/app/app.ts
+++ b/ui/ducks/app/app.ts
@@ -105,6 +105,7 @@ type AppState = {
snapsInstallPrivacyWarningShown: boolean;
isAddingNewNetwork: boolean;
isMultiRpcOnboarding: boolean;
+ errorInSettings: string | null;
};
export type AppSliceState = {
@@ -192,6 +193,7 @@ const initialState: AppState = {
snapsInstallPrivacyWarningShown: false,
isAddingNewNetwork: false,
isMultiRpcOnboarding: false,
+ errorInSettings: null,
};
export default function reduceApp(
@@ -632,6 +634,16 @@ export default function reduceApp(
...appState,
showDataDeletionErrorModal: false,
};
+ case actionConstants.SHOW_SETTINGS_PAGE_ERROR:
+ return {
+ ...appState,
+ errorInSettings: action.payload,
+ };
+ case actionConstants.HIDE_SETTINGS_PAGE_ERROR:
+ return {
+ ...appState,
+ errorInSettings: null,
+ };
///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps)
case actionConstants.SHOW_KEYRING_SNAP_REMOVAL_RESULT:
return {
@@ -720,6 +732,27 @@ export function setCustomTokenAmount(payload: string): PayloadAction
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension 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)).
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g., pulled and built the branch,
reviewed the updated README).
- [ ] 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.
---
ui/components/component-library/README.md | 2 +-
ui/components/component-library/text/README.mdx | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/ui/components/component-library/README.md b/ui/components/component-library/README.md
index ec5006d3491f..a1f865bfe95a 100644
--- a/ui/components/component-library/README.md
+++ b/ui/components/component-library/README.md
@@ -4,7 +4,7 @@ This folder contains design system components that are built 1:1 with the Figma
## Architecture
-All components are built on top of the `Box` component and accept all `Box` [component props](/docs/components-componentlibrary-box--docs#props).
+All components are built on top of the `Box` component and accept all `Box` component props.
### Layout
diff --git a/ui/components/component-library/text/README.mdx b/ui/components/component-library/text/README.mdx
index 5b275aa48e23..183fcbbca9f8 100644
--- a/ui/components/component-library/text/README.mdx
+++ b/ui/components/component-library/text/README.mdx
@@ -580,7 +580,7 @@ Values using the `TextAlign` object from `./ui/helpers/constants/design-system.j
### Box Props
-Box props are now integrated with the `Text` component. Valid Box props: [Box](/docs/components-componentlibrary-box--docs#props)
+Box props are now integrated with the `Text` component.
You no longer need to pass these props as an object through `boxProps`
From 59044a48787bdc4ffbb105219b8c74f59e60befa Mon Sep 17 00:00:00 2001
From: Victor Thomas <10986371+vthomas13@users.noreply.github.com>
Date: Fri, 1 Nov 2024 14:52:31 -0400
Subject: [PATCH 005/111] chore: Adding installType to Sentry Tags for easy
filtering (#28084)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
InstallType is a recently added flag to help quickly determine whether a
Sentry issue is coming from a natural webstore install, or a developer
environment. We want to be able to filter by this flag in the Sentry UI.
Added the tag, but also simplified some previous logic from when I added
extensionId to make adding extra attributes less tedious in the future.
We can also use this pattern for tags.
[](https://codespaces.new/MetaMask/metamask-extension/pull/28084?quickstart=1)
## **Related issues**
Fixes: #27667
## **Manual testing steps**
1. Open App
2. Use developer options to trigger a sentry error
3. Go into Sentry UI and verify that installType is a tag in addition to
being in the extra properties.
## **Screenshots/Recordings**
### **Before**
### **After**
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension 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
- [ ] 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.
---------
Co-authored-by: Harika <153644847+hjetpoluru@users.noreply.github.com>
---
app/scripts/lib/setupSentry.js | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js
index 1b9e9f4ddbfc..354bb0bbb620 100644
--- a/app/scripts/lib/setupSentry.js
+++ b/app/scripts/lib/setupSentry.js
@@ -424,12 +424,17 @@ export function rewriteReport(report) {
if (!report.extra) {
report.extra = {};
}
-
- report.extra.appState = appState;
- if (browser.runtime && browser.runtime.id) {
- report.extra.extensionId = browser.runtime.id;
+ if (!report.tags) {
+ report.tags = {};
}
- report.extra.installType = installType;
+
+ Object.assign(report.extra, {
+ appState,
+ installType,
+ extensionId: browser.runtime?.id,
+ });
+
+ report.tags.installType = installType;
} catch (err) {
log('Error rewriting report', err);
}
From a94de6a93d583325b46166bcb7a7e2ac84f9f38a Mon Sep 17 00:00:00 2001
From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com>
Date: Fri, 1 Nov 2024 15:13:10 -0400
Subject: [PATCH 006/111] fix: Removing `warning` prop from settings (#27990)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
Even though `warning` property is still used in the setting-tab and
security-tab, we are no longer using `displayWarning` to update the
error from the settings. This makes the error displayed in the tabs
irrelevant to the component. So with this PR we are removing the warning
property from settings-tab and security-tab.
We are removing the warning property from advance-tab in
https://github.com/MetaMask/metamask-extension/pull/26999
[](https://codespaces.new/MetaMask/metamask-extension/pull/27990?quickstart=1)
## **Related issues**
Related to https://github.com/MetaMask/metamask-extension/issues/25838
## **Manual testing steps**
1. Go to this page...
2.
3.
## **Screenshots/Recordings**
### **Before**
### **After**
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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.
Co-authored-by: Harika <153644847+hjetpoluru@users.noreply.github.com>
Co-authored-by: Danica Shen
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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.
---
app/_locales/en/messages.json | 3 +++
.../edit-spending-cap-modal.tsx | 16 +++++++++++++++-
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index cc077810750b..4b3c59b52297 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -1824,6 +1824,9 @@
"editSpendingCapError": {
"message": "The spending cap can’t exceed $1 decimal digits. Remove decimal digits to continue."
},
+ "editSpendingCapSpecialCharError": {
+ "message": "Enter numbers only"
+ },
"enable": {
"message": "Enable"
},
diff --git a/ui/pages/confirmations/components/confirm/info/approve/edit-spending-cap-modal/edit-spending-cap-modal.tsx b/ui/pages/confirmations/components/confirm/info/approve/edit-spending-cap-modal/edit-spending-cap-modal.tsx
index 2762e99652a5..f908333e4f25 100644
--- a/ui/pages/confirmations/components/confirm/info/approve/edit-spending-cap-modal/edit-spending-cap-modal.tsx
+++ b/ui/pages/confirmations/components/confirm/info/approve/edit-spending-cap-modal/edit-spending-cap-modal.tsx
@@ -124,6 +124,8 @@ export const EditSpendingCapModal = ({
decimals &&
parseInt(decimals, 10) < countDecimalDigits(customSpendingCapInputValue);
+ const showSpecialCharacterError = /[-+e]/u.test(customSpendingCapInputValue);
+
return (
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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.
---
ui/components/multichain/network-list-item/index.scss | 4 ++++
.../multichain/network-list-item/network-list-item.tsx | 1 +
2 files changed, 5 insertions(+)
diff --git a/ui/components/multichain/network-list-item/index.scss b/ui/components/multichain/network-list-item/index.scss
index 6597487c9cf6..cfbe80f2ce48 100644
--- a/ui/components/multichain/network-list-item/index.scss
+++ b/ui/components/multichain/network-list-item/index.scss
@@ -37,4 +37,8 @@
&__delete {
visibility: hidden;
}
+
+ &__rpc-endpoint {
+ max-width: 100%;
+ }
}
diff --git a/ui/components/multichain/network-list-item/network-list-item.tsx b/ui/components/multichain/network-list-item/network-list-item.tsx
index f80572eb1e4a..204ad7a5861f 100644
--- a/ui/components/multichain/network-list-item/network-list-item.tsx
+++ b/ui/components/multichain/network-list-item/network-list-item.tsx
@@ -190,6 +190,7 @@ export const NetworkListItem = ({
as="button"
variant={TextVariant.bodySmMedium}
color={TextColor.textAlternative}
+ ellipsis
>
{rpcEndpoint.name ?? new URL(rpcEndpoint.url).host}
From 9d7798515fdafd0593a023aa64dbda4b2d33427a Mon Sep 17 00:00:00 2001
From: Brian Bergeron
### **After**
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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.
---
.../confirm/info/typed-sign/typed-sign.tsx | 20 ++++++-------------
.../__snapshots__/confirm.test.tsx.snap | 12 +++++------
.../hooks/useGetTokenStandardAndDetails.ts | 6 +++++-
3 files changed, 17 insertions(+), 21 deletions(-)
diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx
index fa5e61caef1f..f14107c1fd8a 100644
--- a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx
+++ b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useState } from 'react';
+import React from 'react';
import { useSelector } from 'react-redux';
import { isValidAddress } from 'ethereumjs-util';
@@ -14,11 +14,11 @@ import {
import { ConfirmInfoSection } from '../../../../../../components/app/confirm/info/row/section';
import { useI18nContext } from '../../../../../../hooks/useI18nContext';
import { SignatureRequestType } from '../../../../types/confirm';
+import { useGetTokenStandardAndDetails } from '../../../../hooks/useGetTokenStandardAndDetails';
import {
isOrderSignatureRequest,
isPermitSignatureRequest,
} from '../../../../utils';
-import { fetchErc20Decimals } from '../../../../utils/token';
import { useConfirmContext } from '../../../../context/confirm';
import { selectUseTransactionSimulations } from '../../../../selectors/preferences';
import { ConfirmInfoRowTypedSignData } from '../../row/typed-sign-data/typedSignData';
@@ -31,7 +31,6 @@ const TypedSignInfo: React.FC = () => {
const useTransactionSimulations = useSelector(
selectUseTransactionSimulations,
);
- const [decimals, setDecimals] = useState
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension 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.
---
app/images/gravity.svg | 10 ++++++++++
shared/constants/network.ts | 13 +++++++++++++
2 files changed, 23 insertions(+)
create mode 100644 app/images/gravity.svg
diff --git a/app/images/gravity.svg b/app/images/gravity.svg
new file mode 100644
index 000000000000..a94d44f8d285
--- /dev/null
+++ b/app/images/gravity.svg
@@ -0,0 +1,10 @@
+
diff --git a/shared/constants/network.ts b/shared/constants/network.ts
index 64d330b73b2c..4844e7c2e981 100644
--- a/shared/constants/network.ts
+++ b/shared/constants/network.ts
@@ -153,6 +153,8 @@ export const CHAIN_IDS = {
ARBITRUM_SEPOLIA: '0x66eee',
NEAR: '0x18d',
NEAR_TESTNET: '0x18e',
+ GRAVITY_ALPHA_MAINNET: '0x659',
+ GRAVITY_ALPHA_TESTNET_SEPOLIA: '0x34c1',
} as const;
export const CHAINLIST_CHAIN_IDS_MAP = {
@@ -209,6 +211,8 @@ export const CHAINLIST_CHAIN_IDS_MAP = {
FILECOIN: '0x13a',
NUMBERS: '0x290b',
APE: '0x8173',
+ GRAVITY_ALPHA_MAINNET: '0x659',
+ GRAVITY_ALPHA_TESTNET_SEPOLIA: '0x34c1',
} as const;
// To add a deprecation warning to a network, add it to the array
@@ -454,6 +458,8 @@ export const NUMBERS_TOKEN_IMAGE_URL = './images/numbers-token.png';
export const SEI_IMAGE_URL = './images/sei.svg';
export const NEAR_IMAGE_URL = './images/near.svg';
export const APE_IMAGE_URL = './images/ape.svg';
+export const GRAVITY_ALPHA_MAINNET_IMAGE_URL = './images/gravity.svg';
+export const GRAVITY_ALPHA_TESTNET_SEPOLIA_IMAGE_URL = './images/gravity.svg';
export const INFURA_PROVIDER_TYPES = [
NETWORK_TYPES.MAINNET,
@@ -792,6 +798,10 @@ export const CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP = {
[CHAINLIST_CHAIN_IDS_MAP.BASE]: BASE_TOKEN_IMAGE_URL,
[CHAINLIST_CHAIN_IDS_MAP.NUMBERS]: NUMBERS_MAINNET_IMAGE_URL,
[CHAINLIST_CHAIN_IDS_MAP.SEI]: SEI_IMAGE_URL,
+ [CHAINLIST_CHAIN_IDS_MAP.GRAVITY_ALPHA_MAINNET]:
+ GRAVITY_ALPHA_MAINNET_IMAGE_URL,
+ [CHAINLIST_CHAIN_IDS_MAP.GRAVITY_ALPHA_TESTNET_SEPOLIA]:
+ GRAVITY_ALPHA_TESTNET_SEPOLIA_IMAGE_URL,
} as const;
export const CHAIN_ID_TO_ETHERS_NETWORK_NAME_MAP = {
@@ -824,6 +834,9 @@ export const CHAIN_ID_TOKEN_IMAGE_MAP = {
[CHAIN_IDS.MOONBEAM]: MOONBEAM_TOKEN_IMAGE_URL,
[CHAINLIST_CHAIN_IDS_MAP.IOTEX_MAINNET]: IOTEX_TOKEN_IMAGE_URL,
[CHAINLIST_CHAIN_IDS_MAP.APE_MAINNET]: APE_TOKEN_IMAGE_URL,
+ [CHAIN_IDS.GRAVITY_ALPHA_MAINNET]: GRAVITY_ALPHA_MAINNET_IMAGE_URL,
+ [CHAIN_IDS.GRAVITY_ALPHA_TESTNET_SEPOLIA]:
+ GRAVITY_ALPHA_TESTNET_SEPOLIA_IMAGE_URL,
} as const;
export const INFURA_BLOCKED_KEY = 'countryBlocked';
From 63fb3ac6fc30a20cdc112585839e81d013826768 Mon Sep 17 00:00:00 2001
From: Vinicius Stevam <45455812+vinistevam@users.noreply.github.com>
Date: Wed, 6 Nov 2024 08:12:57 +0000
Subject: [PATCH 029/111] fix: remove scroll-to-bottom requirement in
redesigned transaction confirmations (#27910)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
This PR addresses the removal of the scroll-to-bottom requirement in the
redesigned transaction confirmation screens. It eliminates the need for
users to scroll to the bottom in order to enable the confirm button,
streamlining the confirmation process. The scroll-to-bottom arrow is
also removed, ensuring a smoother user experience without unnecessary
interaction barriers.
[](https://codespaces.new/MetaMask/metamask-extension/pull/27910?quickstart=1)
## **Related issues**
Fixes: https://github.com/MetaMask/MetaMask-planning/issues/3495
## **Manual testing steps**
1. Go to test dapp
2. Have 2+ transaction insights snaps installed
3. Click Create Token
4. See the confirm button disabled until you scroll to bottom
## **Screenshots/Recordings**
[deploy.webm](https://github.com/user-attachments/assets/79716a68-e70f-456a-b962-ccec8732935b)
### **Before**
### **After**
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension 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.
---
.../scroll-to-bottom/scroll-to-bottom.test.tsx | 15 ++++++++++++++-
.../scroll-to-bottom/scroll-to-bottom.tsx | 18 ++++++++++++++++--
2 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/ui/pages/confirmations/components/confirm/scroll-to-bottom/scroll-to-bottom.test.tsx b/ui/pages/confirmations/components/confirm/scroll-to-bottom/scroll-to-bottom.test.tsx
index d5954e56609b..6bf31166b6e5 100644
--- a/ui/pages/confirmations/components/confirm/scroll-to-bottom/scroll-to-bottom.test.tsx
+++ b/ui/pages/confirmations/components/confirm/scroll-to-bottom/scroll-to-bottom.test.tsx
@@ -2,7 +2,10 @@ import React from 'react';
import configureMockStore from 'redux-mock-store';
import { unapprovedTypedSignMsgV4 } from '../../../../../../test/data/confirmations/typed_sign';
-import { getMockPersonalSignConfirmState } from '../../../../../../test/data/confirmations/helper';
+import {
+ getMockContractInteractionConfirmState,
+ getMockPersonalSignConfirmState,
+} from '../../../../../../test/data/confirmations/helper';
import { renderWithConfirmContextProvider } from '../../../../../../test/lib/confirmations/render-helpers';
import * as usePreviousHooks from '../../../../../hooks/usePrevious';
import ScrollToBottom from './scroll-to-bottom';
@@ -116,6 +119,16 @@ describe('ScrollToBottom', () => {
expect(mockSetHasScrolledToBottom).toHaveBeenCalledWith(false);
});
+ it('does not render the scroll button when the confirmation is transaction redesigned', () => {
+ const mockStateTransaction = getMockContractInteractionConfirmState();
+ const { container } = renderWithConfirmContextProvider(
+
### **After**
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension 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.
---------
Co-authored-by: David Murdoch <187813+davidmurdoch@users.noreply.github.com>
---
app/_locales/en/messages.json | 6 ++
app/scripts/background.js | 41 ++++++++
app/scripts/constants/sentry-state.ts | 1 +
.../preferences-controller.test.ts | 17 ++++
.../controllers/preferences-controller.ts | 20 ++++
app/scripts/lib/backup.test.js | 1 +
app/scripts/metamask-controller.js | 4 +
development/build/utils.js | 2 +-
development/create-static-server.js | 13 ++-
development/static-server.js | 2 +-
.../test/plugins.SelfInjectPlugin.test.ts | 4 +-
.../utils/plugins/SelfInjectPlugin/index.ts | 21 +++-
.../utils/plugins/SelfInjectPlugin/types.ts | 15 ++-
package.json | 1 +
shared/modules/add-nonce-to-csp.test.ts | 98 +++++++++++++++++++
shared/modules/add-nonce-to-csp.ts | 38 +++++++
shared/modules/provider-injection.js | 94 +++++++++++-------
shared/modules/provider-injection.test.ts | 6 +-
test/e2e/default-fixture.js | 1 +
test/e2e/fixture-builder.js | 1 +
test/e2e/helpers.js | 5 +-
test/e2e/phishing-warning-page-server.js | 2 +-
.../index.html | 9 ++
.../content-security-policy.spec.ts | 46 +++++++++
...rs-after-init-opt-in-background-state.json | 1 +
.../errors-after-init-opt-in-ui-state.json | 1 +
...s-before-init-opt-in-background-state.json | 1 +
.../errors-before-init-opt-in-ui-state.json | 1 +
.../synchronous-injection.spec.js | 2 +-
ui/helpers/constants/settings.js | 15 +++
ui/helpers/utils/settings-search.js | 6 +-
ui/helpers/utils/settings-search.test.js | 9 +-
.../advanced-tab/advanced-tab.component.js | 45 +++++++++
.../advanced-tab/advanced-tab.container.js | 6 ++
.../advanced-tab/advanced-tab.stories.js | 18 ++++
ui/store/actions.ts | 12 +++
yarn.lock | 10 ++
37 files changed, 515 insertions(+), 60 deletions(-)
create mode 100644 shared/modules/add-nonce-to-csp.test.ts
create mode 100644 shared/modules/add-nonce-to-csp.ts
create mode 100644 test/e2e/tests/content-security-policy/content-security-policy-mock-page/index.html
create mode 100644 test/e2e/tests/content-security-policy/content-security-policy.spec.ts
diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index 62dda6c29ef0..202dc04c2fa8 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -3789,6 +3789,12 @@
"outdatedBrowserNotification": {
"message": "Your browser is out of date. If you don't update your browser, you won't be able to get security patches and new features from MetaMask."
},
+ "overrideContentSecurityPolicyHeader": {
+ "message": "Override Content-Security-Policy header"
+ },
+ "overrideContentSecurityPolicyHeaderDescription": {
+ "message": "This option is a workaround for a known issue in Firefox, where a dapp's Content-Security-Policy header may prevent the extension from loading properly. Disabling this option is not recommended unless required for specific web page compatibility."
+ },
"padlock": {
"message": "Padlock"
},
diff --git a/app/scripts/background.js b/app/scripts/background.js
index bacb6adddf9f..90a52b6c0d19 100644
--- a/app/scripts/background.js
+++ b/app/scripts/background.js
@@ -56,6 +56,8 @@ import {
// TODO: Remove restricted import
// eslint-disable-next-line import/no-restricted-paths
import { getCurrentChainId } from '../../ui/selectors';
+import { addNonceToCsp } from '../../shared/modules/add-nonce-to-csp';
+import { checkURLForProviderInjection } from '../../shared/modules/provider-injection';
import migrations from './migrations';
import Migrator from './lib/migrator';
import ExtensionPlatform from './platforms/extension';
@@ -333,6 +335,40 @@ function maybeDetectPhishing(theController) {
);
}
+/**
+ * Overrides the Content-Security-Policy (CSP) header by adding a nonce to the `script-src` directive.
+ * This is a workaround for [Bug #1446231](https://bugzilla.mozilla.org/show_bug.cgi?id=1446231),
+ * which involves overriding the page CSP for inline script nodes injected by extension content scripts.
+ */
+function overrideContentSecurityPolicyHeader() {
+ // The extension url is unique per install on Firefox, so we can safely add it as a nonce to the CSP header
+ const nonce = btoa(browser.runtime.getURL('/'));
+ browser.webRequest.onHeadersReceived.addListener(
+ ({ responseHeaders, url }) => {
+ // Check whether inpage.js is going to be injected into the page or not.
+ // There is no reason to modify the headers if we are not injecting inpage.js.
+ const isInjected = checkURLForProviderInjection(new URL(url));
+
+ // Check if the user has enabled the overrideContentSecurityPolicyHeader preference
+ const isEnabled =
+ controller.preferencesController.state
+ .overrideContentSecurityPolicyHeader;
+
+ if (isInjected && isEnabled) {
+ for (const header of responseHeaders) {
+ if (header.name.toLowerCase() === 'content-security-policy') {
+ header.value = addNonceToCsp(header.value, nonce);
+ }
+ }
+ }
+
+ return { responseHeaders };
+ },
+ { types: ['main_frame', 'sub_frame'], urls: ['http://*/*', 'https://*/*'] },
+ ['blocking', 'responseHeaders'],
+ );
+}
+
// These are set after initialization
let connectRemote;
let connectExternalExtension;
@@ -479,6 +515,11 @@ async function initialize() {
if (!isManifestV3) {
await loadPhishingWarningPage();
+ // Workaround for Bug #1446231 to override page CSP for inline script nodes injected by extension content scripts
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1446231
+ if (getPlatform() === PLATFORM_FIREFOX) {
+ overrideContentSecurityPolicyHeader();
+ }
}
await sendReadyMessageToTabs();
log.info('MetaMask initialization complete.');
diff --git a/app/scripts/constants/sentry-state.ts b/app/scripts/constants/sentry-state.ts
index 3125016ea0b5..655851590441 100644
--- a/app/scripts/constants/sentry-state.ts
+++ b/app/scripts/constants/sentry-state.ts
@@ -223,6 +223,7 @@ export const SENTRY_BACKGROUND_STATE = {
advancedGasFee: true,
currentLocale: true,
dismissSeedBackUpReminder: true,
+ overrideContentSecurityPolicyHeader: true,
featureFlags: true,
forgottenPassword: true,
identities: false,
diff --git a/app/scripts/controllers/preferences-controller.test.ts b/app/scripts/controllers/preferences-controller.test.ts
index 25010cdd3a0f..39a2d49648b2 100644
--- a/app/scripts/controllers/preferences-controller.test.ts
+++ b/app/scripts/controllers/preferences-controller.test.ts
@@ -837,6 +837,23 @@ describe('preferences controller', () => {
});
});
+ describe('overrideContentSecurityPolicyHeader', () => {
+ it('defaults overrideContentSecurityPolicyHeader to true', () => {
+ const { controller } = setupController({});
+ expect(
+ controller.state.overrideContentSecurityPolicyHeader,
+ ).toStrictEqual(true);
+ });
+
+ it('set overrideContentSecurityPolicyHeader to false', () => {
+ const { controller } = setupController({});
+ controller.setOverrideContentSecurityPolicyHeader(false);
+ expect(
+ controller.state.overrideContentSecurityPolicyHeader,
+ ).toStrictEqual(false);
+ });
+ });
+
describe('snapsAddSnapAccountModalDismissed', () => {
it('defaults snapsAddSnapAccountModalDismissed to false', () => {
const { controller } = setupController({});
diff --git a/app/scripts/controllers/preferences-controller.ts b/app/scripts/controllers/preferences-controller.ts
index b4ce3ca71e64..dce2ef3d0512 100644
--- a/app/scripts/controllers/preferences-controller.ts
+++ b/app/scripts/controllers/preferences-controller.ts
@@ -133,6 +133,7 @@ export type PreferencesControllerState = Omit<
useNonceField: boolean;
usePhishDetect: boolean;
dismissSeedBackUpReminder: boolean;
+ overrideContentSecurityPolicyHeader: boolean;
useMultiAccountBalanceChecker: boolean;
useSafeChainsListValidation: boolean;
use4ByteResolution: boolean;
@@ -175,6 +176,7 @@ export const getDefaultPreferencesControllerState =
useNonceField: false,
usePhishDetect: true,
dismissSeedBackUpReminder: false,
+ overrideContentSecurityPolicyHeader: true,
useMultiAccountBalanceChecker: true,
useSafeChainsListValidation: true,
// set to true means the dynamic list from the API is being used
@@ -306,6 +308,10 @@ const controllerMetadata = {
persist: true,
anonymous: true,
},
+ overrideContentSecurityPolicyHeader: {
+ persist: true,
+ anonymous: true,
+ },
useMultiAccountBalanceChecker: {
persist: true,
anonymous: true,
@@ -1009,6 +1015,20 @@ export class PreferencesController extends BaseController<
});
}
+ /**
+ * A setter for the user preference to override the Content-Security-Policy header
+ *
+ * @param overrideContentSecurityPolicyHeader - User preference for overriding the Content-Security-Policy header.
+ */
+ setOverrideContentSecurityPolicyHeader(
+ overrideContentSecurityPolicyHeader: boolean,
+ ): void {
+ this.update((state) => {
+ state.overrideContentSecurityPolicyHeader =
+ overrideContentSecurityPolicyHeader;
+ });
+ }
+
/**
* A setter for the incomingTransactions in preference to be updated
*
diff --git a/app/scripts/lib/backup.test.js b/app/scripts/lib/backup.test.js
index b3a7f176c2e6..826aa04018d9 100644
--- a/app/scripts/lib/backup.test.js
+++ b/app/scripts/lib/backup.test.js
@@ -150,6 +150,7 @@ const jsonData = JSON.stringify({
useNonceField: false,
usePhishDetect: true,
dismissSeedBackUpReminder: false,
+ overrideContentSecurityPolicyHeader: true,
useTokenDetection: false,
useCollectibleDetection: false,
openSeaEnabled: false,
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index caac30573406..d43c12ff24a1 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -3487,6 +3487,10 @@ export default class MetamaskController extends EventEmitter {
preferencesController.setDismissSeedBackUpReminder.bind(
preferencesController,
),
+ setOverrideContentSecurityPolicyHeader:
+ preferencesController.setOverrideContentSecurityPolicyHeader.bind(
+ preferencesController,
+ ),
setAdvancedGasFee: preferencesController.setAdvancedGasFee.bind(
preferencesController,
),
diff --git a/development/build/utils.js b/development/build/utils.js
index 525815d2520a..626aacd588c7 100644
--- a/development/build/utils.js
+++ b/development/build/utils.js
@@ -293,7 +293,7 @@ function getBuildName({
function makeSelfInjecting(filePath) {
const fileContents = readFileSync(filePath, 'utf8');
const textContent = JSON.stringify(fileContents);
- const js = `{let d=document,s=d.createElement('script');s.textContent=${textContent};d.documentElement.appendChild(s).remove();}`;
+ const js = `{let d=document,s=d.createElement('script');s.textContent=${textContent};s.nonce=btoa((globalThis.browser||chrome).runtime.getURL('/'));d.documentElement.appendChild(s).remove();}`;
writeFileSync(filePath, js, 'utf8');
}
diff --git a/development/create-static-server.js b/development/create-static-server.js
index a8d5e28b0088..8e55fa54ca13 100755
--- a/development/create-static-server.js
+++ b/development/create-static-server.js
@@ -4,10 +4,17 @@ const path = require('path');
const serveHandler = require('serve-handler');
-const createStaticServer = (rootDirectory) => {
+/**
+ * Creates an HTTP server that serves static files from a directory using serve-handler.
+ * If a request URL starts with `/node_modules/`, it rewrites the URL and serves files from the `node_modules` directory.
+ *
+ * @param { NonNullable
getTargetAccountWithSendEtherInfo(state, userAddress),
);
- const networkIdentifier = useSelector(getNetworkIdentifier);
- const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider);
+
+ const { chainId } = txData;
+
+ const networkIdentifier = useSelector((state) =>
+ selectNetworkIdentifierByChainId(state, chainId),
+ );
+
+ const { blockExplorerUrls } =
+ useSelector((state) =>
+ selectNetworkConfigurationByChainId(state, chainId),
+ ) ?? {};
+
+ const blockExplorerUrl = blockExplorerUrls?.[0];
const unapprovedTxCount = useSelector(getUnapprovedTxCount);
const unapprovedTxs = useSelector(getUnapprovedTransactions);
const useCurrencyRateCheck = useSelector(getUseCurrencyRateCheck);
@@ -387,7 +403,7 @@ export default function TokenAllowance({
tokenName={tokenSymbol}
address={tokenAddress}
chainId={fullTxData.chainId}
- rpcPrefs={rpcPrefs}
+ blockExplorerUrl={blockExplorerUrl}
/>
);
@@ -710,7 +726,7 @@ export default function TokenAllowance({
tokenAddress={tokenAddress}
toAddress={toAddress}
chainId={fullTxData.chainId}
- rpcPrefs={rpcPrefs}
+ blockExplorerUrl={blockExplorerUrl}
/>
)}
diff --git a/ui/pages/confirmations/token-allowance/token-allowance.test.js b/ui/pages/confirmations/token-allowance/token-allowance.test.js
index ddfc48a2cfaa..68df89777c7e 100644
--- a/ui/pages/confirmations/token-allowance/token-allowance.test.js
+++ b/ui/pages/confirmations/token-allowance/token-allowance.test.js
@@ -203,7 +203,7 @@ describe('TokenAllowancePage', () => {
status: 'unapproved',
originalGasEstimate: '0xea60',
userEditedGasLimit: false,
- chainId: '0x3',
+ chainId: CHAIN_IDS.MAINNET,
loadingDefaults: false,
dappSuggestedGasFees: {
gasPrice: '0x4a817c800',
diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js
index 94d8f39252d8..c4f2928d8ef2 100644
--- a/ui/selectors/selectors.js
+++ b/ui/selectors/selectors.js
@@ -734,6 +734,51 @@ export const selectDefaultRpcEndpointByChainId = createSelector(
},
);
+/**
+ * @type (state: any, chainId: string) => number | undefined
+ */
+export const selectConversionRateByChainId = createSelector(
+ selectNetworkConfigurationByChainId,
+ (state) => state,
+ (networkConfiguration, state) => {
+ if (!networkConfiguration) {
+ return undefined;
+ }
+
+ const { nativeCurrency } = networkConfiguration;
+ return state.metamask.currencyRates[nativeCurrency]?.conversionRate;
+ },
+);
+
+export const selectNftsByChainId = createSelector(
+ getSelectedInternalAccount,
+ (state) => state.metamask.allNfts,
+ (_state, chainId) => chainId,
+ (selectedAccount, nfts, chainId) => {
+ return nfts?.[selectedAccount.address]?.[chainId] ?? [];
+ },
+);
+
+export const selectNftContractsByChainId = createSelector(
+ getSelectedInternalAccount,
+ (state) => state.metamask.allNftContracts,
+ (_state, chainId) => chainId,
+ (selectedAccount, nftContracts, chainId) => {
+ return nftContracts?.[selectedAccount.address]?.[chainId] ?? [];
+ },
+);
+
+export const selectNetworkIdentifierByChainId = createSelector(
+ selectNetworkConfigurationByChainId,
+ selectDefaultRpcEndpointByChainId,
+ (networkConfiguration, defaultRpcEndpoint) => {
+ const { name: nickname } = networkConfiguration ?? {};
+ const { url: rpcUrl, networkClientId } = defaultRpcEndpoint ?? {};
+
+ return nickname || rpcUrl || networkClientId;
+ },
+);
+
export function getRequestingNetworkInfo(state, chainIds) {
// If chainIds is undefined, set it to an empty array
let processedChainIds = chainIds === undefined ? [] : chainIds;
From e882da087d6028a5cd884306a2d4b6c8a59db366 Mon Sep 17 00:00:00 2001
From: Pedro Figueiredo
- 0x2e0D7...5d09B -
-- You send -
-- - 4 -
-- ETH -
-+ {error.stack} ++ > + ) : null} +
{content}
-{stack}-