diff --git a/.nvmrc b/.nvmrc index 9a2a0e219c9b..94cb37d604f2 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v20 +v20.14 diff --git a/app/_locales/am/messages.json b/app/_locales/am/messages.json index a4a0dc58e868..cb193bc11c36 100644 --- a/app/_locales/am/messages.json +++ b/app/_locales/am/messages.json @@ -69,9 +69,6 @@ "asset": { "message": "ሐብት" }, - "attemptingConnect": { - "message": "ከ blockchain ጋር ለመገናኘት መሞከር።" - }, "attributions": { "message": "አይነታ" }, diff --git a/app/_locales/ar/messages.json b/app/_locales/ar/messages.json index bc33690c7945..e262cebf3537 100644 --- a/app/_locales/ar/messages.json +++ b/app/_locales/ar/messages.json @@ -79,9 +79,6 @@ "asset": { "message": "الأصل" }, - "attemptingConnect": { - "message": "محاولة الاتصال بسلسلة الكتل." - }, "attributions": { "message": "الصفات" }, diff --git a/app/_locales/bg/messages.json b/app/_locales/bg/messages.json index cfe0f8de68a3..2169f13ecf9d 100644 --- a/app/_locales/bg/messages.json +++ b/app/_locales/bg/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Актив" }, - "attemptingConnect": { - "message": "Опит за свързване с blockchain." - }, "attributions": { "message": "Функции" }, diff --git a/app/_locales/bn/messages.json b/app/_locales/bn/messages.json index 592a9a593f28..29e06173be17 100644 --- a/app/_locales/bn/messages.json +++ b/app/_locales/bn/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "সম্পদ" }, - "attemptingConnect": { - "message": "ব্লকচেনে সংযোগ করার চেষ্টা করছে।" - }, "attributions": { "message": "গুণাবলী" }, diff --git a/app/_locales/ca/messages.json b/app/_locales/ca/messages.json index 93555423be6d..4393ea21f108 100644 --- a/app/_locales/ca/messages.json +++ b/app/_locales/ca/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Actius" }, - "attemptingConnect": { - "message": "Intentant conectar a blockchain." - }, "attributions": { "message": "Atribucions" }, diff --git a/app/_locales/cs/messages.json b/app/_locales/cs/messages.json index fc050b199d2d..f67d21b5cb52 100644 --- a/app/_locales/cs/messages.json +++ b/app/_locales/cs/messages.json @@ -39,9 +39,6 @@ "approved": { "message": "Schváleno" }, - "attemptingConnect": { - "message": "Pokouším se připojit k blockchainu." - }, "attributions": { "message": "Zásluhy" }, diff --git a/app/_locales/da/messages.json b/app/_locales/da/messages.json index 9d89b573a536..f5d7c9c89c3e 100644 --- a/app/_locales/da/messages.json +++ b/app/_locales/da/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Aktiv" }, - "attemptingConnect": { - "message": "Forsøger at oprette forbindelse til blokkæden." - }, "attributions": { "message": "Tilskrivninger" }, diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index 731a805b1f2a..2500ff05f254 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -524,9 +524,6 @@ "attemptToCancelSwapForFree": { "message": "Versuch, den Swap kostenlos zu stornieren" }, - "attemptingConnect": { - "message": "Versuch einer Verbindung zur Blockchain." - }, "attributions": { "message": "Zuschreibungen" }, diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json index cfbe0bd874dd..bff686407193 100644 --- a/app/_locales/el/messages.json +++ b/app/_locales/el/messages.json @@ -524,9 +524,6 @@ "attemptToCancelSwapForFree": { "message": "Προσπάθεια ακύρωσης των ανταλλαγών δωρεάν" }, - "attemptingConnect": { - "message": "Προσπάθεια σύνδεσης στο blockchain." - }, "attributions": { "message": "Αποδόσεις" }, diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 39bc6aa95c8f..d59f9d572f6c 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -620,9 +620,6 @@ "attemptToCancelSwapForFree": { "message": "Attempt to cancel swap for free" }, - "attemptingConnect": { - "message": "Attempting to connect to blockchain." - }, "attributions": { "message": "Attributions" }, @@ -6182,6 +6179,12 @@ "updatedWithDate": { "message": "Updated $1" }, + "uploadDropFile": { + "message": "Drop your file here" + }, + "uploadFile": { + "message": "Upload file" + }, "urlErrorMsg": { "message": "URLs require the appropriate HTTP/HTTPS prefix." }, diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index f49efdbc7218..6a70bf40e68f 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -524,9 +524,6 @@ "attemptToCancelSwapForFree": { "message": "Intente cancelar el intercambio de forma gratuita" }, - "attemptingConnect": { - "message": "Intentando una conexión a la cadena de bloques." - }, "attributions": { "message": "Atribuciones" }, diff --git a/app/_locales/es_419/messages.json b/app/_locales/es_419/messages.json index b2f763ced384..662a7f3ede27 100644 --- a/app/_locales/es_419/messages.json +++ b/app/_locales/es_419/messages.json @@ -214,9 +214,6 @@ "assetOptions": { "message": "Opciones de activos" }, - "attemptingConnect": { - "message": "Intentando una conexión a la cadena de bloques." - }, "attributions": { "message": "Atribuciones" }, diff --git a/app/_locales/et/messages.json b/app/_locales/et/messages.json index cba62eb1d7d9..dbfe1f88fb55 100644 --- a/app/_locales/et/messages.json +++ b/app/_locales/et/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Vara" }, - "attemptingConnect": { - "message": "Plokiahelaga ühenduse loomise katse." - }, "attributions": { "message": "Omistamised" }, diff --git a/app/_locales/fa/messages.json b/app/_locales/fa/messages.json index 3f2e3a703f01..9f1d89793c1b 100644 --- a/app/_locales/fa/messages.json +++ b/app/_locales/fa/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "سرمایه" }, - "attemptingConnect": { - "message": "در حال تلاش برای اتصال با زنجیره بلوکی" - }, "attributions": { "message": "مواصفات" }, diff --git a/app/_locales/fi/messages.json b/app/_locales/fi/messages.json index a907aeedbd9e..4f193797912c 100644 --- a/app/_locales/fi/messages.json +++ b/app/_locales/fi/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Omaisuuserä" }, - "attemptingConnect": { - "message": "Yritetään yhdistää lohkoketjuun." - }, "attributions": { "message": "Attribuutiot" }, diff --git a/app/_locales/fil/messages.json b/app/_locales/fil/messages.json index 040a687f7633..ab098442e52e 100644 --- a/app/_locales/fil/messages.json +++ b/app/_locales/fil/messages.json @@ -66,9 +66,6 @@ "approved": { "message": "Inaprubahan" }, - "attemptingConnect": { - "message": "Sinusubukang kumonekta sa blockchain." - }, "attributions": { "message": "Mga Attribution" }, diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index c44d687aeaf6..0cd50d4788f8 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -524,9 +524,6 @@ "attemptToCancelSwapForFree": { "message": "Tentative d’annuler gratuitement le swap" }, - "attemptingConnect": { - "message": "Tentative de connexion au réseau" - }, "attributions": { "message": "Attributions" }, diff --git a/app/_locales/he/messages.json b/app/_locales/he/messages.json index 22f5ac53511e..e29f44c9f834 100644 --- a/app/_locales/he/messages.json +++ b/app/_locales/he/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "נכס" }, - "attemptingConnect": { - "message": "מנסה להתחבר לבלוקצ'יין." - }, "attributions": { "message": "תכונות" }, diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index 7ebd3e958736..5f83ad80bfdf 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -524,9 +524,6 @@ "attemptToCancelSwapForFree": { "message": "स्वैप को मुफ्त में कैंसिल करने की कोशिश करें" }, - "attemptingConnect": { - "message": "ब्लॉकचेन से कनेक्ट करने की कोशिश कर रहे हैं।" - }, "attributions": { "message": "एट्रीब्यूशन्स" }, diff --git a/app/_locales/hn/messages.json b/app/_locales/hn/messages.json index 8dc338db6dc1..03c87498c87f 100644 --- a/app/_locales/hn/messages.json +++ b/app/_locales/hn/messages.json @@ -33,9 +33,6 @@ "approve": { "message": "मंजूर" }, - "attemptingConnect": { - "message": "ब्लॉकचैन से कनेक्ट करने का प्रयास करना होगा।सब्र करे।" - }, "attributions": { "message": "एट्रिब्यूशन" }, diff --git a/app/_locales/hr/messages.json b/app/_locales/hr/messages.json index 3d259868534a..d7e62da80ba4 100644 --- a/app/_locales/hr/messages.json +++ b/app/_locales/hr/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Imovina" }, - "attemptingConnect": { - "message": "Pokušaj povezivanja na podatkovni blok." - }, "attributions": { "message": "Svojstva" }, diff --git a/app/_locales/ht/messages.json b/app/_locales/ht/messages.json index 94bad1913fe6..02f06746a58a 100644 --- a/app/_locales/ht/messages.json +++ b/app/_locales/ht/messages.json @@ -60,9 +60,6 @@ "approved": { "message": "Apwouve" }, - "attemptingConnect": { - "message": "Eseye konekte nan blockchain." - }, "attributions": { "message": "Atribisyon" }, diff --git a/app/_locales/hu/messages.json b/app/_locales/hu/messages.json index 21d413aa64a3..456b63710dd6 100644 --- a/app/_locales/hu/messages.json +++ b/app/_locales/hu/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Eszköz" }, - "attemptingConnect": { - "message": "Próbálunk csatlakozni a blokklánchoz." - }, "attributions": { "message": "Attribúciók" }, diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index 45bc8912c676..45073d2af42b 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -524,9 +524,6 @@ "attemptToCancelSwapForFree": { "message": "Mencoba membatalkan pertukaran secara gratis" }, - "attemptingConnect": { - "message": "Mencoba terhubung ke blockchain." - }, "attributions": { "message": "Atribusi" }, diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index 6a43d90d1624..2ca832f39006 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -297,9 +297,6 @@ "attemptSendingAssets": { "message": "Se si tenta di inviare risorse direttamente da una rete all'altra, ciò potrebbe comportare una perdita permanente della risorca coinvolta. Assicurati di usare un bridge." }, - "attemptingConnect": { - "message": "Tentativo di connessione alla blockchain." - }, "attributions": { "message": "Attribuzioni" }, diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index 4ca1b2faaf7f..ad69880ffd8e 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -524,9 +524,6 @@ "attemptToCancelSwapForFree": { "message": "無料でスワップのキャンセルを試行" }, - "attemptingConnect": { - "message": "ブロックチェーンへの接続を試みています。" - }, "attributions": { "message": "属性" }, diff --git a/app/_locales/kn/messages.json b/app/_locales/kn/messages.json index 0e44c06e69ce..0b0479e3dddf 100644 --- a/app/_locales/kn/messages.json +++ b/app/_locales/kn/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "ಆಸ್ತಿ" }, - "attemptingConnect": { - "message": "ಬ್ಲಾಕ್‌ಚೈನ್‌ಗೆ ಸಂಪರ್ಕಿಸಲು ಪ್ರಯತ್ನಿಸಲಾಗುತ್ತಿದೆ." - }, "attributions": { "message": "ಗುಣಲಕ್ಷಣಗಳು" }, diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index af94a9026392..9121a9b84281 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -524,9 +524,6 @@ "attemptToCancelSwapForFree": { "message": "무료 스왑 취소 시도" }, - "attemptingConnect": { - "message": "블록체인에 연결 중입니다." - }, "attributions": { "message": "속성" }, diff --git a/app/_locales/lt/messages.json b/app/_locales/lt/messages.json index 893d0a345fd5..0600ea96f32b 100644 --- a/app/_locales/lt/messages.json +++ b/app/_locales/lt/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Turtas" }, - "attemptingConnect": { - "message": "Mėginama prisijungti prie „blockchain“." - }, "attributions": { "message": "Požymiai" }, diff --git a/app/_locales/lv/messages.json b/app/_locales/lv/messages.json index bf058e6bb2fe..c0dfc6d573b8 100644 --- a/app/_locales/lv/messages.json +++ b/app/_locales/lv/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Aktīvs" }, - "attemptingConnect": { - "message": "Mēģina izveidot savienojumu ar bloku ķēdi." - }, "attributions": { "message": "Atribūti" }, diff --git a/app/_locales/ms/messages.json b/app/_locales/ms/messages.json index 61e4c37cae7a..b8a0cb2ac507 100644 --- a/app/_locales/ms/messages.json +++ b/app/_locales/ms/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Aset" }, - "attemptingConnect": { - "message": "Sedang cuba menyambungkan kepada rantaian blok." - }, "attributions": { "message": "Atribusi" }, diff --git a/app/_locales/nl/messages.json b/app/_locales/nl/messages.json index fc847537e00b..f3ae82f80616 100644 --- a/app/_locales/nl/messages.json +++ b/app/_locales/nl/messages.json @@ -33,9 +33,6 @@ "approve": { "message": "Goedkeuren" }, - "attemptingConnect": { - "message": "Poging om verbinding te maken met blockchain." - }, "attributions": { "message": "Bevoegdheden" }, diff --git a/app/_locales/no/messages.json b/app/_locales/no/messages.json index c2825ea5bfe7..56c05ffd958c 100644 --- a/app/_locales/no/messages.json +++ b/app/_locales/no/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Ressurs" }, - "attemptingConnect": { - "message": "Prøver å opprette forbindelse med blokkjede" - }, "attributions": { "message": "Henvisninger" }, diff --git a/app/_locales/ph/messages.json b/app/_locales/ph/messages.json index 3d3b2428bac3..fbace0f2117f 100644 --- a/app/_locales/ph/messages.json +++ b/app/_locales/ph/messages.json @@ -134,9 +134,6 @@ "assetOptions": { "message": "Mga opsyon sa asset" }, - "attemptingConnect": { - "message": "Sinusubukang kumonekta sa blockchain." - }, "attributions": { "message": "Mga Attribution" }, diff --git a/app/_locales/pl/messages.json b/app/_locales/pl/messages.json index a49b7bd23b16..dbc986a194e4 100644 --- a/app/_locales/pl/messages.json +++ b/app/_locales/pl/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Składnik aktywów" }, - "attemptingConnect": { - "message": "Próba połączenia z blockchainem." - }, "attributions": { "message": "Atrybuty" }, diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json index fe80de66b981..e83e1b6d4eea 100644 --- a/app/_locales/pt/messages.json +++ b/app/_locales/pt/messages.json @@ -524,9 +524,6 @@ "attemptToCancelSwapForFree": { "message": "Tentar cancelar a troca sem custo" }, - "attemptingConnect": { - "message": "Tentando conexão com a blockchain." - }, "attributions": { "message": "Atribuições" }, diff --git a/app/_locales/pt_BR/messages.json b/app/_locales/pt_BR/messages.json index cc4c97e70ff6..688f5758ac26 100644 --- a/app/_locales/pt_BR/messages.json +++ b/app/_locales/pt_BR/messages.json @@ -214,9 +214,6 @@ "assetOptions": { "message": "Opções do ativo" }, - "attemptingConnect": { - "message": "Tentando conexão com o blockchain." - }, "attributions": { "message": "Atribuições" }, diff --git a/app/_locales/ro/messages.json b/app/_locales/ro/messages.json index fa02911ca8f3..a7f916825e57 100644 --- a/app/_locales/ro/messages.json +++ b/app/_locales/ro/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Activ" }, - "attemptingConnect": { - "message": "Se încearcă conectarea la blockchain." - }, "attributions": { "message": "Atribuții" }, diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index 3106cf4540f4..cb41df257fe1 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -524,9 +524,6 @@ "attemptToCancelSwapForFree": { "message": "Бесплатная попытка отменить своп" }, - "attemptingConnect": { - "message": "Попытка подключения к блокчейну..." - }, "attributions": { "message": "Атрибуции" }, diff --git a/app/_locales/sk/messages.json b/app/_locales/sk/messages.json index a136cc940f79..79a185cf896c 100644 --- a/app/_locales/sk/messages.json +++ b/app/_locales/sk/messages.json @@ -72,9 +72,6 @@ "approved": { "message": "Schváleno" }, - "attemptingConnect": { - "message": "Pokouším se připojit k blockchainu." - }, "attributions": { "message": "Zásluhy" }, diff --git a/app/_locales/sl/messages.json b/app/_locales/sl/messages.json index bfc2a7d8b1d1..64e7c5662c3c 100644 --- a/app/_locales/sl/messages.json +++ b/app/_locales/sl/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Sredstva" }, - "attemptingConnect": { - "message": "Povezovanje z verigo blokov ..." - }, "attributions": { "message": "Dodelitve" }, diff --git a/app/_locales/sr/messages.json b/app/_locales/sr/messages.json index eaf957f685d7..1741b7567833 100644 --- a/app/_locales/sr/messages.json +++ b/app/_locales/sr/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Sredstva" }, - "attemptingConnect": { - "message": "Pokušava da se poveže na lanac blokova" - }, "attributions": { "message": "Atribucije" }, diff --git a/app/_locales/sv/messages.json b/app/_locales/sv/messages.json index 2f130ff20383..df3766108437 100644 --- a/app/_locales/sv/messages.json +++ b/app/_locales/sv/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Tillgång" }, - "attemptingConnect": { - "message": "Försöker ansluta till blockkedja." - }, "attributions": { "message": "Tillskrivningar" }, diff --git a/app/_locales/sw/messages.json b/app/_locales/sw/messages.json index 652a45bdcf27..7eb535bee573 100644 --- a/app/_locales/sw/messages.json +++ b/app/_locales/sw/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Rasilimali" }, - "attemptingConnect": { - "message": "Inajaribu kuunganisha kwenye blockchain." - }, "attributions": { "message": "Sifa" }, diff --git a/app/_locales/ta/messages.json b/app/_locales/ta/messages.json index d1277cdb0e52..f9c7274ac55c 100644 --- a/app/_locales/ta/messages.json +++ b/app/_locales/ta/messages.json @@ -45,9 +45,6 @@ "approved": { "message": "அங்கீகரிக்கப்பட்ட" }, - "attemptingConnect": { - "message": "இணைக்க முயற்சி செய்க ப்ளாக்சைன்" - }, "attributions": { "message": "பண்புகளும்" }, diff --git a/app/_locales/th/messages.json b/app/_locales/th/messages.json index 05f4970d383a..0b2dbb8664aa 100644 --- a/app/_locales/th/messages.json +++ b/app/_locales/th/messages.json @@ -39,9 +39,6 @@ "approve": { "message": "อนุมัติ" }, - "attemptingConnect": { - "message": "กำลังเชื่อมต่อกับบล็อกเชน" - }, "attributions": { "message": "อ้างถึง" }, diff --git a/app/_locales/tl/messages.json b/app/_locales/tl/messages.json index 4a570071faa5..cbd81acfcbc6 100644 --- a/app/_locales/tl/messages.json +++ b/app/_locales/tl/messages.json @@ -524,9 +524,6 @@ "attemptToCancelSwapForFree": { "message": "Subukang kanselahin ang swap nang libre" }, - "attemptingConnect": { - "message": "Sinusubukang kumonekta sa blockchain." - }, "attributions": { "message": "Mga Attribution" }, diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json index 51aafd650946..13887164bfd1 100644 --- a/app/_locales/tr/messages.json +++ b/app/_locales/tr/messages.json @@ -524,9 +524,6 @@ "attemptToCancelSwapForFree": { "message": "Swap işlemini ücretsiz iptal etme girişimi" }, - "attemptingConnect": { - "message": "Blockzincirine bağlanmaya çalışılıyor." - }, "attributions": { "message": "Özellikler" }, diff --git a/app/_locales/uk/messages.json b/app/_locales/uk/messages.json index cadac70b7102..59bb0b477008 100644 --- a/app/_locales/uk/messages.json +++ b/app/_locales/uk/messages.json @@ -75,9 +75,6 @@ "asset": { "message": "Актив" }, - "attemptingConnect": { - "message": "Спроба підключення до розподіленої бази даних." - }, "attributions": { "message": "Авторство" }, diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index 6f2cba66d83b..3afd6bf2403e 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -524,9 +524,6 @@ "attemptToCancelSwapForFree": { "message": "Cố gắng hủy hoán đổi miễn phí" }, - "attemptingConnect": { - "message": "Đang cố gắng kết nối với chuỗi khối." - }, "attributions": { "message": "Ghi nhận đóng góp" }, diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index ca5b01c48545..6cdb6aaf1e3f 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -524,9 +524,6 @@ "attemptToCancelSwapForFree": { "message": "尝试免费取消兑换" }, - "attemptingConnect": { - "message": "正在尝试连接到区块链。" - }, "attributions": { "message": "参与者" }, diff --git a/app/_locales/zh_TW/messages.json b/app/_locales/zh_TW/messages.json index 26f086433a96..d91d749ccffa 100644 --- a/app/_locales/zh_TW/messages.json +++ b/app/_locales/zh_TW/messages.json @@ -130,9 +130,6 @@ "assetOptions": { "message": "資產選項" }, - "attemptingConnect": { - "message": "正在嘗試連結區塊鏈。" - }, "attributions": { "message": "來源" }, diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index dd7350281085..1a511523778f 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -43,7 +43,7 @@ export default class AppStateController extends EventEmitter { fullScreenGasPollTokens: [], recoveryPhraseReminderHasBeenShown: false, recoveryPhraseReminderLastShown: new Date().getTime(), - outdatedBrowserWarningLastShown: new Date().getTime(), + outdatedBrowserWarningLastShown: null, nftsDetectionNoticeDismissed: false, showTestnetMessageInDropdown: true, showBetaHeader: isBeta(), diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 771f164b7b4c..5509d804b6fd 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -61,9 +61,7 @@ export default class PreferencesController { useCurrencyRateCheck: true, useRequestQueue: true, openSeaEnabled: true, // todo set this to true - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) securityAlertsEnabled: true, - ///: END:ONLY_INCLUDE_IF ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) addSnapAccountEnabled: false, ///: END:ONLY_INCLUDE_IF @@ -276,7 +274,6 @@ export default class PreferencesController { }); } - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) /** * Setter for the `securityAlertsEnabled` property * @@ -287,7 +284,6 @@ export default class PreferencesController { securityAlertsEnabled, }); } - ///: END:ONLY_INCLUDE_IF ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) /** diff --git a/app/scripts/lib/createRPCMethodTrackingMiddleware.js b/app/scripts/lib/createRPCMethodTrackingMiddleware.js index 195f9c05fed5..1d7f42710cd6 100644 --- a/app/scripts/lib/createRPCMethodTrackingMiddleware.js +++ b/app/scripts/lib/createRPCMethodTrackingMiddleware.js @@ -11,18 +11,13 @@ import { parseTypedDataMessage } from '../../../shared/modules/transaction.utils import { BlockaidResultType, - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) BlockaidReason, - ///: END:ONLY_INCLUDE_IF } from '../../../shared/constants/security-provider'; - -///: BEGIN:ONLY_INCLUDE_IF(blockaid) import { EIP712_PRIMARY_TYPE_PERMIT, SIGNING_METHODS, } from '../../../shared/constants/transaction'; import { getBlockaidMetricsProps } from '../../../ui/helpers/utils/metrics'; -///: END:ONLY_INCLUDE_IF import { REDESIGN_APPROVAL_TYPES } from '../../../ui/pages/confirmations/utils/confirm'; import { getSnapAndHardwareInfoForMetrics } from './snap-keyring/metrics'; @@ -135,7 +130,6 @@ const TRANSFORM_PARAMS_MAP = { const rateLimitTimeoutsByMethod = {}; let globalRateLimitCount = 0; -///: BEGIN:ONLY_INCLUDE_IF(blockaid) /** * Returns a middleware that tracks inpage_provider usage using sampling for * each type of event except those that require user interaction, such as @@ -161,7 +155,6 @@ let globalRateLimitCount = 0; * tracked within the globalRateLimitTimeout time window. * @returns {Function} */ -///: END:ONLY_INCLUDE_IF export default function createRPCMethodTrackingMiddleware({ trackEvent, @@ -174,9 +167,7 @@ export default function createRPCMethodTrackingMiddleware({ getDeviceModel, isConfirmationRedesignEnabled, snapAndHardwareMessenger, - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) appStateController, - ///: END:ONLY_INCLUDE_IF }) { return async function rpcMethodTrackingMiddleware( /** @type {any} */ req, @@ -254,7 +245,6 @@ export default function createRPCMethodTrackingMiddleware({ data = req?.params?.[1]; } - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) if (req.securityAlertResponse?.providerRequestsCount) { Object.keys(req.securityAlertResponse.providerRequestsCount).forEach( (key) => { @@ -275,7 +265,7 @@ export default function createRPCMethodTrackingMiddleware({ eventProperties.security_alert_description = req.securityAlertResponse.description; } - ///: END:ONLY_INCLUDE_IF + const isConfirmationRedesign = isConfirmationRedesignEnabled() && REDESIGN_APPROVAL_TYPES.find( @@ -380,8 +370,6 @@ export default function createRPCMethodTrackingMiddleware({ } let blockaidMetricProps = {}; - - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) if (!isDisabledRPCMethod) { if (SIGNING_METHODS.includes(method)) { const securityAlertResponse = @@ -394,7 +382,6 @@ export default function createRPCMethodTrackingMiddleware({ }); } } - ///: END:ONLY_INCLUDE_IF const properties = { ...eventProperties, diff --git a/app/scripts/lib/transaction/metrics.test.ts b/app/scripts/lib/transaction/metrics.test.ts index 74d5aaa13ca0..3fed7842378b 100644 --- a/app/scripts/lib/transaction/metrics.test.ts +++ b/app/scripts/lib/transaction/metrics.test.ts @@ -19,12 +19,10 @@ import { MetaMetricsEventCategory, } from '../../../../shared/constants/metametrics'; import { TRANSACTION_ENVELOPE_TYPE_NAMES } from '../../../../shared/lib/transactions-controller-utils'; -///: BEGIN:ONLY_INCLUDE_IF(blockaid) import { BlockaidReason, BlockaidResultType, } from '../../../../shared/constants/security-provider'; -///: END:ONLY_INCLUDE_IF(blockaid) import { handleTransactionAdded, handleTransactionApproved, diff --git a/app/scripts/lib/transaction/metrics.ts b/app/scripts/lib/transaction/metrics.ts index ff8b937c3b4c..15713a72b62e 100644 --- a/app/scripts/lib/transaction/metrics.ts +++ b/app/scripts/lib/transaction/metrics.ts @@ -36,9 +36,7 @@ import { getSwapsTokensReceivedFromTxMeta, TRANSACTION_ENVELOPE_TYPE_NAMES, } from '../../../../shared/lib/transactions-controller-utils'; -///: BEGIN:ONLY_INCLUDE_IF(blockaid) import { getBlockaidMetricsProps } from '../../../../ui/helpers/utils/metrics'; -///: END:ONLY_INCLUDE_IF import { getSmartTransactionMetricsProperties } from '../../../../shared/modules/metametrics'; import { getSnapAndHardwareInfoForMetrics, @@ -968,7 +966,6 @@ async function buildEventFragmentProperties({ ); } - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any const blockaidProperties: any = getBlockaidMetricsProps(transactionMeta); @@ -976,7 +973,6 @@ async function buildEventFragmentProperties({ if (blockaidProperties?.ui_customizations?.length > 0) { uiCustomizations.push(...blockaidProperties.ui_customizations); } - ///: END:ONLY_INCLUDE_IF if (simulationFails) { uiCustomizations.push(MetaMetricsEventUiCustomization.GasEstimationFailed); @@ -1009,9 +1005,7 @@ async function buildEventFragmentProperties({ token_standard: tokenStandard, transaction_type: transactionType, transaction_speed_up: type === TransactionType.retry, - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) ...blockaidProperties, - ///: END:ONLY_INCLUDE_IF // ui_customizations must come after ...blockaidProperties ui_customizations: uiCustomizations.length > 0 ? uiCustomizations : null, ...smartTransactionMetricsProperties, diff --git a/app/scripts/lib/transaction/util.test.ts b/app/scripts/lib/transaction/util.test.ts index 782a27e87cb1..f8b07cc7b17c 100644 --- a/app/scripts/lib/transaction/util.test.ts +++ b/app/scripts/lib/transaction/util.test.ts @@ -95,10 +95,8 @@ describe('Transaction Utils', () => { let dappRequest: AddDappTransactionRequest; let transactionController: jest.Mocked; let userOperationController: jest.Mocked; - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) const validateRequestWithPPOMMock = jest.mocked(validateRequestWithPPOM); const generateSecurityAlertIdMock = jest.mocked(generateSecurityAlertId); - ///: END:ONLY_INCLUDE_IF beforeEach(() => { jest.resetAllMocks(); @@ -106,10 +104,8 @@ describe('Transaction Utils', () => { request = cloneDeep(TRANSACTION_REQUEST_MOCK); transactionController = createTransactionControllerMock(); userOperationController = createUserOperationControllerMock(); - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) // eslint-disable-next-line @typescript-eslint/no-explicit-any request.ppomController = {} as any; - ///: END:ONLY_INCLUDE_IF transactionController.addTransaction.mockResolvedValue({ result: Promise.resolve('testHash'), diff --git a/app/scripts/lib/transaction/util.ts b/app/scripts/lib/transaction/util.ts index adf24fea3ed3..d62ea2af02f3 100644 --- a/app/scripts/lib/transaction/util.ts +++ b/app/scripts/lib/transaction/util.ts @@ -11,7 +11,6 @@ import { } from '@metamask/user-operation-controller'; import type { Hex } from '@metamask/utils'; import { addHexPrefix } from 'ethereumjs-util'; -///: BEGIN:ONLY_INCLUDE_IF(blockaid) import { PPOMController } from '@metamask/ppom-validator'; import { @@ -25,7 +24,6 @@ import { SECURITY_PROVIDER_EXCLUDED_TRANSACTION_TYPES, SECURITY_PROVIDER_SUPPORTED_CHAIN_IDS, } from '../../../../shared/constants/security-provider'; -///: END:ONLY_INCLUDE_IF export type AddTransactionOptions = NonNullable< Parameters[1] @@ -66,10 +64,7 @@ export async function addDappTransaction( ): Promise { const { dappRequest } = request; const { id: actionId, method, origin } = dappRequest; - - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) const { securityAlertResponse } = dappRequest; - ///: END:ONLY_INCLUDE_IF const transactionOptions: AddTransactionOptions = { actionId, @@ -77,9 +72,7 @@ export async function addDappTransaction( origin, // This is the default behaviour but specified here for clarity requireApproval: true, - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) securityAlertResponse, - ///: END:ONLY_INCLUDE_IF }; const { waitForHash } = await addTransactionOrUserOperation({ @@ -223,7 +216,6 @@ function getTransactionByHash( } function validateSecurity(request: AddTransactionRequest) { - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) const { chainId, ppomController, @@ -290,5 +282,4 @@ function validateSecurity(request: AddTransactionRequest) { } catch (error) { handlePPOMError(error, 'Error validating JSON RPC using PPOM: '); } - ///: END:ONLY_INCLUDE_IF } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 8256b72c910c..ab5fbdefe179 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -102,10 +102,7 @@ import { CustodyController } from '@metamask-institutional/custody-controller'; import { TransactionUpdateController } from '@metamask-institutional/transaction-update'; ///: END:ONLY_INCLUDE_IF import { SignatureController } from '@metamask/signature-controller'; -///: BEGIN:ONLY_INCLUDE_IF(blockaid) import { PPOMController } from '@metamask/ppom-validator'; -///: END:ONLY_INCLUDE_IF - import { ApprovalType, ERC1155, @@ -241,11 +238,8 @@ import { keyringSnapPermissionsBuilder } from './lib/snap-keyring/keyring-snaps- import { SnapsNameProvider } from './lib/SnapsNameProvider'; import { AddressBookPetnamesBridge } from './lib/AddressBookPetnamesBridge'; import { AccountIdentitiesPetnamesBridge } from './lib/AccountIdentitiesPetnamesBridge'; - -///: BEGIN:ONLY_INCLUDE_IF(blockaid) import { createPPOMMiddleware } from './lib/ppom/ppom-middleware'; import * as PPOMModule from './lib/ppom/ppom'; -///: END:ONLY_INCLUDE_IF import { onMessageReceived, checkForMultipleVersionsRunning, @@ -298,9 +292,7 @@ import { unrestrictedMethods, } from './controllers/permissions'; import createRPCMethodTrackingMiddleware from './lib/createRPCMethodTrackingMiddleware'; -///: BEGIN:ONLY_INCLUDE_IF(blockaid) import { IndexedDBPPOMStorage } from './lib/ppom/indexed-db-backend'; -///: END:ONLY_INCLUDE_IF import { updateCurrentLocale } from './translate'; import { TrezorOffscreenBridge } from './lib/offscreen-bridge/trezor-offscreen-bridge'; import { LedgerOffscreenBridge } from './lib/offscreen-bridge/ledger-offscreen-bridge'; @@ -865,7 +857,6 @@ export default class MetamaskController extends EventEmitter { stalelistRefreshInterval: process.env.IN_TEST ? 30 * SECOND : undefined, }); - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) this.ppomController = new PPOMController({ messenger: this.controllerMessenger.getRestricted({ name: 'PPOMController', @@ -884,7 +875,6 @@ export default class MetamaskController extends EventEmitter { cdnBaseUrl: process.env.BLOCKAID_FILE_CDN, blockaidPublicKey: process.env.BLOCKAID_PUBLIC_KEY, }); - ///: END:ONLY_INCLUDE_IF const announcementMessenger = this.controllerMessenger.getRestricted({ name: 'AnnouncementController', @@ -2176,9 +2166,7 @@ export default class MetamaskController extends EventEmitter { SwapsController: this.swapsController.store, EnsController: this.ensController, ApprovalController: this.approvalController, - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) PPOMController: this.ppomController, - ///: END:ONLY_INCLUDE_IF }; this.store.updateStructure({ @@ -2221,9 +2209,7 @@ export default class MetamaskController extends EventEmitter { this.institutionalFeaturesController.store, MmiConfigurationController: this.mmiConfigurationController.store, ///: END:ONLY_INCLUDE_IF - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) PPOMController: this.ppomController, - ///: END:ONLY_INCLUDE_IF NameController: this.nameController, UserOperationController: this.userOperationController, // Notification Controllers @@ -3060,13 +3046,10 @@ export default class MetamaskController extends EventEmitter { this.preferencesController, ), getProviderConfig: () => this.networkController.state.providerConfig, - - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) setSecurityAlertsEnabled: preferencesController.setSecurityAlertsEnabled.bind( preferencesController, ), - ///: END:ONLY_INCLUDE_IF ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) setAddSnapAccountEnabled: preferencesController.setAddSnapAccountEnabled.bind( @@ -4648,13 +4631,11 @@ export default class MetamaskController extends EventEmitter { transactionOptions, transactionParams, userOperationController: this.userOperationController, - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) chainId: this.networkController.state.providerConfig.chainId, ppomController: this.ppomController, securityAlertsEnabled: this.preferencesController.store.getState()?.securityAlertsEnabled, updateSecurityAlertResponse: this.updateSecurityAlertResponse.bind(this), - ///: END:ONLY_INCLUDE_IF }; } @@ -5137,7 +5118,6 @@ export default class MetamaskController extends EventEmitter { engine.push(createTxVerificationMiddleware(this.networkController)); } - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) engine.push( createPPOMMiddleware( this.ppomController, @@ -5147,7 +5127,6 @@ export default class MetamaskController extends EventEmitter { this.updateSecurityAlertResponse.bind(this), ), ); - ///: END:ONLY_INCLUDE_IF const isConfirmationRedesignEnabled = () => { return this.preferencesController.store.getState().preferences @@ -5173,9 +5152,7 @@ export default class MetamaskController extends EventEmitter { 'AccountsController:getSelectedAccount', ], }), - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) appStateController: this.appStateController, - ///: END:ONLY_INCLUDE_IF }), ); diff --git a/builds.yml b/builds.yml index af64cfb8d0ef..35fa7341aa44 100644 --- a/builds.yml +++ b/builds.yml @@ -17,7 +17,6 @@ buildTypes: features: - build-main - keyring-snaps - - blockaid # Additional env variables that are specific to this build env: - INFURA_PROD_PROJECT_ID @@ -26,7 +25,7 @@ buildTypes: - SEGMENT_WRITE_KEY_REF: SEGMENT_PROD_WRITE_KEY - ALLOW_LOCAL_SNAPS: false - REQUIRE_SNAPS_ALLOWLIST: true - - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/iframe/6.4.0/index.html + - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/iframe/6.5.0/index.html - ACCOUNT_SNAPS_DIRECTORY_URL: https://snaps.metamask.io/account-management - BTC_BETA_SUPPORT: false # Main build uses the default browser manifest @@ -39,7 +38,6 @@ buildTypes: features: - build-beta - keyring-snaps - - blockaid env: - INFURA_BETA_PROJECT_ID - SEGMENT_BETA_WRITE_KEY @@ -47,7 +45,7 @@ buildTypes: - SEGMENT_WRITE_KEY_REF: SEGMENT_BETA_WRITE_KEY - ALLOW_LOCAL_SNAPS: false - REQUIRE_SNAPS_ALLOWLIST: true - - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/iframe/6.4.0/index.html + - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/iframe/6.5.0/index.html - ACCOUNT_SNAPS_DIRECTORY_URL: https://snaps.metamask.io/account-management # Modifies how the version is displayed. # eg. instead of 10.25.0 -> 10.25.0-beta.2 @@ -62,13 +60,12 @@ buildTypes: features: - build-flask - keyring-snaps - - blockaid env: - INFURA_FLASK_PROJECT_ID - SEGMENT_FLASK_WRITE_KEY - ALLOW_LOCAL_SNAPS: true - REQUIRE_SNAPS_ALLOWLIST: false - - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/iframe/6.4.0/index.html + - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/iframe/6.5.0/index.html - SUPPORT_LINK: https://support.metamask.io/ - SUPPORT_REQUEST_LINK: https://support.metamask.io/ - INFURA_ENV_KEY_REF: INFURA_FLASK_PROJECT_ID @@ -83,7 +80,6 @@ buildTypes: mmi: features: - build-mmi - - blockaid env: - INFURA_MMI_PROJECT_ID - SEGMENT_MMI_WRITE_KEY @@ -92,7 +88,7 @@ buildTypes: - SEGMENT_WRITE_KEY_REF: SEGMENT_MMI_WRITE_KEY - ALLOW_LOCAL_SNAPS: false - REQUIRE_SNAPS_ALLOWLIST: true - - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/iframe/6.4.0/index.html + - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/iframe/6.5.0/index.html - MMI_CONFIGURATION_SERVICE_URL: https://configuration.metamask-institutional.io/v2/configuration/default - SUPPORT_LINK: https://mmi-support.metamask.io/hc/en-us - SUPPORT_REQUEST_LINK: https://mmi-support.metamask.io/hc/en-us/requests/new @@ -107,10 +103,6 @@ buildTypes: # Each feature can have code fences that add new code # as well declaring, defining and overriding env variables features: - blockaid: - env: - - BLOCKAID_FILE_CDN: static.cx.metamask.io/api/v1/confirmations/ppom - - BLOCKAID_PUBLIC_KEY: 066ad3e8af5583385e312c156d238055215d5f25247c1e91055afa756cb98a88 ### # Build Type code extensions. Things like different support links, warning pages, banners ### @@ -156,6 +148,10 @@ env: - SUPPORT_LINK: https://support.metamask.io - SUPPORT_REQUEST_LINK: https://support.metamask.io - SKIP_BACKGROUND_INITIALIZATION: false + # CDN for blockaid files + - BLOCKAID_FILE_CDN: static.cx.metamask.io/api/v1/confirmations/ppom + # Blockaid public key for verifying signatures of data files downloaded from CDN + - BLOCKAID_PUBLIC_KEY: 066ad3e8af5583385e312c156d238055215d5f25247c1e91055afa756cb98a88 - ENABLE_MV3: true # These are exclusively used for MV3 @@ -256,10 +252,6 @@ env: - NODE_DEBUG: '' # Used by react-devtools-core - EDITOR_URL: '' - # CDN for blockaid files - - BLOCKAID_FILE_CDN - # Blockaid public key for verifying signatures of data files downloaded from CDN - - BLOCKAID_PUBLIC_KEY # Determines if feature flagged Multichain Transactions should be used - TRANSACTION_MULTICHAIN: '' # Determines if feature flagged Chain permissions diff --git a/development/build/static.js b/development/build/static.js index ecff5d2501c0..cf0cd1078423 100644 --- a/development/build/static.js +++ b/development/build/static.js @@ -29,7 +29,6 @@ module.exports = function createStaticAssetTasks({ const [copyTargetsProd, copyTargetsDev] = getCopyTargets( shouldIncludeLockdown, shouldIncludeSnow, - activeFeatures, ); copyTargetsProds[browser] = copyTargetsProd; copyTargetsDevs[browser] = copyTargetsDev; @@ -108,11 +107,7 @@ module.exports = function createStaticAssetTasks({ } }; -function getCopyTargets( - shouldIncludeLockdown, - shouldIncludeSnow, - activeFeatures, -) { +function getCopyTargets(shouldIncludeLockdown, shouldIncludeSnow) { const allCopyTargets = [ { src: `./app/_locales/`, @@ -202,6 +197,15 @@ function getCopyTargets( pattern: `*.html`, dest: '', }, + { + src: getPathInsideNodeModules('@blockaid/ppom_release', '/'), + pattern: '*.wasm', + dest: + process.env.ENABLE_MV3 === 'true' || + process.env.ENABLE_MV3 === undefined + ? 'scripts/' + : '', + }, ...(process.env.ENABLE_MV3 === 'true' || process.env.ENABLE_MV3 === undefined ? [ @@ -225,18 +229,6 @@ function getCopyTargets( : []), ]; - if (activeFeatures.includes('blockaid')) { - allCopyTargets.push({ - src: getPathInsideNodeModules('@blockaid/ppom_release', '/'), - pattern: '*.wasm', - dest: - process.env.ENABLE_MV3 === 'true' || - process.env.ENABLE_MV3 === undefined - ? 'scripts/' - : '', - }); - } - const copyTargetsDev = [ ...allCopyTargets, { diff --git a/package.json b/package.json index ac75935f2f60..1afbb70c1e20 100644 --- a/package.json +++ b/package.json @@ -221,7 +221,7 @@ "semver@7.3.8": "^7.5.4", "@trezor/schema-utils@npm:1.0.2": "patch:@trezor/schema-utils@npm%3A1.0.2#~/.yarn/patches/@trezor-schema-utils-npm-1.0.2-7dd48689b2.patch", "lavamoat-core@npm:^15.1.1": "patch:lavamoat-core@npm%3A15.1.1#~/.yarn/patches/lavamoat-core-npm-15.1.1-51fbe39988.patch", - "@metamask/snaps-sdk": "^5.0.0", + "@metamask/snaps-sdk": "^6.0.0", "@metamask/transaction-controller": "^32.0.0", "@babel/runtime@npm:^7.7.6": "patch:@babel/runtime@npm%3A7.24.0#~/.yarn/patches/@babel-runtime-npm-7.24.0-7eb1dd11a2.patch", "@babel/runtime@npm:^7.9.2": "patch:@babel/runtime@npm%3A7.24.0#~/.yarn/patches/@babel-runtime-npm-7.24.0-7eb1dd11a2.patch", @@ -335,11 +335,11 @@ "@metamask/selected-network-controller": "^15.0.2", "@metamask/signature-controller": "^16.0.0", "@metamask/smart-transactions-controller": "^10.1.2", - "@metamask/snaps-controllers": "^9.0.0", - "@metamask/snaps-execution-environments": "^6.4.0", - "@metamask/snaps-rpc-methods": "^9.1.3", - "@metamask/snaps-sdk": "^5.0.0", - "@metamask/snaps-utils": "^7.6.0", + "@metamask/snaps-controllers": "^9.2.0", + "@metamask/snaps-execution-environments": "^6.5.0", + "@metamask/snaps-rpc-methods": "^9.1.4", + "@metamask/snaps-sdk": "^6.0.0", + "@metamask/snaps-utils": "^7.7.0", "@metamask/transaction-controller": "^32.0.0", "@metamask/user-operation-controller": "^10.0.0", "@metamask/utils": "^8.2.1", diff --git a/test/e2e/snaps/enums.js b/test/e2e/snaps/enums.js index daeaf9db924f..98bbdfea099a 100644 --- a/test/e2e/snaps/enums.js +++ b/test/e2e/snaps/enums.js @@ -1,3 +1,3 @@ module.exports = { - TEST_SNAPS_WEBSITE_URL: 'https://metamask.github.io/snaps/test-snaps/2.9.0/', + TEST_SNAPS_WEBSITE_URL: 'https://metamask.github.io/snaps/test-snaps/2.11.0/', }; diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json index 534d5e4d606a..84fef8e26a90 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json @@ -30,7 +30,7 @@ "fullScreenGasPollTokens": "object", "recoveryPhraseReminderHasBeenShown": true, "recoveryPhraseReminderLastShown": "number", - "outdatedBrowserWarningLastShown": "number", + "outdatedBrowserWarningLastShown": "object", "nftsDetectionNoticeDismissed": false, "showTestnetMessageInDropdown": true, "showBetaHeader": false, diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json index 7bcbd81bf539..1dd7775ec70f 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json @@ -66,7 +66,7 @@ "fullScreenGasPollTokens": "object", "recoveryPhraseReminderHasBeenShown": true, "recoveryPhraseReminderLastShown": "number", - "outdatedBrowserWarningLastShown": "number", + "outdatedBrowserWarningLastShown": "object", "nftsDetectionNoticeDismissed": false, "showTestnetMessageInDropdown": true, "showBetaHeader": false, diff --git a/test/e2e/tests/onboarding/onboarding.spec.js b/test/e2e/tests/onboarding/onboarding.spec.js index de0939ac2282..c9cb594f403d 100644 --- a/test/e2e/tests/onboarding/onboarding.spec.js +++ b/test/e2e/tests/onboarding/onboarding.spec.js @@ -372,7 +372,7 @@ describe('MetaMask onboarding @no-mmi', function () { json: { jsonrpc: '2.0', id: '1111111111111111', - result: '0x1', + result: '0x0', }, }; }), @@ -508,7 +508,7 @@ describe('MetaMask onboarding @no-mmi', function () { json: { jsonrpc: '2.0', id: '1111111111111111', - result: '0x1', + result: '0x0', }, }; }), diff --git a/ui/components/app/app-components.scss b/ui/components/app/app-components.scss index 34b0bce89369..63c916a5b256 100644 --- a/ui/components/app/app-components.scss +++ b/ui/components/app/app-components.scss @@ -23,6 +23,7 @@ @import 'snaps/snap-ui-renderer/index'; @import 'snaps/snap-ui-markdown/index'; @import 'snaps/snap-ui-button/index'; +@import 'snaps/snap-ui-file-input/index'; @import 'snaps/snap-delineator/index'; @import 'snaps/snap-list-item/index'; @import 'snaps/copyable/index'; diff --git a/ui/components/app/metamask-template-renderer/safe-component-list.js b/ui/components/app/metamask-template-renderer/safe-component-list.js index 2c7905c9d2a2..5c7f9218283a 100644 --- a/ui/components/app/metamask-template-renderer/safe-component-list.js +++ b/ui/components/app/metamask-template-renderer/safe-component-list.js @@ -27,10 +27,13 @@ import { SnapUIMarkdown } from '../snaps/snap-ui-markdown'; import { SnapUILink } from '../snaps/snap-ui-link'; import { SmartTransactionStatusPage } from '../../../pages/smart-transactions/smart-transaction-status-page'; import { SnapUIImage } from '../snaps/snap-ui-image'; +import { SnapUIFileInput } from '../snaps/snap-ui-file-input'; import { SnapUIInput } from '../snaps/snap-ui-input'; import { SnapUIForm } from '../snaps/snap-ui-form'; import { SnapUIButton } from '../snaps/snap-ui-button'; import { SnapUIDropdown } from '../snaps/snap-ui-dropdown'; +import { SnapUICheckbox } from '../snaps/snap-ui-checkbox'; +import { SnapUITooltip } from '../snaps/snap-ui-tooltip'; ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) import { SnapAccountSuccessMessage } from '../../../pages/confirmations/components/snap-account-success-message'; import { SnapAccountErrorMessage } from '../../../pages/confirmations/components/snap-account-error-message'; @@ -78,10 +81,13 @@ export const safeComponentList = { ConfirmInfoRow, ConfirmInfoRowAddress, ConfirmInfoRowValueDouble, + SnapUIFileInput, SnapUIInput, SnapUIButton, SnapUIForm, SnapUIDropdown, + SnapUICheckbox, + SnapUITooltip, ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) CreateSnapAccount, RemoveSnapAccount, diff --git a/ui/components/app/network-display/index.scss b/ui/components/app/network-display/index.scss index 9d6fa922819e..1c4e3dd568cb 100644 --- a/ui/components/app/network-display/index.scss +++ b/ui/components/app/network-display/index.scss @@ -1,37 +1,5 @@ .network-display { - display: flex; - align-items: center; - justify-content: flex-start; - padding: 0 10px; - border-radius: 4px; - min-height: 25px; - user-select: none; - - &--disabled { - cursor: not-allowed; - } - - &.chip { - margin: 0; - max-width: 100%; - } - - & .chip__label { - padding-left: 2px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - & .chip__left-icon { - padding-left: 8px; - } - - & .chip__right-icon { - margin-right: 4px; - } - - &--clickable { - cursor: pointer; + &:not([disabled]):active { + background-color: transparent; } } diff --git a/ui/components/app/network-display/network-display.js b/ui/components/app/network-display/network-display.js index d4b81ec38d0a..11c56a60fcb7 100644 --- a/ui/components/app/network-display/network-display.js +++ b/ui/components/app/network-display/network-display.js @@ -1,129 +1,27 @@ import React from 'react'; -import PropTypes from 'prop-types'; -import classnames from 'classnames'; import { useSelector } from 'react-redux'; -import { - NETWORK_TYPES, - BUILT_IN_NETWORKS, -} from '../../../../shared/constants/network'; -import LoadingIndicator from '../../ui/loading-indicator'; -import ColorIndicator from '../../ui/color-indicator'; import { BorderColor, - IconColor, - Size, - TypographyVariant, + BackgroundColor, } from '../../../helpers/constants/design-system'; -import Chip from '../../ui/chip/chip'; -import { useI18nContext } from '../../../hooks/useI18nContext'; -import { isNetworkLoading } from '../../../selectors'; -import { Icon, IconName, IconSize } from '../../component-library'; -import { getProviderConfig } from '../../../ducks/metamask/metamask'; -import { getNetworkLabelKey } from '../../../helpers/utils/i18n-helper'; - -/** - * @deprecated The `` component has been deprecated in favor of the new `` component from the component-library. - * Please update your code to use the new `` component instead, which can be found at ui/components/component-library/picker-network/picker-network.tsx. - * You can find documentation for the new `PickerNetwork` component in the MetaMask Storybook: - * {@link https://metamask.github.io/metamask-storybook/?path=/docs/components-componentlibrary-pickernetwork--docs} - * If you would like to help with the replacement of the old `NetworkDisplay` component, please submit a pull request against this GitHub issue: - * {@link https://github.com/MetaMask/metamask-extension/issues/20485} - */ - -export default function NetworkDisplay({ - indicatorSize, - disabled, - labelProps, - targetNetwork, - onClick, -}) { - const networkIsLoading = useSelector(isNetworkLoading); - const providerConfig = useSelector(getProviderConfig); - const t = useI18nContext(); - - const { nickname, type: networkType } = targetNetwork ?? providerConfig; +import { getCurrentNetwork } from '../../../selectors'; +import { PickerNetwork, AvatarNetworkSize } from '../../component-library'; +export default function NetworkDisplay() { + const currentNetwork = useSelector(getCurrentNetwork); return ( - - - - } - rightIcon={ - onClick ? : null - } - label={ - networkType === NETWORK_TYPES.RPC - ? nickname ?? t('privateNetwork') - : t(getNetworkLabelKey(networkType)) - } - className={classnames('network-display', { - 'network-display--disabled': disabled, - 'network-display--clickable': typeof onClick === 'function', - })} - labelProps={{ - variant: TypographyVariant.H7, - ...labelProps, - }} + ); } -NetworkDisplay.propTypes = { - /** - * The size of the indicator - */ - indicatorSize: PropTypes.oneOf(Object.values(Size)), - /** - * The label props of the label can use most of the Typography props - */ - labelProps: Chip.propTypes.labelProps, - /** - * The target network - */ - targetNetwork: PropTypes.shape({ - type: PropTypes.oneOf([ - ...Object.keys(BUILT_IN_NETWORKS), - NETWORK_TYPES.RPC, - ]), - nickname: PropTypes.string, - }), - /** - * Whether the NetworkDisplay is disabled - */ - disabled: PropTypes.bool, - /** - * The onClick event handler of the NetworkDisplay - * if it is not passed it is assumed that the NetworkDisplay - * should not be interactive and removes the caret and changes the border color - * of the NetworkDisplay - */ - onClick: PropTypes.func, -}; - -NetworkDisplay.defaultProps = { - indicatorSize: Size.LG, -}; diff --git a/ui/components/app/network-display/network-display.stories.js b/ui/components/app/network-display/network-display.stories.js index 5a67dc676ae4..2392a107b6e9 100644 --- a/ui/components/app/network-display/network-display.stories.js +++ b/ui/components/app/network-display/network-display.stories.js @@ -1,107 +1,10 @@ import React from 'react'; - -import { - BUILT_IN_NETWORKS, - NETWORK_TYPES, -} from '../../../../shared/constants/network'; -import { Severity, Size } from '../../../helpers/constants/design-system'; - -import { BannerAlert } from '../../component-library/banner-alert'; import NetworkDisplay from '.'; export default { title: 'Components/App/NetworkDisplay', - - argTypes: { - indicatorSize: { - control: 'select', - options: Object.values(Size), - }, - labelProps: { - control: 'object', - }, - targetNetwork: { - control: 'select', - options: [...Object.keys(BUILT_IN_NETWORKS), NETWORK_TYPES.RPC], - }, - disabled: { - control: 'boolean', - }, - onClick: { - action: 'onClick', - description: - 'The onClick event handler of the NetworkDisplay. If it is not passed it is assumed that the NetworkDisplay SHOULD NOT be interactive and removes the caret and changes the border color of the NetworkDisplay to border-muted', - }, - }, - args: { - targetNetwork: 'goerli', - }, }; -export const DefaultStory = (args) => ( - <> - - - -); +export const DefaultStory = () => ; DefaultStory.storyName = 'Default'; - -export const TargetNetwork = (args) => { - const targetNetworkArr = [ - ...Object.keys(BUILT_IN_NETWORKS), - NETWORK_TYPES.RPC, - ]; - return ( - <> - {Object.values(targetNetworkArr).map((variant) => ( - - ))} - - ); -}; - -export const DisplayOnly = (args) => { - const targetNetworkArr = [ - ...Object.keys(BUILT_IN_NETWORKS), - NETWORK_TYPES.RPC, - ]; - return ( - <> - {Object.values(targetNetworkArr).map((variant) => ( - - ))} - - ); -}; diff --git a/ui/components/app/snaps/snap-ui-button/snap-ui-button.tsx b/ui/components/app/snaps/snap-ui-button/snap-ui-button.tsx index 5c6735d6d16a..998a7ca2d782 100644 --- a/ui/components/app/snaps/snap-ui-button/snap-ui-button.tsx +++ b/ui/components/app/snaps/snap-ui-button/snap-ui-button.tsx @@ -36,7 +36,10 @@ export const SnapUIButton: FunctionComponent< event.preventDefault(); } - handleEvent({ event: UserInputEventType.ButtonClickEvent, name }); + handleEvent({ + event: UserInputEventType.ButtonClickEvent, + name, + }); }; const overriddenVariant = disabled ? 'disabled' : variant; diff --git a/ui/components/app/snaps/snap-ui-checkbox/index.ts b/ui/components/app/snaps/snap-ui-checkbox/index.ts new file mode 100644 index 000000000000..e75fe2634f38 --- /dev/null +++ b/ui/components/app/snaps/snap-ui-checkbox/index.ts @@ -0,0 +1 @@ +export * from './snap-ui-checkbox'; diff --git a/ui/components/app/snaps/snap-ui-checkbox/snap-ui-checkbox.tsx b/ui/components/app/snaps/snap-ui-checkbox/snap-ui-checkbox.tsx new file mode 100644 index 000000000000..39df1c0ff8f7 --- /dev/null +++ b/ui/components/app/snaps/snap-ui-checkbox/snap-ui-checkbox.tsx @@ -0,0 +1,81 @@ +import React, { FunctionComponent, useEffect, useState } from 'react'; +import { useSnapInterfaceContext } from '../../../../contexts/snaps'; +import { + Display, + FlexDirection, +} from '../../../../helpers/constants/design-system'; +import { + Box, + Label, + HelpText, + HelpTextSeverity, + Checkbox, +} from '../../../component-library'; +import ToggleButton from '../../../ui/toggle-button'; + +export type SnapUICheckboxProps = { + name: string; + fieldLabel?: string; + variant?: 'default' | 'toggle'; + label?: string; + error?: string; + form?: string; +}; + +export const SnapUICheckbox: FunctionComponent = ({ + name, + variant, + fieldLabel, + label, + error, + form, + ...props +}) => { + const { handleInputChange, getValue } = useSnapInterfaceContext(); + + const initialValue = getValue(name, form); + + const [value, setValue] = useState(initialValue ?? false); + + useEffect(() => { + if (initialValue !== undefined && initialValue !== null) { + setValue(initialValue); + } + }, [initialValue]); + + const handleChange = () => { + setValue(!value); + handleInputChange(name, !value, form); + }; + + return ( + + {fieldLabel && } + {variant === 'toggle' ? ( + + ) : ( + + )} + {error && ( + + {error} + + )} + + ); +}; diff --git a/ui/components/app/snaps/snap-ui-dropdown/snap-ui-dropdown.tsx b/ui/components/app/snaps/snap-ui-dropdown/snap-ui-dropdown.tsx index f729436c776b..2e70f2809399 100644 --- a/ui/components/app/snaps/snap-ui-dropdown/snap-ui-dropdown.tsx +++ b/ui/components/app/snaps/snap-ui-dropdown/snap-ui-dropdown.tsx @@ -29,7 +29,7 @@ export const SnapUIDropdown: FunctionComponent = ({ }) => { const { handleInputChange, getValue } = useSnapInterfaceContext(); - const initialValue = getValue(name, form); + const initialValue = getValue(name, form); const [value, setValue] = useState(initialValue ?? ''); diff --git a/ui/components/app/snaps/snap-ui-file-input/index.scss b/ui/components/app/snaps/snap-ui-file-input/index.scss new file mode 100644 index 000000000000..787eb6150728 --- /dev/null +++ b/ui/components/app/snaps/snap-ui-file-input/index.scss @@ -0,0 +1,21 @@ +.snap-ui-renderer { + &__file-input { + &__drop-zone { + background-color: var(--color-background-alternative); + + .mm-icon, + .mm-text { + color: var(--color-icon-alternative); + } + + &:hover .mm-icon, + &:hover .mm-text { + color: var(--color-info-default); + } + + &:hover { + background-color: var(--color-background-alternative-hover); + } + } + } +} diff --git a/ui/components/app/snaps/snap-ui-file-input/index.ts b/ui/components/app/snaps/snap-ui-file-input/index.ts new file mode 100644 index 000000000000..fa2b7b5ad2a1 --- /dev/null +++ b/ui/components/app/snaps/snap-ui-file-input/index.ts @@ -0,0 +1 @@ +export * from './snap-ui-file-input'; diff --git a/ui/components/app/snaps/snap-ui-file-input/snap-ui-file-input.tsx b/ui/components/app/snaps/snap-ui-file-input/snap-ui-file-input.tsx new file mode 100644 index 000000000000..9508dae3e0d3 --- /dev/null +++ b/ui/components/app/snaps/snap-ui-file-input/snap-ui-file-input.tsx @@ -0,0 +1,212 @@ +import React, { + ChangeEvent, + // eslint-disable-next-line @typescript-eslint/no-shadow + DragEvent, + FunctionComponent, + useRef, + useState, +} from 'react'; +import classnames from 'classnames'; +import { useSnapInterfaceContext } from '../../../../contexts/snaps'; +import { + Box, + ButtonIcon, + ButtonIconSize, + HelpText, + HelpTextSeverity, + Icon, + IconName, + IconSize, + Label, + Text, +} from '../../../component-library'; +import { + AlignItems, + BackgroundColor, + BorderColor, + BorderRadius, + BorderStyle, + Display, + FlexDirection, + IconColor, + JustifyContent, + TextAlign, +} from '../../../../helpers/constants/design-system'; +import { useI18nContext } from '../../../../hooks/useI18nContext'; + +export type SnapUIFileInputProps = { + name: string; + label?: string; + form?: string; + accept?: string[]; + compact?: boolean; + error?: boolean; + helpText?: string; +}; + +/** + * A file input component, which is used to create a file input field for Snaps + * user interfaces. + * + * @param props - The props of the component. + * @param props.name - The name of the file input. This is used to identify the + * file input field in the form data. + * @param props.label - The label of the file input, which is displayed above + * the file input field. + * @param props.form - The name of the form that the file input belongs to. This + * is used to group the file input field with other form fields. + * @param props.accept - The types of files that the file input can accept. This + * is used to filter the files that the user can select when the input field is + * clicked. + * @param props.compact - Whether the file input should be displayed in a + * compact mode. In compact mode, the file input is displayed as a button with + * an icon. + * @param props.error - Whether the file input has an error. If the file input + * has an error, the help text is displayed in red. + * @param props.helpText - The help text of the file input, which is displayed + * below the file input field. + * @returns A file input element. + */ +export const SnapUIFileInput: FunctionComponent = ({ + name, + label, + form, + accept, + compact, + error, + helpText, +}) => { + const t = useI18nContext(); + const { handleFileChange } = useSnapInterfaceContext(); + const ref = useRef(null); + const [active, setActive] = useState(false); + + const handleClick = () => { + ref.current?.click(); + }; + + const handleChange = (event: ChangeEvent) => { + const file = event.target.files?.[0] ?? null; + handleFileChange(name, file, form); + }; + + const handleDragOver = (event: DragEvent) => { + event.preventDefault(); + setActive(true); + }; + + const handleDragLeave = (event: DragEvent) => { + event.preventDefault(); + setActive(false); + }; + + const handleDrop = (event: DragEvent) => { + event.preventDefault(); + setActive(false); + + const file = event.dataTransfer?.files?.[0] ?? null; + handleFileChange(name, file, form); + }; + + const header = ( + <> + {label && ( + + )} + + + ); + + const footer = ( + <> + {helpText && ( + + {helpText} + + )} + + ); + + if (compact) { + return ( + + {header} + + {footer} + + ); + } + + return ( + + {header} + + + + {t('uploadDropFile')} + + + {footer} + + ); +}; diff --git a/ui/components/app/snaps/snap-ui-form/snap-ui-form.tsx b/ui/components/app/snaps/snap-ui-form/snap-ui-form.tsx index 4dfe245b854f..6f265bc71710 100644 --- a/ui/components/app/snaps/snap-ui-form/snap-ui-form.tsx +++ b/ui/components/app/snaps/snap-ui-form/snap-ui-form.tsx @@ -19,7 +19,10 @@ export const SnapUIForm: FunctionComponent = ({ const handleSubmit = (event: FormEvent) => { event.preventDefault(); - handleEvent({ event: UserInputEventType.FormSubmitEvent, name }); + handleEvent({ + event: UserInputEventType.FormSubmitEvent, + name, + }); }; return ( diff --git a/ui/components/app/snaps/snap-ui-input/snap-ui-input.tsx b/ui/components/app/snaps/snap-ui-input/snap-ui-input.tsx index 2374e00f3927..43c612517139 100644 --- a/ui/components/app/snaps/snap-ui-input/snap-ui-input.tsx +++ b/ui/components/app/snaps/snap-ui-input/snap-ui-input.tsx @@ -17,7 +17,7 @@ export const SnapUIInput: FunctionComponent< > = ({ name, form, ...props }) => { const { handleInputChange, getValue } = useSnapInterfaceContext(); - const initialValue = getValue(name, form); + const initialValue = getValue(name, form); const [value, setValue] = useState(initialValue ?? ''); diff --git a/ui/components/app/snaps/snap-ui-renderer/components/checkbox.ts b/ui/components/app/snaps/snap-ui-renderer/components/checkbox.ts new file mode 100644 index 000000000000..862ca5203950 --- /dev/null +++ b/ui/components/app/snaps/snap-ui-renderer/components/checkbox.ts @@ -0,0 +1,16 @@ +import { CheckboxElement } from '@metamask/snaps-sdk/jsx'; + +import { UIComponentFactory } from './types'; + +export const checkbox: UIComponentFactory = ({ + element, + form, +}) => ({ + element: 'SnapUICheckbox', + props: { + name: element.props.name, + label: element.props.label, + variant: element.props.variant, + form, + }, +}); diff --git a/ui/components/app/snaps/snap-ui-renderer/components/field.ts b/ui/components/app/snaps/snap-ui-renderer/components/field.ts index 193f618346ca..eb5b0b0e2256 100644 --- a/ui/components/app/snaps/snap-ui-renderer/components/field.ts +++ b/ui/components/app/snaps/snap-ui-renderer/components/field.ts @@ -4,10 +4,12 @@ import { ButtonElement, JSXElement, DropdownElement, + CheckboxElement, } from '@metamask/snaps-sdk/jsx'; import { getJsxChildren } from '@metamask/snaps-utils'; import { button as buttonFn } from './button'; import { dropdown as dropdownFn } from './dropdown'; +import { checkbox as checkboxFn } from './checkbox'; import { UIComponentFactory, UIComponentParams } from './types'; export const field: UIComponentFactory = ({ element, form }) => { @@ -16,12 +18,28 @@ export const field: UIComponentFactory = ({ element, form }) => { const child = children[0] as JSXElement; switch (child.type) { + case 'FileInput': { + return { + element: 'SnapUIFileInput', + props: { + name: child.props.name, + accept: child.props.accept, + compact: child.props.compact, + label: element.props.label, + form, + error: element.props.error !== undefined, + helpText: element.props.error, + }, + }; + } + case 'Input': { const input = child as InputElement; const button = children[1] as ButtonElement; const buttonMapped = button && buttonFn({ element: button } as UIComponentParams); + return { element: 'SnapUIInput', props: { @@ -66,6 +84,22 @@ export const field: UIComponentFactory = ({ element, form }) => { }; } + case 'Checkbox': { + const checkbox = child as CheckboxElement; + const checkboxMapped = checkboxFn({ + element: checkbox, + } as UIComponentParams); + return { + element: 'SnapUICheckbox', + props: { + ...checkboxMapped.props, + fieldLabel: element.props.label, + form, + error: element.props.error, + }, + }; + } + default: throw new Error(`Invalid Field child: ${child.type}`); } diff --git a/ui/components/app/snaps/snap-ui-renderer/components/file-input.ts b/ui/components/app/snaps/snap-ui-renderer/components/file-input.ts new file mode 100644 index 000000000000..edeba6d89551 --- /dev/null +++ b/ui/components/app/snaps/snap-ui-renderer/components/file-input.ts @@ -0,0 +1,19 @@ +import { FileInputElement } from '@metamask/snaps-sdk/jsx'; + +import { UIComponentFactory } from './types'; + +export const fileInput: UIComponentFactory = ({ + element, + form, +}) => ({ + element: 'SnapUIInput', + props: { + element: 'SnapUIFileInput', + props: { + name: element.props.name, + accept: element.props.accept, + compact: element.props.compact, + form, + }, + }, +}); diff --git a/ui/components/app/snaps/snap-ui-renderer/components/index.ts b/ui/components/app/snaps/snap-ui-renderer/components/index.ts index 9aa6796de1a3..eed08c75fb91 100644 --- a/ui/components/app/snaps/snap-ui-renderer/components/index.ts +++ b/ui/components/app/snaps/snap-ui-renderer/components/index.ts @@ -8,6 +8,7 @@ import { row } from './row'; import { address } from './address'; import { copyable } from './copyable'; import { button } from './button'; +import { fileInput } from './file-input'; import { form } from './form'; import { input } from './input'; import { bold } from './bold'; @@ -16,6 +17,8 @@ import { link } from './link'; import { field } from './field'; import { dropdown } from './dropdown'; import { value } from './value'; +import { checkbox } from './checkbox'; +import { tooltip } from './tooltip'; export const COMPONENT_MAPPING = { Box: box, @@ -28,6 +31,7 @@ export const COMPONENT_MAPPING = { Row: row, Address: address, Button: button, + FileInput: fileInput, Form: form, Input: input, Bold: bold, @@ -36,4 +40,6 @@ export const COMPONENT_MAPPING = { Field: field, Dropdown: dropdown, Value: value, + Checkbox: checkbox, + Tooltip: tooltip, }; diff --git a/ui/components/app/snaps/snap-ui-renderer/components/text.ts b/ui/components/app/snaps/snap-ui-renderer/components/text.ts index 7ed7d9be1236..9502df1aabaa 100644 --- a/ui/components/app/snaps/snap-ui-renderer/components/text.ts +++ b/ui/components/app/snaps/snap-ui-renderer/components/text.ts @@ -23,5 +23,6 @@ export const text: UIComponentFactory = ({ overflowWrap: OverflowWrap.Anywhere, color: TextColor.inherit, className: 'snap-ui-renderer__text', + textAlign: element.props.alignment, }, }); diff --git a/ui/components/app/snaps/snap-ui-renderer/components/tooltip.ts b/ui/components/app/snaps/snap-ui-renderer/components/tooltip.ts new file mode 100644 index 000000000000..facf3dcd7168 --- /dev/null +++ b/ui/components/app/snaps/snap-ui-renderer/components/tooltip.ts @@ -0,0 +1,23 @@ +import { JSXElement, Text, TooltipElement } from '@metamask/snaps-sdk/jsx'; +import { getJsxChildren } from '@metamask/snaps-utils'; +import { mapToTemplate } from '../utils'; +import { UIComponentFactory } from './types'; + +export const tooltip: UIComponentFactory = ({ + element, + ...params +}) => ({ + element: 'SnapUITooltip', + children: getJsxChildren(element).map((children) => + mapToTemplate({ element: children as JSXElement, ...params }), + ), + propComponents: { + content: mapToTemplate({ + element: + typeof element.props.content === 'string' + ? Text({ children: element.props.content }) + : element.props.content, + ...params, + }), + }, +}); diff --git a/ui/components/app/snaps/snap-ui-renderer/components/types.ts b/ui/components/app/snaps/snap-ui-renderer/components/types.ts index ab1048d0b3a7..4e4824f686e1 100644 --- a/ui/components/app/snaps/snap-ui-renderer/components/types.ts +++ b/ui/components/app/snaps/snap-ui-renderer/components/types.ts @@ -1,4 +1,4 @@ -import { JSXElement, MaybeArray } from '@metamask/snaps-sdk/jsx'; +import { JSXElement, SnapsChildren } from '@metamask/snaps-sdk/jsx'; export type UIComponentParams = { map: Record; @@ -9,7 +9,7 @@ export type UIComponentParams = { export type UIComponent = { element: string; props?: Record; - children?: MaybeArray; + children?: SnapsChildren; key?: string; }; diff --git a/ui/components/app/snaps/snap-ui-tooltip/index.ts b/ui/components/app/snaps/snap-ui-tooltip/index.ts new file mode 100644 index 000000000000..8a97b4d74e26 --- /dev/null +++ b/ui/components/app/snaps/snap-ui-tooltip/index.ts @@ -0,0 +1 @@ +export * from './snap-ui-tooltip'; diff --git a/ui/components/app/snaps/snap-ui-tooltip/snap-ui-tooltip.tsx b/ui/components/app/snaps/snap-ui-tooltip/snap-ui-tooltip.tsx new file mode 100644 index 000000000000..953ee50c87b5 --- /dev/null +++ b/ui/components/app/snaps/snap-ui-tooltip/snap-ui-tooltip.tsx @@ -0,0 +1,22 @@ +import React, { FunctionComponent, ReactNode } from 'react'; +import Tooltip from '../../../ui/tooltip'; + +export type SnapUITooltipProps = { + content: ReactNode; +}; + +export const SnapUITooltip: FunctionComponent = ({ + content, + children, +}) => { + return ( + + {children} + + ); +}; diff --git a/ui/components/app/whats-new-popup/whats-new-popup.js b/ui/components/app/whats-new-popup/whats-new-popup.js index a56ad75fe7fd..9a316af62889 100644 --- a/ui/components/app/whats-new-popup/whats-new-popup.js +++ b/ui/components/app/whats-new-popup/whats-new-popup.js @@ -17,9 +17,7 @@ import { MetaMetricsContext } from '../../../contexts/metametrics'; import { getCurrentLocale } from '../../../ducks/locale/locale'; import { TextVariant } from '../../../helpers/constants/design-system'; import { useEqualityCheck } from '../../../hooks/useEqualityCheck'; -///: BEGIN:ONLY_INCLUDE_IF(blockaid) import { useTheme } from '../../../hooks/useTheme'; -///: END:ONLY_INCLUDE_IF import { getSortedAnnouncementsToShow } from '../../../selectors'; import { updateViewedNotifications } from '../../../store/actions'; import { ButtonPrimary, Text } from '../../component-library'; @@ -165,10 +163,7 @@ export default function WhatsNewPopup({ onClose }) { const notifications = useSelector(getSortedAnnouncementsToShow); const locale = useSelector(getCurrentLocale); - - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) const theme = useTheme(); - ///: END:ONLY_INCLUDE_IF const [seenNotifications, setSeenNotifications] = useState({}); const [shouldShowScrollButton, setShouldShowScrollButton] = useState(true); @@ -272,14 +267,9 @@ export default function WhatsNewPopup({ onClose }) { >
{notifications.map(({ id }, index) => { - const notification = getTranslatedUINotifications( - t, - locale, - - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) - theme, - ///: END:ONLY_INCLUDE_IF - )[id]; + const notification = getTranslatedUINotifications(t, locale, theme)[ + id + ]; const isLast = index === notifications.length - 1; // Choose the appropriate rendering function based on the id const renderNotification = diff --git a/ui/contexts/snaps/snap-interface.tsx b/ui/contexts/snaps/snap-interface.tsx index 1943e35a2745..45af0572a03e 100644 --- a/ui/contexts/snaps/snap-interface.tsx +++ b/ui/contexts/snaps/snap-interface.tsx @@ -1,8 +1,10 @@ import { + File as FileObject, FormState, InterfaceState, UserInputEventType, } from '@metamask/snaps-sdk'; +import { encodeBase64 } from '@metamask/snaps-utils'; import { Json } from '@metamask/utils'; import { debounce, throttle } from 'lodash'; import React, { @@ -20,25 +22,32 @@ import { } from '../../store/actions'; import { mergeValue } from './utils'; -export type HandleEvent = (args: { +export type HandleEvent = (args: { event: UserInputEventType; name?: string; - value?: string; + value?: Type; flush?: boolean; }) => void; -export type HandleInputChange = ( +export type HandleInputChange = ( name: string, - value: string | null, + value: Type | null, form?: string, ) => void; -export type GetValue = (name: string, form?: string) => string | undefined; +export type GetValue = (name: string, form?: string) => Type | undefined; + +export type HandleFileChange = ( + name: string, + file: File | null, + form?: string, +) => void; export type SnapInterfaceContextType = { handleEvent: HandleEvent; getValue: GetValue; handleInputChange: HandleInputChange; + handleFileChange: HandleFileChange; }; export const SnapInterfaceContext = @@ -75,12 +84,13 @@ export const SnapInterfaceContextProvider: FunctionComponent< > = ({ children, interfaceId, snapId, initialState, context }) => { const dispatch = useDispatch(); - // We keep an internal copy of the state to speed-up the state update in the UI. - // It's kept in a ref to avoid useless re-rendering of the entire tree of components. + // We keep an internal copy of the state to speed up the state update in the + // UI. It's kept in a ref to avoid useless re-rendering of the entire tree of + // components. const internalState = useRef(initialState ?? {}); - // Since the internal state is kept in a reference, it won't update when the interface is updated. - // We have to manually update it + // Since the internal state is kept in a reference, it won't update when the + // interface is updated. We have to manually update it. useEffect(() => { internalState.current = initialState; }, [initialState]); @@ -88,8 +98,8 @@ export const SnapInterfaceContextProvider: FunctionComponent< const rawSnapRequestFunction = ( event: UserInputEventType, name?: string, - value?: string, - ) => + value?: unknown, + ) => { handleSnapRequest({ snapId, origin: '', @@ -109,13 +119,14 @@ export const SnapInterfaceContextProvider: FunctionComponent< }, }, }).then(() => forceUpdateMetamaskState(dispatch)); + }; - // The submittion of user input events is debounced or throttled to avoid crashing the snap if - // there's too much events sent at the same time + // The submission of user input events is debounced or throttled to avoid + // crashing the snap if there's too many events sent at the same time. const snapRequestDebounced = debounce(rawSnapRequestFunction, 200); const snapRequestThrottled = throttle(rawSnapRequestFunction, 200); - // The update of the state is debounced to avoid crashes due to too much + // The update of the state is debounced to avoid crashes due to too many // updates in a short amount of time. const updateStateDebounced = debounce( (state) => dispatch(updateInterfaceState(interfaceId, state)), @@ -129,7 +140,8 @@ export const SnapInterfaceContextProvider: FunctionComponent< * @param options.event - The event type. * @param options.name - The name of the component emitting the event. * @param options.value - The value of the component emitting the event. - * @param options.flush - Optional flag to indicate whether the debounce should be flushed. + * @param options.flush - Optional flag to indicate whether the debounce + * should be flushed. */ const handleEvent: HandleEvent = ({ event, @@ -139,9 +151,11 @@ export const SnapInterfaceContextProvider: FunctionComponent< }) => { // We always flush the debounced request for updating the state. updateStateDebounced.flush(); + const fn = THROTTLED_EVENTS.includes(event) ? snapRequestThrottled : snapRequestDebounced; + fn(event, name, value); // Certain events have their own debounce or throttling logic @@ -175,7 +189,73 @@ export const SnapInterfaceContextProvider: FunctionComponent< internalState.current = state; updateStateDebounced(state); - handleInputChangeDebounced(name, value ?? ''); + handleInputChangeDebounced(name, value); + }; + + const uploadFile = (name: string, file: File | null) => { + handleSnapRequest({ + snapId, + origin: '', + handler: 'onUserInput', + request: { + jsonrpc: '2.0', + method: ' ', + params: { + event: { + type: UserInputEventType.FileUploadEvent, + name, + file, + }, + id: interfaceId, + context, + }, + }, + }).then(() => forceUpdateMetamaskState(dispatch)); + }; + + /** + * Handle the file change of an input. + * + * @param name - The name of the input. + * @param file - The file to upload. + * @param form - The name of the form containing the input. + */ + const handleFileChange: HandleFileChange = (name, file, form) => { + if (file) { + file + .arrayBuffer() + .then((arrayBuffer) => new Uint8Array(arrayBuffer)) + .then((uint8Array) => encodeBase64(uint8Array)) + .then((base64) => { + const fileObject: FileObject = { + name: file.name, + size: file.size, + contentType: file.type, + contents: base64, + }; + + const state = mergeValue( + internalState.current, + name, + fileObject, + form, + ); + + internalState.current = state; + updateStateDebounced(state); + updateStateDebounced.flush(); + uploadFile(name, fileObject); + }); + + return; + } + + const state = mergeValue(internalState.current, name, null, form); + + internalState.current = state; + updateStateDebounced(state); + updateStateDebounced.flush(); + uploadFile(name, null); }; /** @@ -200,7 +280,7 @@ export const SnapInterfaceContextProvider: FunctionComponent< return ( {children} diff --git a/ui/contexts/snaps/utils.ts b/ui/contexts/snaps/utils.ts index 9d13c13eec1d..2dbf75be662a 100644 --- a/ui/contexts/snaps/utils.ts +++ b/ui/contexts/snaps/utils.ts @@ -10,10 +10,10 @@ import { FormState, InterfaceState } from '@metamask/snaps-sdk'; * Optional if the input is not contained in a form. * @returns The interface state with the new value merged in. */ -export const mergeValue = ( +export const mergeValue = ( state: InterfaceState, name: string, - value: string | null, + value: Type | null, form?: string, ): InterfaceState => { if (form) { diff --git a/ui/helpers/utils/metrics.js b/ui/helpers/utils/metrics.js index 36d80b689c5e..a890d8f06f73 100644 --- a/ui/helpers/utils/metrics.js +++ b/ui/helpers/utils/metrics.js @@ -1,10 +1,8 @@ -///: BEGIN:ONLY_INCLUDE_IF(blockaid) import { BlockaidReason, BlockaidResultType, } from '../../../shared/constants/security-provider'; import { MetaMetricsEventUiCustomization } from '../../../shared/constants/metametrics'; -///: END:ONLY_INCLUDE_IF export function getMethodName(camelCase) { if (!camelCase || typeof camelCase !== 'string') { @@ -25,7 +23,6 @@ export function formatAccountType(accountType) { return accountType; } -///: BEGIN:ONLY_INCLUDE_IF(blockaid) /** * Returns the ui_customization string value based on the result type * @@ -89,4 +86,3 @@ export const getBlockaidMetricsProps = ({ securityAlertResponse }) => { return params; }; -///: END:ONLY_INCLUDE_IF diff --git a/ui/pages/confirmations/components/confirm-page-container/confirm-page-container-header/__snapshots__/confirm-page-container-header.component.test.js.snap b/ui/pages/confirmations/components/confirm-page-container/confirm-page-container-header/__snapshots__/confirm-page-container-header.component.test.js.snap index e18103e853e5..ba0839bfd123 100644 --- a/ui/pages/confirmations/components/confirm-page-container/confirm-page-container-header/__snapshots__/confirm-page-container-header.component.test.js.snap +++ b/ui/pages/confirmations/components/confirm-page-container/confirm-page-container-header/__snapshots__/confirm-page-container-header.component.test.js.snap @@ -25,26 +25,21 @@ exports[`Confirm Detail Row Component should match snapshot 1`] = `
-
- -
+ ?
- Private network - + class="mm-box mm-text mm-text--body-sm mm-text--ellipsis mm-box--color-text-default" + data-testid="network-display" + /> +
diff --git a/ui/pages/confirmations/components/confirm/blockaid-loading-indicator/__snapshots__/blockaid-loading-indicator.test.tsx.snap b/ui/pages/confirmations/components/confirm/blockaid-loading-indicator/__snapshots__/blockaid-loading-indicator.test.tsx.snap new file mode 100644 index 000000000000..b60f849b51f2 --- /dev/null +++ b/ui/pages/confirmations/components/confirm/blockaid-loading-indicator/__snapshots__/blockaid-loading-indicator.test.tsx.snap @@ -0,0 +1,49 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`BlockaidLoadingIndicator returns spinner when there blockaid validation is in progress for signature 1`] = ` +
+
+ + + + + + + + + +
+
+`; diff --git a/ui/pages/confirmations/components/confirm/blockaid-loading-indicator/blockaid-loading-indicator.test.tsx b/ui/pages/confirmations/components/confirm/blockaid-loading-indicator/blockaid-loading-indicator.test.tsx new file mode 100644 index 000000000000..5be896e98827 --- /dev/null +++ b/ui/pages/confirmations/components/confirm/blockaid-loading-indicator/blockaid-loading-indicator.test.tsx @@ -0,0 +1,79 @@ +import React from 'react'; +import configureStore from 'redux-mock-store'; +import { + TransactionStatus, + TransactionType, +} from '@metamask/transaction-controller'; + +import mockState from '../../../../../../test/data/mock-state.json'; +import { BlockaidResultType } from '../../../../../../shared/constants/security-provider'; +import { renderWithProvider } from '../../../../../../test/lib/render-helpers'; +import { SecurityAlertResponse } from '../../../types/confirm'; + +import BlockaidLoadingIndicator from './blockaid-loading-indicator'; + +const mockSecurityAlertResponse: SecurityAlertResponse = { + securityAlertId: 'test-id-mock', + reason: 'test-reason', + result_type: BlockaidResultType.Loading, +}; + +const render = ( + securityAlertResponse: SecurityAlertResponse = mockSecurityAlertResponse, +) => { + const currentConfirmationMock = { + id: '1', + status: TransactionStatus.unapproved, + time: new Date().getTime(), + type: TransactionType.personalSign, + securityAlertResponse, + chainId: '0x1', + }; + + const mockExpectedState = { + ...mockState, + metamask: { + ...mockState.metamask, + unapprovedPersonalMsgs: { + '1': { ...currentConfirmationMock, msgParams: {} }, + }, + pendingApprovals: { + '1': { + ...currentConfirmationMock, + origin: 'origin', + requestData: {}, + requestState: null, + expectsResult: false, + }, + }, + preferences: { redesignedConfirmationsEnabled: true }, + signatureSecurityAlertResponses: { + 'test-id-mock': securityAlertResponse, + }, + }, + confirm: { currentConfirmation: currentConfirmationMock }, + }; + + const defaultStore = configureStore()(mockExpectedState); + return renderWithProvider(, defaultStore); +}; + +describe('BlockaidLoadingIndicator', () => { + it('returns spinner when there blockaid validation is in progress for signature', () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); + + it('returns null if blockaid validation is not in progress', () => { + const { container } = render({ + reason: 'test-reason', + result_type: BlockaidResultType.Benign, + }); + expect(container).toBeEmptyDOMElement(); + }); + + it('returns null if there is not blockaid validation response', () => { + const { container } = render({} as SecurityAlertResponse); + expect(container).toBeEmptyDOMElement(); + }); +}); diff --git a/ui/pages/confirmations/components/confirm/blockaid-loading-indicator/blockaid-loading-indicator.tsx b/ui/pages/confirmations/components/confirm/blockaid-loading-indicator/blockaid-loading-indicator.tsx new file mode 100644 index 000000000000..49f9c8b199cd --- /dev/null +++ b/ui/pages/confirmations/components/confirm/blockaid-loading-indicator/blockaid-loading-indicator.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { useSelector } from 'react-redux'; + +import Preloader from '../../../../../components/ui/icon/preloader'; +import { BlockaidResultType } from '../../../../../../shared/constants/security-provider'; +import { Box } from '../../../../../components/component-library'; + +import { currentSignatureRequestSecurityResponseSelector } from '../../../selectors'; + +const BlockaidLoadingIndicator = () => { + const signatureSecurityAlertResponse = useSelector( + currentSignatureRequestSecurityResponseSelector, + ); + + if ( + signatureSecurityAlertResponse?.result_type !== BlockaidResultType.Loading + ) { + return null; + } + + return ( + + + + ); +}; + +export default BlockaidLoadingIndicator; diff --git a/ui/pages/confirmations/components/confirm/blockaid-loading-indicator/index.ts b/ui/pages/confirmations/components/confirm/blockaid-loading-indicator/index.ts new file mode 100644 index 000000000000..331dd7ee53b6 --- /dev/null +++ b/ui/pages/confirmations/components/confirm/blockaid-loading-indicator/index.ts @@ -0,0 +1 @@ +export { default as BlockaidLoadingIndicator } from './blockaid-loading-indicator'; diff --git a/ui/pages/confirmations/components/signature-request-original/signature-request-original.component.js b/ui/pages/confirmations/components/signature-request-original/signature-request-original.component.js index 7f147a394e10..dbf451e0ff6f 100644 --- a/ui/pages/confirmations/components/signature-request-original/signature-request-original.component.js +++ b/ui/pages/confirmations/components/signature-request-original/signature-request-original.component.js @@ -42,10 +42,7 @@ import { ///: END:ONLY_INCLUDE_IF } from '../../../../components/component-library'; -///: BEGIN:ONLY_INCLUDE_IF(blockaid) import BlockaidBannerAlert from '../security-provider-banner-alert/blockaid-banner-alert/blockaid-banner-alert'; -///: END:ONLY_INCLUDE_IF - import ConfirmPageContainerNavigation from '../confirm-page-container/confirm-page-container-navigation'; import SecurityProviderBannerMessage from '../security-provider-banner-message/security-provider-banner-message'; @@ -143,16 +140,12 @@ export default class SignatureRequestOriginal extends Component { return (
- { - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) - - ///: END:ONLY_INCLUDE_IF - } + {isSuspiciousResponse(txData?.securityProviderResponse) && (
- { - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) - - ///: END:ONLY_INCLUDE_IF - } + {showSecurityProviderBanner && (
-
- -
+ C
- goerli + Chain 5 +
@@ -109,26 +106,23 @@ exports[`SignatureRequestHeader renders correctly without fromAccount 1`] = ` class="signature-request-header--network" >
-
- -
+ C
- goerli + Chain 5 +
diff --git a/ui/pages/confirmations/components/signature-request/signature-request.js b/ui/pages/confirmations/components/signature-request/signature-request.js index 0bd45a30c936..fc812ef54634 100644 --- a/ui/pages/confirmations/components/signature-request/signature-request.js +++ b/ui/pages/confirmations/components/signature-request/signature-request.js @@ -76,10 +76,7 @@ import { ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) import { useMMICustodySignMessage } from '../../../../hooks/useMMICustodySignMessage'; ///: END:ONLY_INCLUDE_IF -///: BEGIN:ONLY_INCLUDE_IF(blockaid) import BlockaidBannerAlert from '../security-provider-banner-alert/blockaid-banner-alert/blockaid-banner-alert'; -///: END:ONLY_INCLUDE_IF - import InsightWarnings from '../../../../components/app/snaps/insight-warnings'; import { BlockaidUnavailableBannerAlert } from '../blockaid-unavailable-banner-alert/blockaid-unavailable-banner-alert'; import Message from './signature-request-message'; @@ -209,16 +206,12 @@ const SignatureRequest = ({ txData, warnings }) => {
- { - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) - - ///: END:ONLY_INCLUDE_IF - } + {(txData?.securityProviderResponse?.flagAsDangerous !== undefined && txData?.securityProviderResponse?.flagAsDangerous !== diff --git a/ui/pages/confirmations/components/transaction-alerts/transaction-alerts.js b/ui/pages/confirmations/components/transaction-alerts/transaction-alerts.js index 58bd513d362a..534447781d25 100644 --- a/ui/pages/confirmations/components/transaction-alerts/transaction-alerts.js +++ b/ui/pages/confirmations/components/transaction-alerts/transaction-alerts.js @@ -20,9 +20,7 @@ import ZENDESK_URLS from '../../../../helpers/constants/zendesk-url'; ///: END:ONLY_INCLUDE_IF import { isSuspiciousResponse } from '../../../../../shared/modules/security-provider.utils'; -///: BEGIN:ONLY_INCLUDE_IF(blockaid) import BlockaidBannerAlert from '../security-provider-banner-alert/blockaid-banner-alert/blockaid-banner-alert'; -///: END:ONLY_INCLUDE_IF import SecurityProviderBannerMessage from '../security-provider-banner-message/security-provider-banner-message'; import { getNativeCurrency } from '../../../../ducks/metamask/metamask'; import { parseStandardTokenTransactionData } from '../../../../../shared/modules/transaction.utils'; @@ -74,11 +72,7 @@ const TransactionAlerts = ({ return (
- { - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) - - ///: END:ONLY_INCLUDE_IF - } + {isSuspiciousResponse(txData?.securityProviderResponse) && ( - { - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) - - ///: END:ONLY_INCLUDE_IF - } + {isSuspiciousResponse(txData?.securityProviderResponse) && (
-
- -
+ C
- goerli + Chain 5 +
{ const { toAddress: propsToAddress, @@ -163,7 +177,6 @@ const mapStateToProps = (state, ownProps) => { to: txParamsToAddress, gasPrice, gas: gasLimit, - value: amount, data, } = (transaction && transaction.txParams) || txParams; const accounts = getMetaMaskAccounts(state); @@ -171,20 +184,13 @@ const mapStateToProps = (state, ownProps) => { const currentChainSupportsSmartTransactions = getCurrentChainSupportsSmartTransactions(state); - const transactionData = parseStandardTokenTransactionData(data); - const tokenToAddress = getTokenAddressParam(transactionData); - const { balance } = accounts[fromAddress]; const fromInternalAccount = getInternalAccountByAddress(state, fromAddress); const fromName = fromInternalAccount?.metadata.name; const keyring = findKeyringForAddress(state, fromAddress); - const isSendingAmount = - type === TransactionType.simpleSend || !isEmptyHexString(amount); - - const toAddress = isSendingAmount - ? txParamsToAddress - : propsToAddress || tokenToAddress || txParamsToAddress; + const tokenToAddress = getTokenToAddress(data, type); + const toAddress = propsToAddress || tokenToAddress || txParamsToAddress; const toAccounts = getSendToAccounts(state); diff --git a/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.test.js b/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.test.js index bc36b2667576..918c24ed6681 100644 --- a/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.test.js +++ b/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.test.js @@ -775,7 +775,7 @@ describe('Confirm Transaction Base', () => { TransactionType.contractInteraction; }); - describe('when there is an amount being sent (it should be treated as a general contract intereaction rather than custom one)', () => { + describe('when there is an amount being sent (it should be treated as a general contract interaction rather than custom one)', () => { it('should use txParams.to address (contract address)', async () => { const state = mockedStoreWithConfirmTxParams(baseStore, { ...mockTxParams, @@ -795,33 +795,69 @@ describe('Confirm Transaction Base', () => { }); }); - describe(`when there is no amount being sent`, () => { - it('should use propToAddress (toAddress passed as prop)', async () => { + describe('when determines the recipient from transaction data args', () => { + const testCases = [ + { + type: TransactionType.tokenMethodTransfer, + data: `0xa9059cbb000000000000000000000000${mockParsedTxDataToAddressWithout0x}0000000000000000000000000000000000000000000000000000000000000001`, + description: 'tokenMethodTransfer', + }, + { + type: TransactionType.tokenMethodSafeTransferFrom, + data: `0x42842e0e000000000000000000000000806627172af48bd5b0765d3449a7def80d6576ff000000000000000000000000${mockParsedTxDataToAddressWithout0x}000000000000000000000000000000000000000000000000000000000009a7cc`, + description: 'tokenMethodSafeTransferFrom', + }, + { + type: TransactionType.tokenMethodTransferFrom, + data: `0x23b872dd000000000000000000000000ac9539a7d5c43940af498008a7c8f3abb35c3725000000000000000000000000${mockParsedTxDataToAddressWithout0x}000000000000000000000000000000000000000000000000000000000009a7b8`, + description: 'tokenMethodTransferFrom', + }, + ]; + + it.each(testCases)( + 'identifies correctly the recipient for $description transactions', + async ({ type, data }) => { + const state = mockedStoreWithConfirmTxParams(baseStore, { + ...mockTxParams, + data, + }); + state.confirmTransaction.txData = { + ...state.confirmTransaction.txData, + type, + }; + + const { container } = await render({ state }); + + const recipientElem = container.querySelector( + sendToRecipientSelector, + ); + expect(recipientElem).toHaveTextContent(mockParsedTxDataToAddress); + }, + ); + }); + + describe('when a non-transfer function matching the ABIs', () => { + it('does not determine the recipient from transaction data args', async () => { const state = mockedStoreWithConfirmTxParams(baseStore, { ...mockTxParams, - value: '0x0', + data: `0xa22cb465000000000000000000000000${mockParsedTxDataToAddressWithout0x}0000000000000000000000000000000000000000000000000000000000000001`, }); state.confirmTransaction.txData = { ...state.confirmTransaction.txData, type: TransactionType.contractInteraction, }; - const props = { - // we want to test toAddress provided by ownProps in mapStateToProps, but this - // currently overrides toAddress this should pan out fine when we refactor the - // component into a functional component and remove the container.js file - toAddress: mockPropsToAddress, - }; - - const { container } = await render({ props, state }); + const { container } = await render({ state }); const recipientElem = container.querySelector( sendToRecipientSelector, ); - expect(recipientElem).toHaveTextContent(mockPropsToAddressConcat); + expect(recipientElem).toHaveTextContent(mockTxParamsToAddressConcat); }); + }); - it('should use address parsed from transaction data if propToAddress is not provided', async () => { + describe(`when there is no amount being sent`, () => { + it('should use propToAddress (toAddress passed as prop)', async () => { const state = mockedStoreWithConfirmTxParams(baseStore, { ...mockTxParams, value: '0x0', @@ -831,14 +867,19 @@ describe('Confirm Transaction Base', () => { type: TransactionType.contractInteraction, }; - const props = {}; + const props = { + // we want to test toAddress provided by ownProps in mapStateToProps, but this + // currently overrides toAddress this should pan out fine when we refactor the + // component into a functional component and remove the container.js file + toAddress: mockPropsToAddress, + }; const { container } = await render({ props, state }); const recipientElem = container.querySelector( sendToRecipientSelector, ); - expect(recipientElem).toHaveTextContent(mockParsedTxDataToAddress); + expect(recipientElem).toHaveTextContent(mockPropsToAddressConcat); }); it('should use txParams.to if neither propToAddress is not provided nor the transaction data to address were provided', async () => { diff --git a/ui/pages/confirmations/confirm-transaction/confirm-transaction.transaction.test.js b/ui/pages/confirmations/confirm-transaction/confirm-transaction.transaction.test.js index 5ea10a6183de..f9101c0e7d7c 100644 --- a/ui/pages/confirmations/confirm-transaction/confirm-transaction.transaction.test.js +++ b/ui/pages/confirmations/confirm-transaction/confirm-transaction.transaction.test.js @@ -54,7 +54,7 @@ describe('Confirm Transaction', () => { )), ); - expect(result.getByText('0xb19Ac...f0c5e')).toBeInTheDocument(); + expect(result.getByText('Ledger Hardware 2')).toBeInTheDocument(); expect(result.getByRole('button', { name: 'Details' })).toBeInTheDocument(); expect(result.getByRole('button', { name: 'Hex' })).toBeInTheDocument(); }); diff --git a/ui/pages/confirmations/confirm/confirm.tsx b/ui/pages/confirmations/confirm/confirm.tsx index 96d6357fe88a..89a2fe5256be 100644 --- a/ui/pages/confirmations/confirm/confirm.tsx +++ b/ui/pages/confirmations/confirm/confirm.tsx @@ -5,6 +5,7 @@ import { Page } from '../../../components/multichain/pages/page'; import { MMISignatureMismatchBanner } from '../../../components/app/mmi-signature-mismatch-banner'; ///: END:ONLY_INCLUDE_IF +import { BlockaidLoadingIndicator } from '../components/confirm/blockaid-loading-indicator'; import ScrollToBottom from '../components/confirm/scroll-to-bottom'; import setCurrentConfirmation from '../hooks/setCurrentConfirmation'; import syncConfirmPath from '../hooks/syncConfirmPath'; @@ -46,6 +47,7 @@ const Confirm = () => { ///: END:ONLY_INCLUDE_IF } + <Info showAdvancedDetails={showAdvancedDetails} /> diff --git a/ui/pages/confirmations/confirmation/confirmation.js b/ui/pages/confirmations/confirmation/confirmation.js index 88da801651c7..649d7bc08409 100644 --- a/ui/pages/confirmations/confirmation/confirmation.js +++ b/ui/pages/confirmations/confirmation/confirmation.js @@ -22,7 +22,6 @@ import { import MetaMaskTemplateRenderer from '../../../components/app/metamask-template-renderer'; import ConfirmationWarningModal from '../components/confirmation-warning-modal'; import { DEFAULT_ROUTE } from '../../../helpers/constants/routes'; -import { Size, TextColor } from '../../../helpers/constants/design-system'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { MetaMetricsContext } from '../../../contexts/metametrics'; import { @@ -511,10 +510,7 @@ export default function ConfirmationPage({ <div className="confirmation-page__content"> {templatedValues.networkDisplay ? ( <Box justifyContent="center" marginTop={2}> - <NetworkDisplay - indicatorSize={Size.XS} - labelProps={{ color: TextColor.textDefault }} - /> + <NetworkDisplay /> </Box> ) : null} {useSnapHeader && ( diff --git a/ui/pages/confirmations/confirmation/templates/__snapshots__/add-ethereum-chain.test.js.snap b/ui/pages/confirmations/confirmation/templates/__snapshots__/add-ethereum-chain.test.js.snap index 4891743b24de..8fd320c388cc 100644 --- a/ui/pages/confirmations/confirmation/templates/__snapshots__/add-ethereum-chain.test.js.snap +++ b/ui/pages/confirmations/confirmation/templates/__snapshots__/add-ethereum-chain.test.js.snap @@ -12,26 +12,21 @@ exports[`add-ethereum-chain confirmation should match snapshot 1`] = ` class="box box--margin-top-2 box--flex-direction-row box--justify-content-center box--display-flex" > <div - class="network-display chip chip--with-left-icon chip--border-color-border-muted chip--background-color-undefined chip--max-content" - data-testid="network-display" + class="mm-box mm-picker-network network-display mm-box--padding-right-4 mm-box--padding-left-2 mm-box--display-flex mm-box--gap-2 mm-box--align-items-center mm-box--background-color-transparent mm-box--rounded-pill mm-box--border-color-border-muted mm-box--border-width-0 box--border-style-solid box--border-width-1" > <div - class="chip__left-icon" + class="mm-box mm-text mm-avatar-base mm-avatar-base--size-xs mm-avatar-network mm-picker-network__avatar-network mm-text--body-xs mm-text--text-transform-uppercase mm-box--display-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-full mm-box--border-color-transparent box--border-style-solid box--border-width-1" > - <div - class="color-indicator color-indicator--filled color-indicator--color-icon-muted color-indicator--size-xs" - data-testid="color-icon-icon-muted" - > - <span - class="color-indicator__inner-circle" - /> - </div> + ? </div> <span - class="mm-box mm-text chip__label mm-text--h7 mm-box--color-text-default" - > - Test initial state - </span> + class="mm-box mm-text mm-text--body-sm mm-text--ellipsis mm-box--color-text-default" + data-testid="network-display" + /> + <span + class="mm-box mm-picker-network__arrow-down-icon mm-icon mm-icon--size-xs mm-box--margin-left-auto mm-box--display-none mm-box--color-icon-default" + style="mask-image: url('./images/icons/arrow-down.svg');" + /> </div> </div> <h3 diff --git a/ui/pages/confirmations/confirmation/templates/__snapshots__/switch-ethereum-chain.test.js.snap b/ui/pages/confirmations/confirmation/templates/__snapshots__/switch-ethereum-chain.test.js.snap index 8e0ba8ed7bfb..4671e67ab89c 100644 --- a/ui/pages/confirmations/confirmation/templates/__snapshots__/switch-ethereum-chain.test.js.snap +++ b/ui/pages/confirmations/confirmation/templates/__snapshots__/switch-ethereum-chain.test.js.snap @@ -12,26 +12,21 @@ exports[`switch-ethereum-chain confirmation should match snapshot 1`] = ` class="box box--margin-top-2 box--flex-direction-row box--justify-content-center box--display-flex" > <div - class="network-display chip chip--with-left-icon chip--border-color-border-muted chip--background-color-undefined chip--max-content" - data-testid="network-display" + class="mm-box mm-picker-network network-display mm-box--padding-right-4 mm-box--padding-left-2 mm-box--display-flex mm-box--gap-2 mm-box--align-items-center mm-box--background-color-transparent mm-box--rounded-pill mm-box--border-color-border-muted mm-box--border-width-0 box--border-style-solid box--border-width-1" > <div - class="chip__left-icon" + class="mm-box mm-text mm-avatar-base mm-avatar-base--size-xs mm-avatar-network mm-picker-network__avatar-network mm-text--body-xs mm-text--text-transform-uppercase mm-box--display-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-full mm-box--border-color-transparent box--border-style-solid box--border-width-1" > - <div - class="color-indicator color-indicator--filled color-indicator--color-icon-muted color-indicator--size-xs" - data-testid="color-icon-icon-muted" - > - <span - class="color-indicator__inner-circle" - /> - </div> + ? </div> <span - class="mm-box mm-text chip__label mm-text--h7 mm-box--color-text-default" - > - Test initial state - </span> + class="mm-box mm-text mm-text--body-sm mm-text--ellipsis mm-box--color-text-default" + data-testid="network-display" + /> + <span + class="mm-box mm-picker-network__arrow-down-icon mm-icon mm-icon--size-xs mm-box--margin-left-auto mm-box--display-none mm-box--color-icon-default" + style="mask-image: url('./images/icons/arrow-down.svg');" + /> </div> </div> <h3 @@ -131,26 +126,21 @@ exports[`switch-ethereum-chain confirmation should show alert if there are pendi class="box box--margin-top-2 box--flex-direction-row box--justify-content-center box--display-flex" > <div - class="network-display chip chip--with-left-icon chip--border-color-border-muted chip--background-color-undefined chip--max-content" - data-testid="network-display" + class="mm-box mm-picker-network network-display mm-box--padding-right-4 mm-box--padding-left-2 mm-box--display-flex mm-box--gap-2 mm-box--align-items-center mm-box--background-color-transparent mm-box--rounded-pill mm-box--border-color-border-muted mm-box--border-width-0 box--border-style-solid box--border-width-1" > <div - class="chip__left-icon" + class="mm-box mm-text mm-avatar-base mm-avatar-base--size-xs mm-avatar-network mm-picker-network__avatar-network mm-text--body-xs mm-text--text-transform-uppercase mm-box--display-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-full mm-box--border-color-transparent box--border-style-solid box--border-width-1" > - <div - class="color-indicator color-indicator--filled color-indicator--color-icon-muted color-indicator--size-xs" - data-testid="color-icon-icon-muted" - > - <span - class="color-indicator__inner-circle" - /> - </div> + ? </div> <span - class="mm-box mm-text chip__label mm-text--h7 mm-box--color-text-default" - > - Test initial state - </span> + class="mm-box mm-text mm-text--body-sm mm-text--ellipsis mm-box--color-text-default" + data-testid="network-display" + /> + <span + class="mm-box mm-picker-network__arrow-down-icon mm-icon mm-icon--size-xs mm-box--margin-left-auto mm-box--display-none mm-box--color-icon-default" + style="mask-image: url('./images/icons/arrow-down.svg');" + /> </div> </div> <h3 diff --git a/ui/pages/confirmations/hooks/alerts/useBlockaidAlerts.ts b/ui/pages/confirmations/hooks/alerts/useBlockaidAlerts.ts index ad93e1a87d5f..ae87e60d64f6 100644 --- a/ui/pages/confirmations/hooks/alerts/useBlockaidAlerts.ts +++ b/ui/pages/confirmations/hooks/alerts/useBlockaidAlerts.ts @@ -13,7 +13,10 @@ import { REDESIGN_TRANSACTION_TYPES, SIGNATURE_TRANSACTION_TYPES, } from '../../utils'; -import { currentConfirmationSelector } from '../../selectors'; +import { + currentConfirmationSelector, + currentSignatureRequestSecurityResponseSelector, +} from '../../selectors'; import { normalizeProviderAlert } from './utils'; const SUPPORTED_TRANSACTION_TYPES = [ @@ -47,8 +50,7 @@ const useBlockaidAlerts = (): Alert[] => { const transactionType = currentConfirmation?.type as TransactionType; const signatureSecurityAlertResponse = useSelector( - (state: SecurityAlertResponsesState) => - state.metamask.signatureSecurityAlertResponses?.[securityAlertId], + currentSignatureRequestSecurityResponseSelector, ); const transactionSecurityAlertResponse = useSelector( diff --git a/ui/pages/confirmations/selectors/confirm.test.ts b/ui/pages/confirmations/selectors/confirm.test.ts index e95da11e2cba..0aa56cb3f82e 100644 --- a/ui/pages/confirmations/selectors/confirm.test.ts +++ b/ui/pages/confirmations/selectors/confirm.test.ts @@ -1,12 +1,24 @@ import { ApprovalType } from '@metamask/controller-utils'; import { TransactionType } from '@metamask/transaction-controller'; -import { ConfirmMetamaskState } from '../types/confirm'; + +import { + BlockaidReason, + BlockaidResultType, +} from '../../../../shared/constants/security-provider'; +import { ConfirmMetamaskState, SecurityAlertResponse } from '../types/confirm'; import { currentConfirmationSelector, + currentSignatureRequestSecurityResponseSelector, latestPendingConfirmationSelector, pendingConfirmationsSelector, } from './confirm'; +const SECURITY_ALERT_RESPONSE_MOCK: SecurityAlertResponse = { + securityAlertId: '1', + result_type: BlockaidResultType.Malicious, + reason: BlockaidReason.permitFarming, +}; + describe('confirm selectors', () => { const mockedState: ConfirmMetamaskState = { confirm: { @@ -75,4 +87,28 @@ describe('confirm selectors', () => { expect(result).toStrictEqual(mockedState.confirm.currentConfirmation); }); }); + + describe('currentSignatureRequestSecurityResponseSelector', () => { + it('should return SecurityAlertResponse for current signature', () => { + const sigMockState: ConfirmMetamaskState = { + confirm: { + currentConfirmation: { + id: '1', + type: TransactionType.personalSign, + securityAlertResponse: SECURITY_ALERT_RESPONSE_MOCK, + }, + }, + metamask: { + pendingApprovals: {}, + approvalFlows: [], + signatureSecurityAlertResponses: { 1: SECURITY_ALERT_RESPONSE_MOCK }, + }, + }; + + const result = + currentSignatureRequestSecurityResponseSelector(sigMockState); + + expect(result).toStrictEqual(SECURITY_ALERT_RESPONSE_MOCK); + }); + }); }); diff --git a/ui/pages/confirmations/selectors/confirm.ts b/ui/pages/confirmations/selectors/confirm.ts index 8cc7dd19a95f..e4af9333e8d5 100644 --- a/ui/pages/confirmations/selectors/confirm.ts +++ b/ui/pages/confirmations/selectors/confirm.ts @@ -2,8 +2,13 @@ import { ApprovalType } from '@metamask/controller-utils'; import { createSelector } from 'reselect'; import { getPendingApprovals } from '../../../selectors/approvals'; -import { ConfirmMetamaskState } from '../types/confirm'; +import { + ConfirmMetamaskState, + Confirmation, + SecurityAlertResponse, +} from '../types/confirm'; import { createDeepEqualSelector } from '../../../selectors/util'; +import { isSignatureTransactionType } from '../utils'; const ConfirmationApprovalTypes = [ ApprovalType.EthSign, @@ -43,3 +48,23 @@ export const confirmSelector = (state: ConfirmMetamaskState) => state.confirm; export const currentConfirmationSelector = (state: ConfirmMetamaskState) => state.confirm.currentConfirmation; + +export const currentSignatureRequestSecurityResponseSelector = ( + state: ConfirmMetamaskState, +) => { + const currentConfirmation: Confirmation | undefined = + currentConfirmationSelector(state); + + if ( + !currentConfirmation || + !isSignatureTransactionType(currentConfirmation) + ) { + return undefined; + } + + const securityAlertId = ( + currentConfirmation?.securityAlertResponse as SecurityAlertResponse + )?.securityAlertId as string; + + return state.metamask.signatureSecurityAlertResponses?.[securityAlertId]; +}; diff --git a/ui/pages/confirmations/token-allowance/token-allowance.js b/ui/pages/confirmations/token-allowance/token-allowance.js index e8d6bbf5bbbe..56519615e00c 100644 --- a/ui/pages/confirmations/token-allowance/token-allowance.js +++ b/ui/pages/confirmations/token-allowance/token-allowance.js @@ -61,9 +61,7 @@ import { NUM_W_OPT_DECIMAL_COMMA_OR_DOT_REGEX, } from '../../../../shared/constants/tokens'; import { isSuspiciousResponse } from '../../../../shared/modules/security-provider.utils'; -///: BEGIN:ONLY_INCLUDE_IF(blockaid) import BlockaidBannerAlert from '../components/security-provider-banner-alert/blockaid-banner-alert/blockaid-banner-alert'; -///: END:ONLY_INCLUDE_IF import { ConfirmPageContainerNavigation } from '../components/confirm-page-container'; import { useSimulationFailureWarning } from '../hooks/useSimulationFailureWarning'; import SimulationErrorMessage from '../components/simulation-error-message'; @@ -381,16 +379,12 @@ export default function TokenAllowance({ accountAddress={userAddress} chainId={fullTxData.chainId} /> - { - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) - <BlockaidBannerAlert - txData={txData} - marginTop={4} - marginLeft={4} - marginRight={4} - /> - ///: END:ONLY_INCLUDE_IF - } + <BlockaidBannerAlert + txData={txData} + marginTop={4} + marginLeft={4} + marginRight={4} + /> <BlockaidUnavailableBannerAlert /> {isSuspiciousResponse(txData?.securityProviderResponse) && ( <SecurityProviderBannerMessage diff --git a/ui/pages/confirmations/types/confirm.ts b/ui/pages/confirmations/types/confirm.ts index 8b2a6b4cd293..36a1b6a31397 100644 --- a/ui/pages/confirmations/types/confirm.ts +++ b/ui/pages/confirmations/types/confirm.ts @@ -46,5 +46,6 @@ export type ConfirmMetamaskState = { metamask: { pendingApprovals: ApprovalControllerState['pendingApprovals']; approvalFlows: ApprovalControllerState['approvalFlows']; + signatureSecurityAlertResponses?: Record<string, SecurityAlertResponse>; }; }; diff --git a/ui/pages/settings/security-tab/security-tab.component.js b/ui/pages/settings/security-tab/security-tab.component.js index b20435e4b258..1ed946f259cb 100644 --- a/ui/pages/settings/security-tab/security-tab.component.js +++ b/ui/pages/settings/security-tab/security-tab.component.js @@ -99,9 +99,7 @@ export default class SecurityTab extends PureComponent { securityAlertsEnabled: PropTypes.bool, useExternalServices: PropTypes.bool, toggleExternalServices: PropTypes.func.isRequired, - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) setSecurityAlertsEnabled: PropTypes.func, - ///: END:ONLY_INCLUDE_IF }; state = { @@ -999,7 +997,6 @@ export default class SecurityTab extends PureComponent { ); } - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) /** * toggleSecurityAlert * @@ -1017,7 +1014,6 @@ export default class SecurityTab extends PureComponent { }); setSecurityAlertsEnabled(newValue); } - ///: END:ONLY_INCLUDE_IF renderUseExternalServices() { const { t } = this.context; @@ -1132,9 +1128,7 @@ export default class SecurityTab extends PureComponent { {this.context.t('security')} </span> {this.renderSeedWords()} - {/* ///: BEGIN:ONLY_INCLUDE_IF(blockaid) */} {this.renderSecurityAlertsToggle()} - {/* ///: END:ONLY_INCLUDE_IF */} <span className="settings-page__security-tab-sub-header__bold"> {this.context.t('privacy')} </span> diff --git a/ui/pages/settings/security-tab/security-tab.container.js b/ui/pages/settings/security-tab/security-tab.container.js index 98a2c7c9c3f5..66aee77ae962 100644 --- a/ui/pages/settings/security-tab/security-tab.container.js +++ b/ui/pages/settings/security-tab/security-tab.container.js @@ -19,15 +19,11 @@ import { setUseSafeChainsListValidation, setUseExternalNameSources, setUseTransactionSimulations, - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) setSecurityAlertsEnabled, - ///: END:ONLY_INCLUDE_IF } from '../../../store/actions'; import { getAllNetworks, - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) getIsSecurityAlertsEnabled, - ///: END:ONLY_INCLUDE_IF getPetnamesEnabled, } from '../../../selectors'; import { openBasicFunctionalityModal } from '../../../ducks/app/app'; @@ -80,9 +76,7 @@ const mapStateToProps = (state) => { useExternalNameSources, useExternalServices, petnamesEnabled, - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) securityAlertsEnabled: getIsSecurityAlertsEnabled(state), - ///: END:ONLY_INCLUDE_IF useTransactionSimulations: metamask.useTransactionSimulations, }; }; @@ -122,9 +116,7 @@ const mapDispatchToProps = (dispatch) => { setUseTransactionSimulations: (value) => { return dispatch(setUseTransactionSimulations(value)); }, - ///: BEGIN:ONLY_INCLUDE_IF(blockaid) setSecurityAlertsEnabled: (value) => setSecurityAlertsEnabled(value), - ///: END:ONLY_INCLUDE_IF }; }; diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index 8653ac48d0ce..f613015efb7c 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -2247,7 +2247,6 @@ export function getUseRequestQueue(state) { return state.metamask.useRequestQueue; } -///: BEGIN:ONLY_INCLUDE_IF(blockaid) /** * To get the `getIsSecurityAlertsEnabled` value which determines whether security check is enabled * @@ -2257,7 +2256,6 @@ export function getUseRequestQueue(state) { export function getIsSecurityAlertsEnabled(state) { return state.metamask.securityAlertsEnabled; } -///: END:ONLY_INCLUDE_IF ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) /** diff --git a/ui/store/actions.ts b/ui/store/actions.ts index 8082409268c2..4a75d4828212 100644 --- a/ui/store/actions.ts +++ b/ui/store/actions.ts @@ -4956,7 +4956,6 @@ export function setNetworkClientIdForDomain( ]); } -///: BEGIN:ONLY_INCLUDE_IF(blockaid) export function setSecurityAlertsEnabled(val: boolean): void { try { submitRequestToBackground('setSecurityAlertsEnabled', [val]); @@ -4964,7 +4963,6 @@ export function setSecurityAlertsEnabled(val: boolean): void { logErrorWithMessage(error); } } -///: END:ONLY_INCLUDE_IF ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) export async function setAddSnapAccountEnabled(value: boolean): Promise<void> { diff --git a/yarn.lock b/yarn.lock index 3d4c54fc1746..c9fac8508f47 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6396,9 +6396,9 @@ __metadata: languageName: node linkType: hard -"@metamask/snaps-controllers@npm:^9.0.0": - version: 9.0.0 - resolution: "@metamask/snaps-controllers@npm:9.0.0" +"@metamask/snaps-controllers@npm:^9.2.0": + version: 9.2.0 + resolution: "@metamask/snaps-controllers@npm:9.2.0" dependencies: "@metamask/approval-controller": "npm:^7.0.0" "@metamask/base-controller": "npm:^6.0.0" @@ -6410,9 +6410,9 @@ __metadata: "@metamask/post-message-stream": "npm:^8.1.0" "@metamask/rpc-errors": "npm:^6.2.1" "@metamask/snaps-registry": "npm:^3.1.0" - "@metamask/snaps-rpc-methods": "npm:^9.1.3" - "@metamask/snaps-sdk": "npm:^5.0.0" - "@metamask/snaps-utils": "npm:^7.6.0" + "@metamask/snaps-rpc-methods": "npm:^9.1.4" + "@metamask/snaps-sdk": "npm:^6.0.0" + "@metamask/snaps-utils": "npm:^7.7.0" "@metamask/utils": "npm:^8.3.0" "@xstate/fsm": "npm:^2.0.0" browserify-zlib: "npm:^0.2.0" @@ -6425,30 +6425,30 @@ __metadata: readable-web-to-node-stream: "npm:^3.0.2" tar-stream: "npm:^3.1.7" peerDependencies: - "@metamask/snaps-execution-environments": ^6.4.0 + "@metamask/snaps-execution-environments": ^6.5.0 peerDependenciesMeta: "@metamask/snaps-execution-environments": optional: true - checksum: 10/12e89e622865025e89c0f06f34e9dad278f91b3621e2b9944b154a7f190e5b47d5a899beb65e431627e023ebcd00969c492a280a5051239b57ed24cf5c3347ec + checksum: 10/3926bdfc3f064d57162825028aca2cf433e7adfe02ecdade174e2c75686c3dff407ee195f352662754846fc4edad8d2c6c5ce73471e3a09191a91070a98ba046 languageName: node linkType: hard -"@metamask/snaps-execution-environments@npm:^6.4.0": - version: 6.4.0 - resolution: "@metamask/snaps-execution-environments@npm:6.4.0" +"@metamask/snaps-execution-environments@npm:^6.5.0": + version: 6.5.0 + resolution: "@metamask/snaps-execution-environments@npm:6.5.0" dependencies: "@metamask/json-rpc-engine": "npm:^9.0.0" "@metamask/object-multiplex": "npm:^2.0.0" "@metamask/post-message-stream": "npm:^8.1.0" "@metamask/providers": "npm:^17.0.0" "@metamask/rpc-errors": "npm:^6.2.1" - "@metamask/snaps-sdk": "npm:^5.0.0" - "@metamask/snaps-utils": "npm:^7.6.0" + "@metamask/snaps-sdk": "npm:^6.0.0" + "@metamask/snaps-utils": "npm:^7.7.0" "@metamask/utils": "npm:^8.3.0" nanoid: "npm:^3.1.31" readable-stream: "npm:^3.6.2" superstruct: "npm:^1.0.3" - checksum: 10/ef487a7b8e2b1aa46c214d06e14d482a741abdc75f5904ff61f38b019cd253422cd5ae95fba7263b0fab57256eb081a3c44eeafcdff8ad71d5bf9163d65fd5dc + checksum: 10/f502fb1ff1c7c574bf4b7e189cc636d85aacb9e86116720a8c6305ce2054a3ebd966b2f73be242bf5f8f301c79f6b3461a7d2c631301b6593ad1d3f09e100c21 languageName: node linkType: hard @@ -6464,38 +6464,38 @@ __metadata: languageName: node linkType: hard -"@metamask/snaps-rpc-methods@npm:^9.1.2, @metamask/snaps-rpc-methods@npm:^9.1.3": - version: 9.1.3 - resolution: "@metamask/snaps-rpc-methods@npm:9.1.3" +"@metamask/snaps-rpc-methods@npm:^9.1.2, @metamask/snaps-rpc-methods@npm:^9.1.4": + version: 9.1.4 + resolution: "@metamask/snaps-rpc-methods@npm:9.1.4" dependencies: "@metamask/key-tree": "npm:^9.1.1" "@metamask/permission-controller": "npm:^10.0.0" "@metamask/rpc-errors": "npm:^6.2.1" - "@metamask/snaps-sdk": "npm:^5.0.0" - "@metamask/snaps-utils": "npm:^7.6.0" + "@metamask/snaps-sdk": "npm:^6.0.0" + "@metamask/snaps-utils": "npm:^7.7.0" "@metamask/utils": "npm:^8.3.0" "@noble/hashes": "npm:^1.3.1" superstruct: "npm:^1.0.3" - checksum: 10/d346f12fb170dac694b4b5d1580fe9bc212cd266cece063636be85c442be0a7d0fa98e1d93d999da3dc67a9b5ce49c5a67e5345567b97062dd94e7d10c4e2959 + checksum: 10/db4963c2eaf1763ca48be4f095b0adae29596efc9ebf7876ac92fa6e3ef8d2bc5d45634293566b8a4703109c569f2666b4350700139d0566cb29f65be77a17f1 languageName: node linkType: hard -"@metamask/snaps-sdk@npm:^5.0.0": - version: 5.0.0 - resolution: "@metamask/snaps-sdk@npm:5.0.0" +"@metamask/snaps-sdk@npm:^6.0.0": + version: 6.0.0 + resolution: "@metamask/snaps-sdk@npm:6.0.0" dependencies: "@metamask/key-tree": "npm:^9.1.1" "@metamask/providers": "npm:^17.0.0" "@metamask/rpc-errors": "npm:^6.2.1" "@metamask/utils": "npm:^8.3.0" superstruct: "npm:^1.0.3" - checksum: 10/2419edb193c32fbd7292ebddbe37e9af6b09dc175fa03b74e9b732b859cdd1b6ddd5d18d19dcf0d550fdcfdb6210ec89168e020c382d3cf41178f51e0e1e888c + checksum: 10/91774ea791423a3cfef4ddbe30fc0351d9bfb9bad071ebce6a74be85cdd9b864b2666785cb6f0e8257a9778bc630f2de71544258d0367a93917ffe3d72ef90a5 languageName: node linkType: hard -"@metamask/snaps-utils@npm:^7.1.0, @metamask/snaps-utils@npm:^7.4.0, @metamask/snaps-utils@npm:^7.5.0, @metamask/snaps-utils@npm:^7.6.0": - version: 7.6.0 - resolution: "@metamask/snaps-utils@npm:7.6.0" +"@metamask/snaps-utils@npm:^7.1.0, @metamask/snaps-utils@npm:^7.4.0, @metamask/snaps-utils@npm:^7.5.0, @metamask/snaps-utils@npm:^7.7.0": + version: 7.7.0 + resolution: "@metamask/snaps-utils@npm:7.7.0" dependencies: "@babel/core": "npm:^7.23.2" "@babel/types": "npm:^7.23.0" @@ -6505,7 +6505,7 @@ __metadata: "@metamask/rpc-errors": "npm:^6.2.1" "@metamask/slip44": "npm:^3.1.0" "@metamask/snaps-registry": "npm:^3.1.0" - "@metamask/snaps-sdk": "npm:^5.0.0" + "@metamask/snaps-sdk": "npm:^6.0.0" "@metamask/utils": "npm:^8.3.0" "@noble/hashes": "npm:^1.3.1" "@scure/base": "npm:^1.1.1" @@ -6520,7 +6520,7 @@ __metadata: ses: "npm:^1.1.0" superstruct: "npm:^1.0.3" validate-npm-package-name: "npm:^5.0.0" - checksum: 10/e81e0185ab1678822b47e400c4422023449be1641bea7ce3d679386257545091ecc73c9a4626c0ed585d93d9fe3a1354dc8e4b8310c27c33871f7fb0bb029506 + checksum: 10/ac5b216b81157f71244e5922befccb214be402f0f5b784086cea46d7b0142f14f555ec7986cb7c867d1b99bfe43b08a687d8db22db85fada55764c2f4afcff97 languageName: node linkType: hard @@ -25506,11 +25506,11 @@ __metadata: "@metamask/selected-network-controller": "npm:^15.0.2" "@metamask/signature-controller": "npm:^16.0.0" "@metamask/smart-transactions-controller": "npm:^10.1.2" - "@metamask/snaps-controllers": "npm:^9.0.0" - "@metamask/snaps-execution-environments": "npm:^6.4.0" - "@metamask/snaps-rpc-methods": "npm:^9.1.3" - "@metamask/snaps-sdk": "npm:^5.0.0" - "@metamask/snaps-utils": "npm:^7.6.0" + "@metamask/snaps-controllers": "npm:^9.2.0" + "@metamask/snaps-execution-environments": "npm:^6.5.0" + "@metamask/snaps-rpc-methods": "npm:^9.1.4" + "@metamask/snaps-sdk": "npm:^6.0.0" + "@metamask/snaps-utils": "npm:^7.7.0" "@metamask/test-bundler": "npm:^1.0.0" "@metamask/test-dapp": "npm:^8.4.0" "@metamask/transaction-controller": "npm:^32.0.0"