diff --git a/.circleci/config.yml b/.circleci/config.yml
index e25e89fa5..68a1c199a 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 e5c86c47b..c63d2a78d 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 4c56dcf01..3695fede5 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 cd00fe2c9..4766b0221 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 d7d56a93b..39e7a9573 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 bbdd98c4a..af623de01 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 f976670c9..ec81fdc4f 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 c4f6316a2..30823b2d1 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 e770df626..2ac044508 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 ef63aba70..c82644e4b 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 c32d55258..a9544c378 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 bad7ed48f..8c560db82 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 8eea14401..f8747ac19 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 9fb967075..96038a220 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 dcfabd1d9..10dde0e64 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 0bce662da..9eee48c84 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 21e237c3a..000000000
--- 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 5abde4485..000000000
--- 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 45e128b12..000000000
--- 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 37c06025b..000000000
--- 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 bf09f39b7..000000000
--- 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 4f3d182c9..000000000
--- 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 000000000..cb97c42fd
--- /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 0f61d9888..450c59597 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 9e7f65d0d..d92fddb81 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 eed68abae..cbc87aef7 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 935b9ec60..81c6887e0 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 4bcffe953..37c1c111a 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)
@@ -2671,10 +2683,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();
@@ -2699,7 +2709,7 @@ export default class MetamaskController extends EventEmitter {
}
async clearLoginArtifacts() {
- await browser.storage.session.remove(['loginToken', 'loginSalt']);
+ await this.extension.storage.session.remove(['loginToken', 'loginSalt']);
}
/**
@@ -4117,7 +4127,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 826e0236c..af2e5c62f 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('should not reset states if already set', function () {
- // global.isFirstTime should also remain false
- assert.equal(globalThis.isFirstTimeProfileLoaded, false);
+ 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('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/coverage-targets.js b/coverage-targets.js
index 6157a706d..6097331d1 100644
--- a/coverage-targets.js
+++ b/coverage-targets.js
@@ -6,10 +6,10 @@
// subset of files to check against these targets.
module.exports = {
global: {
- lines: 65.5,
- branches: 53.5,
- statements: 64.75,
- functions: 58,
+ lines: 66,
+ branches: 54.4,
+ statements: 65,
+ functions: 58.5,
},
transforms: {
branches: 100,
diff --git a/development/build/index.js b/development/build/index.js
index 9c9f75f16..a82d9bbd3 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 58817372e..e95690868 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 9dabcb169..e8581ffcb 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 dd174c63d..7d359e522 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 fa9312ae5..8fc8f7bcd 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 fa9312ae5..8fc8f7bcd 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 dd174c63d..7d359e522 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 6dc22b4da..2b1815983 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 f1a5ff738..10c24bbfe 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 5e3695a05..3ded4081b 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 2babba866..b477fade4 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 126ad5e5b..cbee5ff15 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 031d14271..f2b51321b 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 a57f2241e..3e116c6e3 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 c5adf1637..d14852a52 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 26809c18d..5113a327a 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 3c596ba08..3505a6c85 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 b8fbe0063..138e42897 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 aff7214d4..ac80c18ff 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 000000000..9da4eedc1
--- /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 aa0e9af93..bf93877b3 100644
--- a/ui/components/app/app-components.scss
+++ b/ui/components/app/app-components.scss
@@ -92,7 +92,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 a8f8f8c38..b6d6f1ae5 100644
--- a/ui/components/app/asset-list/asset-list.js
+++ b/ui/components/app/asset-list/asset-list.js
@@ -30,7 +30,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 0271403bb..12f1ddce4 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', [
-
Plain text