diff --git a/.circleci/config.yml b/.circleci/config.yml
index e25e89fa54f2..68a1c199a49b 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -701,7 +701,7 @@ jobs:
test-e2e-firefox-snaps:
executor: node-browsers
- parallelism: 2
+ parallelism: 4
steps:
- checkout
- run:
@@ -738,7 +738,7 @@ jobs:
test-e2e-chrome-snaps:
executor: node-browsers
- parallelism: 2
+ parallelism: 4
steps:
- checkout
- run:
diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json
index e5c86c47be59..c63d2a78d8b8 100644
--- a/app/_locales/de/messages.json
+++ b/app/_locales/de/messages.json
@@ -2327,12 +2327,6 @@
"notifications15Title": {
"message": "Ethereum Merge ist da!"
},
- "notifications17ActionText": {
- "message": "Sicherheits- und Datenschutzeinstellungen anzeigen"
- },
- "notifications17Title": {
- "message": "Sicherheits- und Datenschutzeinstellungen"
- },
"notifications1Description": {
"message": "Mobile MetaMask-Anwender können jetzt Token in ihren mobilen Wallets swappen. Scannen Sie den QR-Code, um die mobile App zu erhalten und mit dem Swapping zu beginnen.",
"description": "Description of a notification in the 'See What's New' popup. Describes the swapping on mobile feature."
diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json
index 4c56dcf01b53..3695fede50ac 100644
--- a/app/_locales/el/messages.json
+++ b/app/_locales/el/messages.json
@@ -2327,12 +2327,6 @@
"notifications15Title": {
"message": "Η συγχώνευση στο Ethereum είναι εδώ!"
},
- "notifications17ActionText": {
- "message": "Εμφάνιση ρυθμίσεων Ασφάλειας & Απορρήτου"
- },
- "notifications17Title": {
- "message": "Ρυθμίσεις Ασφάλειας & Απορρήτου"
- },
"notifications1Description": {
"message": "Οι χρήστες του MetaMask Mobile μπορούν τώρα να ανταλλάξουν tokens μέσα στο κινητό τους πορτοφόλι. Σαρώστε τον κωδικό QR για να πάρετε την εφαρμογή για κινητά και να αρχίσετε να ανταλλάζετε.",
"description": "Description of a notification in the 'See What's New' popup. Describes the swapping on mobile feature."
diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index cd00fe2c940e..4766b0221e47 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -2471,40 +2471,37 @@
"notifications15Title": {
"message": "The Ethereum Merge is here!"
},
- "notifications16ActionText": {
+ "notifications18ActionText": {
"message": "Enable security alerts"
},
- "notifications16DescriptionOne": {
+ "notifications18DescriptionOne": {
"message": "Get alerts from third parties when you may have received a malicious request.",
"description": "Description of a notification in the 'See What's New' popup. Describes Opensea Security Provider feature."
},
- "notifications16DescriptionThree": {
+ "notifications18DescriptionThree": {
"message": "Always be sure to do your own due diligence before approving any requests.",
"description": "Description of a notification in the 'See What's New' popup. Describes Opensea Security Provider feature."
},
- "notifications16DescriptionTwo": {
+ "notifications18DescriptionTwo": {
"message": "OpenSea is the first provider for this feature. More providers coming soon!",
"description": "Description of a notification in the 'See What's New' popup. Describes Opensea Security Provider feature."
},
- "notifications16Title": {
- "message": "Stay safe with security alerts"
- },
- "notifications17ActionText": {
+ "notifications19ActionText": {
"message": "Enable NFT autodetection"
},
- "notifications17DescriptionOne": {
+ "notifications19DescriptionOne": {
"message": "Two ways you can get started:",
"description": "Description of a notification in the 'See What's New' popup. Describes NFT autodetection feature."
},
- "notifications17DescriptionThree": {
+ "notifications19DescriptionThree": {
"message": "We only support ERC-721 at the moment.",
"description": "Description of a notification in the 'See What's New' popup. Describes NFT autodetection feature."
},
- "notifications17DescriptionTwo": {
+ "notifications19DescriptionTwo": {
"message": "Manually add your NFTs, or turn on NFT autodetection in Settings > Experimental.",
"description": "Description of a notification in the 'See What's New' popup. Describes NFT autodetection feature."
},
- "notifications17Title": {
+ "notifications19Title": {
"message": "See your NFTs like never before"
},
"notifications1Description": {
diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json
index d7d56a93b6eb..39e7a957311e 100644
--- a/app/_locales/es/messages.json
+++ b/app/_locales/es/messages.json
@@ -2327,12 +2327,6 @@
"notifications15Title": {
"message": "¡La Fusión de Ethereum está aquí!"
},
- "notifications17ActionText": {
- "message": "Mostrar configuración de seguridad y privacidad"
- },
- "notifications17Title": {
- "message": "Configuración de Seguridad y privacidad"
- },
"notifications1Description": {
"message": "Los usuarios de la aplicación móvil de MetaMask ahora pueden canjear tokens en su cartera móvil. Escanee el código QR para obtener la aplicación móvil y comience a canjear.",
"description": "Description of a notification in the 'See What's New' popup. Describes the swapping on mobile feature."
diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json
index bbdd98c4add8..af623de01a7f 100644
--- a/app/_locales/fr/messages.json
+++ b/app/_locales/fr/messages.json
@@ -2327,12 +2327,6 @@
"notifications15Title": {
"message": "La fusion Ethereum est en marche !"
},
- "notifications17ActionText": {
- "message": "Afficher les paramètres de sécurité et de confidentialité"
- },
- "notifications17Title": {
- "message": "Paramètres de sécurité et de confidentialité"
- },
"notifications1Description": {
"message": "Les utilisateurs de MetaMask Mobile peuvent désormais échanger des jetons dans leur portefeuille mobile. Scannez le code QR pour obtenir l’application mobile et commencez à échanger.",
"description": "Description of a notification in the 'See What's New' popup. Describes the swapping on mobile feature."
diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json
index f976670c9ffc..ec81fdc4f28a 100644
--- a/app/_locales/hi/messages.json
+++ b/app/_locales/hi/messages.json
@@ -1601,11 +1601,11 @@
"description": "Is the bolded text in 'holdToRevealContent1'"
},
"holdToRevealContent3": {
- "message": "इसे किसी के साथ साझा न करें। $1$2",
+ "message": "इसे किसी के साथ साझा न करें। $1,$2",
"description": "$1 is a message from 'holdToRevealContent4' and $2 is a text link with the message from 'holdToRevealContent5'"
},
"holdToRevealContent4": {
- "message": "MetaMask सपोर्ट इसका अनुरोध नहीं करेगा,",
+ "message": "MetaMask सपोर्ट इसका अनुरोध नहीं करेगा",
"description": "Part of 'holdToRevealContent3'"
},
"holdToRevealContent5": {
@@ -2327,12 +2327,6 @@
"notifications15Title": {
"message": "इथेरियम मर्ज यहाँ है!"
},
- "notifications17ActionText": {
- "message": "सुरक्षा और गोपनीयता सेटिंग्स को दिखाएं"
- },
- "notifications17Title": {
- "message": "सुरक्षा और गोपनीयता सेटिंग्स"
- },
"notifications1Description": {
"message": "MetaMask Mobile उपयोगकर्ता अब अपने मोबाइल वॉलेट के अंदर टोकन स्वैप कर सकते हैं। मोबाइल ऐप प्राप्त करने के लिए QR कोड को स्कैन करें और स्वैप करना शुरू करें।",
"description": "Description of a notification in the 'See What's New' popup. Describes the swapping on mobile feature."
diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json
index c4f6316a23cb..30823b2d1620 100644
--- a/app/_locales/id/messages.json
+++ b/app/_locales/id/messages.json
@@ -2327,12 +2327,6 @@
"notifications15Title": {
"message": "Penggabungan Ethereum telah tiba!"
},
- "notifications17ActionText": {
- "message": "Tampilkan pengaturan Keamanan & Privasi"
- },
- "notifications17Title": {
- "message": "Pengaturan Keamanan & Privasi"
- },
"notifications1Description": {
"message": "Pengguna MetaMask Mobile kini bisa menukar token di dalam dompet seluler mereka. Pindai kode QR untuk mendapatkan aplikasi seluler dan mulai menukar.",
"description": "Description of a notification in the 'See What's New' popup. Describes the swapping on mobile feature."
diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json
index e770df62694c..2ac044508587 100644
--- a/app/_locales/ja/messages.json
+++ b/app/_locales/ja/messages.json
@@ -1601,11 +1601,11 @@
"description": "Is the bolded text in 'holdToRevealContent1'"
},
"holdToRevealContent3": {
- "message": "これは誰にも教えないでください。$1$2",
+ "message": "これは誰にも教えないでください。$1、$2",
"description": "$1 is a message from 'holdToRevealContent4' and $2 is a text link with the message from 'holdToRevealContent5'"
},
"holdToRevealContent4": {
- "message": "MetaMask サポートがこの情報を尋ねることはなく、",
+ "message": "MetaMask サポートがこの情報を尋ねることはなく",
"description": "Part of 'holdToRevealContent3'"
},
"holdToRevealContent5": {
@@ -2327,12 +2327,6 @@
"notifications15Title": {
"message": "Ethereum のマージ (Merge) が完了しました!"
},
- "notifications17ActionText": {
- "message": "セキュリティおよびプライバシー設定を表示"
- },
- "notifications17Title": {
- "message": "セキュリティおよびプライバシー設定"
- },
"notifications1Description": {
"message": "MetaMask Mobileのユーザーが、モバイルウォレット内でトークンを交換できるようになりました。QRコードをスキャンしてモバイルアプリを取得し、スワップを開始します。",
"description": "Description of a notification in the 'See What's New' popup. Describes the swapping on mobile feature."
diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json
index ef63aba706d6..c82644e4be54 100644
--- a/app/_locales/ko/messages.json
+++ b/app/_locales/ko/messages.json
@@ -2327,12 +2327,6 @@
"notifications15Title": {
"message": "이더리움 머지가 완료되었습니다!"
},
- "notifications17ActionText": {
- "message": "보안 및 개인정보 설정 표시"
- },
- "notifications17Title": {
- "message": "보안 및 개인정보 설정 표시"
- },
"notifications1Description": {
"message": "MetaMask 모바일 사용자는 이제 모바일 지갑에서 토큰을 스왑할 수 있습니다. QR 코드를 스캔하여 모바일 앱을 설치하고 스왑을 시작하세요.",
"description": "Description of a notification in the 'See What's New' popup. Describes the swapping on mobile feature."
diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json
index c32d5525870f..a9544c37892f 100644
--- a/app/_locales/pt/messages.json
+++ b/app/_locales/pt/messages.json
@@ -2327,12 +2327,6 @@
"notifications15Title": {
"message": "A fusão do Ethereum chegou!"
},
- "notifications17ActionText": {
- "message": "Mostrar configurações de segurança e privacidade"
- },
- "notifications17Title": {
- "message": "Configurações de segurança e privacidade"
- },
"notifications1Description": {
"message": "Usuários da MetaMask Mobile agora podem trocar tokens dentro de sua carteira mobile. Leia o QR code para obter o aplicativo para dispositivos móveis e comece a trocar.",
"description": "Description of a notification in the 'See What's New' popup. Describes the swapping on mobile feature."
diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json
index bad7ed48f9e3..8c560db82103 100644
--- a/app/_locales/ru/messages.json
+++ b/app/_locales/ru/messages.json
@@ -2327,12 +2327,6 @@
"notifications15Title": {
"message": "Ethereum Merge уже досутпно!"
},
- "notifications17ActionText": {
- "message": "Показать настройки безопасности и конфиденциальности"
- },
- "notifications17Title": {
- "message": "Настройки безопасности и конфиденциальности"
- },
"notifications1Description": {
"message": "Теперь пользователи MetaMask Mobile могут обменивать токены в своем мобильном кошельке. Отсканируйте QR-код, чтобы скачать мобильное приложение и начать обмен.",
"description": "Description of a notification in the 'See What's New' popup. Describes the swapping on mobile feature."
diff --git a/app/_locales/tl/messages.json b/app/_locales/tl/messages.json
index 8eea144019d4..f8747ac19c12 100644
--- a/app/_locales/tl/messages.json
+++ b/app/_locales/tl/messages.json
@@ -2327,12 +2327,6 @@
"notifications15Title": {
"message": "Narito na ang Ethereum Merge!"
},
- "notifications17ActionText": {
- "message": "Ipakita ang mga setting ng Seguridad at Pagkapribado"
- },
- "notifications17Title": {
- "message": "Mga Setting ng Seguridad at Pagkapribado"
- },
"notifications1Description": {
"message": "Ang mga user ng MetaMask Mobile ay maaari na ngayong mag-swap ng mga token sa loob ng kanilang mobile wallet. I-scan ang QR code para makuha ang mobile app at magsimulang mag-swap.",
"description": "Description of a notification in the 'See What's New' popup. Describes the swapping on mobile feature."
diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json
index 9fb967075ff6..96038a2209ac 100644
--- a/app/_locales/tr/messages.json
+++ b/app/_locales/tr/messages.json
@@ -1593,7 +1593,7 @@
"message": "GKİ'yi göstermek için basılı tut"
},
"holdToRevealContent1": {
- "message": "Gizli Kurtarma İfadeniz: $1$",
+ "message": "Gizli Kurtarma İfadeniz: $1",
"description": "$1 is a bolded text with the message from 'holdToRevealContent2'"
},
"holdToRevealContent2": {
@@ -2327,12 +2327,6 @@
"notifications15Title": {
"message": "Ethereum Birleşmesi başladı!"
},
- "notifications17ActionText": {
- "message": "Güvenlik ve Gizlilik ayarlarını göster"
- },
- "notifications17Title": {
- "message": "Güvenlik ve Gizlilik Ayarları"
- },
"notifications1Description": {
"message": "MetaMask Mobil kullanıcıları artık mobil cüzdanları içinde token takas edebilirler. Mobil uygulamayı edinmek ve takas yapmaya başlamak için QR kodunu tarayın.",
"description": "Description of a notification in the 'See What's New' popup. Describes the swapping on mobile feature."
diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json
index dcfabd1d92e6..10dde0e64c6d 100644
--- a/app/_locales/vi/messages.json
+++ b/app/_locales/vi/messages.json
@@ -2327,12 +2327,6 @@
"notifications15Title": {
"message": "Hợp nhất Ethereum đã được triển khai!"
},
- "notifications17ActionText": {
- "message": "Hiển thị cài đặt Bảo mật và Quyền riêng tư"
- },
- "notifications17Title": {
- "message": "Cài đặt Bảo mật và Quyền riêng tư"
- },
"notifications1Description": {
"message": "Giờ đây, người dùng MetaMask trên điện thoại di động có thể hoán đổi token trong ví di động của họ. Quét mã QR để tải ứng dụng di động và bắt đầu hoán đổi.",
"description": "Description of a notification in the 'See What's New' popup. Describes the swapping on mobile feature."
diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json
index 0bce662da545..9eee48c84a10 100644
--- a/app/_locales/zh_CN/messages.json
+++ b/app/_locales/zh_CN/messages.json
@@ -2327,12 +2327,6 @@
"notifications15Title": {
"message": "以太坊合并来了!"
},
- "notifications17ActionText": {
- "message": "显示安全和隐私设置"
- },
- "notifications17Title": {
- "message": "安全和隐私设置"
- },
"notifications1Description": {
"message": "MetaMask Mobile 用户现在可以在他们的移动钱包中交换代币。扫描二维码以获取移动应用程序并开始交换。",
"description": "Description of a notification in the 'See What's New' popup. Describes the swapping on mobile feature."
diff --git a/app/build-types/mmi/images/bitgo.svg b/app/build-types/mmi/images/bitgo.svg
deleted file mode 100644
index 21e237c3a652..000000000000
--- a/app/build-types/mmi/images/bitgo.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/app/build-types/mmi/images/cactus.svg b/app/build-types/mmi/images/cactus.svg
deleted file mode 100644
index 5abde4485e85..000000000000
--- a/app/build-types/mmi/images/cactus.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/build-types/mmi/images/curv-logo-horizontal-black.svg b/app/build-types/mmi/images/curv-logo-horizontal-black.svg
deleted file mode 100644
index 45e128b12315..000000000000
--- a/app/build-types/mmi/images/curv-logo-horizontal-black.svg
+++ /dev/null
@@ -1,40 +0,0 @@
-
diff --git a/app/build-types/mmi/images/curv-logo.svg b/app/build-types/mmi/images/curv-logo.svg
deleted file mode 100644
index 37c06025b065..000000000000
--- a/app/build-types/mmi/images/curv-logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/build-types/mmi/images/parfin.svg b/app/build-types/mmi/images/parfin.svg
deleted file mode 100644
index bf09f39b7bd2..000000000000
--- a/app/build-types/mmi/images/parfin.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
diff --git a/app/build-types/mmi/images/qredo.svg b/app/build-types/mmi/images/qredo.svg
deleted file mode 100644
index 4f3d182c9b59..000000000000
--- a/app/build-types/mmi/images/qredo.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-
diff --git a/app/images/icons/arrow-2-up-right.svg b/app/images/icons/arrow-2-up-right.svg
new file mode 100644
index 000000000000..cb97c42fd0f1
--- /dev/null
+++ b/app/images/icons/arrow-2-up-right.svg
@@ -0,0 +1,3 @@
+
diff --git a/app/scripts/app-init.js b/app/scripts/app-init.js
index 0f61d9888ef1..450c5959737e 100644
--- a/app/scripts/app-init.js
+++ b/app/scripts/app-init.js
@@ -127,10 +127,6 @@ chrome.runtime.onMessage.addListener(() => {
return false;
});
-chrome.runtime.onStartup.addListener(() => {
- globalThis.isFirstTimeProfileLoaded = true;
-});
-
/*
* This content script is injected programmatically because
* MAIN world injection does not work properly via manifest
diff --git a/app/scripts/background.js b/app/scripts/background.js
index 9e7f65d0d49e..d92fddb816a9 100644
--- a/app/scripts/background.js
+++ b/app/scripts/background.js
@@ -268,7 +268,23 @@ async function initialize() {
await DesktopManager.init(platform.getVersion());
///: END:ONLY_INCLUDE_IN
- setupController(initState, initLangCode);
+ let isFirstMetaMaskControllerSetup;
+ if (isManifestV3) {
+ const sessionData = await browser.storage.session.get([
+ 'isFirstMetaMaskControllerSetup',
+ ]);
+
+ isFirstMetaMaskControllerSetup =
+ sessionData?.isFirstMetaMaskControllerSetup === undefined;
+ await browser.storage.session.set({ isFirstMetaMaskControllerSetup });
+ }
+
+ setupController(
+ initState,
+ initLangCode,
+ {},
+ isFirstMetaMaskControllerSetup,
+ );
if (!isManifestV3) {
await loadPhishingWarningPage();
}
@@ -410,8 +426,14 @@ export async function loadStateFromPersistence() {
* @param {object} initState - The initial state to start the controller with, matches the state that is emitted from the controller.
* @param {string} initLangCode - The region code for the language preferred by the current user.
* @param {object} overrides - object with callbacks that are allowed to override the setup controller logic (usefull for desktop app)
+ * @param isFirstMetaMaskControllerSetup
*/
-export function setupController(initState, initLangCode, overrides) {
+export function setupController(
+ initState,
+ initLangCode,
+ overrides,
+ isFirstMetaMaskControllerSetup,
+) {
//
// MetaMask Controller
//
@@ -437,6 +459,7 @@ export function setupController(initState, initLangCode, overrides) {
},
localStore,
overrides,
+ isFirstMetaMaskControllerSetup,
});
setupEnsIpfsResolver({
diff --git a/app/scripts/lib/account-tracker.js b/app/scripts/lib/account-tracker.js
index eed68abae502..cbc87aef749a 100644
--- a/app/scripts/lib/account-tracker.js
+++ b/app/scripts/lib/account-tracker.js
@@ -62,7 +62,7 @@ export default class AccountTracker {
accounts: {},
currentBlockGasLimit: '',
};
- this.store = new ObservableStore(initState);
+ this.store = new ObservableStore({ ...initState, ...opts.initState });
this.resetState = () => {
this.store.updateState(initState);
diff --git a/app/scripts/lib/rpc-method-middleware/handlers/switch-ethereum-chain.js b/app/scripts/lib/rpc-method-middleware/handlers/switch-ethereum-chain.js
index 935b9ec60111..81c6887e048d 100644
--- a/app/scripts/lib/rpc-method-middleware/handlers/switch-ethereum-chain.js
+++ b/app/scripts/lib/rpc-method-middleware/handlers/switch-ethereum-chain.js
@@ -115,7 +115,7 @@ async function switchEthereumChainHandler(
) {
setProviderType(approvedRequestData.type);
} else {
- await setActiveNetwork(approvedRequestData);
+ await setActiveNetwork(approvedRequestData.id);
}
res.result = null;
} catch (error) {
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index 1c4f4be5e42a..28a7311c0e16 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -62,7 +62,6 @@ import {
} from '@metamask/snaps-controllers';
///: END:ONLY_INCLUDE_IN
-import browser from 'webextension-polyfill';
import {
AssetType,
TransactionStatus,
@@ -204,6 +203,8 @@ export default class MetamaskController extends EventEmitter {
constructor(opts) {
super();
+ const { isFirstMetaMaskControllerSetup } = opts;
+
this.defaultMaxListeners = 20;
this.sendUpdate = debounce(
@@ -547,10 +548,14 @@ export default class MetamaskController extends EventEmitter {
this.phishingController.setStalelistRefreshInterval(30 * SECOND);
}
- this.announcementController = new AnnouncementController(
- { allAnnouncements: UI_NOTIFICATIONS },
- initState.AnnouncementController,
- );
+ const announcementMessenger = this.controllerMessenger.getRestricted({
+ name: 'AnnouncementController',
+ });
+ this.announcementController = new AnnouncementController({
+ messenger: announcementMessenger,
+ allAnnouncements: UI_NOTIFICATIONS,
+ state: initState.AnnouncementController,
+ });
// token exchange rate tracker
this.tokenRatesController = new TokenRatesController(
@@ -638,6 +643,12 @@ export default class MetamaskController extends EventEmitter {
},
preferencesController: this.preferencesController,
onboardingController: this.onboardingController,
+ initState:
+ isManifestV3 &&
+ isFirstMetaMaskControllerSetup === false &&
+ initState.AccountTracker?.accounts
+ ? { accounts: initState.AccountTracker.accounts }
+ : { accounts: {} },
});
// start and stop polling for balances based on activeControllerConnections
@@ -1369,8 +1380,11 @@ export default class MetamaskController extends EventEmitter {
];
if (isManifestV3) {
- if (globalThis.isFirstTimeProfileLoaded === true) {
+ if (isFirstMetaMaskControllerSetup === true) {
this.resetStates(resetMethods);
+ this.extension.storage.session.set({
+ isFirstMetaMaskControllerSetup: false,
+ });
}
} else {
// it's always the first time in MV2
@@ -1445,8 +1459,6 @@ export default class MetamaskController extends EventEmitter {
console.error(err);
}
});
-
- globalThis.isFirstTimeProfileLoaded = false;
}
///: BEGIN:ONLY_INCLUDE_IN(flask)
@@ -2679,10 +2691,8 @@ export default class MetamaskController extends EventEmitter {
*/
async submitEncryptionKey() {
try {
- const { loginToken, loginSalt } = await browser.storage.session.get([
- 'loginToken',
- 'loginSalt',
- ]);
+ const { loginToken, loginSalt } =
+ await this.extension.storage.session.get(['loginToken', 'loginSalt']);
if (loginToken && loginSalt) {
const { vault } = this.keyringController.store.getState();
@@ -2707,7 +2717,7 @@ export default class MetamaskController extends EventEmitter {
}
async clearLoginArtifacts() {
- await browser.storage.session.remove(['loginToken', 'loginSalt']);
+ await this.extension.storage.session.remove(['loginToken', 'loginSalt']);
}
/**
@@ -4125,7 +4135,7 @@ export default class MetamaskController extends EventEmitter {
);
if (isManifestV3) {
- await browser.storage.session.set({ loginToken, loginSalt });
+ await this.extension.storage.session.set({ loginToken, loginSalt });
}
if (!addresses.length) {
diff --git a/app/scripts/metamask-controller.test.js b/app/scripts/metamask-controller.test.js
index 826e0236c4e1..af2e5c62f816 100644
--- a/app/scripts/metamask-controller.test.js
+++ b/app/scripts/metamask-controller.test.js
@@ -30,6 +30,9 @@ const browserPolyfillMock = {
},
getPlatformInfo: async () => 'mac',
},
+ storage: {
+ session: {},
+ },
};
let loggerMiddlewareMock;
@@ -79,6 +82,10 @@ const MetaMaskController = proxyquire('./metamask-controller', {
'ethjs-contract': MockEthContract,
}).default;
+const MetaMaskControllerMV3 = proxyquire('./metamask-controller', {
+ '../../shared/modules/mv3.utils': { isManifestV3: true },
+}).default;
+
const currentNetworkId = '5';
const DEFAULT_LABEL = 'Account 1';
const TEST_SEED =
@@ -168,10 +175,13 @@ describe('MetaMaskController', function () {
const sandbox = sinon.createSandbox();
const noop = () => undefined;
+ browserPolyfillMock.storage.session.set = sandbox.spy();
+
before(async function () {
globalThis.isFirstTimeProfileLoaded = true;
await ganacheServer.start();
sinon.spy(MetaMaskController.prototype, 'resetStates');
+ sinon.spy(MetaMaskControllerMV3.prototype, 'resetStates');
});
beforeEach(function () {
@@ -224,6 +234,7 @@ describe('MetaMaskController', function () {
},
browser: browserPolyfillMock,
infuraProjectId: 'foo',
+ isFirstMetaMaskControllerSetup: true,
});
// add sinon method spies
@@ -247,14 +258,70 @@ describe('MetaMaskController', function () {
});
describe('should reset states on first time profile load', function () {
- it('should reset state', function () {
- assert(metamaskController.resetStates.calledOnce);
- assert.equal(globalThis.isFirstTimeProfileLoaded, false);
+ it('in mv2, it should reset state without attempting to call browser storage', function () {
+ assert.equal(metamaskController.resetStates.callCount, 1);
+ assert.equal(browserPolyfillMock.storage.session.set.callCount, 0);
+ });
+
+ it('in mv3, it should reset state', function () {
+ MetaMaskControllerMV3.prototype.resetStates.resetHistory();
+ const metamaskControllerMV3 = new MetaMaskControllerMV3({
+ showUserConfirmation: noop,
+ encryptor: {
+ encrypt(_, object) {
+ this.object = object;
+ return Promise.resolve('mock-encrypted');
+ },
+ decrypt() {
+ return Promise.resolve(this.object);
+ },
+ },
+ initState: cloneDeep(firstTimeState),
+ initLangCode: 'en_US',
+ platform: {
+ showTransactionNotification: () => undefined,
+ getVersion: () => 'foo',
+ },
+ browser: browserPolyfillMock,
+ infuraProjectId: 'foo',
+ isFirstMetaMaskControllerSetup: true,
+ });
+ assert.equal(metamaskControllerMV3.resetStates.callCount, 1);
+ assert.equal(browserPolyfillMock.storage.session.set.callCount, 1);
+ assert.deepEqual(
+ browserPolyfillMock.storage.session.set.getCall(0).args[0],
+ {
+ isFirstMetaMaskControllerSetup: false,
+ },
+ );
});
- it('should not reset states if already set', function () {
- // global.isFirstTime should also remain false
- assert.equal(globalThis.isFirstTimeProfileLoaded, false);
+ it('in mv3, it should not reset states if isFirstMetaMaskControllerSetup is false', function () {
+ MetaMaskControllerMV3.prototype.resetStates.resetHistory();
+ browserPolyfillMock.storage.session.set.resetHistory();
+ const metamaskControllerMV3 = new MetaMaskControllerMV3({
+ showUserConfirmation: noop,
+ encryptor: {
+ encrypt(_, object) {
+ this.object = object;
+ return Promise.resolve('mock-encrypted');
+ },
+ decrypt() {
+ return Promise.resolve(this.object);
+ },
+ },
+ initState: cloneDeep(firstTimeState),
+ initLangCode: 'en_US',
+ platform: {
+ showTransactionNotification: () => undefined,
+ getVersion: () => 'foo',
+ },
+ browser: browserPolyfillMock,
+ infuraProjectId: 'foo',
+ isFirstMetaMaskControllerSetup: false,
+ });
+ assert.equal(metamaskControllerMV3.resetStates.callCount, 0);
+ assert.equal(browserPolyfillMock.storage.session.set.callCount, 0);
});
});
diff --git a/development/build/index.js b/development/build/index.js
index 9c9f75f16ce8..a82d9bbd39b5 100755
--- a/development/build/index.js
+++ b/development/build/index.js
@@ -147,6 +147,9 @@ async function defineAndRunBuildTasks() {
browserPlatforms,
browserVersionMap,
buildType,
+ applyLavaMoat,
+ shouldIncludeSnow,
+ entryTask,
});
const styleTasks = createStyleTasks({ livereload });
diff --git a/development/build/manifest.js b/development/build/manifest.js
index 58817372efc5..e9569086832d 100644
--- a/development/build/manifest.js
+++ b/development/build/manifest.js
@@ -1,14 +1,16 @@
const { promises: fs } = require('fs');
const path = require('path');
-const { mergeWith, cloneDeep } = require('lodash');
+const childProcess = require('child_process');
+const { mergeWith, cloneDeep, capitalize } = require('lodash');
const baseManifest = process.env.ENABLE_MV3
? require('../../app/manifest/v3/_base.json')
: require('../../app/manifest/v2/_base.json');
const { BuildType } = require('../lib/build-type');
-const { TASKS } = require('./constants');
+const { TASKS, ENVIRONMENT } = require('./constants');
const { createTask, composeSeries } = require('./task');
+const { getEnvironment } = require('./utils');
module.exports = createManifestTasks;
@@ -16,6 +18,9 @@ function createManifestTasks({
browserPlatforms,
browserVersionMap,
buildType,
+ applyLavaMoat,
+ shouldIncludeSnow,
+ entryTask,
}) {
// merge base manifest with per-platform manifests
const prepPlatforms = async () => {
@@ -38,6 +43,9 @@ function createManifestTasks({
await getBuildModifications(buildType, platform),
customArrayMerge,
);
+
+ modifyNameAndDescForNonProd(result);
+
const dir = path.join('.', 'dist', platform);
await fs.mkdir(dir, { recursive: true });
await writeJson(result, path.join(dir, 'manifest.json'));
@@ -101,12 +109,39 @@ function createManifestTasks({
);
const manifest = await readJson(manifestPath);
transformFn(manifest);
+
await writeJson(manifest, manifestPath);
}),
);
};
}
+ // For non-production builds only, modify the extension's name and description
+ function modifyNameAndDescForNonProd(manifest) {
+ const environment = getEnvironment({ buildTarget: entryTask });
+
+ if (environment === ENVIRONMENT.PRODUCTION) {
+ return;
+ }
+
+ const mv3Str = process.env.ENABLE_MV3 ? ' MV3' : '';
+ const lavamoatStr = applyLavaMoat ? ' lavamoat' : '';
+ const snowStr = shouldIncludeSnow ? ' snow' : '';
+
+ // Get the first 8 characters of the git revision id
+ const gitRevisionStr = childProcess
+ .execSync('git rev-parse HEAD')
+ .toString()
+ .trim()
+ .substring(0, 8);
+
+ manifest.name = `MetaMask ${capitalize(
+ buildType,
+ )}${mv3Str}${lavamoatStr}${snowStr}`;
+
+ manifest.description = `${environment} build from git id: ${gitRevisionStr}`;
+ }
+
// helper for merging obj value
function customArrayMerge(objValue, srcValue) {
if (Array.isArray(objValue)) {
diff --git a/development/ts-migration-dashboard/files-to-convert.json b/development/ts-migration-dashboard/files-to-convert.json
index 254019f80dab..0af9207be158 100644
--- a/development/ts-migration-dashboard/files-to-convert.json
+++ b/development/ts-migration-dashboard/files-to-convert.json
@@ -386,9 +386,9 @@
"ui/components/app/asset-list-item/asset-list-item.js",
"ui/components/app/asset-list-item/index.js",
"ui/components/app/asset-list/asset-list.js",
- "ui/components/app/asset-list/detetcted-tokens-link/detected-tokens-link.js",
- "ui/components/app/asset-list/detetcted-tokens-link/detected-tokens-link.stories.js",
- "ui/components/app/asset-list/detetcted-tokens-link/detected-tokens-link.test.js",
+ "ui/components/app/asset-list/detected-tokens-link/detected-tokens-link.js",
+ "ui/components/app/asset-list/detected-tokens-link/detected-tokens-link.stories.js",
+ "ui/components/app/asset-list/detected-tokens-link/detected-tokens-link.test.js",
"ui/components/app/asset-list/index.js",
"ui/components/app/cancel-button/cancel-button.js",
"ui/components/app/cancel-button/index.js",
diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json
index dd174c63d024..7d359e5227d4 100644
--- a/lavamoat/browserify/beta/policy.json
+++ b/lavamoat/browserify/beta/policy.json
@@ -686,18 +686,10 @@
},
"@metamask/announcement-controller": {
"packages": {
- "@metamask/announcement-controller>@metamask/base-controller": true
- }
- },
- "@metamask/announcement-controller>@metamask/base-controller": {
- "packages": {
- "immer": true
+ "@metamask/base-controller": true
}
},
"@metamask/approval-controller": {
- "globals": {
- "console.log": true
- },
"packages": {
"@metamask/approval-controller>nanoid": true,
"@metamask/base-controller": true,
diff --git a/lavamoat/browserify/desktop/policy.json b/lavamoat/browserify/desktop/policy.json
index fa9312ae50ea..8fc8f7bcd5fa 100644
--- a/lavamoat/browserify/desktop/policy.json
+++ b/lavamoat/browserify/desktop/policy.json
@@ -686,18 +686,10 @@
},
"@metamask/announcement-controller": {
"packages": {
- "@metamask/announcement-controller>@metamask/base-controller": true
- }
- },
- "@metamask/announcement-controller>@metamask/base-controller": {
- "packages": {
- "immer": true
+ "@metamask/base-controller": true
}
},
"@metamask/approval-controller": {
- "globals": {
- "console.log": true
- },
"packages": {
"@metamask/approval-controller>nanoid": true,
"@metamask/base-controller": true,
diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json
index fa9312ae50ea..8fc8f7bcd5fa 100644
--- a/lavamoat/browserify/flask/policy.json
+++ b/lavamoat/browserify/flask/policy.json
@@ -686,18 +686,10 @@
},
"@metamask/announcement-controller": {
"packages": {
- "@metamask/announcement-controller>@metamask/base-controller": true
- }
- },
- "@metamask/announcement-controller>@metamask/base-controller": {
- "packages": {
- "immer": true
+ "@metamask/base-controller": true
}
},
"@metamask/approval-controller": {
- "globals": {
- "console.log": true
- },
"packages": {
"@metamask/approval-controller>nanoid": true,
"@metamask/base-controller": true,
diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json
index dd174c63d024..7d359e5227d4 100644
--- a/lavamoat/browserify/main/policy.json
+++ b/lavamoat/browserify/main/policy.json
@@ -686,18 +686,10 @@
},
"@metamask/announcement-controller": {
"packages": {
- "@metamask/announcement-controller>@metamask/base-controller": true
- }
- },
- "@metamask/announcement-controller>@metamask/base-controller": {
- "packages": {
- "immer": true
+ "@metamask/base-controller": true
}
},
"@metamask/approval-controller": {
- "globals": {
- "console.log": true
- },
"packages": {
"@metamask/approval-controller>nanoid": true,
"@metamask/base-controller": true,
diff --git a/package.json b/package.json
index 6dc22b4daa26..2b18159833f8 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
"start": "yarn build:dev dev --apply-lavamoat=false --snow=false",
"start:lavamoat": "yarn build:dev dev --apply-lavamoat=true",
"start:mv3": "ENABLE_MV3=true yarn build:dev dev --apply-lavamoat=false",
+ "start:flask": "yarn start --build-type flask",
"dist": "yarn build dist",
"build": "yarn lavamoat:build",
"build:dev": "node development/build/index.js",
@@ -226,7 +227,7 @@
"@lavamoat/snow": "^1.5.0",
"@material-ui/core": "^4.11.0",
"@metamask/address-book-controller": "^1.0.0",
- "@metamask/announcement-controller": "^1.0.0",
+ "@metamask/announcement-controller": "^2.0.1",
"@metamask/approval-controller": "^1.0.0",
"@metamask/assets-controllers": "^4.0.1",
"@metamask/base-controller": "^1.0.0",
diff --git a/shared/notifications/index.js b/shared/notifications/index.js
index f1a5ff738942..10c24bbfeb19 100644
--- a/shared/notifications/index.js
+++ b/shared/notifications/index.js
@@ -81,13 +81,21 @@ export const UI_NOTIFICATIONS = {
16: {
id: 16,
date: null,
+ },
+ 17: {
+ id: 17,
+ date: null,
+ },
+ 18: {
+ id: 18,
+ date: null,
image: {
src: 'images/open-sea-security-provider.svg',
width: '100%',
},
},
- 17: {
- id: 17,
+ 19: {
+ id: 19,
date: null,
image: {
src: 'images/nfts.svg',
@@ -240,34 +248,34 @@ export const getTranslatedUINotifications = (t, locale) => {
)
: '',
},
- 16: {
- ...UI_NOTIFICATIONS[16],
- title: t('notifications16Title'),
+ 18: {
+ ...UI_NOTIFICATIONS[18],
+ title: t('notifications18Title'),
description: [
- t('notifications16DescriptionOne'),
- t('notifications16DescriptionTwo'),
- t('notifications16DescriptionThree'),
+ t('notifications18DescriptionOne'),
+ t('notifications18DescriptionTwo'),
+ t('notifications18DescriptionThree'),
],
- actionText: t('notifications16ActionText'),
- date: UI_NOTIFICATIONS[16].date
+ actionText: t('notifications18ActionText'),
+ date: UI_NOTIFICATIONS[18].date
? new Intl.DateTimeFormat(formattedLocale).format(
- new Date(UI_NOTIFICATIONS[16].date),
+ new Date(UI_NOTIFICATIONS[18].date),
)
: '',
},
- 17: {
- ...UI_NOTIFICATIONS[17],
- title: t('notifications17Title'),
+ 19: {
+ ...UI_NOTIFICATIONS[19],
+ title: t('notifications19Title'),
description: [
- t('notifications17DescriptionOne'),
- t('notifications17DescriptionTwo'),
- t('notifications17DescriptionThree'),
+ t('notifications19DescriptionOne'),
+ t('notifications19DescriptionTwo'),
+ t('notifications19DescriptionThree'),
],
- actionText: t('notifications17ActionText'),
- date: UI_NOTIFICATIONS[17].date
+ actionText: t('notifications19ActionText'),
+ date: UI_NOTIFICATIONS[19].date
? new Intl.DateTimeFormat(formattedLocale).format(
- new Date(UI_NOTIFICATIONS[17].date),
+ new Date(UI_NOTIFICATIONS[19].date),
)
: '',
},
diff --git a/test/e2e/fixture-builder.js b/test/e2e/fixture-builder.js
index 5e3695a05e53..3ded4081b6cc 100644
--- a/test/e2e/fixture-builder.js
+++ b/test/e2e/fixture-builder.js
@@ -117,11 +117,21 @@ function defaultFixture() {
16: {
date: null,
id: 16,
- isShown: true,
+ isShown: false,
},
17: {
date: null,
id: 17,
+ isShown: false,
+ },
+ 18: {
+ date: null,
+ id: 18,
+ isShown: true,
+ },
+ 19: {
+ date: null,
+ id: 19,
isShown: true,
},
},
diff --git a/test/e2e/snaps/test-snap-bip-32.spec.js b/test/e2e/snaps/test-snap-bip-32.spec.js
index 2babba866499..b477fade4ce8 100644
--- a/test/e2e/snaps/test-snap-bip-32.spec.js
+++ b/test/e2e/snaps/test-snap-bip-32.spec.js
@@ -1,4 +1,3 @@
-const { strict: assert } = require('assert');
const { withFixtures } = require('../helpers');
const FixtureBuilder = require('../fixture-builder');
const { TEST_SNAPS_WEBSITE_URL } = require('./enums');
@@ -61,7 +60,7 @@ describe('Test Snap bip-32', function () {
});
// wait for permissions popover, click checkboxes and confirm
- await driver.delay(1000);
+ await driver.delay(500);
await driver.clickElement('#key-access-bip32-m-44h-0h-secp256k1-0');
await driver.clickElement('#key-access-bip32-m-44h-0h-ed25519-1');
await driver.clickElement(
@@ -73,7 +72,6 @@ describe('Test Snap bip-32', function () {
});
await driver.waitForSelector({ text: 'Ok' });
-
await driver.clickElement({
text: 'Ok',
tag: 'button',
@@ -90,46 +88,30 @@ describe('Test Snap bip-32', function () {
// scroll to and click get public key
await driver.delay(1000);
- const snapButton2 = await driver.findElement('#bip32GetPublic');
- await driver.scrollToElement(snapButton2);
- await driver.delay(1000);
+ await driver.waitForSelector({ text: 'Get Public Key' });
await driver.clickElement('#bip32GetPublic');
- // check for proper public key response
- await driver.delay(1000);
- const retrievePublicKeyResult1 = await driver.findElement(
- '#bip32PublicKeyResult',
- );
- assert.equal(
- await retrievePublicKeyResult1.getText(),
- '"0x043e98d696ae15caef75fa8dd204a7c5c08d1272b2218ba3c20feeb4c691eec366606ece56791c361a2320e7fad8bcbb130f66d51c591fc39767ab2856e93f8dfb"',
- );
+ // check for proper public key response using waitForSelector
+ await driver.waitForSelector({
+ css: '#bip32PublicKeyResult',
+ text: '"0x043e98d696ae15caef75fa8dd204a7c5c08d1272b2218ba3c20feeb4c691eec366606ece56791c361a2320e7fad8bcbb130f66d51c591fc39767ab2856e93f8dfb',
+ });
// scroll to and click get compressed public key
- await driver.delay(1000);
- const snapButton3 = await driver.findElement(
- '#bip32GetCompressedPublic',
- );
- await driver.scrollToElement(snapButton3);
- await driver.delay(1000);
+ await driver.waitForSelector({ text: 'Get Compressed Public Key' });
await driver.clickElement('#bip32GetCompressedPublic');
- // check for proper public key response
- await driver.delay(1000);
- const retrievePublicKeyResult2 = await driver.findElement(
- '#bip32PublicKeyResult',
- );
- assert.equal(
- await retrievePublicKeyResult2.getText(),
- '"0x033e98d696ae15caef75fa8dd204a7c5c08d1272b2218ba3c20feeb4c691eec366"',
- );
+ // check for proper public key response using waitForSelector
+ await driver.waitForSelector({
+ css: '#bip32PublicKeyResult',
+ text: '"0x033e98d696ae15caef75fa8dd204a7c5c08d1272b2218ba3c20feeb4c691eec366',
+ });
// wait then run SECP256K1 test
- await driver.delay(1000);
- await driver.pasteIntoField('#bip32Message-secp256k1', 'foo bar');
+ await driver.fill('#bip32Message-secp256k1', 'foo bar');
await driver.clickElement('#sendBip32-secp256k1');
- // hit 'approve' on the custom confirm
+ // hit 'approve' on the signature confirmation
windowHandles = await driver.waitUntilXWindowHandles(2, 1000, 10000);
await driver.switchToWindowWithTitle(
'MetaMask Notification',
@@ -140,28 +122,23 @@ describe('Test Snap bip-32', function () {
tag: 'button',
});
+ // switch back to the test-snaps window
windowHandles = await driver.waitUntilXWindowHandles(1, 1000, 10000);
await driver.switchToWindowWithTitle('Test Snaps', windowHandles);
- // check result
- await driver.delay(1000);
- const secp256k1Result = await driver.findElement(
- '#bip32MessageResult-secp256k1',
- );
- assert.equal(
- await secp256k1Result.getText(),
- '"0x3045022100b3ade2992ea3e5eb58c7550e9bddad356e9554233c8b099ebc3cb418e9301ae2022064746e15ae024808f0ba5d860e44dc4c97e65c8cba6f5ef9ea2e8c819930d2dc"',
- );
+ // check results of the secp256k1 signature with waitForSelector
+ await driver.waitForSelector({
+ css: '#bip32MessageResult-secp256k1',
+ text: '"0x3045022100b3ade2992ea3e5eb58c7550e9bddad356e9554233c8b099ebc3cb418e9301ae2022064746e15ae024808f0ba5d860e44dc4c97e65c8cba6f5ef9ea2e8c819930d2dc',
+ });
// scroll further into messages section
- await driver.delay(1000);
- const snapButton4 = await driver.findElement('#bip32Message-ed25519');
+ const snapButton4 = await driver.findElement('#sendBip32-ed25519');
await driver.scrollToElement(snapButton4);
- await driver.delay(1000);
// wait then run ed25519 test
- await driver.delay(1000);
- await driver.pasteIntoField('#bip32Message-ed25519', 'foo bar');
+ await driver.delay(500);
+ await driver.fill('#bip32Message-ed25519', 'foo bar');
await driver.clickElement('#sendBip32-ed25519');
// hit 'approve' on the custom confirm
@@ -178,15 +155,11 @@ describe('Test Snap bip-32', function () {
windowHandles = await driver.waitUntilXWindowHandles(1, 1000, 10000);
await driver.switchToWindowWithTitle('Test Snaps', windowHandles);
- // check result
- await driver.delay(1000);
- const ed25519Result = await driver.findElement(
- '#bip32MessageResult-ed25519',
- );
- assert.equal(
- await ed25519Result.getText(),
- '"0xf3215b4d6c59aac7e01b4ceef530d1e2abf4857926b85a81aaae3894505699243768a887b7da4a8c2e0f25196196ba290b6531050db8dc15c252bdd508532a0a"',
- );
+ // check results of ed25519 signature with waitForSelector
+ await driver.waitForSelector({
+ css: '#bip32MessageResult-ed25519',
+ text: '"0xf3215b4d6c59aac7e01b4ceef530d1e2abf4857926b85a81aaae3894505699243768a887b7da4a8c2e0f25196196ba290b6531050db8dc15c252bdd508532a0a"',
+ });
},
);
});
diff --git a/test/e2e/snaps/test-snap-bip-44.spec.js b/test/e2e/snaps/test-snap-bip-44.spec.js
index 126ad5e5b5b8..cbee5ff15d49 100644
--- a/test/e2e/snaps/test-snap-bip-44.spec.js
+++ b/test/e2e/snaps/test-snap-bip-44.spec.js
@@ -1,4 +1,3 @@
-const { strict: assert } = require('assert');
const { withFixtures } = require('../helpers');
const FixtureBuilder = require('../fixture-builder');
const { TEST_SNAPS_WEBSITE_URL } = require('./enums');
@@ -31,13 +30,15 @@ describe('Test Snap bip-44', function () {
// navigate to test snaps page and connect
await driver.driver.get(TEST_SNAPS_WEBSITE_URL);
await driver.delay(1000);
+
+ // find and scroll to the bip44 test and connect
const snapButton1 = await driver.findElement('#connectBip44Snap');
await driver.scrollToElement(snapButton1);
await driver.delay(1000);
await driver.clickElement('#connectBip44Snap');
await driver.delay(1000);
- // switch to metamask extension and click connect
+ // switch to metamask extension and click connect and approve
let windowHandles = await driver.waitUntilXWindowHandles(
2,
1000,
@@ -51,31 +52,26 @@ describe('Test Snap bip-44', function () {
text: 'Connect',
tag: 'button',
});
-
await driver.waitForSelector({ text: 'Approve & install' });
-
await driver.clickElement({
text: 'Approve & install',
tag: 'button',
});
// deal with permissions popover
- await driver.delay(1000);
+ await driver.delay(500);
await driver.clickElement('#key-access-bip44-1-0');
- await driver.delay(1500);
await driver.clickElement({
text: 'Confirm',
tag: 'button',
});
-
await driver.waitForSelector({ text: 'Ok' });
-
await driver.clickElement({
text: 'Ok',
tag: 'button',
});
- // click send inputs on test snap page
+ // switch back to test-snaps window
await driver.switchToWindowWithTitle('Test Snaps', windowHandles);
// wait for npm installation success
@@ -84,22 +80,21 @@ describe('Test Snap bip-44', function () {
text: 'Reconnect to BIP-44 Snap',
});
+ // find and click bip44 test
await driver.clickElement('#sendBip44Test');
- // check the results of the public key test
- await driver.delay(1000);
- const bip44Result = await driver.findElement('#bip44Result');
- assert.equal(
- await bip44Result.getText(),
- '"0x86debb44fb3a984d93f326131d4c1db0bc39644f1a67b673b3ab45941a1cea6a385981755185ac4594b6521e4d1e08d1"',
- );
+ // check the results of the public key test using waitForSelector
+ await driver.waitForSelector({
+ css: '#bip44Result',
+ text: '"0x86debb44fb3a984d93f326131d4c1db0bc39644f1a67b673b3ab45941a1cea6a385981755185ac4594b6521e4d1e08d1"',
+ });
// enter a message to sign
await driver.pasteIntoField('#bip44Message', '1234');
- await driver.delay(1000);
+ await driver.delay(500);
const snapButton3 = await driver.findElement('#signBip44Message');
await driver.scrollToElement(snapButton3);
- await driver.delay(1000);
+ await driver.delay(500);
await driver.clickElement('#signBip44Message');
// Switch to approve signature message window and approve
@@ -116,14 +111,12 @@ describe('Test Snap bip-44', function () {
// switch back to test-snaps page
windowHandles = await driver.waitUntilXWindowHandles(1, 1000, 10000);
await driver.switchToWindowWithTitle('Test Snaps', windowHandles);
- await driver.delay(1000);
- // check the results of the message signature
- const bip44SignResult = await driver.findElement('#bip44SignResult');
- assert.equal(
- await bip44SignResult.getText(),
- '"0xa41ab87ca50606eefd47525ad90294bbe44c883f6bc53655f1b8a55aa8e1e35df216f31be62e52c7a1faa519420e20810162e07dedb0fde2a4d997ff7180a78232ecd8ce2d6f4ba42ccacad33c5e9e54a8c4d41506bdffb2bb4c368581d8b086"',
- );
+ // check the results of the message signature using waitForSelector
+ await driver.waitForSelector({
+ css: '#bip44SignResult',
+ text: '"0xa41ab87ca50606eefd47525ad90294bbe44c883f6bc53655f1b8a55aa8e1e35df216f31be62e52c7a1faa519420e20810162e07dedb0fde2a4d997ff7180a78232ecd8ce2d6f4ba42ccacad33c5e9e54a8c4d41506bdffb2bb4c368581d8b086"',
+ });
},
);
});
diff --git a/test/e2e/snaps/test-snap-dialog.spec.js b/test/e2e/snaps/test-snap-dialog.spec.js
index 031d14271e0b..f2b51321b8a3 100644
--- a/test/e2e/snaps/test-snap-dialog.spec.js
+++ b/test/e2e/snaps/test-snap-dialog.spec.js
@@ -77,7 +77,7 @@ describe('Test Snap Dialog', function () {
// click on alert dialog
await driver.clickElement('#sendAlertButton');
- await driver.delay(1000);
+ await driver.delay(500);
// switch to dialog popup
windowHandles = await driver.waitUntilXWindowHandles(3, 1000, 10000);
@@ -85,12 +85,12 @@ describe('Test Snap Dialog', function () {
'MetaMask Notification',
windowHandles,
);
- await driver.delay(1000);
+ await driver.delay(500);
// check dialog contents
let result = await driver.findElement('.snap-ui-renderer__panel');
await driver.scrollToElement(result);
- await driver.delay(1000);
+ await driver.delay(500);
assert.equal(await result.getText(), 'Alert Dialog\nText here');
// click ok button
@@ -105,12 +105,12 @@ describe('Test Snap Dialog', function () {
// check result is null
result = await driver.findElement('#dialogResult');
- await driver.delay(1000);
+ await driver.delay(500);
assert.equal(await result.getText(), 'null');
// click conf button
await driver.clickElement('#sendConfButton');
- await driver.delay(1000);
+ await driver.delay(500);
// switch to dialog popup
windowHandles = await driver.waitUntilXWindowHandles(3, 1000, 10000);
@@ -118,7 +118,7 @@ describe('Test Snap Dialog', function () {
'MetaMask Notification',
windowHandles,
);
- await driver.delay(1000);
+ await driver.delay(500);
// click reject
await driver.clickElement({
@@ -132,12 +132,12 @@ describe('Test Snap Dialog', function () {
// check for false result
result = await driver.findElement('#dialogResult');
- await driver.delay(1000);
+ await driver.delay(500);
assert.equal(await result.getText(), 'false');
// click conf button again
await driver.clickElement('#sendConfButton');
- await driver.delay(1000);
+ await driver.delay(500);
// switch to dialog popup
windowHandles = await driver.waitUntilXWindowHandles(3, 1000, 10000);
@@ -145,7 +145,7 @@ describe('Test Snap Dialog', function () {
'MetaMask Notification',
windowHandles,
);
- await driver.delay(1000);
+ await driver.delay(500);
// click accept
await driver.clickElement({
@@ -159,12 +159,12 @@ describe('Test Snap Dialog', function () {
// check for true result
result = await driver.findElement('#dialogResult');
- await driver.delay(1000);
+ await driver.delay(500);
assert.equal(await result.getText(), 'true');
// click prompt button
await driver.clickElement('#sendPromptButton');
- await driver.delay(1000);
+ await driver.delay(500);
// switch to dialog popup
windowHandles = await driver.waitUntilXWindowHandles(3, 1000, 10000);
@@ -172,7 +172,7 @@ describe('Test Snap Dialog', function () {
'MetaMask Notification',
windowHandles,
);
- await driver.delay(1000);
+ await driver.delay(500);
// click cancel button
await driver.clickElement({
@@ -186,12 +186,12 @@ describe('Test Snap Dialog', function () {
// check result is equal to 'null'
result = await driver.findElement('#dialogResult');
- await driver.delay(1000);
+ await driver.delay(500);
assert.equal(await result.getText(), 'null');
// click prompt button
await driver.clickElement('#sendPromptButton');
- await driver.delay(1000);
+ await driver.delay(500);
// switch to dialog popup
windowHandles = await driver.waitUntilXWindowHandles(3, 1000, 10000);
@@ -199,7 +199,7 @@ describe('Test Snap Dialog', function () {
'MetaMask Notification',
windowHandles,
);
- await driver.delay(1000);
+ await driver.delay(500);
// fill '2323' in form field
await driver.pasteIntoField('.MuiInput-input', '2323');
@@ -216,7 +216,6 @@ describe('Test Snap Dialog', function () {
// check result is equal to '2323'
result = await driver.findElement('#dialogResult');
- await driver.delay(1000);
assert.equal(await result.getText(), '"2323"');
},
);
diff --git a/test/e2e/snaps/test-snap-error.spec.js b/test/e2e/snaps/test-snap-error.spec.js
index a57f2241eaee..3e116c6e309c 100644
--- a/test/e2e/snaps/test-snap-error.spec.js
+++ b/test/e2e/snaps/test-snap-error.spec.js
@@ -81,7 +81,7 @@ describe('Test Snap Error', function () {
// switch back to the extension page
await driver.switchToWindow(extensionPage);
- await driver.delay(1000);
+ await driver.delay(500);
// look for the actual error and check if it is correct
const error = await driver.findElement(
diff --git a/test/e2e/snaps/test-snap-installed.spec.js b/test/e2e/snaps/test-snap-installed.spec.js
index c5adf1637888..d14852a52546 100644
--- a/test/e2e/snaps/test-snap-installed.spec.js
+++ b/test/e2e/snaps/test-snap-installed.spec.js
@@ -1,4 +1,3 @@
-const { strict: assert } = require('assert');
const { withFixtures } = require('../helpers');
const FixtureBuilder = require('../fixture-builder');
const { TEST_SNAPS_WEBSITE_URL } = require('./enums');
@@ -33,9 +32,9 @@ describe('Test Snap Installed', function () {
await driver.delay(1000);
const confirmButton = await driver.findElement('#connectDialogSnap');
await driver.scrollToElement(confirmButton);
- await driver.delay(1000);
+ await driver.delay(500);
await driver.clickElement('#connectDialogSnap');
- await driver.delay(1000);
+ await driver.delay(500);
// switch to metamask extension and click connect
let windowHandles = await driver.waitUntilXWindowHandles(
@@ -77,7 +76,7 @@ describe('Test Snap Installed', function () {
const errorButton = await driver.findElement('#connectErrorSnap');
await driver.scrollToElement(errorButton);
- await driver.delay(1000);
+ await driver.delay(500);
await driver.clickElement('#connectErrorSnap');
// switch to metamask extension and click connect
@@ -109,17 +108,9 @@ describe('Test Snap Installed', function () {
// wait for npm installation success
await driver.waitForSelector({
- css: '#connectErrorSnap',
- text: 'Reconnect to Error Snap',
+ css: '#installedSnapsResult',
+ text: 'npm:@metamask/test-snap-dialog, npm:@metamask/test-snap-error',
});
-
- const result = await driver.findElement('#installedSnapsResult');
- await driver.scrollToElement(result);
- await driver.delay(1000);
- assert.equal(
- await result.getText(),
- 'npm:@metamask/test-snap-dialog, npm:@metamask/test-snap-error',
- );
},
);
});
diff --git a/test/e2e/snaps/test-snap-notification.spec.js b/test/e2e/snaps/test-snap-notification.spec.js
index 26809c18d8fb..5113a327a0ac 100644
--- a/test/e2e/snaps/test-snap-notification.spec.js
+++ b/test/e2e/snaps/test-snap-notification.spec.js
@@ -82,7 +82,7 @@ describe('Test Snap Notification', function () {
// switch back to the extension page
await driver.switchToWindow(extensionPage);
- await driver.delay(1500);
+ await driver.delay(1000);
// check to see that there is one notification
const notificationResult = await driver.findElement(
@@ -92,14 +92,14 @@ describe('Test Snap Notification', function () {
// try to click on the account menu icon (via xpath)
await driver.clickElement('.account-menu__icon');
- await driver.delay(1000);
+ await driver.delay(500);
// try to click on the notification item (via xpath)
await driver.clickElement({
text: 'Notifications',
tag: 'div',
});
- await driver.delay(1000);
+ await driver.delay(500);
// look for the correct text in notifications (via xpath)
const notificationResultMessage = await driver.findElement(
diff --git a/test/e2e/snaps/test-snap-rpc.spec.js b/test/e2e/snaps/test-snap-rpc.spec.js
index 3c596ba08a98..3505a6c85d2f 100644
--- a/test/e2e/snaps/test-snap-rpc.spec.js
+++ b/test/e2e/snaps/test-snap-rpc.spec.js
@@ -1,4 +1,3 @@
-const { strict: assert } = require('assert');
const { withFixtures } = require('../helpers');
const FixtureBuilder = require('../fixture-builder');
const { TEST_SNAPS_WEBSITE_URL } = require('./enums');
@@ -62,7 +61,7 @@ describe('Test Snap RPC', function () {
});
// wait for permissions popover, click checkboxes and confirm
- await driver.delay(1000);
+ await driver.delay(500);
await driver.clickElement('#key-access-bip32-m-44h-0h-secp256k1-0');
await driver.clickElement('#key-access-bip32-m-44h-0h-ed25519-1');
await driver.clickElement(
@@ -127,14 +126,11 @@ describe('Test Snap RPC', function () {
await driver.delay(1000);
await driver.clickElement('#sendRpc');
- // delay for result creation
- await driver.delay(2500);
-
- const confirmResult = await driver.findElement('#rpcResult');
- assert.equal(
- await confirmResult.getText(),
- '"0x033e98d696ae15caef75fa8dd204a7c5c08d1272b2218ba3c20feeb4c691eec366"',
- );
+ // check result with waitForSelector
+ await driver.waitForSelector({
+ css: '#rpcResult',
+ text: '"0x033e98d696ae15caef75fa8dd204a7c5c08d1272b2218ba3c20feeb4c691eec366"',
+ });
},
);
});
diff --git a/test/e2e/snaps/test-snap-txinsights.spec.js b/test/e2e/snaps/test-snap-txinsights.spec.js
index b8fbe0063fcf..138e428976f4 100644
--- a/test/e2e/snaps/test-snap-txinsights.spec.js
+++ b/test/e2e/snaps/test-snap-txinsights.spec.js
@@ -100,7 +100,7 @@ describe('Test Snap TxInsights', function () {
'MetaMask Notification',
windowHandles,
);
- await driver.delay(2000);
+ await driver.delay(1000);
await driver.clickElement({
text: 'TxInsightsTest',
tag: 'button',
diff --git a/test/e2e/snaps/test-snap-update.spec.js b/test/e2e/snaps/test-snap-update.spec.js
index aff7214d47d8..ac80c18ffeba 100644
--- a/test/e2e/snaps/test-snap-update.spec.js
+++ b/test/e2e/snaps/test-snap-update.spec.js
@@ -1,4 +1,3 @@
-const { strict: assert } = require('assert');
const { withFixtures } = require('../helpers');
const FixtureBuilder = require('../fixture-builder');
const { TEST_SNAPS_WEBSITE_URL } = require('./enums');
@@ -37,7 +36,7 @@ describe('Test Snap update', function () {
await driver.scrollToElement(snapButton);
await driver.delay(1000);
await driver.clickElement('#connectUpdate');
- await driver.delay(2000);
+ await driver.delay(1000);
// switch to metamask extension and click connect
let windowHandles = await driver.waitUntilXWindowHandles(
@@ -62,7 +61,7 @@ describe('Test Snap update', function () {
});
// wait for permissions popover, click checkboxes and confirm
- await driver.delay(1000);
+ await driver.delay(500);
await driver.clickElement('#key-access-bip32-m-44h-0h-secp256k1-0');
await driver.clickElement('#key-access-bip32-m-44h-0h-ed25519-1');
await driver.clickElement(
@@ -96,11 +95,8 @@ describe('Test Snap update', function () {
await driver.clickElement('#connectUpdateNew');
await driver.delay(1000);
- // switch to metamask extension and click connect
+ // switch to metamask extension and update
await driver.waitUntilXWindowHandles(2, 1000, 10000);
- await driver.delay(1000);
-
- // approve update of snap
windowHandles = await driver.getAllWindowHandles();
await driver.switchToWindowWithTitle(
'MetaMask Notification',
@@ -125,9 +121,10 @@ describe('Test Snap update', function () {
await driver.switchToWindowWithTitle('Test Snaps', windowHandles);
// look for the correct version text
- const versionResult = await driver.findElement('#updateSnapVersion');
- await driver.delay(1000);
- assert.equal(await versionResult.getText(), '"5.1.2"');
+ await driver.waitForSelector({
+ css: '#updateSnapVersion',
+ text: '"5.1.2"',
+ });
},
);
});
diff --git a/test/e2e/tests/switch-custom-network.spec.js b/test/e2e/tests/switch-custom-network.spec.js
new file mode 100644
index 000000000000..9da4eedc1da1
--- /dev/null
+++ b/test/e2e/tests/switch-custom-network.spec.js
@@ -0,0 +1,102 @@
+const { strict: assert } = require('assert');
+const FixtureBuilder = require('../fixture-builder');
+const { convertToHexValue, withFixtures } = require('../helpers');
+
+describe('Swtich ethereum chain', function () {
+ const ganacheOptions = {
+ accounts: [
+ {
+ secretKey:
+ '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC',
+ balance: convertToHexValue(25000000000000000000),
+ },
+ ],
+ concurrent: { port: 8546, chainId: 1338, ganacheOptions2: {} },
+ };
+
+ it('should successfully change the network in response to wallet_switchEthereumChain', async function () {
+ await withFixtures(
+ {
+ dapp: true,
+ fixtures: new FixtureBuilder()
+ .withPermissionControllerConnectedToTestDapp()
+ .build(),
+ ganacheOptions,
+ title: this.test.title,
+ failOnConsoleError: false,
+ },
+ async ({ driver }) => {
+ await driver.navigate();
+ await driver.fill('#password', 'correct horse battery staple');
+ await driver.press('#password', driver.Key.ENTER);
+
+ const windowHandles = await driver.getAllWindowHandles();
+ const extension = windowHandles[0];
+
+ await driver.openNewPage('http://127.0.0.1:8080/');
+
+ await driver.clickElement({
+ tag: 'button',
+ text: 'Add Localhost 8546',
+ });
+
+ await driver.waitUntilXWindowHandles(3);
+
+ await driver.switchToWindowWithTitle(
+ 'MetaMask Notification',
+ windowHandles,
+ );
+
+ await driver.clickElement({
+ tag: 'button',
+ text: 'Approve',
+ });
+
+ await driver.findElement({
+ tag: 'h3',
+ text: 'Allow this site to switch the network?',
+ });
+
+ // Don't switch to network now, because we will click the 'Switch to Localhost 8546' button below
+ await driver.clickElement({
+ tag: 'button',
+ text: 'Cancel',
+ });
+
+ await driver.waitUntilXWindowHandles(2);
+
+ await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles);
+ await driver.clickElement({
+ tag: 'button',
+ text: 'Switch to Localhost 8546',
+ });
+
+ await driver.waitUntilXWindowHandles(3);
+
+ await driver.switchToWindowWithTitle(
+ 'MetaMask Notification',
+ windowHandles,
+ );
+
+ await driver.clickElement({
+ tag: 'button',
+ text: 'Switch network',
+ });
+
+ await driver.waitUntilXWindowHandles(2);
+
+ await driver.switchToWindow(extension);
+
+ const currentNetworkName = await driver.findElement({
+ tag: 'span',
+ text: 'Localhost 8546',
+ });
+
+ assert.ok(
+ Boolean(currentNetworkName),
+ 'Failed to switch to custom network',
+ );
+ },
+ );
+ });
+});
diff --git a/ui/components/app/app-components.scss b/ui/components/app/app-components.scss
index 196ab6c901ad..adb1ff1f6066 100644
--- a/ui/components/app/app-components.scss
+++ b/ui/components/app/app-components.scss
@@ -93,7 +93,7 @@
@import 'advanced-gas-fee-popover/advanced-gas-fee-input-subtext/index';
@import 'advanced-gas-fee-popover/advanced-gas-fee-defaults/index';
@import 'currency-input/index';
-@import 'asset-list/detetcted-tokens-link/index';
+@import 'asset-list/detected-tokens-link/index';
@import 'detected-token/detected-token-address/index';
@import 'detected-token/detected-token-aggregators/index';
@import 'detected-token/detected-token-values/index';
diff --git a/ui/components/app/asset-list/asset-list.js b/ui/components/app/asset-list/asset-list.js
index 5e305dcf9458..f4ca2f5a196e 100644
--- a/ui/components/app/asset-list/asset-list.js
+++ b/ui/components/app/asset-list/asset-list.js
@@ -35,7 +35,7 @@ import {
MultichainImportTokenLink,
} from '../../multichain';
import { Text } from '../../component-library';
-import DetectedTokensLink from './detetcted-tokens-link/detected-tokens-link';
+import DetectedTokensLink from './detected-tokens-link/detected-tokens-link';
const AssetList = ({ onClickAsset }) => {
const t = useI18nContext();
diff --git a/ui/components/app/asset-list/detetcted-tokens-link/detected-tokens-link.js b/ui/components/app/asset-list/detected-tokens-link/detected-tokens-link.js
similarity index 100%
rename from ui/components/app/asset-list/detetcted-tokens-link/detected-tokens-link.js
rename to ui/components/app/asset-list/detected-tokens-link/detected-tokens-link.js
diff --git a/ui/components/app/asset-list/detetcted-tokens-link/detected-tokens-link.stories.js b/ui/components/app/asset-list/detected-tokens-link/detected-tokens-link.stories.js
similarity index 100%
rename from ui/components/app/asset-list/detetcted-tokens-link/detected-tokens-link.stories.js
rename to ui/components/app/asset-list/detected-tokens-link/detected-tokens-link.stories.js
diff --git a/ui/components/app/asset-list/detetcted-tokens-link/detected-tokens-link.test.js b/ui/components/app/asset-list/detected-tokens-link/detected-tokens-link.test.js
similarity index 100%
rename from ui/components/app/asset-list/detetcted-tokens-link/detected-tokens-link.test.js
rename to ui/components/app/asset-list/detected-tokens-link/detected-tokens-link.test.js
diff --git a/ui/components/app/asset-list/detetcted-tokens-link/index.scss b/ui/components/app/asset-list/detected-tokens-link/index.scss
similarity index 100%
rename from ui/components/app/asset-list/detetcted-tokens-link/index.scss
rename to ui/components/app/asset-list/detected-tokens-link/index.scss
diff --git a/ui/components/app/custom-spending-cap/custom-spending-cap.js b/ui/components/app/custom-spending-cap/custom-spending-cap.js
index 0271403bbb22..12f1ddce431b 100644
--- a/ui/components/app/custom-spending-cap/custom-spending-cap.js
+++ b/ui/components/app/custom-spending-cap/custom-spending-cap.js
@@ -6,16 +6,14 @@ import BigNumber from 'bignumber.js';
import { I18nContext } from '../../../contexts/i18n';
import Box from '../../ui/box';
import FormField from '../../ui/form-field';
-import Typography from '../../ui/typography';
+import { Text, ButtonLink } from '../../component-library';
import { Icon, ICON_NAMES } from '../../component-library/icon/deprecated';
-import { ButtonLink } from '../../component-library';
import {
AlignItems,
DISPLAY,
FLEX_DIRECTION,
TEXT_ALIGN,
- FONT_WEIGHT,
- TypographyVariant,
+ TextVariant,
JustifyContent,
Size,
BLOCK_SIZES,
@@ -72,14 +70,14 @@ export default function CustomSpendingCap({
return {
className: 'custom-spending-cap__lowerValue',
description: t('inputLogicEqualOrSmallerNumber', [
-