diff --git a/.eslintrc.js b/.eslintrc.js index c4c4cc41927e..64c51bd1e503 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -21,6 +21,36 @@ module.exports = { plugins: ['@metamask/design-tokens'], rules: { '@metamask/design-tokens/color-no-hex': 'warn', + 'import/no-restricted-paths': [ + 'error', + { + basePath: './', + zones: [ + { + target: './app', + from: './ui', + message: + 'Should not import from UI in background, use shared directory instead', + }, + { + target: './ui', + from: './app', + message: + 'Should not import from background in UI, use shared directory instead', + }, + { + target: './shared', + from: './app', + message: 'Should not import from background in shared', + }, + { + target: './shared', + from: './ui', + message: 'Should not import from UI in shared', + }, + ], + }, + ], }, overrides: [ /** diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index 85e776155793..3b23de7fb61b 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -1005,9 +1005,6 @@ "confirmTitleDescSIWESignature": { "message": "Eine Website möchte, dass Sie sich anmelden, um zu beweisen, dass Sie dieses Konto besitzen." }, - "confirmTitleDescSignature": { - "message": "Bestätigen Sie diese Nachricht nur, wenn Sie dem Inhalt zustimmen und der anfragenden Website vertrauen." - }, "confirmTitlePermitTokens": { "message": "Antrag auf Ausgabenobergrenze" }, @@ -2867,10 +2864,11 @@ }, "nativeTokenScamWarningDescription": { "message": "Dieses Netzwerk passt nicht zu seiner zugehörigen Chain-ID oder seinem Namen. Viele beliebte Tokens verwenden den Namen $1, was sie zu einem Ziel für Betrüger macht. Betrüger könnten Sie dazu verleiten, ihnen im Gegenzug wertvollere Währung zu schicken. Überprüfen Sie alles, bevor Sie fortfahren.", - "description": "$1 represents the currency name" + "description": "$1 represents the currency name, $2 represents the expected currency symbol" }, "nativeTokenScamWarningTitle": { - "message": "Dies ist ein möglicher Betrug" + "message": "Dies ist ein möglicher Betrug", + "description": "Title for nativeTokenScamWarningDescription" }, "needHelp": { "message": "Brauchen Sie Hilfe? Kontaktieren Sie $1.", diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json index a8cee7a6aab1..5df72a342c5f 100644 --- a/app/_locales/el/messages.json +++ b/app/_locales/el/messages.json @@ -1005,9 +1005,6 @@ "confirmTitleDescSIWESignature": { "message": "Ένας ιστότοπος θέλει να συνδεθείτε για να αποδείξετε ότι είστε ο κάτοχος αυτού του λογαριασμού." }, - "confirmTitleDescSignature": { - "message": "Επιβεβαιώστε αυτό το μήνυμα μόνο εάν εγκρίνετε το περιεχόμενο και εμπιστεύεστε τον ιστότοπο που το ζητάει." - }, "confirmTitlePermitTokens": { "message": "Αίτημα ανώτατου ορίου δαπανών" }, @@ -2867,10 +2864,11 @@ }, "nativeTokenScamWarningDescription": { "message": "Αυτό το δίκτυο δεν ταιριάζει με το αναγνωριστικό ή το όνομα της σχετικής αλυσίδας. Πολλά δημοφιλή tokens χρησιμοποιούν το όνομα $1, καθιστώντας το στόχο για απάτες. Οι απατεώνες μπορεί να σας ξεγελάσουν για να τους στείλετε πιο πολύτιμα νομίσματα σε αντάλλαγμα. Επαληθεύστε τα πάντα προτού συνεχίσετε.", - "description": "$1 represents the currency name" + "description": "$1 represents the currency name, $2 represents the expected currency symbol" }, "nativeTokenScamWarningTitle": { - "message": "Πρόκειται για πιθανή απάτη" + "message": "Πρόκειται για πιθανή απάτη", + "description": "Title for nativeTokenScamWarningDescription" }, "needHelp": { "message": "Χρειάζεστε βοήθεια; Επικοινωνήστε με $1", diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index bd1ebb7f0de8..18236e3b109d 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1062,8 +1062,8 @@ "confirmTitleDescSIWESignature": { "message": "A site wants you to sign in to prove you own this account." }, - "confirmTitleDescSignature": { - "message": "Only confirm this message if you approve the content and trust the requesting site." + "confirmTitleDescSign": { + "message": "Review request details before you confirm." }, "confirmTitlePermitTokens": { "message": "Spending cap request" @@ -2986,11 +2986,16 @@ "message": "Edit network details" }, "nativeTokenScamWarningDescription": { - "message": "This network doesn't match its associated chain ID or name. Many popular tokens use the name $1, making it a target for scams. Scammers may trick you into sending them more valuable currency in return. Verify everything before you continue.", - "description": "$1 represents the currency name" + "message": "The native token symbol does not match the expected symbol of the native token for the network with the associated chain ID. You have entered $1 while the expected token symbol is $2. Please verify you are connected to the correct chain.", + "description": "$1 represents the currency name, $2 represents the expected currency symbol" + }, + "nativeTokenScamWarningDescriptionExpectedTokenFallback": { + "message": "something else", + "description": "graceful fallback for when token symbol isn't found" }, "nativeTokenScamWarningTitle": { - "message": "This is a potential scam" + "message": "Unexpected Native Token Symbol", + "description": "Title for nativeTokenScamWarningDescription" }, "needHelp": { "message": "Need help? Contact $1", @@ -3770,6 +3775,9 @@ "permissionDetails": { "message": "Permission details" }, + "permissionFor": { + "message": "Permission for" + }, "permissionRequest": { "message": "Permission request" }, @@ -4733,6 +4741,9 @@ "setApprovalForAll": { "message": "Set approval for all" }, + "setApprovalForAllRedesignedTitle": { + "message": "Withdrawal request" + }, "setApprovalForAllTitle": { "message": "Approve $1 with no spend limit", "description": "The token symbol that is being approved" @@ -4852,6 +4863,9 @@ "simulationDetailsOutgoingHeading": { "message": "You send" }, + "simulationDetailsSetApprovalForAllDesc": { + "message": "You're giving permission for someone else to withdraw NFTs from your account." + }, "simulationDetailsTitle": { "message": "Estimated changes" }, @@ -6536,6 +6550,9 @@ "whatsThis": { "message": "What's this?" }, + "withdrawing": { + "message": "Withdrawing" + }, "wrongNetworkName": { "message": "According to our records, the network name may not correctly match this chain ID." }, diff --git a/app/_locales/en_GB/messages.json b/app/_locales/en_GB/messages.json index e67b9f0e4fcb..63fadc1b03e0 100644 --- a/app/_locales/en_GB/messages.json +++ b/app/_locales/en_GB/messages.json @@ -1036,9 +1036,6 @@ "confirmTitleDescSIWESignature": { "message": "A site wants you to sign in to prove you own this account." }, - "confirmTitleDescSignature": { - "message": "Only confirm this message if you approve the content and trust the requesting site." - }, "confirmTitlePermitTokens": { "message": "Spending cap request" }, @@ -6458,9 +6455,6 @@ "whatsThis": { "message": "What's this?" }, - "wrongChainId": { - "message": "This chain ID doesn’t match the network name." - }, "wrongNetworkName": { "message": "According to our records, the network name may not correctly match this chain ID." }, diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index 2346fda97d16..67143b9609d3 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -1002,9 +1002,6 @@ "confirmTitleDescSIWESignature": { "message": "Un sitio quiere que inicie sesión para demostrar que es el propietario de esta cuenta." }, - "confirmTitleDescSignature": { - "message": "Solo confirme este mensaje si aprueba el contenido y confía en el sitio solicitante." - }, "confirmTitlePermitTokens": { "message": "Solicitud de límite de gasto" }, @@ -2864,10 +2861,11 @@ }, "nativeTokenScamWarningDescription": { "message": "Esta red no coincide con su ID de cadena o nombre asociado. Muchos tokens populares usan el nombre $1, lo que los convierte en blanco de estafas. Los estafadores pueden engañarlo para que les envíe dinero más valioso a cambio. Verifique todo antes de continuar.", - "description": "$1 represents the currency name" + "description": "$1 represents the currency name, $2 represents the expected currency symbol" }, "nativeTokenScamWarningTitle": { - "message": "Esto es una estafa potencial" + "message": "Esto es una estafa potencial", + "description": "Title for nativeTokenScamWarningDescription" }, "needHelp": { "message": "¿Necesita ayuda? Comuníquese con $1", diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index eff9261237fa..e63594a57539 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -1005,9 +1005,6 @@ "confirmTitleDescSIWESignature": { "message": "Un site vous demande de vous connecter pour prouver que vous êtes le titulaire de ce compte." }, - "confirmTitleDescSignature": { - "message": "Ne confirmez ce message que si vous approuvez son contenu et faites confiance au site demandeur." - }, "confirmTitlePermitTokens": { "message": "Demande de plafonnement des dépenses" }, @@ -2867,10 +2864,11 @@ }, "nativeTokenScamWarningDescription": { "message": "L’ID ou le nom de la chaîne associée à ce réseau n’est pas correct. De nombreux jetons populaires utilisent le nom $1, ce qui en fait une cible pour les escrocs. Vérifiez tout avant de continuer, car vous risquez de vous faire arnaquer.", - "description": "$1 represents the currency name" + "description": "$1 represents the currency name, $2 represents the expected currency symbol" }, "nativeTokenScamWarningTitle": { - "message": "Il pourrait s’agir d’une arnaque" + "message": "Il pourrait s’agir d’une arnaque", + "description": "Title for nativeTokenScamWarningDescription" }, "needHelp": { "message": "Vous avez besoin d’aide ? Contactez $1", diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index a41bda8439cc..f75c0279d401 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -1005,9 +1005,6 @@ "confirmTitleDescSIWESignature": { "message": "एक साइट चाहती है कि आप यह साबित करने के लिए साइन इन करें कि यह आपका अकाउंट है।" }, - "confirmTitleDescSignature": { - "message": "इस संदेश को केवल तभी कन्फर्म करें जब आप कंटेंट को एप्रूव करते हैं और अनुरोध करने वाली साइट पर भरोसा करते हैं।" - }, "confirmTitlePermitTokens": { "message": "खर्च करने की सीमा का अनुरोध" }, @@ -2867,10 +2864,11 @@ }, "nativeTokenScamWarningDescription": { "message": "यह नेटवर्क अपनी एसोसिएटेड चेन ID या नाम से मेल नहीं खाता है। कई लोकप्रिय टोकन $1 नाम का उपयोग करते हैं, जिससे इसमें स्कैम किया जा सकता है। स्कैम करने वाले आपको बदले में ज़्यादा कीमती करेंसी भेजने का झांसा दे सकते हैं। आगे बढ़ने से पहले सब कुछ वेरीफाई करें।", - "description": "$1 represents the currency name" + "description": "$1 represents the currency name, $2 represents the expected currency symbol" }, "nativeTokenScamWarningTitle": { - "message": "यह एक बड़ा स्कैम हो सकता है" + "message": "यह एक बड़ा स्कैम हो सकता है", + "description": "Title for nativeTokenScamWarningDescription" }, "needHelp": { "message": "मदद चाहिए? $1 से कॉन्टेक्ट करें", diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index b13602011b99..185af2ea637a 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -1005,9 +1005,6 @@ "confirmTitleDescSIWESignature": { "message": "Sebuah situs ingin Anda masuk untuk membuktikan Anda pemilik akun ini." }, - "confirmTitleDescSignature": { - "message": "Konfirmasikan pesan ini hanya jika Anda menyetujui isinya dan memercayai situs yang memintanya." - }, "confirmTitlePermitTokens": { "message": "Permintaan batas penggunaan" }, @@ -2867,10 +2864,11 @@ }, "nativeTokenScamWarningDescription": { "message": "Jaringan ini tidak cocok dengan ID chain atau nama yang terkait. Banyak token populer menggunakan nama $1, menjadikannya target penipuan. Penipu dapat mengelabui Anda agar mengirimkan mata uang yang lebih berharga sebagai imbalannya. Verifikasikan semuanya sebelum melanjutkan.", - "description": "$1 represents the currency name" + "description": "$1 represents the currency name, $2 represents the expected currency symbol" }, "nativeTokenScamWarningTitle": { - "message": "Ini berpotensi penipuan" + "message": "Ini berpotensi penipuan", + "description": "Title for nativeTokenScamWarningDescription" }, "needHelp": { "message": "Butuh bantuan? Hubungi $1", diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index 8d006fef2257..e699ccf2dc09 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -1005,9 +1005,6 @@ "confirmTitleDescSIWESignature": { "message": "サイトがこのアカウントを所有することを証明するためにサインインを求めています。" }, - "confirmTitleDescSignature": { - "message": "このメッセージの内容を承認し、要求元のサイトを信頼する場合にのみ確定してください。" - }, "confirmTitlePermitTokens": { "message": "使用上限リクエスト" }, @@ -2867,10 +2864,11 @@ }, "nativeTokenScamWarningDescription": { "message": "このネットワークは関連付けられているチェーンIDまたは名前と一致していません。人気のトークンの多くが「$1」という名前を使用しているため、詐欺の対象となっています。詐欺師はより価値の高い通貨を送り返すよう仕向けてくる可能性があります。続行する前にすべてを確認してください。", - "description": "$1 represents the currency name" + "description": "$1 represents the currency name, $2 represents the expected currency symbol" }, "nativeTokenScamWarningTitle": { - "message": "これは詐欺の可能性があります" + "message": "これは詐欺の可能性があります", + "description": "Title for nativeTokenScamWarningDescription" }, "needHelp": { "message": "アシスタンスが必要な場合は、$1にお問い合わせください", diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index 666d99d90b00..8419b0437090 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -1005,9 +1005,6 @@ "confirmTitleDescSIWESignature": { "message": "회원님이 이 계정을 소유하고 있음을 확인하기 위해 로그인을 요청하는 사이트가 있습니다." }, - "confirmTitleDescSignature": { - "message": "요청하는 사이트를 신뢰하고 그 내용을 완전히 이해하는 경우에만 이 메시지를 컨펌하세요." - }, "confirmTitlePermitTokens": { "message": "지출 한도 요청" }, @@ -2867,10 +2864,11 @@ }, "nativeTokenScamWarningDescription": { "message": "이 네트워크는 연결된 체인 ID 또는 이름이 일치하지 않습니다. 여러 인기 토큰이 $1(이)라는 이름을 사용하기 때문에 사기의 표적이 되고 있습니다. 사기꾼은 더 가격이 높은 암호화폐를 주겠다고 속일 수 있습니다. 계속하기 전에 모든 사항을 확인하세요.", - "description": "$1 represents the currency name" + "description": "$1 represents the currency name, $2 represents the expected currency symbol" }, "nativeTokenScamWarningTitle": { - "message": "사기일 수 있습니다" + "message": "사기일 수 있습니다", + "description": "Title for nativeTokenScamWarningDescription" }, "needHelp": { "message": "도움이 필요하신가요? $1에 문의하세요.", diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json index a5de21cb0889..246d2f7dce02 100644 --- a/app/_locales/pt/messages.json +++ b/app/_locales/pt/messages.json @@ -1005,9 +1005,6 @@ "confirmTitleDescSIWESignature": { "message": "Um site quer que você faça login para comprovar que é titular desta conta." }, - "confirmTitleDescSignature": { - "message": "Confirme esta mensagem somente se você aprova o conteúdo e confia no site solicitante." - }, "confirmTitlePermitTokens": { "message": "Solicitação de limite de gastos" }, @@ -2867,10 +2864,11 @@ }, "nativeTokenScamWarningDescription": { "message": "Esta rede não corresponde ao seu ID da cadeia ou nome associado. Como muitos tokens populares usam o nome $1, ele é visado para golpes. Golpistas podem enganar você para que envie a eles alguma moeda mais valiosa em troca. Confirme todas as informações antes de prosseguir.", - "description": "$1 represents the currency name" + "description": "$1 represents the currency name, $2 represents the expected currency symbol" }, "nativeTokenScamWarningTitle": { - "message": "Isto é um possível golpe" + "message": "Isto é um possível golpe", + "description": "Title for nativeTokenScamWarningDescription" }, "needHelp": { "message": "Precisa de ajuda? Contate $1", diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index aba23b0b3284..088c2c904e33 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -1005,9 +1005,6 @@ "confirmTitleDescSIWESignature": { "message": "Сайт требует, чтобы вы вошли в систему и доказали, что вы являетесь владельцем этого счета." }, - "confirmTitleDescSignature": { - "message": "Подтверждайте это сообщение только в том случае, если вы одобряете его содержание и доверяете запрашивающему сайту." - }, "confirmTitlePermitTokens": { "message": "Запрос лимита расходов" }, @@ -2867,10 +2864,11 @@ }, "nativeTokenScamWarningDescription": { "message": "Эта сеть не соответствует ID или имени связанного с ней блокчейна. Многие популярные токены используют название $1, что делает его объектом мошенничества. Мошенники могут обманом заставить вас отправить им взамен более ценную валюту. Проверьте все, прежде чем продолжить.", - "description": "$1 represents the currency name" + "description": "$1 represents the currency name, $2 represents the expected currency symbol" }, "nativeTokenScamWarningTitle": { - "message": "Это потенциальное мошенничество" + "message": "Это потенциальное мошенничество", + "description": "Title for nativeTokenScamWarningDescription" }, "needHelp": { "message": "Нужна помощь? Обратитесь в $1", diff --git a/app/_locales/tl/messages.json b/app/_locales/tl/messages.json index 9089ff123db1..0f17e7a2148b 100644 --- a/app/_locales/tl/messages.json +++ b/app/_locales/tl/messages.json @@ -1005,9 +1005,6 @@ "confirmTitleDescSIWESignature": { "message": "Nais ng site na mag-sign in ka upang patunayan na pag-aari mo ang account na ito." }, - "confirmTitleDescSignature": { - "message": "Kumpirmahin lamang ang mensaheng ito kung ganap mong nauunawaan ang nilalaman at nagtitiwala sa site na humihiling." - }, "confirmTitlePermitTokens": { "message": "Hiling sa limitasyon ng paggastos" }, @@ -2867,10 +2864,11 @@ }, "nativeTokenScamWarningDescription": { "message": "Ang network na ito ay hindi tugma sa kaugnay na chain ID o pangalan nito. Maraming popular na token ang gumagamit ng pangalang $1, kaya nagiging puntirya ito ng mga scam. Maaari kang linlangin ng mga scammer na magpadala sa kanila ng mas mahal na currency bilang kapalit. I-verify ang lahat bago magpatuloy.", - "description": "$1 represents the currency name" + "description": "$1 represents the currency name, $2 represents the expected currency symbol" }, "nativeTokenScamWarningTitle": { - "message": "Isa itong potensyal na scam" + "message": "Isa itong potensyal na scam", + "description": "Title for nativeTokenScamWarningDescription" }, "needHelp": { "message": "Kailangan ng tulong? Makipag-ugnayan sa $1", diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json index 7537fd19b1fe..b521a5e9a182 100644 --- a/app/_locales/tr/messages.json +++ b/app/_locales/tr/messages.json @@ -1005,9 +1005,6 @@ "confirmTitleDescSIWESignature": { "message": "Bir site bu hesabın sahibi olduğunuzu kanıtlamak için giriş yapmanızı istiyor." }, - "confirmTitleDescSignature": { - "message": "Bu mesajı sadece içeriği onaylıyorsanız ve talepte bulunan siteye güveniyorsanız onaylayın." - }, "confirmTitlePermitTokens": { "message": "Harcama üst limiti talebi" }, @@ -2867,10 +2864,11 @@ }, "nativeTokenScamWarningDescription": { "message": "Bu ağ, ilişkili zincir kimliği veya adı ile uyumlu değil. Pek çok popüler token $1 adını kullanarak bunu dolandırıcılar için hedef haline getirir. Dolandırıcılar, karşılığında kendilerine daha değerli para birimi göndermek üzere sizi kandırabilir. Devam etmeden önce her şeyi doğrulayın.", - "description": "$1 represents the currency name" + "description": "$1 represents the currency name, $2 represents the expected currency symbol" }, "nativeTokenScamWarningTitle": { - "message": "Bu potansiyel bir dolandırıcılıktır" + "message": "Bu potansiyel bir dolandırıcılıktır", + "description": "Title for nativeTokenScamWarningDescription" }, "needHelp": { "message": "Yardıma mı ihtiyacınız var? $1 bölümüne ulaşın", diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index 81e8c008a46b..a8946a010469 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -1005,9 +1005,6 @@ "confirmTitleDescSIWESignature": { "message": "Một trang web yêu cầu bạn đăng nhập để chứng minh quyền sở hữu tài khoản này." }, - "confirmTitleDescSignature": { - "message": "Chỉ xác nhận thông báo này nếu bạn chấp thuận nội dung và tin tưởng trang web yêu cầu." - }, "confirmTitlePermitTokens": { "message": "Yêu cầu hạn mức chi tiêu" }, @@ -2867,10 +2864,11 @@ }, "nativeTokenScamWarningDescription": { "message": "Mạng này không trùng khớp với tên hoặc ID chuỗi liên quan của nó. Nhiều token phổ biến sử dụng tên $1, khiến nó trở thành mục tiêu của các hành vi lừa đảo. Kẻ lừa đảo có thể lừa bạn gửi lại cho họ loại tiền tệ có giá trị hơn. Hãy xác minh mọi thứ trước khi tiếp tục.", - "description": "$1 represents the currency name" + "description": "$1 represents the currency name, $2 represents the expected currency symbol" }, "nativeTokenScamWarningTitle": { - "message": "Đây có khả năng là một hành vi lừa đảo" + "message": "Đây có khả năng là một hành vi lừa đảo", + "description": "Title for nativeTokenScamWarningDescription" }, "needHelp": { "message": "Bạn cần trợ giúp? Liên hệ $1", diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index 5b556663ac31..cef81c20f839 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -1005,9 +1005,6 @@ "confirmTitleDescSIWESignature": { "message": "某个网站要求您登录以证明您拥有该账户。" }, - "confirmTitleDescSignature": { - "message": "仅在您批准该内容并信任请求网站的情况下,才能确认此消息。" - }, "confirmTitlePermitTokens": { "message": "支出上限请求" }, @@ -2867,10 +2864,11 @@ }, "nativeTokenScamWarningDescription": { "message": "此网络与其关联的链 ID 或名称不匹配。多种常用代币均使用名称 $1,使其成为欺诈目标。欺诈方可能会诱骗您向其发送更有价值的货币作为回报。在继续之前,请验证所有内容。", - "description": "$1 represents the currency name" + "description": "$1 represents the currency name, $2 represents the expected currency symbol" }, "nativeTokenScamWarningTitle": { - "message": "这可能是欺诈" + "message": "这可能是欺诈", + "description": "Title for nativeTokenScamWarningDescription" }, "needHelp": { "message": "需要帮助?请联系 $1", diff --git a/app/scripts/background.js b/app/scripts/background.js index 3f513e142729..4fbbee449160 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -53,6 +53,8 @@ import { FakeLedgerBridge, FakeTrezorBridge, } from '../../test/stub/keyring-bridge'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getCurrentChainId } from '../../ui/selectors'; import migrations from './migrations'; import Migrator from './lib/migrator'; diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index c7ea00bec97a..32498a1c8bce 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -7,6 +7,8 @@ import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller'; import { MINUTE } from '../../../shared/constants/time'; import { AUTO_LOCK_TIMEOUT_ALARM } from '../../../shared/constants/alarms'; import { isManifestV3 } from '../../../shared/modules/mv3.utils'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { isBeta } from '../../../ui/helpers/utils/build-types'; import { ENVIRONMENT_TYPE_BACKGROUND, diff --git a/app/scripts/controllers/bridge/bridge-controller.ts b/app/scripts/controllers/bridge/bridge-controller.ts index f899879605cf..6ca076c2e060 100644 --- a/app/scripts/controllers/bridge/bridge-controller.ts +++ b/app/scripts/controllers/bridge/bridge-controller.ts @@ -1,4 +1,6 @@ import { BaseController, StateMetadata } from '@metamask/base-controller'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { fetchBridgeFeatureFlags } from '../../../../ui/pages/bridge/bridge.util'; import { BRIDGE_CONTROLLER_NAME, diff --git a/app/scripts/controllers/mmi-controller.ts b/app/scripts/controllers/mmi-controller.ts index 6351de5b7239..cbb08308ec59 100644 --- a/app/scripts/controllers/mmi-controller.ts +++ b/app/scripts/controllers/mmi-controller.ts @@ -28,6 +28,8 @@ import { NetworkController } from '@metamask/network-controller'; import { InternalAccount } from '@metamask/keyring-api'; import { toHex } from '@metamask/controller-utils'; import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { CONNECT_HARDWARE_ROUTE } from '../../../ui/helpers/constants/routes'; import { MMIControllerOptions, @@ -38,6 +40,8 @@ import { ConnectionRequest, } from '../../../shared/constants/mmi-controller'; import AccountTracker from '../lib/account-tracker'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getCurrentChainId } from '../../../ui/selectors'; import MetaMetricsController from './metametrics'; import { getPermissionBackgroundApiMethods } from './permissions'; diff --git a/app/scripts/lib/createRPCMethodTrackingMiddleware.js b/app/scripts/lib/createRPCMethodTrackingMiddleware.js index 6f4c06ee521c..b50905b8cb65 100644 --- a/app/scripts/lib/createRPCMethodTrackingMiddleware.js +++ b/app/scripts/lib/createRPCMethodTrackingMiddleware.js @@ -21,7 +21,11 @@ import { SIGNING_METHODS } from '../../../shared/constants/transaction'; import { generateSignatureUniqueId, getBlockaidMetricsProps, + // TODO: Remove restricted import + // eslint-disable-next-line import/no-restricted-paths } from '../../../ui/helpers/utils/metrics'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { REDESIGN_APPROVAL_TYPES } from '../../../ui/pages/confirmations/utils/confirm'; import { getSnapAndHardwareInfoForMetrics } from './snap-keyring/metrics'; diff --git a/app/scripts/lib/snap-keyring/bitcoin-wallet-snap.ts b/app/scripts/lib/snap-keyring/bitcoin-wallet-snap.ts index 1ffca624f759..98f231607dba 100644 --- a/app/scripts/lib/snap-keyring/bitcoin-wallet-snap.ts +++ b/app/scripts/lib/snap-keyring/bitcoin-wallet-snap.ts @@ -5,6 +5,8 @@ import { Json, JsonRpcRequest } from '@metamask/utils'; // This dependency is still installed as part of the `package.json`, however // the Snap is being pre-installed only for Flask build (for the moment). import BitcoinWalletSnap from '@metamask/bitcoin-wallet-snap/dist/preinstalled-snap.json'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { handleSnapRequest } from '../../../../ui/store/actions'; export const BITCOIN_WALLET_SNAP_ID: SnapId = diff --git a/app/scripts/lib/snap-keyring/snap-keyring.ts b/app/scripts/lib/snap-keyring/snap-keyring.ts index d707b0bb61c4..4e3450bc65d0 100644 --- a/app/scripts/lib/snap-keyring/snap-keyring.ts +++ b/app/scripts/lib/snap-keyring/snap-keyring.ts @@ -10,6 +10,8 @@ import { import { SNAP_MANAGE_ACCOUNTS_CONFIRMATION_TYPES } from '../../../../shared/constants/app'; import { t } from '../../translate'; import MetamaskController from '../../metamask-controller'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { IconName } from '../../../../ui/components/component-library/icon'; import { isBlockedUrl } from './utils/isBlockedUrl'; import { showError, showSuccess } from './utils/showResult'; diff --git a/app/scripts/lib/snap-keyring/utils/showResult.ts b/app/scripts/lib/snap-keyring/utils/showResult.ts index 086f9fe07174..9bb0dfa65dad 100644 --- a/app/scripts/lib/snap-keyring/utils/showResult.ts +++ b/app/scripts/lib/snap-keyring/utils/showResult.ts @@ -2,6 +2,8 @@ import type { ResultComponent, ErrorResult, } from '@metamask/approval-controller'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { IconName } from '../../../../../ui/components/component-library/icon'; import { SnapKeyringBuilderMessenger } from '../types'; diff --git a/app/scripts/lib/transaction/metrics.ts b/app/scripts/lib/transaction/metrics.ts index 3177e2d74b26..66c1e7fcd669 100644 --- a/app/scripts/lib/transaction/metrics.ts +++ b/app/scripts/lib/transaction/metrics.ts @@ -40,10 +40,14 @@ import { import { getBlockaidMetricsProps, getSwapAndSendMetricsProps, + // TODO: Remove restricted import + // eslint-disable-next-line import/no-restricted-paths } from '../../../../ui/helpers/utils/metrics'; import { REDESIGN_DEV_TRANSACTION_TYPES, REDESIGN_USER_TRANSACTION_TYPES, + // TODO: Remove restricted import + // eslint-disable-next-line import/no-restricted-paths } from '../../../../ui/pages/confirmations/utils'; import { getSnapAndHardwareInfoForMetrics, diff --git a/app/scripts/lib/tx-verification/tx-verification-middleware.ts b/app/scripts/lib/tx-verification/tx-verification-middleware.ts index 856305717a45..5349feaf1cf9 100644 --- a/app/scripts/lib/tx-verification/tx-verification-middleware.ts +++ b/app/scripts/lib/tx-verification/tx-verification-middleware.ts @@ -17,6 +17,8 @@ import { TRUSTED_SIGNERS, } from '../../../../shared/constants/verification'; import { MESSAGE_TYPE } from '../../../../shared/constants/app'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getCurrentChainId } from '../../../../ui/selectors'; export type TxParams = { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 6289608c5291..8ad88c088b46 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -155,10 +155,7 @@ import { NotificationServicesPushController, NotificationServicesController, } from '@metamask/notification-services-controller'; -import { - methodsRequiringNetworkSwitch, - methodsWithConfirmation, -} from '../../shared/constants/methods-tags'; +import { methodsRequiringNetworkSwitch } from '../../shared/constants/methods-tags'; ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils'; @@ -228,7 +225,11 @@ import { TOKEN_TRANSFER_LOG_TOPIC_HASH, TRANSFER_SINFLE_LOG_TOPIC_HASH, } from '../../shared/lib/transactions-controller-utils'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getCurrentChainId } from '../../ui/selectors'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getProviderConfig } from '../../ui/ducks/metamask/metamask'; import { endTrace, trace } from '../../shared/lib/trace'; import { BalancesController as MultichainBalancesController } from './lib/accounts/BalancesController'; @@ -5507,16 +5508,7 @@ export default class MetamaskController extends EventEmitter { this.preferencesController, ), shouldEnqueueRequest: (request) => { - if ( - request.method === 'eth_requestAccounts' && - this.permissionController.hasPermission( - request.origin, - PermissionNames.eth_accounts, - ) - ) { - return false; - } - return methodsWithConfirmation.includes(request.method); + return methodsRequiringNetworkSwitch.includes(request.method); }, }); engine.push(requestQueueMiddleware); diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 7440b0cea9cc..4b73862934cb 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -5,6 +5,8 @@ import { startCase, toLower } from 'lodash'; import { TransactionStatus } from '@metamask/transaction-controller'; import { getEnvironmentType } from '../lib/util'; import { ENVIRONMENT_TYPE_BACKGROUND } from '../../../shared/constants/app'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getURLHostName } from '../../../ui/helpers/utils/util'; import { t } from '../translate'; diff --git a/app/scripts/ui.js b/app/scripts/ui.js index fdcfd90621ce..4f06fb8998c4 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -15,6 +15,8 @@ import Eth from '@metamask/ethjs'; import EthQuery from '@metamask/eth-query'; import StreamProvider from 'web3-stream-provider'; import log from 'loglevel'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import launchMetaMaskUi, { updateBackgroundConnection } from '../../ui'; import { ENVIRONMENT_TYPE_FULLSCREEN, diff --git a/package.json b/package.json index 7fa321fb7829..12d1cd30d956 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,7 @@ "lint:changed:fix": "./development/get-changed-file-names.sh | grep -E --regexp='[.](js|ts|tsx)$' | tr '\\n' '\\0' | xargs -0 eslint --fix --cache --cache-location node_modules/.cache/eslint/.eslint-cache", "lint:changelog": "auto-changelog validate", "lint:changelog:rc": "auto-changelog validate --rc", + "lint:debug": "DEBUG=eslint:cli-engine yarn lint", "lint:eslint": "eslint . --ext js,ts,tsx,snap --cache --cache-location node_modules/.cache/eslint/.eslint-cache", "lint:eslint:fix": "yarn lint:eslint --fix --cache --cache-location node_modules/.cache/eslint/.eslint-cache", "lint:lockfile:dedupe": "yarn dedupe --check", diff --git a/shared/constants/methods-tags.ts b/shared/constants/methods-tags.ts index 651109dcedcf..a35954769b1b 100644 --- a/shared/constants/methods-tags.ts +++ b/shared/constants/methods-tags.ts @@ -10,24 +10,9 @@ export const methodsRequiringNetworkSwitch = [ 'eth_sendTransaction', 'eth_sendRawTransaction', 'wallet_switchEthereumChain', - 'wallet_addEthereumChain', 'wallet_watchAsset', 'eth_signTypedData', 'eth_signTypedData_v3', 'eth_signTypedData_v4', 'personal_sign', ] as const; - -/** - * This is a list of methods that can cause a confirmation to be - * presented to the user. Note that some of these methods may - * only sometimes cause a confirmation to appear. - */ -export const methodsWithConfirmation = [ - ...methodsRequiringNetworkSwitch, - 'wallet_requestPermissions', - 'wallet_requestSnaps', - 'eth_decrypt', - 'eth_requestAccounts', - 'eth_getEncryptionPublicKey', -]; diff --git a/shared/constants/mmi-controller.ts b/shared/constants/mmi-controller.ts index 67123b83d5d7..50cc26ef5541 100644 --- a/shared/constants/mmi-controller.ts +++ b/shared/constants/mmi-controller.ts @@ -4,9 +4,17 @@ import { TransactionUpdateController } from '@metamask-institutional/transaction import { CustodyController } from '@metamask-institutional/custody-controller'; import { SignatureController } from '@metamask/signature-controller'; import { NetworkController } from '@metamask/network-controller'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import PreferencesController from '../../app/scripts/controllers/preferences-controller'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { AppStateController } from '../../app/scripts/controllers/app-state'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import AccountTracker from '../../app/scripts/lib/account-tracker'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import MetaMetricsController from '../../app/scripts/controllers/metametrics'; export type MMIControllerOptions = { diff --git a/shared/constants/network.ts b/shared/constants/network.ts index ffc85ea96b4d..a98417794d81 100644 --- a/shared/constants/network.ts +++ b/shared/constants/network.ts @@ -374,7 +374,6 @@ const CHAINLIST_CURRENCY_SYMBOLS_MAP = { export const CHAINLIST_CURRENCY_SYMBOLS_MAP_NETWORK_COLLISION = { WETHIO: 'ZYN', CHZ: 'CHZ', - MATIC: 'POL', }; export const ETH_TOKEN_IMAGE_URL = './images/eth_logo.svg'; diff --git a/shared/lib/error-utils.js b/shared/lib/error-utils.js index 567337eb5ab4..89caef28026d 100644 --- a/shared/lib/error-utils.js +++ b/shared/lib/error-utils.js @@ -1,4 +1,6 @@ import { memoize } from 'lodash'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import getFirstPreferredLangCode from '../../app/scripts/lib/get-first-preferred-lang-code'; import { fetchLocale, loadRelativeTimeFormatLocaleData } from '../modules/i18n'; import switchDirection from './switch-direction'; diff --git a/shared/lib/multichain.ts b/shared/lib/multichain.ts index 07466e439266..fec52295eada 100644 --- a/shared/lib/multichain.ts +++ b/shared/lib/multichain.ts @@ -1,3 +1,5 @@ +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { isEthAddress } from '../../app/scripts/lib/multichain/address'; /** diff --git a/shared/lib/swaps-utils.js b/shared/lib/swaps-utils.js index a49542c273df..d80d70902810 100644 --- a/shared/lib/swaps-utils.js +++ b/shared/lib/swaps-utils.js @@ -14,6 +14,8 @@ import { import { SECOND } from '../constants/time'; import { isValidHexAddress } from '../modules/hexstring-utils'; import { isEqualCaseInsensitive } from '../modules/string-utils'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { addHexPrefix } from '../../app/scripts/lib/util'; import { decimalToHex } from '../modules/conversion.utils'; import fetchWithCache from './fetch-with-cache'; diff --git a/shared/lib/swaps-utils.test.js b/shared/lib/swaps-utils.test.js index c248278d8467..06080a8f55e7 100644 --- a/shared/lib/swaps-utils.test.js +++ b/shared/lib/swaps-utils.test.js @@ -9,6 +9,8 @@ import { import { TOKENS, MOCK_TRADE_RESPONSE_2, + // TODO: Remove restricted import + // eslint-disable-next-line import/no-restricted-paths } from '../../ui/pages/swaps/swaps-util-test-constants'; import { fetchTradesInfo, diff --git a/shared/lib/trace.ts b/shared/lib/trace.ts index aaf3db7d46af..e51c2d3cbdcf 100644 --- a/shared/lib/trace.ts +++ b/shared/lib/trace.ts @@ -1,6 +1,8 @@ import * as Sentry from '@sentry/browser'; import { Primitive, StartSpanOptions } from '@sentry/types'; import { createModuleLogger } from '@metamask/utils'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { log as sentryLogger } from '../../app/scripts/lib/setupSentry'; export enum TraceName { diff --git a/shared/modules/browser-runtime.utils.js b/shared/modules/browser-runtime.utils.js index c082ef9b8c78..94022784c9f9 100644 --- a/shared/modules/browser-runtime.utils.js +++ b/shared/modules/browser-runtime.utils.js @@ -8,6 +8,8 @@ import log from 'loglevel'; import { BROKEN_PRERENDER_BROWSER_VERSIONS, FIXED_PRERENDER_BROWSER_VERSIONS, + // TODO: Remove restricted import + // eslint-disable-next-line import/no-restricted-paths } from '../../ui/helpers/constants/common'; /** diff --git a/shared/modules/metametrics.test.ts b/shared/modules/metametrics.test.ts index 29434cfb1687..93d423fb3d2d 100644 --- a/shared/modules/metametrics.test.ts +++ b/shared/modules/metametrics.test.ts @@ -4,6 +4,8 @@ import { TransactionType, } from '@metamask/transaction-controller'; import { createTestProviderTools } from '../../test/stub/provider'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { TransactionMetricsRequest } from '../../app/scripts/lib/transaction/metrics'; import { CHAIN_IDS } from '../constants/network'; import { getSmartTransactionMetricsProperties } from './metametrics'; diff --git a/shared/modules/metametrics.ts b/shared/modules/metametrics.ts index af049231bdf5..c60c7a0e44cd 100644 --- a/shared/modules/metametrics.ts +++ b/shared/modules/metametrics.ts @@ -1,4 +1,6 @@ import { TransactionMeta } from '@metamask/transaction-controller'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { TransactionMetricsRequest } from '../../app/scripts/lib/transaction/metrics'; type SmartTransactionMetricsProperties = { diff --git a/shared/modules/selectors/account.ts b/shared/modules/selectors/account.ts index e124ed6f0458..4ff0dec0b261 100644 --- a/shared/modules/selectors/account.ts +++ b/shared/modules/selectors/account.ts @@ -1,3 +1,5 @@ +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { isHardwareWallet } from '../../../ui/selectors/selectors'; export { isHardwareWallet }; diff --git a/shared/modules/selectors/feature-flags.ts b/shared/modules/selectors/feature-flags.ts index 930f478aa962..429df2c06da6 100644 --- a/shared/modules/selectors/feature-flags.ts +++ b/shared/modules/selectors/feature-flags.ts @@ -1,3 +1,5 @@ +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getCurrentChainId } from '../../../ui/selectors/selectors'; // TODO: Migrate shared selectors to this file. import { getNetworkNameByChainId } from '../feature-flags'; diff --git a/shared/modules/selectors/index.ts b/shared/modules/selectors/index.ts index d53296394c26..9cd44470752b 100644 --- a/shared/modules/selectors/index.ts +++ b/shared/modules/selectors/index.ts @@ -1,3 +1,5 @@ +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getHardwareWalletType } from '../../../ui/selectors/selectors'; export * from './smart-transactions'; diff --git a/shared/modules/selectors/smart-transactions.ts b/shared/modules/selectors/smart-transactions.ts index 0de20511db49..1c3147632381 100644 --- a/shared/modules/selectors/smart-transactions.ts +++ b/shared/modules/selectors/smart-transactions.ts @@ -7,9 +7,13 @@ import { getCurrentNetwork, accountSupportsSmartTx, getSelectedAccount, + // TODO: Remove restricted import + // eslint-disable-next-line import/no-restricted-paths } from '../../../ui/selectors/selectors'; // TODO: Migrate shared selectors to this file. import { isProduction } from '../environment'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { MultichainState } from '../../../ui/selectors/multichain'; type SmartTransactionsMetaMaskState = { diff --git a/sonar-project.properties b/sonar-project.properties index 31d4a98b41e7..0ee619db70ff 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -2,8 +2,9 @@ sonar.projectKey=metamask-extension sonar.organization=consensys # Source -sonar.sources=app,development,offscreen,shared,test,types,ui -sonar.exclusions=**/*.test.**,**/*.spec.**,app/images,test/** +sonar.sources=app,development,offscreen,shared,types,ui +sonar.exclusions=**/*.test.**,**/*.spec.**,app/images,test/e2e/page-objects,test/data + # Tests sonar.tests=app,development,offscreen,shared,test,types,ui diff --git a/test/data/confirmations/contract-interaction.ts b/test/data/confirmations/contract-interaction.ts index f6ad5a8633ea..0556789ccdb2 100644 --- a/test/data/confirmations/contract-interaction.ts +++ b/test/data/confirmations/contract-interaction.ts @@ -181,3 +181,23 @@ export const genUnapprovedApproveConfirmation = ({ }, type: TransactionType.tokenMethodApprove, }); + +export const genUnapprovedSetApprovalForAllConfirmation = ({ + address = CONTRACT_INTERACTION_SENDER_ADDRESS, + chainId = CHAIN_ID, +}: { + address?: Hex; + chainId?: string; +} = {}) => ({ + ...genUnapprovedContractInteractionConfirmation({ chainId }), + txParams: { + from: address, + data: '0x095ea7b30000000000000000000000002e0d7e8c45221fca00d74a3609a0f7097035d09b0000000000000000000000000000000000000000000000000000000000000001', + gas: '0x16a92', + to: '0x076146c765189d51be3160a2140cf80bfc73ad68', + value: '0x0', + maxFeePerGas: '0x5b06b0c0d', + maxPriorityFeePerGas: '0x59682f00', + }, + type: TransactionType.tokenMethodSetApprovalForAll, +}); diff --git a/test/data/confirmations/helper.ts b/test/data/confirmations/helper.ts index c542ee92feab..9eb8bb234768 100644 --- a/test/data/confirmations/helper.ts +++ b/test/data/confirmations/helper.ts @@ -10,6 +10,7 @@ import { CHAIN_IDS } from '../../../shared/constants/network'; import { genUnapprovedApproveConfirmation, genUnapprovedContractInteractionConfirmation, + genUnapprovedSetApprovalForAllConfirmation, } from './contract-interaction'; import { unapprovedPersonalSignMsg } from './personal_sign'; import { unapprovedTypedSignMsgV4 } from './typed_sign'; @@ -176,3 +177,9 @@ export const getMockApproveConfirmState = () => { genUnapprovedApproveConfirmation({ chainId: '0x5' }), ); }; + +export const getMockSetApprovalForAllConfirmState = () => { + return getMockConfirmStateForTransaction( + genUnapprovedSetApprovalForAllConfirmation({ chainId: '0x5' }), + ); +}; diff --git a/test/e2e/accounts/smart-swap-disabled.spec.ts b/test/e2e/accounts/smart-swap-disabled.spec.ts deleted file mode 100644 index 4e6ce9b2c6ef..000000000000 --- a/test/e2e/accounts/smart-swap-disabled.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Suite } from 'mocha'; -import { withFixtures, defaultGanacheOptions } from '../helpers'; -import { Driver } from '../webdriver/driver'; -import FixtureBuilder from '../fixture-builder'; -import { installSnapSimpleKeyring, makeNewAccountAndSwitch } from './common'; - -describe('Snap Account - Smart Swaps', function (this: Suite) { - it('checks if smart swaps are disabled for snap accounts', async function () { - await withFixtures( - { - fixtures: new FixtureBuilder().build(), - ganacheOptions: defaultGanacheOptions, - title: this.test?.fullTitle(), - }, - async ({ driver }: { driver: Driver }) => { - await installSnapSimpleKeyring(driver, false); - await makeNewAccountAndSwitch(driver); - await driver.clickElement('[data-testid="token-overview-button-swap"]'); - await driver.clickElement('[title="Transaction settings"]'); - - await driver.assertElementNotPresent( - '[data-testid="transaction-settings-smart-swaps-toggle"]', - { findElementGuard: { tag: 'h6', text: 'Slippage tolerance' } }, // wait for the modal to appear - ); - }, - ); - }); -}); diff --git a/test/e2e/page-objects/common.ts b/test/e2e/page-objects/common.ts new file mode 100644 index 000000000000..b1f678b80cca --- /dev/null +++ b/test/e2e/page-objects/common.ts @@ -0,0 +1 @@ +export type RawLocator = string | { css: string; text: string }; diff --git a/test/e2e/page-objects/pages/confirmation.ts b/test/e2e/page-objects/pages/confirmation.ts new file mode 100644 index 000000000000..3ec372cb3163 --- /dev/null +++ b/test/e2e/page-objects/pages/confirmation.ts @@ -0,0 +1,27 @@ +import { Driver } from '../../webdriver/driver'; +import { RawLocator } from '../common'; + +class Confirmation { + protected driver: Driver; + + private scrollToBottomButton: RawLocator; + + private footerConfirmButton: RawLocator; + + constructor(driver: Driver) { + this.driver = driver; + + this.scrollToBottomButton = '.confirm-scroll-to-bottom__button'; + this.footerConfirmButton = '[data-testid="confirm-footer-button"]'; + } + + async clickScrollToBottomButton() { + await this.driver.clickElementSafe(this.scrollToBottomButton); + } + + async clickFooterConfirmButton() { + await this.driver.clickElement(this.footerConfirmButton); + } +} + +export default Confirmation; diff --git a/test/e2e/page-objects/pages/set-approval-for-all-transaction-confirmation.ts b/test/e2e/page-objects/pages/set-approval-for-all-transaction-confirmation.ts new file mode 100644 index 000000000000..ddd6ccb5e2b8 --- /dev/null +++ b/test/e2e/page-objects/pages/set-approval-for-all-transaction-confirmation.ts @@ -0,0 +1,35 @@ +import { tEn } from '../../../lib/i18n-helpers'; +import { Driver } from '../../webdriver/driver'; +import { RawLocator } from '../common'; +import TransactionConfirmation from './transaction-confirmation'; + +class SetApprovalForAllTransactionConfirmation extends TransactionConfirmation { + private setApprovalForAllTitleElement: RawLocator; + + private setApprovalForAllSubHeadingElement: RawLocator; + + constructor(driver: Driver) { + super(driver); + + this.driver = driver; + + this.setApprovalForAllTitleElement = { + css: 'h2', + text: tEn('setApprovalForAllRedesignedTitle') as string, + }; + this.setApprovalForAllSubHeadingElement = { + css: 'p', + text: tEn('confirmTitleDescApproveTransaction') as string, + }; + } + + async check_setApprovalForAllTitle() { + await this.driver.waitForSelector(this.setApprovalForAllTitleElement); + } + + async check_setApprovalForAllSubHeading() { + await this.driver.waitForSelector(this.setApprovalForAllSubHeadingElement); + } +} + +export default SetApprovalForAllTransactionConfirmation; diff --git a/test/e2e/page-objects/pages/test-dapp.ts b/test/e2e/page-objects/pages/test-dapp.ts index 8c2fe513ca10..29ff1f1e16b7 100644 --- a/test/e2e/page-objects/pages/test-dapp.ts +++ b/test/e2e/page-objects/pages/test-dapp.ts @@ -1,4 +1,5 @@ import { Driver } from '../../webdriver/driver'; +import { RawLocator } from '../common'; const DAPP_HOST_ADDRESS = '127.0.0.1:8080'; const DAPP_URL = `http://${DAPP_HOST_ADDRESS}`; @@ -6,8 +7,15 @@ const DAPP_URL = `http://${DAPP_HOST_ADDRESS}`; class TestDapp { private driver: Driver; + private erc721SetApprovalForAllButton: RawLocator; + + private erc1155SetApprovalForAllButton: RawLocator; + constructor(driver: Driver) { this.driver = driver; + + this.erc721SetApprovalForAllButton = '#setApprovalForAllButton'; + this.erc1155SetApprovalForAllButton = '#setApprovalForAllERC1155Button'; } async open({ @@ -32,6 +40,14 @@ class TestDapp { )}`, }); } + + async clickERC721SetApprovalForAllButton() { + await this.driver.clickElement(this.erc721SetApprovalForAllButton); + } + + async clickERC1155SetApprovalForAllButton() { + await this.driver.clickElement(this.erc1155SetApprovalForAllButton); + } } export default TestDapp; diff --git a/test/e2e/page-objects/pages/transaction-confirmation.ts b/test/e2e/page-objects/pages/transaction-confirmation.ts new file mode 100644 index 000000000000..7ae98d74d4c8 --- /dev/null +++ b/test/e2e/page-objects/pages/transaction-confirmation.ts @@ -0,0 +1,5 @@ +import Confirmation from './confirmation'; + +class TransactionConfirmation extends Confirmation {} + +export default TransactionConfirmation; diff --git a/test/e2e/tests/confirmations/alerts/insufficient-funds.spec.ts b/test/e2e/tests/confirmations/alerts/insufficient-funds.spec.ts index f8d70b8e6568..9c74714c82e6 100644 --- a/test/e2e/tests/confirmations/alerts/insufficient-funds.spec.ts +++ b/test/e2e/tests/confirmations/alerts/insufficient-funds.spec.ts @@ -7,7 +7,6 @@ import { WINDOW_TITLES, } from '../../../helpers'; import { SMART_CONTRACTS } from '../../../seeder/smart-contracts'; -import { scrollAndConfirmAndAssertConfirm } from '../helpers'; import { TestSuiteArguments, openDAppWithContract, @@ -48,8 +47,6 @@ describe('Alert for insufficient funds @no-mmi', function () { await verifyAlertForInsufficientBalance(driver); - await scrollAndConfirmAndAssertConfirm(driver); - await verifyConfirmationIsDisabled(driver); }, ); @@ -58,7 +55,7 @@ describe('Alert for insufficient funds @no-mmi', function () { async function verifyConfirmationIsDisabled(driver: Driver) { const confirmButton = await driver.findElement( - '[data-testid="confirm-alert-modal-submit-button"]', + '[data-testid="confirm-footer-button"]', ); assert.equal(await confirmButton.isEnabled(), false); } diff --git a/test/e2e/tests/confirmations/helpers.ts b/test/e2e/tests/confirmations/helpers.ts index 7fe5ef9da87b..ff467f42c320 100644 --- a/test/e2e/tests/confirmations/helpers.ts +++ b/test/e2e/tests/confirmations/helpers.ts @@ -1,6 +1,12 @@ +import { TransactionEnvelopeType } from '@metamask/transaction-controller'; import FixtureBuilder from '../../fixture-builder'; -import { defaultGanacheOptions, withFixtures } from '../../helpers'; +import { + defaultGanacheOptions, + defaultGanacheOptionsForType2Transactions, + withFixtures, +} from '../../helpers'; import { MockedEndpoint, Mockttp } from '../../mock-e2e'; +import { SMART_CONTRACTS } from '../../seeder/smart-contracts'; import { Driver } from '../../webdriver/driver'; export async function scrollAndConfirmAndAssertConfirm(driver: Driver) { @@ -14,15 +20,15 @@ export function withRedesignConfirmationFixtures( // title. It's optional because it's sometimes unset. // eslint-disable-next-line @typescript-eslint/default-param-last title: string = '', + transactionEnvelopeType: TransactionEnvelopeType, testFunction: Parameters[1], - mockSegment?: (mockServer: Mockttp) => Promise, // Add mockSegment as an optional parameter + mocks?: (mockServer: Mockttp) => Promise, // Add mocks as an optional parameter + smartContract?: typeof SMART_CONTRACTS, ) { return withFixtures( { dapp: true, - driverOptions: { - timeOut: 20000, - }, + driverOptions: { timeOut: 20000 }, fixtures: new FixtureBuilder() .withPermissionControllerConnectedToTestDapp() .withMetaMetricsController({ @@ -32,12 +38,17 @@ export function withRedesignConfirmationFixtures( .withPreferencesController({ preferences: { redesignedConfirmationsEnabled: true, + isRedesignedConfirmationsDeveloperEnabled: true, }, }) .build(), - ganacheOptions: defaultGanacheOptions, + ganacheOptions: + transactionEnvelopeType === TransactionEnvelopeType.legacy + ? defaultGanacheOptions + : defaultGanacheOptionsForType2Transactions, + smartContract, + testSpecificMock: mocks, title, - testSpecificMock: mockSegment, }, testFunction, ); diff --git a/test/e2e/tests/confirmations/navigation.spec.ts b/test/e2e/tests/confirmations/navigation.spec.ts index f6347981ce15..8d195656dc44 100644 --- a/test/e2e/tests/confirmations/navigation.spec.ts +++ b/test/e2e/tests/confirmations/navigation.spec.ts @@ -1,11 +1,12 @@ import { strict as assert } from 'assert'; +import { TransactionEnvelopeType } from '@metamask/transaction-controller'; import { Suite } from 'mocha'; import { DAPP_HOST_ADDRESS, WINDOW_TITLES, openDapp, - unlockWallet, regularDelayMs, + unlockWallet, } from '../../helpers'; import { Driver } from '../../webdriver/driver'; import { withRedesignConfirmationFixtures } from './helpers'; @@ -14,6 +15,7 @@ describe('Navigation Signature - Different signature types', function (this: Sui it('initiates and queues multiple signatures and confirms', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver }: { driver: Driver }) => { await unlockWallet(driver); await openDapp(driver); @@ -53,6 +55,7 @@ describe('Navigation Signature - Different signature types', function (this: Sui it('initiates and queues a mix of signatures and transactions and navigates', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver }: { driver: Driver }) => { await unlockWallet(driver); await openDapp(driver); @@ -90,6 +93,7 @@ describe('Navigation Signature - Different signature types', function (this: Sui it('initiates multiple signatures and rejects all', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver }: { driver: Driver }) => { await unlockWallet(driver); await openDapp(driver); diff --git a/test/e2e/tests/confirmations/signatures/malicious-signatures.spec.ts b/test/e2e/tests/confirmations/signatures/malicious-signatures.spec.ts index 7e4568d326f0..bde56537e43f 100644 --- a/test/e2e/tests/confirmations/signatures/malicious-signatures.spec.ts +++ b/test/e2e/tests/confirmations/signatures/malicious-signatures.spec.ts @@ -1,4 +1,5 @@ import { strict as assert } from 'assert'; +import { TransactionEnvelopeType } from '@metamask/transaction-controller'; import { Suite } from 'mocha'; import { MockedEndpoint } from 'mockttp'; import { WINDOW_TITLES } from '../../../helpers'; @@ -19,6 +20,7 @@ describe('Malicious Confirmation Signature - Bad Domain @no-mmi', function (this it('displays alert for domain binding and confirms', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver }: TestSuiteArguments) => { await openDappAndTriggerSignature(driver, SignatureType.SIWE_BadDomain); @@ -41,6 +43,7 @@ describe('Malicious Confirmation Signature - Bad Domain @no-mmi', function (this it('initiates and rejects from confirmation screen', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver, mockedEndpoint: mockedEndpoints, @@ -87,6 +90,7 @@ describe('Malicious Confirmation Signature - Bad Domain @no-mmi', function (this it('initiates and rejects from alert friction modal', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver, mockedEndpoint: mockedEndpoints, diff --git a/test/e2e/tests/confirmations/signatures/permit.spec.ts b/test/e2e/tests/confirmations/signatures/permit.spec.ts index 8455a9fa8254..cd27f359aa87 100644 --- a/test/e2e/tests/confirmations/signatures/permit.spec.ts +++ b/test/e2e/tests/confirmations/signatures/permit.spec.ts @@ -1,11 +1,12 @@ import { strict as assert } from 'assert'; +import { TransactionEnvelopeType } from '@metamask/transaction-controller'; import { Suite } from 'mocha'; import { MockedEndpoint } from 'mockttp'; import { DAPP_HOST_ADDRESS, - WINDOW_TITLES, openDapp, unlockWallet, + WINDOW_TITLES, } from '../../../helpers'; import { Ganache } from '../../../seeder/ganache'; import { Driver } from '../../../webdriver/driver'; @@ -32,6 +33,7 @@ describe('Confirmation Signature - Permit @no-mmi', function (this: Suite) { it('initiates and confirms and emits the correct events', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver, ganacheServer, @@ -75,6 +77,7 @@ describe('Confirmation Signature - Permit @no-mmi', function (this: Suite) { it('initiates and rejects and emits the correct events', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver, mockedEndpoint: mockedEndpoints, diff --git a/test/e2e/tests/confirmations/signatures/personal-sign.spec.ts b/test/e2e/tests/confirmations/signatures/personal-sign.spec.ts index 31adfc9b4212..429881bf2f23 100644 --- a/test/e2e/tests/confirmations/signatures/personal-sign.spec.ts +++ b/test/e2e/tests/confirmations/signatures/personal-sign.spec.ts @@ -1,4 +1,5 @@ import { strict as assert } from 'assert'; +import { TransactionEnvelopeType } from '@metamask/transaction-controller'; import { Suite } from 'mocha'; import { MockedEndpoint } from 'mockttp'; import { DAPP_HOST_ADDRESS, WINDOW_TITLES } from '../../../helpers'; @@ -26,6 +27,7 @@ describe('Confirmation Signature - Personal Sign @no-mmi', function (this: Suite it('initiates and confirms', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver, ganacheServer, @@ -65,6 +67,7 @@ describe('Confirmation Signature - Personal Sign @no-mmi', function (this: Suite it('initiates and rejects', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver, mockedEndpoint: mockedEndpoints, diff --git a/test/e2e/tests/confirmations/signatures/sign-typed-data-v3.spec.ts b/test/e2e/tests/confirmations/signatures/sign-typed-data-v3.spec.ts index 43e30f3b60c0..0eb1d2c698b1 100644 --- a/test/e2e/tests/confirmations/signatures/sign-typed-data-v3.spec.ts +++ b/test/e2e/tests/confirmations/signatures/sign-typed-data-v3.spec.ts @@ -1,4 +1,5 @@ import { strict as assert } from 'assert'; +import { TransactionEnvelopeType } from '@metamask/transaction-controller'; import { Suite } from 'mocha'; import { MockedEndpoint } from 'mockttp'; import { DAPP_HOST_ADDRESS, WINDOW_TITLES } from '../../../helpers'; @@ -27,6 +28,7 @@ describe('Confirmation Signature - Sign Typed Data V3 @no-mmi', function (this: it('initiates and confirms', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver, ganacheServer, @@ -69,6 +71,7 @@ describe('Confirmation Signature - Sign Typed Data V3 @no-mmi', function (this: it('initiates and rejects', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver, mockedEndpoint: mockedEndpoints, diff --git a/test/e2e/tests/confirmations/signatures/sign-typed-data-v4.spec.ts b/test/e2e/tests/confirmations/signatures/sign-typed-data-v4.spec.ts index 98311553d463..d78acb511ce9 100644 --- a/test/e2e/tests/confirmations/signatures/sign-typed-data-v4.spec.ts +++ b/test/e2e/tests/confirmations/signatures/sign-typed-data-v4.spec.ts @@ -1,4 +1,5 @@ import { strict as assert } from 'assert'; +import { TransactionEnvelopeType } from '@metamask/transaction-controller'; import { Suite } from 'mocha'; import { MockedEndpoint } from 'mockttp'; import { DAPP_HOST_ADDRESS, WINDOW_TITLES } from '../../../helpers'; @@ -27,6 +28,7 @@ describe('Confirmation Signature - Sign Typed Data V4 @no-mmi', function (this: it('initiates and confirms', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver, ganacheServer, @@ -75,6 +77,7 @@ describe('Confirmation Signature - Sign Typed Data V4 @no-mmi', function (this: it('initiates and rejects', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver, mockedEndpoint: mockedEndpoints, diff --git a/test/e2e/tests/confirmations/signatures/sign-typed-data.spec.ts b/test/e2e/tests/confirmations/signatures/sign-typed-data.spec.ts index b76a4cfef70b..358d6b112cfc 100644 --- a/test/e2e/tests/confirmations/signatures/sign-typed-data.spec.ts +++ b/test/e2e/tests/confirmations/signatures/sign-typed-data.spec.ts @@ -1,4 +1,5 @@ import { strict as assert } from 'assert'; +import { TransactionEnvelopeType } from '@metamask/transaction-controller'; import { Suite } from 'mocha'; import { MockedEndpoint } from 'mockttp'; import { DAPP_HOST_ADDRESS, WINDOW_TITLES } from '../../../helpers'; @@ -26,6 +27,7 @@ describe('Confirmation Signature - Sign Typed Data @no-mmi', function (this: Sui it('initiates and confirms', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver, ganacheServer, @@ -67,6 +69,7 @@ describe('Confirmation Signature - Sign Typed Data @no-mmi', function (this: Sui it('initiates and rejects', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver, mockedEndpoint: mockedEndpoints, diff --git a/test/e2e/tests/confirmations/signatures/siwe.spec.ts b/test/e2e/tests/confirmations/signatures/siwe.spec.ts index da1ce9bcde27..edc3a2020862 100644 --- a/test/e2e/tests/confirmations/signatures/siwe.spec.ts +++ b/test/e2e/tests/confirmations/signatures/siwe.spec.ts @@ -1,4 +1,5 @@ import { strict as assert } from 'assert'; +import { TransactionEnvelopeType } from '@metamask/transaction-controller'; import { Suite } from 'mocha'; import { MockedEndpoint } from 'mockttp'; import { DAPP_HOST_ADDRESS, WINDOW_TITLES } from '../../../helpers'; @@ -26,6 +27,7 @@ describe('Confirmation Signature - SIWE @no-mmi', function (this: Suite) { it('initiates and confirms', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver, mockedEndpoint: mockedEndpoints, @@ -68,6 +70,7 @@ describe('Confirmation Signature - SIWE @no-mmi', function (this: Suite) { it('initiates and rejects', async function () { await withRedesignConfirmationFixtures( this.test?.fullTitle(), + TransactionEnvelopeType.legacy, async ({ driver, mockedEndpoint: mockedEndpoints, diff --git a/test/e2e/tests/confirmations/transactions/erc1155-set-approval-for-all-redesign.spec.ts b/test/e2e/tests/confirmations/transactions/erc1155-set-approval-for-all-redesign.spec.ts new file mode 100644 index 000000000000..7d87cab123b3 --- /dev/null +++ b/test/e2e/tests/confirmations/transactions/erc1155-set-approval-for-all-redesign.spec.ts @@ -0,0 +1,101 @@ +/* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ +import { TransactionEnvelopeType } from '@metamask/transaction-controller'; +import { DAPP_URL, unlockWallet, WINDOW_TITLES } from '../../../helpers'; +import { Mockttp } from '../../../mock-e2e'; +import SetApprovalForAllTransactionConfirmation from '../../../page-objects/pages/set-approval-for-all-transaction-confirmation'; +import TestDapp from '../../../page-objects/pages/test-dapp'; +import GanacheContractAddressRegistry from '../../../seeder/ganache-contract-address-registry'; +import { Driver } from '../../../webdriver/driver'; +import { withRedesignConfirmationFixtures } from '../helpers'; +import { TestSuiteArguments } from './shared'; + +const { SMART_CONTRACTS } = require('../../../seeder/smart-contracts'); + +describe('Confirmation Redesign ERC1155 setApprovalForAll', function () { + describe('Submit a transaction @no-mmi', function () { + it('Sends a type 0 transaction (Legacy)', async function () { + await withRedesignConfirmationFixtures( + this.test?.fullTitle(), + TransactionEnvelopeType.legacy, + async ({ driver, contractRegistry }: TestSuiteArguments) => { + await createTransactionAssertDetailsAndConfirm( + driver, + contractRegistry, + ); + }, + mocks, + SMART_CONTRACTS.NFTS, + ); + }); + + it('Sends a type 2 transaction (EIP1559)', async function () { + await withRedesignConfirmationFixtures( + this.test?.fullTitle(), + TransactionEnvelopeType.feeMarket, + async ({ driver, contractRegistry }: TestSuiteArguments) => { + await createTransactionAssertDetailsAndConfirm( + driver, + contractRegistry, + ); + }, + mocks, + SMART_CONTRACTS.NFTS, + ); + }); + }); +}); + +async function mocks(server: Mockttp) { + return [await mocked4BytesSetApprovalForAll(server)]; +} + +export async function mocked4BytesSetApprovalForAll(mockServer: Mockttp) { + return await mockServer + .forGet('https://www.4byte.directory/api/v1/signatures/') + .withQuery({ hex_signature: '0xa22cb465' }) + .always() + .thenCallback(() => ({ + statusCode: 200, + json: { + count: 1, + next: null, + previous: null, + results: [ + { + bytes_signature: '¢,´e', + created_at: '2018-04-11T21:47:39.980645Z', + hex_signature: '0xa22cb465', + id: 29659, + text_signature: 'setApprovalForAll(address,bool)', + }, + ], + }, + })); +} + +async function createTransactionAssertDetailsAndConfirm( + driver: Driver, + contractRegistry?: GanacheContractAddressRegistry, +) { + await unlockWallet(driver); + + const contractAddress = await ( + contractRegistry as GanacheContractAddressRegistry + ).getContractAddress(SMART_CONTRACTS.NFTS); + + const testDapp = new TestDapp(driver); + + await testDapp.open({ contractAddress, url: DAPP_URL }); + await testDapp.clickERC1155SetApprovalForAllButton(); + + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); + + const setApprovalForAllConfirmation = + new SetApprovalForAllTransactionConfirmation(driver); + + await setApprovalForAllConfirmation.check_setApprovalForAllTitle(); + await setApprovalForAllConfirmation.check_setApprovalForAllSubHeading(); + + await setApprovalForAllConfirmation.clickScrollToBottomButton(); + await setApprovalForAllConfirmation.clickFooterConfirmButton(); +} diff --git a/test/e2e/tests/confirmations/transactions/erc721-set-approval-for-all-redesign.spec.ts b/test/e2e/tests/confirmations/transactions/erc721-set-approval-for-all-redesign.spec.ts new file mode 100644 index 000000000000..7ca9518cabc2 --- /dev/null +++ b/test/e2e/tests/confirmations/transactions/erc721-set-approval-for-all-redesign.spec.ts @@ -0,0 +1,101 @@ +/* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ +import { TransactionEnvelopeType } from '@metamask/transaction-controller'; +import { DAPP_URL, unlockWallet, WINDOW_TITLES } from '../../../helpers'; +import { Mockttp } from '../../../mock-e2e'; +import SetApprovalForAllTransactionConfirmation from '../../../page-objects/pages/set-approval-for-all-transaction-confirmation'; +import TestDapp from '../../../page-objects/pages/test-dapp'; +import GanacheContractAddressRegistry from '../../../seeder/ganache-contract-address-registry'; +import { Driver } from '../../../webdriver/driver'; +import { withRedesignConfirmationFixtures } from '../helpers'; +import { TestSuiteArguments } from './shared'; + +const { SMART_CONTRACTS } = require('../../../seeder/smart-contracts'); + +describe('Confirmation Redesign ERC721 setApprovalForAll', function () { + describe('Submit a transaction @no-mmi', function () { + it('Sends a type 0 transaction (Legacy)', async function () { + await withRedesignConfirmationFixtures( + this.test?.fullTitle(), + TransactionEnvelopeType.legacy, + async ({ driver, contractRegistry }: TestSuiteArguments) => { + await createTransactionAssertDetailsAndConfirm( + driver, + contractRegistry, + ); + }, + mocks, + SMART_CONTRACTS.NFTS, + ); + }); + + it('Sends a type 2 transaction (EIP1559)', async function () { + await withRedesignConfirmationFixtures( + this.test?.fullTitle(), + TransactionEnvelopeType.feeMarket, + async ({ driver, contractRegistry }: TestSuiteArguments) => { + await createTransactionAssertDetailsAndConfirm( + driver, + contractRegistry, + ); + }, + mocks, + SMART_CONTRACTS.NFTS, + ); + }); + }); +}); + +async function mocks(server: Mockttp) { + return [await mocked4BytesSetApprovalForAll(server)]; +} + +export async function mocked4BytesSetApprovalForAll(mockServer: Mockttp) { + return await mockServer + .forGet('https://www.4byte.directory/api/v1/signatures/') + .withQuery({ hex_signature: '0xa22cb465' }) + .always() + .thenCallback(() => ({ + statusCode: 200, + json: { + count: 1, + next: null, + previous: null, + results: [ + { + bytes_signature: '¢,´e', + created_at: '2018-04-11T21:47:39.980645Z', + hex_signature: '0xa22cb465', + id: 29659, + text_signature: 'setApprovalForAll(address,bool)', + }, + ], + }, + })); +} + +async function createTransactionAssertDetailsAndConfirm( + driver: Driver, + contractRegistry?: GanacheContractAddressRegistry, +) { + await unlockWallet(driver); + + const contractAddress = await ( + contractRegistry as GanacheContractAddressRegistry + ).getContractAddress(SMART_CONTRACTS.NFTS); + + const testDapp = new TestDapp(driver); + + await testDapp.open({ contractAddress, url: DAPP_URL }); + await testDapp.clickERC721SetApprovalForAllButton(); + + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); + + const setApprovalForAllConfirmation = + new SetApprovalForAllTransactionConfirmation(driver); + + await setApprovalForAllConfirmation.check_setApprovalForAllTitle(); + await setApprovalForAllConfirmation.check_setApprovalForAllSubHeading(); + + await setApprovalForAllConfirmation.clickScrollToBottomButton(); + await setApprovalForAllConfirmation.clickFooterConfirmButton(); +} diff --git a/test/e2e/tests/hardware-wallets/trezor-sign.spec.ts b/test/e2e/tests/hardware-wallets/trezor-sign.spec.ts new file mode 100644 index 000000000000..169897ed7b16 --- /dev/null +++ b/test/e2e/tests/hardware-wallets/trezor-sign.spec.ts @@ -0,0 +1,53 @@ +import { strict as assert } from 'assert'; +import { Suite } from 'mocha'; +import { Driver } from '../../webdriver/driver'; +import FixtureBuilder from '../../fixture-builder'; +import { + defaultGanacheOptions, + openDapp, + unlockWallet, + WINDOW_TITLES, + withFixtures, +} from '../../helpers'; +import { KNOWN_PUBLIC_KEY_ADDRESSES } from '../../../stub/keyring-bridge'; + +describe('Trezor Hardware Signatures', function (this: Suite) { + it('sign typed v4', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder() + .withTrezorAccount() + .withPermissionControllerConnectedToTestDapp({ + account: KNOWN_PUBLIC_KEY_ADDRESSES[0].address, + }) + .build(), + ganacheOptions: defaultGanacheOptions, + title: this.test?.fullTitle(), + dapp: true, + }, + async ({ driver }: { driver: Driver }) => { + await unlockWallet(driver); + + await openDapp(driver); + await driver.clickElement('#signTypedDataV4'); + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); + + await driver.clickElement('.confirm-scroll-to-bottom__button'); + await driver.clickElement({ text: 'Confirm', tag: 'button' }); + + await driver.waitUntilXWindowHandles(2); + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp); + await driver.clickElement('#signTypedDataV4Verify'); + + const verifyRecoverAddress = await driver.findElement( + '#signTypedDataV4VerifyResult', + ); + + assert.equal( + await verifyRecoverAddress.getText(), + KNOWN_PUBLIC_KEY_ADDRESSES[0].address.toLocaleLowerCase(), + ); + }, + ); + }); +}); diff --git a/test/e2e/tests/network/update-network.spec.ts b/test/e2e/tests/network/update-network.spec.ts index 1b19f0c14345..08b1bc570c83 100644 --- a/test/e2e/tests/network/update-network.spec.ts +++ b/test/e2e/tests/network/update-network.spec.ts @@ -240,6 +240,7 @@ describe('Update Network:', function (this: Suite) { // Re-open the network menu await driver.delay(regularDelayMs); + await driver.clickElementSafe({ text: 'Got it', tag: 'h6' }); await driver.clickElement('[data-testid="network-display"]'); // Go back to edit the network diff --git a/test/e2e/tests/request-queuing/dapp1-switch-dapp2-eth-request-accounts.spec.js b/test/e2e/tests/request-queuing/dapp1-switch-dapp2-eth-request-accounts.spec.js index 71055f75d2dd..a68884de4a4c 100644 --- a/test/e2e/tests/request-queuing/dapp1-switch-dapp2-eth-request-accounts.spec.js +++ b/test/e2e/tests/request-queuing/dapp1-switch-dapp2-eth-request-accounts.spec.js @@ -45,9 +45,21 @@ describe('Request Queuing Dapp 1 Send Tx -> Dapp 2 Request Accounts Tx', functio // Dapp Send Button await driver.clickElement('#sendButton'); + await driver.delay(regularDelayMs); + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); - // Leave the confirmation pending + await driver.waitForSelector({ + text: 'Reject', + tag: 'button', + }); + + await driver.delay(regularDelayMs); + await driver.switchToWindowWithTitle( + WINDOW_TITLES.ExtensionInFullScreenView, + ); + + // Leave the confirmation pending await openDapp(driver, undefined, DAPP_ONE_URL); const accountsOnload = await ( diff --git a/test/integration/confirmations/signatures/personalSign.test.tsx b/test/integration/confirmations/signatures/personalSign.test.tsx index 9737a3e30ad9..5a965a3d6928 100644 --- a/test/integration/confirmations/signatures/personalSign.test.tsx +++ b/test/integration/confirmations/signatures/personalSign.test.tsx @@ -163,9 +163,7 @@ describe('PersonalSign Confirmation', () => { expect(getByText('Signature request')).toBeInTheDocument(); expect( - getByText( - 'Only confirm this message if you approve the content and trust the requesting site.', - ), + getByText('Review request details before you confirm.'), ).toBeInTheDocument(); }); diff --git a/test/stub/keyring-bridge.js b/test/stub/keyring-bridge.js index 78f1479aa2d1..3d4b4824ed82 100644 --- a/test/stub/keyring-bridge.js +++ b/test/stub/keyring-bridge.js @@ -1,4 +1,5 @@ import { Transaction } from '@ethereumjs/tx'; +import { signTypedData, SignTypedDataVersion } from '@metamask/eth-sig-util'; import { bufferToHex } from 'ethereumjs-util'; import { addHexPrefix, Common } from './keyring-utils'; @@ -106,6 +107,30 @@ export class FakeTrezorBridge extends FakeKeyringBridge { }, }; } + + async ethereumSignTypedData(message) { + const typedData = { + types: message.data.types, + domain: message.data.domain, + primaryType: message.data.primaryType, + message: message.data.message, + }; + + const signature = signTypedData({ + privateKey: KNOWN_PRIVATE_KEYS[0], + data: typedData, + version: SignTypedDataVersion.V4, + }); + + return { + id: 1, + success: true, + payload: { + address: KNOWN_PUBLIC_KEY_ADDRESSES[0].address, + signature, + }, + }; + } } export class FakeLedgerBridge extends FakeKeyringBridge { diff --git a/ui/components/app/account-list-item/account-list-item.js b/ui/components/app/account-list-item/account-list-item.js index 476a545acd8d..35728bb2a281 100644 --- a/ui/components/app/account-list-item/account-list-item.js +++ b/ui/components/app/account-list-item/account-list-item.js @@ -2,6 +2,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import Identicon from '../../ui/identicon'; import AccountMismatchWarning from '../../ui/account-mismatch-warning/account-mismatch-warning.component'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { normalizeSafeAddress } from '../../../../app/scripts/lib/multichain/address'; export default function AccountListItem({ diff --git a/ui/components/app/assets/nfts/nft-details/nft-details.tsx b/ui/components/app/assets/nfts/nft-details/nft-details.tsx index 8a857da43989..5ee8525cc98b 100644 --- a/ui/components/app/assets/nfts/nft-details/nft-details.tsx +++ b/ui/components/app/assets/nfts/nft-details/nft-details.tsx @@ -69,6 +69,8 @@ import { getShortDateFormatterV2 } from '../../../../../pages/asset/util'; import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../../../shared/constants/swaps'; import { getConversionRate } from '../../../../../ducks/metamask/metamask'; import { Numeric } from '../../../../../../shared/modules/Numeric'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { addUrlProtocolPrefix } from '../../../../../../app/scripts/lib/util'; import useGetAssetImageUrl from '../../../../../hooks/useGetAssetImageUrl'; import NftDetailInformationRow from './nft-detail-information-row'; diff --git a/ui/components/app/assets/nfts/nfts-items/nfts-items.js b/ui/components/app/assets/nfts/nfts-items/nfts-items.js index c44de72b261b..ff5d7ea877bf 100644 --- a/ui/components/app/assets/nfts/nfts-items/nfts-items.js +++ b/ui/components/app/assets/nfts/nfts-items/nfts-items.js @@ -16,6 +16,8 @@ import { FLEX_WRAP, } from '../../../../../helpers/constants/design-system'; import { ENVIRONMENT_TYPE_POPUP } from '../../../../../../shared/constants/app'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../../../../app/scripts/lib/util'; import { getCurrentChainId, diff --git a/ui/components/app/assets/token-cell/__snapshots__/token-cell.test.tsx.snap b/ui/components/app/assets/token-cell/__snapshots__/token-cell.test.tsx.snap index e40a15f69863..4eeeb5603d46 100644 --- a/ui/components/app/assets/token-cell/__snapshots__/token-cell.test.tsx.snap +++ b/ui/components/app/assets/token-cell/__snapshots__/token-cell.test.tsx.snap @@ -27,7 +27,7 @@ exports[`Token Cell should match snapshot 1`] = ` class="mm-box mm-badge-wrapper__badge-container mm-badge-wrapper__badge-container--circular-top-right" >
?
diff --git a/ui/components/app/assets/token-cell/token-cell.test.tsx b/ui/components/app/assets/token-cell/token-cell.test.tsx index d92be927acdc..70714e9975f8 100644 --- a/ui/components/app/assets/token-cell/token-cell.test.tsx +++ b/ui/components/app/assets/token-cell/token-cell.test.tsx @@ -5,6 +5,8 @@ import { fireEvent } from '@testing-library/react'; import { useSelector } from 'react-redux'; import { renderWithProvider } from '../../../../../test/lib/render-helpers'; import { useTokenFiatAmount } from '../../../../hooks/useTokenFiatAmount'; +import { getTokenList } from '../../../../selectors'; +import { getMultichainCurrentChainId } from '../../../../selectors/multichain'; import { useIsOriginalTokenSymbol } from '../../../../hooks/useIsOriginalTokenSymbol'; import TokenCell from '.'; @@ -90,7 +92,16 @@ describe('Token Cell', () => { image: '', onClick: jest.fn(), }; - (useSelector as jest.Mock).mockReturnValue(MOCK_GET_TOKEN_LIST); + const useSelectorMock = useSelector; + (useSelectorMock as jest.Mock).mockImplementation((selector) => { + if (selector === getTokenList) { + return MOCK_GET_TOKEN_LIST; + } + if (selector === getMultichainCurrentChainId) { + return '0x89'; + } + return undefined; + }); (useTokenFiatAmount as jest.Mock).mockReturnValue('5.00'); it('should match snapshot', () => { diff --git a/ui/components/app/configure-snap-popup/configure-snap-popup.test.tsx b/ui/components/app/configure-snap-popup/configure-snap-popup.test.tsx index 54aef803245e..b4f7c21fb7d4 100644 --- a/ui/components/app/configure-snap-popup/configure-snap-popup.test.tsx +++ b/ui/components/app/configure-snap-popup/configure-snap-popup.test.tsx @@ -2,6 +2,8 @@ import React from 'react'; import { fireEvent } from '@testing-library/react'; import configureMockStore from 'redux-mock-store'; import { renderWithProvider } from '../../../../test/lib/render-helpers'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import messages from '../../../../app/_locales/en/messages.json'; import mockState from '../../../../test/data/mock-state.json'; import ConfigureSnapPopup, { diff --git a/ui/components/app/modals/hold-to-reveal-modal/hold-to-reveal-modal.test.js b/ui/components/app/modals/hold-to-reveal-modal/hold-to-reveal-modal.test.js index 612b972ef83c..cde1f407dfcc 100644 --- a/ui/components/app/modals/hold-to-reveal-modal/hold-to-reveal-modal.test.js +++ b/ui/components/app/modals/hold-to-reveal-modal/hold-to-reveal-modal.test.js @@ -9,6 +9,8 @@ import { holdToRevealContent4, holdToRevealContent5, holdToRevealSRPTitle, + // TODO: Remove restricted import + // eslint-disable-next-line import/no-restricted-paths } from '../../../../../app/_locales/en/messages.json'; import mockState from '../../../../../test/data/mock-state.json'; import { renderWithProvider } from '../../../../../test/lib/render-helpers'; diff --git a/ui/components/app/modals/modal.js b/ui/components/app/modals/modal.js index ecae704a2270..753c01f21374 100644 --- a/ui/components/app/modals/modal.js +++ b/ui/components/app/modals/modal.js @@ -2,6 +2,8 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { connect } from 'react-redux'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; import isMobileView from '../../../helpers/utils/is-mobile-view'; diff --git a/ui/components/app/modals/new-account-modal/new-account-modal.test.tsx b/ui/components/app/modals/new-account-modal/new-account-modal.test.tsx index bb078773cd66..81955eca3b2b 100644 --- a/ui/components/app/modals/new-account-modal/new-account-modal.test.tsx +++ b/ui/components/app/modals/new-account-modal/new-account-modal.test.tsx @@ -4,6 +4,8 @@ import { waitFor, fireEvent } from '@testing-library/react'; import configureStore from 'redux-mock-store'; import { renderWithProvider } from '../../../../../test/jest'; import mockState from '../../../../../test/data/mock-state.json'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import messages from '../../../../../app/_locales/en/messages.json'; import NewAccountModal from './new-account-modal.container'; diff --git a/ui/components/app/modals/nickname-popovers/nickname-popovers.component.test.tsx b/ui/components/app/modals/nickname-popovers/nickname-popovers.component.test.tsx index db3ddef0caca..20d95f59a4f9 100644 --- a/ui/components/app/modals/nickname-popovers/nickname-popovers.component.test.tsx +++ b/ui/components/app/modals/nickname-popovers/nickname-popovers.component.test.tsx @@ -9,6 +9,8 @@ import { MultichainNetworks, } from '../../../../../shared/constants/multichain/networks'; import { createMockInternalAccount } from '../../../../../test/jest/mocks'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { normalizeSafeAddress } from '../../../../../app/scripts/lib/multichain/address'; import { mockNetworkState } from '../../../../../test/stub/networks'; import NicknamePopover from './nickname-popovers.component'; diff --git a/ui/components/app/modals/qr-scanner/qr-scanner.component.js b/ui/components/app/modals/qr-scanner/qr-scanner.component.js index 7eaf3f9549e1..75e1a83417b9 100644 --- a/ui/components/app/modals/qr-scanner/qr-scanner.component.js +++ b/ui/components/app/modals/qr-scanner/qr-scanner.component.js @@ -4,6 +4,8 @@ import log from 'loglevel'; import { BrowserQRCodeReader } from '@zxing/browser'; import { usePrevious } from '../../../../hooks/usePrevious'; import { useI18nContext } from '../../../../hooks/useI18nContext'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; import { getURL } from '../../../../helpers/utils/util'; import WebcamUtils from '../../../../helpers/utils/webcam-utils'; diff --git a/ui/components/app/multi-rpc-edit-modal/multi-rpc-edit-modal.tsx b/ui/components/app/multi-rpc-edit-modal/multi-rpc-edit-modal.tsx index 6df73c0b86d8..0d6985dbfb4d 100644 --- a/ui/components/app/multi-rpc-edit-modal/multi-rpc-edit-modal.tsx +++ b/ui/components/app/multi-rpc-edit-modal/multi-rpc-edit-modal.tsx @@ -21,6 +21,8 @@ import { TextVariant, } from '../../../helpers/constants/design-system'; import { setShowMultiRpcModal } from '../../../store/actions'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import { getNetworkConfigurationsByChainId } from '../../../selectors'; import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; diff --git a/ui/components/app/permission-page-container/permission-page-container.component.js b/ui/components/app/permission-page-container/permission-page-container.component.js index 2ef99bacd3f3..f2a04e7616ca 100644 --- a/ui/components/app/permission-page-container/permission-page-container.component.js +++ b/ui/components/app/permission-page-container/permission-page-container.component.js @@ -9,6 +9,8 @@ import { MetaMetricsEventCategory } from '../../../../shared/constants/metametri import { PageContainerFooter } from '../../ui/page-container'; import PermissionsConnectFooter from '../permissions-connect-footer'; import { RestrictedMethods } from '../../../../shared/constants/permissions'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { PermissionNames } from '../../../../app/scripts/controllers/permissions'; import SnapPrivacyWarning from '../snaps/snap-privacy-warning'; diff --git a/ui/components/app/qr-hardware-popover/base-reader.js b/ui/components/app/qr-hardware-popover/base-reader.js index 7aca256db53d..f1776dc7d1dc 100644 --- a/ui/components/app/qr-hardware-popover/base-reader.js +++ b/ui/components/app/qr-hardware-popover/base-reader.js @@ -2,6 +2,8 @@ import React, { useEffect, useRef, useState } from 'react'; import log from 'loglevel'; import { URDecoder } from '@ngraveio/bc-ur'; import PropTypes from 'prop-types'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../shared/constants/app'; import WebcamUtils from '../../../helpers/utils/webcam-utils'; diff --git a/ui/components/app/selected-account/selected-account.component.js b/ui/components/app/selected-account/selected-account.component.js index c405f64022b3..6dfe73f5766c 100644 --- a/ui/components/app/selected-account/selected-account.component.js +++ b/ui/components/app/selected-account/selected-account.component.js @@ -7,6 +7,8 @@ import Tooltip from '../../ui/tooltip'; import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; import { SECOND } from '../../../../shared/constants/time'; ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; import { AccountType } from '../../../../shared/constants/custody'; diff --git a/ui/components/app/snaps/keyring-snap-removal-warning/keyring-snap-removal-warning.test.tsx b/ui/components/app/snaps/keyring-snap-removal-warning/keyring-snap-removal-warning.test.tsx index 2c00fa1861ec..24eb666e6385 100644 --- a/ui/components/app/snaps/keyring-snap-removal-warning/keyring-snap-removal-warning.test.tsx +++ b/ui/components/app/snaps/keyring-snap-removal-warning/keyring-snap-removal-warning.test.tsx @@ -6,6 +6,8 @@ import userEvent from '@testing-library/user-event'; import mockStore from '../../../../../test/data/mock-state.json'; import { renderWithProvider } from '../../../../../test/jest'; import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import messages from '../../../../../app/_locales/en/messages.json'; import KeyringSnapRemovalWarning from './keyring-snap-removal-warning'; 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 e489d2a6f4a5..b6f68c646ec5 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 @@ -34,6 +34,7 @@ export const SnapUIInput: FunctionComponent< return ( ; jest.mock('../../../ducks/locale/locale', () => ({ getIntlLocale: jest.fn(), })); +jest.mock( + '../../../pages/settings/networks-tab/networks-form/use-safe-chains', + () => ({ + useSafeChains: jest.fn().mockReturnValue({ + safeChains: [safeChainDetails], + }), + }), +); + const mockGetIntlLocale = getIntlLocale; +const mockGetSafeChains = useSafeChains; describe('TokenListItem', () => { beforeAll(() => { @@ -100,6 +118,34 @@ describe('TokenListItem', () => { showPercentage: true, tokenImage: '', title: '', + tokenSymbol: 'SCAM_TOKEN', + }; + const { getByTestId, getByText } = renderWithProvider( + , + store, + ); + + const warningScamModal = getByTestId('scam-warning'); + fireEvent.click(warningScamModal); + + expect( + getByText( + 'The native token symbol does not match the expected symbol of the native token for the network with the associated chain ID. You have entered SCAM_TOKEN while the expected token symbol is ETH. Please verify you are connected to the correct chain.', + ), + ).toBeInTheDocument(); + }); + + it('should display warning scam modal fallback when safechains fails to resolve correctly', () => { + (mockGetSafeChains as unknown as jest.Mock).mockReturnValue([]); + const store = configureMockStore()(state); + const propsToUse = { + primary: '11.9751 ETH', + isNativeCurrency: true, + isOriginalTokenSymbol: false, + showPercentage: true, + tokenImage: '', + title: '', + tokenSymbol: 'SCAM_TOKEN', }; const { getByTestId, getByText } = renderWithProvider( , @@ -109,7 +155,11 @@ describe('TokenListItem', () => { const warningScamModal = getByTestId('scam-warning'); fireEvent.click(warningScamModal); - expect(getByText('This is a potential scam')).toBeInTheDocument(); + expect( + getByText( + 'The native token symbol does not match the expected symbol of the native token for the network with the associated chain ID. You have entered SCAM_TOKEN while the expected token symbol is something else. Please verify you are connected to the correct chain.', + ), + ).toBeInTheDocument(); }); it('should render crypto balance if useNativeCurrencyAsPrimaryCurrency is false', () => { diff --git a/ui/components/multichain/token-list-item/token-list-item.tsx b/ui/components/multichain/token-list-item/token-list-item.tsx index 5c6fb0f56799..1198d3bdd165 100644 --- a/ui/components/multichain/token-list-item/token-list-item.tsx +++ b/ui/components/multichain/token-list-item/token-list-item.tsx @@ -56,10 +56,15 @@ import { MetaMetricsEventName, } from '../../../../shared/constants/metametrics'; import { CURRENCY_SYMBOLS } from '../../../../shared/constants/network'; +import { hexToDecimal } from '../../../../shared/modules/conversion.utils'; import { NETWORKS_ROUTE } from '../../../helpers/constants/routes'; import { setEditedNetwork } from '../../../store/actions'; import { getPortfolioUrl } from '../../../helpers/utils/portfolio'; +import { + SafeChain, + useSafeChains, +} from '../../../pages/settings/networks-tab/networks-form/use-safe-chains'; import { PercentageChange } from './price/percentage-change/percentage-change'; type TokenListItemProps = { @@ -100,6 +105,16 @@ export const TokenListItem = ({ const metaMetricsId = useSelector(getMetaMetricsId); const isMetaMetricsEnabled = useSelector(getParticipateInMetaMetrics); const isMarketingEnabled = useSelector(getDataCollectionForMarketing); + const { safeChains } = useSafeChains(); + + const decimalChainId = isEvm && parseInt(hexToDecimal(chainId), 10); + + const safeChainDetails: SafeChain | undefined = safeChains?.find((chain) => { + if (typeof decimalChainId === 'number') { + return chain.chainId === decimalChainId.toString(); + } + return undefined; + }); // Scam warning const showScamWarning = @@ -401,11 +416,15 @@ export const TokenListItem = ({ setShowScamWarningModal(false)}> - {t('nativeTokenScamWarningTitle')} - - - {t('nativeTokenScamWarningDescription', [tokenSymbol])} - + setShowScamWarningModal(false)}> + {t('nativeTokenScamWarningTitle')} + + + {t('nativeTokenScamWarningDescription', [ + tokenSymbol, + safeChainDetails?.nativeCurrency?.symbol || + t('nativeTokenScamWarningDescriptionExpectedTokenFallback'), // never render "undefined" string value + ])} (args: { event: UserInputEventType; name?: string; - value?: Type; - flush?: boolean; + value?: Type | null; }) => void; export type HandleInputChange = ( @@ -62,14 +60,6 @@ export type SnapInterfaceContextProviderProps = { context: Json; }; -// We want button clicks to be instant and therefore use throttling -// to protect the Snap -// Any event not in this array will be debounced instead of throttled -const THROTTLED_EVENTS = [ - UserInputEventType.ButtonClickEvent, - UserInputEventType.FormSubmitEvent, -]; - /** * The Snap interface context provider that handles all the interface state operations. * @@ -97,12 +87,12 @@ export const SnapInterfaceContextProvider: FunctionComponent< internalState.current = initialState; }, [initialState]); - const rawSnapRequestFunction = ( + const handleSnapRequest = ( event: UserInputEventType, name?: string, value?: unknown, ) => { - handleSnapRequest[0]>({ + handleSnapRequestFunction[0]>({ snapId, origin: '', handler: 'onUserInput', @@ -123,17 +113,8 @@ export const SnapInterfaceContextProvider: FunctionComponent< }).then(() => forceUpdateMetamaskState(dispatch)); }; - // 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 many - // updates in a short amount of time. - const updateStateDebounced = debounce( - (state) => dispatch(updateInterfaceState(interfaceId, state)), - 200, - ); + const updateState = (state: InterfaceState) => + dispatch(updateInterfaceState(interfaceId, state)); /** * Handle the submission of an user input event to the Snap. @@ -142,41 +123,19 @@ 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. */ const handleEvent: HandleEvent = ({ event, name, value = name ? internalState.current[name] : undefined, - flush = false, - }) => { - // We always flush the debounced request for updating the state. - updateStateDebounced.flush(); - - const fn = THROTTLED_EVENTS.includes(event) - ? snapRequestThrottled - : snapRequestDebounced; - - fn(event, name, value); + }) => handleSnapRequest(event, name, value); - // Certain events have their own debounce or throttling logic - // and therefore may want to flush - if (flush) { - fn.flush(); - } - }; - - const handleInputChangeDebounced = debounce( - (name, value) => - handleEvent({ - event: UserInputEventType.InputChangeEvent, - name, - value, - flush: true, - }), - 300, - ); + const submitInputChange = (name: string, value: State | null) => + handleEvent({ + event: UserInputEventType.InputChangeEvent, + name, + value, + }); /** * Handle the value change of an input. @@ -190,12 +149,12 @@ export const SnapInterfaceContextProvider: FunctionComponent< const state = mergeValue(internalState.current, name, value, form); internalState.current = state; - updateStateDebounced(state); - handleInputChangeDebounced(name, value); + updateState(state); + submitInputChange(name, value); }; const uploadFile = (name: string, file: FileObject | null) => { - handleSnapRequest[0]>({ + handleSnapRequestFunction[0]>({ snapId, origin: '', handler: 'onUserInput', @@ -244,8 +203,7 @@ export const SnapInterfaceContextProvider: FunctionComponent< ); internalState.current = state; - updateStateDebounced(state); - updateStateDebounced.flush(); + updateState(state); uploadFile(name, fileObject); }); @@ -255,8 +213,7 @@ export const SnapInterfaceContextProvider: FunctionComponent< const state = mergeValue(internalState.current, name, null, form); internalState.current = state; - updateStateDebounced(state); - updateStateDebounced.flush(); + updateState(state); uploadFile(name, null); }; diff --git a/ui/ducks/bridge/actions.ts b/ui/ducks/bridge/actions.ts index 456c9ed36679..a0c852512867 100644 --- a/ui/ducks/bridge/actions.ts +++ b/ui/ducks/bridge/actions.ts @@ -1,3 +1,5 @@ +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { BridgeBackgroundAction } from '../../../app/scripts/controllers/bridge/types'; import { forceUpdateMetamaskState } from '../../store/actions'; import { submitRequestToBackground } from '../../store/background-connection'; diff --git a/ui/ducks/bridge/bridge.test.ts b/ui/ducks/bridge/bridge.test.ts index f47d3c4f64b2..6b6acf115396 100644 --- a/ui/ducks/bridge/bridge.test.ts +++ b/ui/ducks/bridge/bridge.test.ts @@ -3,6 +3,8 @@ import thunk from 'redux-thunk'; import { createBridgeMockStore } from '../../../test/jest/mock-store'; import { CHAIN_IDS } from '../../../shared/constants/network'; import { setBackgroundConnection } from '../../store/background-connection'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { BridgeBackgroundAction } from '../../../app/scripts/controllers/bridge/types'; import bridgeReducer from './bridge'; import { setBridgeFeatureFlags, setToChain } from './actions'; diff --git a/ui/ducks/bridge/selectors.ts b/ui/ducks/bridge/selectors.ts index 9b355bd0df74..5f482ddecb91 100644 --- a/ui/ducks/bridge/selectors.ts +++ b/ui/ducks/bridge/selectors.ts @@ -8,6 +8,8 @@ import { ALLOWED_BRIDGE_CHAIN_IDS } from '../../../shared/constants/bridge'; import { BridgeControllerState, BridgeFeatureFlagsKey, + // TODO: Remove restricted import + // eslint-disable-next-line import/no-restricted-paths } from '../../../app/scripts/controllers/bridge/types'; import { FEATURED_RPCS } from '../../../shared/constants/network'; import { createDeepEqualSelector } from '../../selectors/util'; diff --git a/ui/ducks/locale/locale.test.ts b/ui/ducks/locale/locale.test.ts index 17abc6547d0a..37fc1f99e29a 100644 --- a/ui/ducks/locale/locale.test.ts +++ b/ui/ducks/locale/locale.test.ts @@ -1,3 +1,5 @@ +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import locales from '../../../app/_locales/index.json'; import { getIntlLocale } from './locale'; diff --git a/ui/helpers/utils/accounts.js b/ui/helpers/utils/accounts.js index 29330509a16e..bb789cb74b6a 100644 --- a/ui/helpers/utils/accounts.js +++ b/ui/helpers/utils/accounts.js @@ -8,6 +8,8 @@ import { import { BackgroundColor } from '../constants/design-system'; import { KeyringType } from '../../../shared/constants/keyring'; import { HardwareKeyringNames } from '../../../shared/constants/hardware-wallets'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { t } from '../../../app/scripts/translate'; export function getAccountNameErrorMessage( diff --git a/ui/helpers/utils/build-types.js b/ui/helpers/utils/build-types.js index e0b003527ccb..bb3913771b84 100644 --- a/ui/helpers/utils/build-types.js +++ b/ui/helpers/utils/build-types.js @@ -1,7 +1,11 @@ ///: BEGIN:ONLY_INCLUDE_IF(build-flask) +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import flaskJson from '../../../app/build-types/flask/images/flask-mascot.json'; ///: END:ONLY_INCLUDE_IF ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import mmiJson from '../../../app/build-types/mmi/mmi-mascot.json'; ///: END:ONLY_INCLUDE_IF diff --git a/ui/helpers/utils/multichain/blockExplorer.ts b/ui/helpers/utils/multichain/blockExplorer.ts index 958bb3384fa9..c61c10339df2 100644 --- a/ui/helpers/utils/multichain/blockExplorer.ts +++ b/ui/helpers/utils/multichain/blockExplorer.ts @@ -1,6 +1,8 @@ import { getAccountLink } from '@metamask/etherscan-link'; import { KnownCaipNamespace, parseCaipChainId } from '@metamask/utils'; import { MultichainNetwork } from '../../../selectors/multichain'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { normalizeSafeAddress } from '../../../../app/scripts/lib/multichain/address'; export const getMultichainBlockExplorerUrl = ( diff --git a/ui/helpers/utils/permission.js b/ui/helpers/utils/permission.js index d6a6a3bcd670..b1d1856c40df 100644 --- a/ui/helpers/utils/permission.js +++ b/ui/helpers/utils/permission.js @@ -26,6 +26,8 @@ import { TextColor, TextVariant, } from '../constants/design-system'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { PermissionNames } from '../../../app/scripts/controllers/permissions'; import { getURLHost } from './util'; diff --git a/ui/helpers/utils/transactions.util.js b/ui/helpers/utils/transactions.util.js index d6a1717056de..51f36523676f 100644 --- a/ui/helpers/utils/transactions.util.js +++ b/ui/helpers/utils/transactions.util.js @@ -5,6 +5,8 @@ import { TransactionStatus, TransactionType, } from '@metamask/transaction-controller'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { addHexPrefix } from '../../../app/scripts/lib/util'; import { TransactionGroupStatus } from '../../../shared/constants/transaction'; import { readAddressAsContract } from '../../../shared/modules/contract-utils'; diff --git a/ui/helpers/utils/util.js b/ui/helpers/utils/util.js index 2b021e89c399..01cffeea3cdc 100644 --- a/ui/helpers/utils/util.js +++ b/ui/helpers/utils/util.js @@ -30,6 +30,8 @@ import { OUTDATED_BROWSER_VERSIONS } from '../constants/common'; import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils'; import { hexToDecimal } from '../../../shared/modules/conversion.utils'; import { SNAPS_VIEW_ROUTE } from '../constants/routes'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { normalizeSafeAddress } from '../../../app/scripts/lib/multichain/address'; export function formatDate(date, format = "M/d/y 'at' T") { diff --git a/ui/helpers/utils/webcam-utils.js b/ui/helpers/utils/webcam-utils.js index ef7e80160d66..a44e9ac457bf 100644 --- a/ui/helpers/utils/webcam-utils.js +++ b/ui/helpers/utils/webcam-utils.js @@ -5,6 +5,8 @@ import { PLATFORM_BRAVE, PLATFORM_FIREFOX, } from '../../../shared/constants/app'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType, getPlatform } from '../../../app/scripts/lib/util'; class WebcamUtils { diff --git a/ui/hooks/useEventFragment.js b/ui/hooks/useEventFragment.js index 86e80fdc9b2b..810d0ac76b6b 100644 --- a/ui/hooks/useEventFragment.js +++ b/ui/hooks/useEventFragment.js @@ -1,5 +1,7 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import { useSelector } from 'react-redux'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../app/scripts/lib/util'; import { selectMatchingFragment } from '../selectors'; import { diff --git a/ui/hooks/useIsOriginalNativeTokenSymbol.js b/ui/hooks/useIsOriginalNativeTokenSymbol.js index 06dc380d861d..9a546dba8305 100644 --- a/ui/hooks/useIsOriginalNativeTokenSymbol.js +++ b/ui/hooks/useIsOriginalNativeTokenSymbol.js @@ -11,6 +11,8 @@ import { getMultichainIsEvm, getMultichainCurrentNetwork, } from '../selectors/multichain'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getValidUrl } from '../../app/scripts/lib/util'; export function useIsOriginalNativeTokenSymbol( diff --git a/ui/hooks/useTransactionDisplayData.test.js b/ui/hooks/useTransactionDisplayData.test.js index 55cb05c256b6..0aa77675bd7c 100644 --- a/ui/hooks/useTransactionDisplayData.test.js +++ b/ui/hooks/useTransactionDisplayData.test.js @@ -11,6 +11,8 @@ import { import mockState from '../../test/data/mock-state.json'; import configureStore from '../store/store'; import transactions from '../../test/data/transaction-data.json'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import messages from '../../app/_locales/en/messages.json'; import { ASSET_ROUTE, DEFAULT_ROUTE } from '../helpers/constants/routes'; import { TransactionGroupCategory } from '../../shared/constants/transaction'; diff --git a/ui/index.js b/ui/index.js index 4f98eab94209..fec0321164dd 100644 --- a/ui/index.js +++ b/ui/index.js @@ -6,9 +6,13 @@ import React from 'react'; import { render } from 'react-dom'; import browser from 'webextension-polyfill'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../app/scripts/lib/util'; import { AlertTypes } from '../shared/constants/alerts'; import { maskObject } from '../shared/modules/object.utils'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { SENTRY_UI_STATE } from '../app/scripts/constants/sentry-state'; import { ENVIRONMENT_TYPE_POPUP } from '../shared/constants/app'; import { COPY_OPTIONS } from '../shared/constants/copy'; diff --git a/ui/pages/bridge/bridge.util.ts b/ui/pages/bridge/bridge.util.ts index e7506ede2066..0f72b75a0787 100644 --- a/ui/pages/bridge/bridge.util.ts +++ b/ui/pages/bridge/bridge.util.ts @@ -2,6 +2,8 @@ import { add0x } from '@metamask/utils'; import { BridgeFeatureFlagsKey, BridgeFeatureFlags, + // TODO: Remove restricted import + // eslint-disable-next-line import/no-restricted-paths } from '../../../app/scripts/controllers/bridge/types'; import { BRIDGE_API_BASE_URL, diff --git a/ui/pages/confirmations/components/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js b/ui/pages/confirmations/components/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js index 0ee751357114..88b5fad9ed2d 100644 --- a/ui/pages/confirmations/components/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js +++ b/ui/pages/confirmations/components/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js @@ -5,6 +5,8 @@ import { ENVIRONMENT_TYPE_NOTIFICATION, ORIGIN_METAMASK, } from '../../../../../../shared/constants/app'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../../../../app/scripts/lib/util'; import NetworkDisplay from '../../../../../components/app/network-display'; import Identicon from '../../../../../components/ui/identicon'; diff --git a/ui/pages/confirmations/components/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js b/ui/pages/confirmations/components/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js index 0a6296eb329e..2cf7d13393a9 100644 --- a/ui/pages/confirmations/components/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js +++ b/ui/pages/confirmations/components/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js @@ -2,6 +2,8 @@ import React from 'react'; import configureStore from 'redux-mock-store'; import { ORIGIN_METAMASK } from '../../../../../../shared/constants/app'; import { renderWithProvider } from '../../../../../../test/lib/render-helpers'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../../../../app/scripts/lib/util'; import { CHAIN_IDS } from '../../../../../../shared/constants/network'; import { mockNetworkState } from '../../../../../../test/stub/networks'; diff --git a/ui/pages/confirmations/components/confirm/footer/footer.test.tsx b/ui/pages/confirmations/components/confirm/footer/footer.test.tsx index 2c735a508422..014c583737ff 100644 --- a/ui/pages/confirmations/components/confirm/footer/footer.test.tsx +++ b/ui/pages/confirmations/components/confirm/footer/footer.test.tsx @@ -27,6 +27,7 @@ import { Severity } from '../../../../../helpers/constants/design-system'; import { SignatureRequestType } from '../../../types/confirm'; import * as confirmContext from '../../../context/confirm'; +import { Alert } from '../../../../../ducks/confirm-alerts/confirm-alerts'; import Footer from './footer'; jest.mock('react-redux', () => ({ @@ -247,7 +248,8 @@ describe('ConfirmFooter', () => { const OWNER_ID_MOCK = '123'; const KEY_ALERT_KEY_MOCK = 'Key'; const ALERT_MESSAGE_MOCK = 'Alert 1'; - const alertsMock = [ + + const alertsMock: Alert[] = [ { key: KEY_ALERT_KEY_MOCK, field: KEY_ALERT_KEY_MOCK, @@ -257,32 +259,63 @@ describe('ConfirmFooter', () => { alertDetails: ['Detail 1', 'Detail 2'], }, ]; - const stateWithAlertsMock = getMockPersonalSignConfirmStateForRequest( - { - ...unapprovedPersonalSignMsg, - id: OWNER_ID_MOCK, - msgParams: { - from: '0xc42edfcc21ed14dda456aa0756c153f7985d8813', - }, - } as SignatureRequestType, - { - confirmAlerts: { - alerts: { [OWNER_ID_MOCK]: alertsMock }, - confirmed: { - [OWNER_ID_MOCK]: { [KEY_ALERT_KEY_MOCK]: false }, + + const createStateWithAlerts = ( + alerts: Alert[], + confirmed: Record, + ) => { + return getMockPersonalSignConfirmStateForRequest( + { + ...unapprovedPersonalSignMsg, + id: OWNER_ID_MOCK, + msgParams: { + from: '0xc42edfcc21ed14dda456aa0756c153f7985d8813', }, + } as SignatureRequestType, + { + confirmAlerts: { + alerts: { [OWNER_ID_MOCK]: alerts }, + confirmed: { [OWNER_ID_MOCK]: confirmed }, + }, + metamask: {}, }, - metamask: {}, - }, - ); - it('renders the review alerts button when there are unconfirmed alerts', () => { - const { getByText } = render(stateWithAlertsMock); - expect(getByText('Confirm')).toBeInTheDocument(); + ); + }; + + const stateWithAlertsMock = createStateWithAlerts(alertsMock, { + [KEY_ALERT_KEY_MOCK]: false, }); - it('renders the confirm button when there are no unconfirmed alerts', () => { - const { getByText } = render(); - expect(getByText('Confirm')).toBeInTheDocument(); + it('renders the "review alerts" button when there are unconfirmed alerts', () => { + const stateWithMultipleDangerAlerts = createStateWithAlerts( + [ + alertsMock[0], + { + ...alertsMock[0], + key: 'From', + }, + ], + { [KEY_ALERT_KEY_MOCK]: false }, + ); + const { getByText } = render(stateWithMultipleDangerAlerts); + expect(getByText('Review alerts')).toBeInTheDocument(); + }); + + it('renders the "review alerts" button disabled when there are blocking alerts', () => { + const stateWithMultipleDangerAlerts = createStateWithAlerts( + [ + alertsMock[0], + { + ...alertsMock[0], + key: 'From', + isBlocking: true, + }, + ], + { [KEY_ALERT_KEY_MOCK]: false }, + ); + const { getByText } = render(stateWithMultipleDangerAlerts); + expect(getByText('Review alerts')).toBeInTheDocument(); + expect(getByText('Review alerts')).toBeDisabled(); }); it('sets the alert modal visible when the review alerts button is clicked', () => { @@ -290,5 +323,10 @@ describe('ConfirmFooter', () => { fireEvent.click(getByTestId('confirm-footer-button')); expect(getByTestId('confirm-alert-modal-submit-button')).toBeDefined(); }); + + it('renders the "confirm" button when there are no alerts', () => { + const { getByText } = render(); + expect(getByText('Confirm')).toBeInTheDocument(); + }); }); }); diff --git a/ui/pages/confirmations/components/confirm/footer/footer.tsx b/ui/pages/confirmations/components/confirm/footer/footer.tsx index c1666b6f238d..67f3d133afb7 100644 --- a/ui/pages/confirmations/components/confirm/footer/footer.tsx +++ b/ui/pages/confirmations/components/confirm/footer/footer.tsx @@ -37,6 +37,7 @@ import { import { useConfirmContext } from '../../../context/confirm'; import { getConfirmationSender } from '../utils'; import { MetaMetricsEventLocation } from '../../../../../../shared/constants/metametrics'; +import { Severity } from '../../../../../helpers/constants/design-system'; export type OnCancelHandler = ({ location, @@ -44,6 +45,22 @@ export type OnCancelHandler = ({ location: MetaMetricsEventLocation; }) => void; +function getButtonDisabledState( + hasUnconfirmedDangerAlerts: boolean, + hasBlockingAlerts: boolean, + disabled: boolean, +) { + if (hasBlockingAlerts) { + return true; + } + + if (hasUnconfirmedDangerAlerts) { + return false; + } + + return disabled; +} + const ConfirmButton = ({ alertOwnerId = '', disabled, @@ -63,6 +80,10 @@ const ConfirmButton = ({ const { dangerAlerts, hasDangerAlerts, hasUnconfirmedDangerAlerts } = useAlerts(alertOwnerId); + const hasDangerBlockingAlerts = dangerAlerts.some( + (alert) => alert.severity === Severity.Danger && alert.isBlocking, + ); + const handleCloseConfirmModal = useCallback(() => { setConfirmModalVisible(false); }, []); @@ -86,12 +107,16 @@ const ConfirmButton = ({ block danger data-testid="confirm-footer-button" - disabled={hasUnconfirmedDangerAlerts ? false : disabled} + disabled={getButtonDisabledState( + hasUnconfirmedDangerAlerts, + hasDangerBlockingAlerts, + disabled, + )} onClick={handleOpenConfirmModal} size={ButtonSize.Lg} startIconName={IconName.Danger} > - {dangerAlerts?.length > 1 ? t('reviewAlerts') : t('confirm')} + {dangerAlerts?.length > 0 ? t('reviewAlerts') : t('confirm')} ) : ( + + +
+
+
+

+ Speed +

+
+
+
+
+

+ 🦊 Market +

+

+ + ~ + 0 sec + +

+
+
+
+ + +`; + +exports[`Info renders info section for contract interaction request 1`] = ` +
+
+
+
+
+

+ Estimated changes +

+
+
+ +
+
+
+
+ + + + + + + + + +
+
+
+
+
+
+
+
+

+ Request from +

+
+
+ +
+
+
+
+
+

+ metamask.github.io +

+
+
+
+
+
+

+ Interacting with +

+
+
+ +
+
+
+
+
+
+ +

+ 0x88AA6...A5125 +

+
+
+
+
+
+
+
+
+

+ Network fee +

+
+
+ +
+
+
+
+
+

+ 0.0001 ETH +

+

+ $0.04 +

+ +
+
+
+
+
+

+ Speed +

+
+
+
+
+

+ 🦊 Market +

+

+ + ~ + 0 sec + +

+
+
+
+
+
+`; + exports[`Info renders info section for personal sign request 1`] = `
`; +exports[`Info renders info section for setApprovalForAll request 1`] = ` +
+
+
+
+
+

+ Estimated changes +

+
+
+ +
+
+
+
+
+

+ You're giving permission for someone else to withdraw NFTs from your account. +

+
+
+
+
+
+

+ Withdrawing +

+
+
+
+
+
+

+ All +

+
+
+
+ +

+ 0x07614...3ad68 +

+
+
+
+
+
+
+
+
+
+
+
+

+ Data +

+
+
+
+ + + + + + + + + +
+
+
+
+
+
+

+ Request from +

+
+
+ +
+
+
+
+
+

+ metamask.github.io +

+
+
+
+
+
+
+
+

+ Network fee +

+
+
+ +
+
+
+
+
+

+ 0.0001 ETH +

+

+ $0.04 +

+ +
+
+
+
+
+

+ Speed +

+
+
+
+
+

+ 🦊 Market +

+

+ + ~ + 0 sec + +

+
+
+
+
+
+`; + exports[`Info renders info section for typed sign request 1`] = `
renders component for approve details 1`] = `
`; + +exports[` renders component for approve details for setApprovalForAll 1`] = ` +
+
+
+
+
+
+

+ Data +

+
+
+
+ + + + + + + + + +
+
+
+
+
+`; diff --git a/ui/pages/confirmations/components/confirm/info/approve/approve-details/approve-details.test.tsx b/ui/pages/confirmations/components/confirm/info/approve/approve-details/approve-details.test.tsx index 72c4f62d4adb..daec14c166af 100644 --- a/ui/pages/confirmations/components/confirm/info/approve/approve-details/approve-details.test.tsx +++ b/ui/pages/confirmations/components/confirm/info/approve/approve-details/approve-details.test.tsx @@ -17,4 +17,14 @@ describe('', () => { ); expect(container).toMatchSnapshot(); }); + + it('renders component for approve details for setApprovalForAll', () => { + const state = mockState; + const mockStore = configureMockStore(middleware)(state); + const { container } = renderWithConfirmContextProvider( + , + mockStore, + ); + expect(container).toMatchSnapshot(); + }); }); diff --git a/ui/pages/confirmations/components/confirm/info/approve/approve-details/approve-details.tsx b/ui/pages/confirmations/components/confirm/info/approve/approve-details/approve-details.tsx index 6c38842e8e39..57d8903994bb 100644 --- a/ui/pages/confirmations/components/confirm/info/approve/approve-details/approve-details.tsx +++ b/ui/pages/confirmations/components/confirm/info/approve/approve-details/approve-details.tsx @@ -19,7 +19,11 @@ import { } from '../../shared/transaction-details/transaction-details'; import { useIsNFT } from '../hooks/use-is-nft'; -const Spender = () => { +const Spender = ({ + isSetApprovalForAll = false, +}: { + isSetApprovalForAll?: boolean; +}) => { const t = useI18nContext(); const { currentConfirmation: transactionMeta } = @@ -44,7 +48,7 @@ const Spender = () => { return ( <> { ); }; -export const ApproveDetails = () => { +export const ApproveDetails = ({ + isSetApprovalForAll = false, +}: { + isSetApprovalForAll?: boolean; +}) => { const showAdvancedDetails = useSelector( selectConfirmationAdvancedDetailsOpen, ); return ( - + {showAdvancedDetails && ( <> diff --git a/ui/pages/confirmations/components/confirm/info/approve/hooks/use-received-token.ts b/ui/pages/confirmations/components/confirm/info/approve/hooks/use-received-token.ts index 319e340e89e1..44ed0fd9667a 100644 --- a/ui/pages/confirmations/components/confirm/info/approve/hooks/use-received-token.ts +++ b/ui/pages/confirmations/components/confirm/info/approve/hooks/use-received-token.ts @@ -1,6 +1,8 @@ import { TransactionMeta } from '@metamask/transaction-controller'; import { useSelector } from 'react-redux'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { normalizeSafeAddress } from '../../../../../../../../app/scripts/lib/multichain/address'; import { useAccountTotalFiatBalance } from '../../../../../../../hooks/useAccountTotalFiatBalance'; import { getSelectedAccount } from '../../../../../../../selectors'; diff --git a/ui/pages/confirmations/components/confirm/info/info.test.tsx b/ui/pages/confirmations/components/confirm/info/info.test.tsx index f2c0a232259a..4931c2fbaa01 100644 --- a/ui/pages/confirmations/components/confirm/info/info.test.tsx +++ b/ui/pages/confirmations/components/confirm/info/info.test.tsx @@ -2,7 +2,10 @@ import React from 'react'; import configureMockStore from 'redux-mock-store'; import { + getMockApproveConfirmState, + getMockContractInteractionConfirmState, getMockPersonalSignConfirmState, + getMockSetApprovalForAllConfirmState, getMockTypedSignConfirmState, } from '../../../../../../test/data/confirmations/helper'; import { renderWithConfirmContextProvider } from '../../../../../../test/lib/confirmations/render-helpers'; @@ -17,6 +20,14 @@ jest.mock( }), ); +jest.mock('../../../../../store/actions', () => ({ + ...jest.requireActual('../../../../../store/actions'), + getGasFeeTimeEstimate: jest.fn().mockResolvedValue({ + lowerTimeBound: 0, + upperTimeBound: 60000, + }), +})); + describe('Info', () => { it('renders info section for personal sign request', () => { const state = getMockPersonalSignConfirmState(); @@ -31,4 +42,25 @@ describe('Info', () => { const { container } = renderWithConfirmContextProvider(, mockStore); expect(container).toMatchSnapshot(); }); + + it('renders info section for contract interaction request', () => { + const state = getMockContractInteractionConfirmState(); + const mockStore = configureMockStore([])(state); + const { container } = renderWithConfirmContextProvider(, mockStore); + expect(container).toMatchSnapshot(); + }); + + it('renders info section for approve request', () => { + const state = getMockApproveConfirmState(); + const mockStore = configureMockStore([])(state); + const { container } = renderWithConfirmContextProvider(, mockStore); + expect(container).toMatchSnapshot(); + }); + + it('renders info section for setApprovalForAll request', () => { + const state = getMockSetApprovalForAllConfirmState(); + const mockStore = configureMockStore([])(state); + const { container } = renderWithConfirmContextProvider(, mockStore); + expect(container).toMatchSnapshot(); + }); }); diff --git a/ui/pages/confirmations/components/confirm/info/info.tsx b/ui/pages/confirmations/components/confirm/info/info.tsx index 665829ecef1b..5a9c4757158e 100644 --- a/ui/pages/confirmations/components/confirm/info/info.tsx +++ b/ui/pages/confirmations/components/confirm/info/info.tsx @@ -1,12 +1,13 @@ import { TransactionType } from '@metamask/transaction-controller'; import React, { useMemo } from 'react'; -import { SignatureRequestType } from '../../../types/confirm'; import { useConfirmContext } from '../../../context/confirm'; +import { SignatureRequestType } from '../../../types/confirm'; +import ApproveInfo from './approve/approve'; import BaseTransactionInfo from './base-transaction-info/base-transaction-info'; import PersonalSignInfo from './personal-sign/personal-sign'; +import SetApprovalForAllInfo from './set-approval-for-all-info/set-approval-for-all-info'; import TypedSignV1Info from './typed-sign-v1/typed-sign-v1'; import TypedSignInfo from './typed-sign/typed-sign'; -import ApproveInfo from './approve/approve'; const Info = () => { const { currentConfirmation } = useConfirmContext(); @@ -26,6 +27,8 @@ const Info = () => { [TransactionType.deployContract]: () => BaseTransactionInfo, [TransactionType.tokenMethodApprove]: () => ApproveInfo, [TransactionType.tokenMethodIncreaseAllowance]: () => ApproveInfo, + [TransactionType.tokenMethodSetApprovalForAll]: () => + SetApprovalForAllInfo, }), [currentConfirmation], ); diff --git a/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/__snapshots__/set-approval-for-all-info.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/__snapshots__/set-approval-for-all-info.test.tsx.snap new file mode 100644 index 000000000000..9f009645f67b --- /dev/null +++ b/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/__snapshots__/set-approval-for-all-info.test.tsx.snap @@ -0,0 +1,334 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` does not render component when no transaction is in state 1`] = `
`; + +exports[` renders component for approve request 1`] = ` +
+
+
+
+
+

+ Estimated changes +

+
+
+ +
+
+
+
+
+

+ You're giving permission for someone else to withdraw NFTs from your account. +

+
+
+
+
+
+

+ Withdrawing +

+
+
+
+
+
+

+ All +

+
+
+
+ +

+ 0x07614...3ad68 +

+
+
+
+
+
+
+
+
+
+
+
+

+ Data +

+
+
+
+ + + + + + + + + +
+
+
+
+
+
+

+ Request from +

+
+
+ +
+
+
+
+
+

+ metamask.github.io +

+
+
+
+
+
+
+
+

+ Network fee +

+
+
+ +
+
+
+
+
+

+ 0.0001 ETH +

+

+ $0.04 +

+ +
+
+
+
+
+

+ Speed +

+
+
+
+
+

+ 🦊 Market +

+

+ + ~ + 0 sec + +

+
+
+
+
+
+`; diff --git a/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/set-approval-for-all-info.test.tsx b/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/set-approval-for-all-info.test.tsx new file mode 100644 index 000000000000..3460b1d8e76e --- /dev/null +++ b/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/set-approval-for-all-info.test.tsx @@ -0,0 +1,63 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { + getMockConfirmState, + getMockSetApprovalForAllConfirmState, +} from '../../../../../../../test/data/confirmations/helper'; +import mockState from '../../../../../../../test/data/mock-state.json'; +import { renderWithConfirmContextProvider } from '../../../../../../../test/lib/confirmations/render-helpers'; +import SetApprovalForAllInfo from './set-approval-for-all-info'; + +jest.mock('../../../../../../store/actions', () => ({ + ...jest.requireActual('../../../../../../store/actions'), + getGasFeeTimeEstimate: jest.fn().mockResolvedValue({ + lowerTimeBound: 0, + upperTimeBound: 60000, + }), +})); + +jest.mock( + '../../../../../../components/app/alert-system/contexts/alertMetricsContext', + () => ({ + useAlertMetrics: jest.fn(() => ({ + trackAlertMetrics: jest.fn(), + })), + }), +); + +describe('', () => { + const middleware = [thunk]; + + it('renders component for approve request', async () => { + const state = getMockSetApprovalForAllConfirmState(); + + const mockStore = configureMockStore(middleware)(state); + + const { container } = renderWithConfirmContextProvider( + , + mockStore, + ); + + expect(container).toMatchSnapshot(); + }); + + it('does not render component when no transaction is in state', async () => { + const state = getMockConfirmState({ + metamask: { + ...mockState.metamask, + pendingApprovals: {}, + transactions: [], + }, + }); + + const mockStore = configureMockStore(middleware)(state); + + const { container } = renderWithConfirmContextProvider( + , + mockStore, + ); + + expect(container).toMatchSnapshot(); + }); +}); diff --git a/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/set-approval-for-all-info.tsx b/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/set-approval-for-all-info.tsx new file mode 100644 index 000000000000..9ed773e5a350 --- /dev/null +++ b/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/set-approval-for-all-info.tsx @@ -0,0 +1,33 @@ +import { TransactionMeta } from '@metamask/transaction-controller'; +import React from 'react'; +import { useSelector } from 'react-redux'; +import { useConfirmContext } from '../../../../context/confirm'; +import { selectConfirmationAdvancedDetailsOpen } from '../../../../selectors/preferences'; +import { ApproveDetails } from '../approve/approve-details/approve-details'; +import { AdvancedDetails } from '../shared/advanced-details/advanced-details'; +import { GasFeesSection } from '../shared/gas-fees-section/gas-fees-section'; +import { SetApprovalForAllStaticSimulation } from './set-approval-for-all-static-simulation/set-approval-for-all-static-simulation'; + +const SetApprovalForAllInfo = () => { + const { currentConfirmation: transactionMeta } = + useConfirmContext(); + + const showAdvancedDetails = useSelector( + selectConfirmationAdvancedDetailsOpen, + ); + + if (!transactionMeta?.txParams) { + return null; + } + + return ( + <> + + + + {showAdvancedDetails && } + + ); +}; + +export default SetApprovalForAllInfo; diff --git a/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/set-approval-for-all-static-simulation/__snapshots__/set-approval-for-all-static-simulation.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/set-approval-for-all-static-simulation/__snapshots__/set-approval-for-all-static-simulation.test.tsx.snap new file mode 100644 index 000000000000..9ab4107ff173 --- /dev/null +++ b/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/set-approval-for-all-static-simulation/__snapshots__/set-approval-for-all-static-simulation.test.tsx.snap @@ -0,0 +1,106 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders component for approve request 1`] = ` +
+
+
+
+
+

+ Estimated changes +

+
+
+ +
+
+
+
+
+

+ You're giving permission for someone else to withdraw NFTs from your account. +

+
+
+
+
+
+

+ Withdrawing +

+
+
+
+
+
+

+ All +

+
+
+
+ +

+ 0x07614...3ad68 +

+
+
+
+
+
+
+
+`; diff --git a/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/set-approval-for-all-static-simulation/set-approval-for-all-static-simulation.test.tsx b/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/set-approval-for-all-static-simulation/set-approval-for-all-static-simulation.test.tsx new file mode 100644 index 000000000000..a964d008ada0 --- /dev/null +++ b/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/set-approval-for-all-static-simulation/set-approval-for-all-static-simulation.test.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { getMockSetApprovalForAllConfirmState } from '../../../../../../../../test/data/confirmations/helper'; +import { renderWithConfirmContextProvider } from '../../../../../../../../test/lib/confirmations/render-helpers'; +import { SetApprovalForAllStaticSimulation } from './set-approval-for-all-static-simulation'; + +describe('', () => { + const middleware = [thunk]; + + it('renders component for approve request', async () => { + const state = getMockSetApprovalForAllConfirmState(); + + const mockStore = configureMockStore(middleware)(state); + + const { container } = renderWithConfirmContextProvider( + , + mockStore, + ); + + expect(container).toMatchSnapshot(); + }); +}); diff --git a/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/set-approval-for-all-static-simulation/set-approval-for-all-static-simulation.tsx b/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/set-approval-for-all-static-simulation/set-approval-for-all-static-simulation.tsx new file mode 100644 index 000000000000..89686f4faa7d --- /dev/null +++ b/ui/pages/confirmations/components/confirm/info/set-approval-for-all-info/set-approval-for-all-static-simulation/set-approval-for-all-static-simulation.tsx @@ -0,0 +1,61 @@ +import { NameType } from '@metamask/name-controller'; +import { TransactionMeta } from '@metamask/transaction-controller'; +import React from 'react'; +import Name from '../../../../../../../components/app/name'; +import { Box, Text } from '../../../../../../../components/component-library'; +import { + AlignItems, + BackgroundColor, + BlockSize, + BorderRadius, + Display, + TextAlign, +} from '../../../../../../../helpers/constants/design-system'; +import { useI18nContext } from '../../../../../../../hooks/useI18nContext'; +import { useConfirmContext } from '../../../../../context/confirm'; +import StaticSimulation from '../../shared/static-simulation/static-simulation'; + +export const SetApprovalForAllStaticSimulation = () => { + const t = useI18nContext(); + + const { currentConfirmation: transactionMeta } = useConfirmContext() as { + currentConfirmation: TransactionMeta; + }; + + const SetApprovalForAllRow = ( + + + + {t('all')} + + + + + ); + + const simulationElements = SetApprovalForAllRow; + + return ( + + ); +}; diff --git a/ui/pages/confirmations/components/confirm/info/shared/transaction-data/transaction-data.tsx b/ui/pages/confirmations/components/confirm/info/shared/transaction-data/transaction-data.tsx index 0ec00c1a9be4..b8c3a44078f1 100644 --- a/ui/pages/confirmations/components/confirm/info/shared/transaction-data/transaction-data.tsx +++ b/ui/pages/confirmations/components/confirm/info/shared/transaction-data/transaction-data.tsx @@ -25,6 +25,8 @@ import { DecodedTransactionDataParam, DecodedTransactionDataSource, } from '../../../../../../../../shared/types/transaction-decode'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { UniswapPathPool } from '../../../../../../../../app/scripts/lib/transaction/decode/uniswap'; import { useConfirmContext } from '../../../../../context/confirm'; diff --git a/ui/pages/confirmations/components/confirm/ledger-info/ledger-info.tsx b/ui/pages/confirmations/components/confirm/ledger-info/ledger-info.tsx index 0f250a9b0a47..07110aef3b3d 100644 --- a/ui/pages/confirmations/components/confirm/ledger-info/ledger-info.tsx +++ b/ui/pages/confirmations/components/confirm/ledger-info/ledger-info.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { useDispatch, useSelector } from 'react-redux'; - +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../../shared/constants/app'; import { diff --git a/ui/pages/confirmations/components/confirm/title/title.test.tsx b/ui/pages/confirmations/components/confirm/title/title.test.tsx index d886eccc7ac6..938ed46d5537 100644 --- a/ui/pages/confirmations/components/confirm/title/title.test.tsx +++ b/ui/pages/confirmations/components/confirm/title/title.test.tsx @@ -2,22 +2,30 @@ import React from 'react'; import configureMockStore from 'redux-mock-store'; import { + getMockApproveConfirmState, getMockContractInteractionConfirmState, getMockPersonalSignConfirmState, getMockPersonalSignConfirmStateForRequest, + getMockSetApprovalForAllConfirmState, getMockTypedSignConfirmState, getMockTypedSignConfirmStateForRequest, } from '../../../../../../test/data/confirmations/helper'; -import { renderWithConfirmContextProvider } from '../../../../../../test/lib/confirmations/render-helpers'; -import { permitSignatureMsg } from '../../../../../../test/data/confirmations/typed_sign'; import { unapprovedPersonalSignMsg } from '../../../../../../test/data/confirmations/personal_sign'; -import { Severity } from '../../../../../helpers/constants/design-system'; +import { permitSignatureMsg } from '../../../../../../test/data/confirmations/typed_sign'; +import { renderWithConfirmContextProvider } from '../../../../../../test/lib/confirmations/render-helpers'; +import { tEn } from '../../../../../../test/lib/i18n-helpers'; import { Alert, ConfirmAlertsState, } from '../../../../../ducks/confirm-alerts/confirm-alerts'; +import { Severity } from '../../../../../helpers/constants/design-system'; +import { useIsNFT } from '../info/approve/hooks/use-is-nft'; import ConfirmTitle from './title'; +jest.mock('../info/approve/hooks/use-is-nft', () => ({ + useIsNFT: jest.fn(() => ({ isNFT: true })), +})); + describe('ConfirmTitle', () => { it('should render the title and description for a personal signature', () => { const mockStore = configureMockStore([])(getMockPersonalSignConfirmState); @@ -28,9 +36,7 @@ describe('ConfirmTitle', () => { expect(getByText('Signature request')).toBeInTheDocument(); expect( - getByText( - 'Only confirm this message if you approve the content and trust the requesting site.', - ), + getByText('Review request details before you confirm.'), ).toBeInTheDocument(); }); @@ -58,9 +64,7 @@ describe('ConfirmTitle', () => { expect(getByText('Signature request')).toBeInTheDocument(); expect( - getByText( - 'Only confirm this message if you approve the content and trust the requesting site.', - ), + getByText('Review request details before you confirm.'), ).toBeInTheDocument(); }); @@ -73,7 +77,63 @@ describe('ConfirmTitle', () => { mockStore, ); - expect(getByText('Transaction request')).toBeInTheDocument(); + expect( + getByText(tEn('confirmTitleTransaction') as string), + ).toBeInTheDocument(); + }); + + it('should render the title and description for a approval transaction for NFTs', () => { + const mockStore = configureMockStore([])(getMockApproveConfirmState()); + const { getByText } = renderWithConfirmContextProvider( + , + mockStore, + ); + + expect( + getByText(tEn('confirmTitleApproveTransaction') as string), + ).toBeInTheDocument(); + expect( + getByText(tEn('confirmTitleDescApproveTransaction') as string), + ).toBeInTheDocument(); + }); + + it('should render the title and description for a approval transaction for erc20 tokens', () => { + const mockedUseIsNFT = jest.mocked(useIsNFT); + + mockedUseIsNFT.mockImplementation(() => ({ + isNFT: false, + pending: false, + })); + + const mockStore = configureMockStore([])(getMockApproveConfirmState()); + const { getByText } = renderWithConfirmContextProvider( + , + mockStore, + ); + + expect( + getByText(tEn('confirmTitlePermitTokens') as string), + ).toBeInTheDocument(); + expect( + getByText(tEn('confirmTitleDescERC20ApproveTransaction') as string), + ).toBeInTheDocument(); + }); + + it('should render the title and description for a setApprovalForAll transaction', () => { + const mockStore = configureMockStore([])( + getMockSetApprovalForAllConfirmState(), + ); + const { getByText } = renderWithConfirmContextProvider( + , + mockStore, + ); + + expect( + getByText(tEn('setApprovalForAllRedesignedTitle') as string), + ).toBeInTheDocument(); + expect( + getByText(tEn('confirmTitleDescApproveTransaction') as string), + ).toBeInTheDocument(); }); describe('Alert banner', () => { diff --git a/ui/pages/confirmations/components/confirm/title/title.tsx b/ui/pages/confirmations/components/confirm/title/title.tsx index f61fcf7d7775..94acee877900 100644 --- a/ui/pages/confirmations/components/confirm/title/title.tsx +++ b/ui/pages/confirmations/components/confirm/title/title.tsx @@ -86,6 +86,8 @@ const getTitle = ( return t('confirmTitlePermitTokens'); case TransactionType.tokenMethodIncreaseAllowance: return t('confirmTitlePermitTokens'); + case TransactionType.tokenMethodSetApprovalForAll: + return t('setApprovalForAllRedesignedTitle'); default: return ''; } @@ -105,11 +107,11 @@ const getDescription = ( if (isSIWESignatureRequest(confirmation as SignatureRequestType)) { return t('confirmTitleDescSIWESignature'); } - return t('confirmTitleDescSignature'); + return t('confirmTitleDescSign'); case TransactionType.signTypedData: return isPermitSignatureRequest(confirmation as SignatureRequestType) ? t('confirmTitleDescPermitSignature') - : t('confirmTitleDescSignature'); + : t('confirmTitleDescSign'); case TransactionType.tokenMethodApprove: if (isNFT) { return t('confirmTitleDescApproveTransaction'); @@ -117,6 +119,8 @@ const getDescription = ( return t('confirmTitleDescERC20ApproveTransaction'); case TransactionType.tokenMethodIncreaseAllowance: return t('confirmTitleDescPermitSignature'); + case TransactionType.tokenMethodSetApprovalForAll: + return t('confirmTitleDescApproveTransaction'); default: return ''; } diff --git a/ui/pages/confirmations/components/ledger-instruction-field/ledger-instruction-field.js b/ui/pages/confirmations/components/ledger-instruction-field/ledger-instruction-field.js index 99b5e458d829..14ea55e4526c 100644 --- a/ui/pages/confirmations/components/ledger-instruction-field/ledger-instruction-field.js +++ b/ui/pages/confirmations/components/ledger-instruction-field/ledger-instruction-field.js @@ -1,6 +1,8 @@ import PropTypes from 'prop-types'; import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../shared/constants/app'; import { diff --git a/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.container.js b/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.container.js index cc3de6095f2d..803ea8698cd4 100644 --- a/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.container.js +++ b/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.container.js @@ -80,6 +80,8 @@ import { ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) getEnvironmentType, ///: END:ONLY_INCLUDE_IF + // TODO: Remove restricted import + // eslint-disable-next-line import/no-restricted-paths } from '../../../../app/scripts/lib/util'; import { diff --git a/ui/pages/confirmations/confirm-transaction/confirm-transaction.component.js b/ui/pages/confirmations/confirm-transaction/confirm-transaction.component.js index cb740dd9a99a..7caade1d14fb 100644 --- a/ui/pages/confirmations/confirm-transaction/confirm-transaction.component.js +++ b/ui/pages/confirmations/confirm-transaction/confirm-transaction.component.js @@ -47,6 +47,8 @@ import ConfirmSignatureRequest from '../confirm-signature-request'; import ConfirmTransactionSwitch from '../confirm-transaction-switch'; import Confirm from '../confirm/confirm'; import useCurrentConfirmation from '../hooks/useCurrentConfirmation'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import { useAsyncResult } from '../../../hooks/useAsyncResult'; import { TraceName } from '../../../../shared/lib/trace'; diff --git a/ui/pages/confirmations/confirm/__snapshots__/confirm.test.tsx.snap b/ui/pages/confirmations/confirm/__snapshots__/confirm.test.tsx.snap index 585c0a8cee03..460f5097af1f 100644 --- a/ui/pages/confirmations/confirm/__snapshots__/confirm.test.tsx.snap +++ b/ui/pages/confirmations/confirm/__snapshots__/confirm.test.tsx.snap @@ -99,7 +99,7 @@ exports[`Confirm matches snapshot for signature - personal sign type 1`] = `

- Only confirm this message if you approve the content and trust the requesting site. + Review request details before you confirm.

- Only confirm this message if you approve the content and trust the requesting site. + Review request details before you confirm.

- Only confirm this message if you approve the content and trust the requesting site. + Review request details before you confirm.

{ const { id: paramsConfirmationId } = useParams<{ id: string }>(); - const latestPendingApproval = useSelector(latestPendingConfirmationSelector); - const confirmationId = paramsConfirmationId ?? latestPendingApproval?.id; + const oldestPendingApproval = useSelector(oldestPendingConfirmationSelector); + const confirmationId = paramsConfirmationId ?? oldestPendingApproval?.id; const isRedesignedSignaturesUserSettingEnabled = useSelector( getRedesignedConfirmationsEnabled, diff --git a/ui/pages/confirmations/selectors/confirm.test.ts b/ui/pages/confirmations/selectors/confirm.test.ts index d765e6df5f51..c573a7d5822b 100644 --- a/ui/pages/confirmations/selectors/confirm.test.ts +++ b/ui/pages/confirmations/selectors/confirm.test.ts @@ -3,7 +3,7 @@ import { ApprovalType } from '@metamask/controller-utils'; import { ConfirmMetamaskState } from '../types/confirm'; import { getIsRedesignedConfirmationsDeveloperEnabled, - latestPendingConfirmationSelector, + oldestPendingConfirmationSelector, pendingConfirmationsSelector, } from './confirm'; @@ -54,11 +54,11 @@ describe('confirm selectors', () => { }); }); - describe('latestPendingConfirmationSelector', () => { - it('should return latest pending confirmation from state', () => { - const result = latestPendingConfirmationSelector(mockedState); + describe('oldestPendingConfirmationSelector', () => { + it('should return oldest pending confirmation from state', () => { + const result = oldestPendingConfirmationSelector(mockedState); - expect(result).toStrictEqual(mockedState.metamask.pendingApprovals[2]); + expect(result).toStrictEqual(mockedState.metamask.pendingApprovals[3]); }); }); diff --git a/ui/pages/confirmations/selectors/confirm.ts b/ui/pages/confirmations/selectors/confirm.ts index 54b4cc4f61b8..57107bdf3021 100644 --- a/ui/pages/confirmations/selectors/confirm.ts +++ b/ui/pages/confirmations/selectors/confirm.ts @@ -2,9 +2,9 @@ import { ApprovalType } from '@metamask/controller-utils'; import { createSelector } from 'reselect'; import { getPendingApprovals } from '../../../selectors/approvals'; -import { ConfirmMetamaskState } from '../types/confirm'; -import { createDeepEqualSelector } from '../../../selectors/util'; import { getPreferences } from '../../../selectors/selectors'; +import { createDeepEqualSelector } from '../../../selectors/util'; +import { ConfirmMetamaskState } from '../types/confirm'; const ConfirmationApprovalTypes = [ ApprovalType.PersonalSign, @@ -28,15 +28,14 @@ export function pendingConfirmationsSortedSelector( .sort((a1, a2) => a1.time - a2.time); } -const internalLatestPendingConfirmationSelector = createSelector( +const firstPendingConfirmationSelector = createSelector( pendingConfirmationsSortedSelector, - (pendingConfirmations) => - pendingConfirmations.sort((a1, a2) => a2.time - a1.time)[0], + (pendingConfirmations) => pendingConfirmations[0], ); -export const latestPendingConfirmationSelector = createDeepEqualSelector( - internalLatestPendingConfirmationSelector, - (latestPendingConfirmation) => latestPendingConfirmation, +export const oldestPendingConfirmationSelector = createDeepEqualSelector( + firstPendingConfirmationSelector, + (firstPendingConfirmation) => firstPendingConfirmation, ); // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/ui/pages/confirmations/send/send-content/add-recipient/domain-input.component.js b/ui/pages/confirmations/send/send-content/add-recipient/domain-input.component.js index 0b2514f12414..f9d529fb18f3 100644 --- a/ui/pages/confirmations/send/send-content/add-recipient/domain-input.component.js +++ b/ui/pages/confirmations/send/send-content/add-recipient/domain-input.component.js @@ -3,6 +3,8 @@ import PropTypes from 'prop-types'; import classnames from 'classnames'; import { isHexString } from '@metamask/utils'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { addHexPrefix } from '../../../../../../app/scripts/lib/util'; import { shortenAddress } from '../../../../../helpers/utils/util'; import { diff --git a/ui/pages/confirmations/send/send.utils.js b/ui/pages/confirmations/send/send.utils.js index e5e787142fa1..498240b85eec 100644 --- a/ui/pages/confirmations/send/send.utils.js +++ b/ui/pages/confirmations/send/send.utils.js @@ -1,5 +1,6 @@ import { encode } from '@metamask/abi-utils'; - +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { addHexPrefix } from '../../../../app/scripts/lib/util'; import { TokenStandard } from '../../../../shared/constants/transaction'; import { Numeric } from '../../../../shared/modules/Numeric'; diff --git a/ui/pages/confirmations/utils/confirm.ts b/ui/pages/confirmations/utils/confirm.ts index a52a1a766f50..1fa7ff36085e 100644 --- a/ui/pages/confirmations/utils/confirm.ts +++ b/ui/pages/confirmations/utils/confirm.ts @@ -25,6 +25,7 @@ export const REDESIGN_DEV_TRANSACTION_TYPES = [ ...REDESIGN_USER_TRANSACTION_TYPES, TransactionType.tokenMethodApprove, TransactionType.tokenMethodIncreaseAllowance, + TransactionType.tokenMethodSetApprovalForAll, ]; const SIGNATURE_APPROVAL_TYPES = [ diff --git a/ui/pages/error/error.component.js b/ui/pages/error/error.component.js index 04095cec4ce1..57a8e40c6473 100644 --- a/ui/pages/error/error.component.js +++ b/ui/pages/error/error.component.js @@ -1,5 +1,7 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_POPUP } from '../../../shared/constants/app'; import { SUPPORT_REQUEST_LINK } from '../../helpers/constants/common'; diff --git a/ui/pages/home/home.container.js b/ui/pages/home/home.container.js index 671e02985769..42bdfc685779 100644 --- a/ui/pages/home/home.container.js +++ b/ui/pages/home/home.container.js @@ -79,6 +79,8 @@ import { import { getWeb3ShimUsageAlertEnabledness } from '../../ducks/metamask/metamask'; import { getSwapsFeatureIsLive } from '../../ducks/swaps/swaps'; import { fetchBuyableChains } from '../../ducks/ramps'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../app/scripts/lib/util'; import { getIsBrowserDeprecated } from '../../helpers/utils/util'; import { diff --git a/ui/pages/notifications/notification-components/erc1155-sent-received/erc1155-sent-received.tsx b/ui/pages/notifications/notification-components/erc1155-sent-received/erc1155-sent-received.tsx index ea4dabbac22a..4c2e3075b2e3 100644 --- a/ui/pages/notifications/notification-components/erc1155-sent-received/erc1155-sent-received.tsx +++ b/ui/pages/notifications/notification-components/erc1155-sent-received/erc1155-sent-received.tsx @@ -1,6 +1,8 @@ import React from 'react'; import { NotificationServicesController } from '@metamask/notification-services-controller'; import { CHAIN_IDS } from '../../../../../shared/constants/network'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { t } from '../../../../../app/scripts/translate'; import { type ExtractedNotification, isOfTypeNodeGuard } from '../node-guard'; diff --git a/ui/pages/notifications/notification-components/erc20-sent-received/erc20-sent-received.tsx b/ui/pages/notifications/notification-components/erc20-sent-received/erc20-sent-received.tsx index b80a769b70d4..8bed89216575 100644 --- a/ui/pages/notifications/notification-components/erc20-sent-received/erc20-sent-received.tsx +++ b/ui/pages/notifications/notification-components/erc20-sent-received/erc20-sent-received.tsx @@ -1,5 +1,7 @@ import React from 'react'; import { NotificationServicesController } from '@metamask/notification-services-controller'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { t } from '../../../../../app/scripts/translate'; import { CHAIN_IDS } from '../../../../../shared/constants/network'; import { type ExtractedNotification, isOfTypeNodeGuard } from '../node-guard'; diff --git a/ui/pages/notifications/notification-components/erc721-sent-received/erc721-sent-received.tsx b/ui/pages/notifications/notification-components/erc721-sent-received/erc721-sent-received.tsx index 239fb97f687f..7626691d2027 100644 --- a/ui/pages/notifications/notification-components/erc721-sent-received/erc721-sent-received.tsx +++ b/ui/pages/notifications/notification-components/erc721-sent-received/erc721-sent-received.tsx @@ -1,6 +1,8 @@ import React from 'react'; import { NotificationServicesController } from '@metamask/notification-services-controller'; import { CHAIN_IDS } from '../../../../../shared/constants/network'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { t } from '../../../../../app/scripts/translate'; import { type ExtractedNotification, isOfTypeNodeGuard } from '../node-guard'; diff --git a/ui/pages/notifications/notification-components/eth-sent-received/eth-sent-received.tsx b/ui/pages/notifications/notification-components/eth-sent-received/eth-sent-received.tsx index a277d732d6bb..6971a0cadaf0 100644 --- a/ui/pages/notifications/notification-components/eth-sent-received/eth-sent-received.tsx +++ b/ui/pages/notifications/notification-components/eth-sent-received/eth-sent-received.tsx @@ -1,5 +1,7 @@ import React from 'react'; import { NotificationServicesController } from '@metamask/notification-services-controller'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { t } from '../../../../../app/scripts/translate'; import { CHAIN_IDS } from '../../../../../shared/constants/network'; import { type ExtractedNotification, isOfTypeNodeGuard } from '../node-guard'; diff --git a/ui/pages/notifications/notification-components/lido-stake-ready-to-be-withdrawn/lido-stake-ready-to-be-withdrawn.tsx b/ui/pages/notifications/notification-components/lido-stake-ready-to-be-withdrawn/lido-stake-ready-to-be-withdrawn.tsx index b0c14799bbc6..f8cdbdf3216c 100644 --- a/ui/pages/notifications/notification-components/lido-stake-ready-to-be-withdrawn/lido-stake-ready-to-be-withdrawn.tsx +++ b/ui/pages/notifications/notification-components/lido-stake-ready-to-be-withdrawn/lido-stake-ready-to-be-withdrawn.tsx @@ -11,6 +11,8 @@ import { NotificationDetailBlockExplorerButton, NotificationDetailAddress, } from '../../../../components/multichain'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { t } from '../../../../../app/scripts/translate'; import { createTextItems, diff --git a/ui/pages/notifications/notification-components/lido-withdrawal-requested/lido-withdrawal-requested.tsx b/ui/pages/notifications/notification-components/lido-withdrawal-requested/lido-withdrawal-requested.tsx index 284218557145..47063c97e5ac 100644 --- a/ui/pages/notifications/notification-components/lido-withdrawal-requested/lido-withdrawal-requested.tsx +++ b/ui/pages/notifications/notification-components/lido-withdrawal-requested/lido-withdrawal-requested.tsx @@ -20,6 +20,8 @@ import { getNetworkDetailsByChainId, getUsdAmount, } from '../../../../helpers/utils/notification.util'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { t } from '../../../../../app/scripts/translate'; import { TextVariant, diff --git a/ui/pages/notifications/notification-components/stake/stake.tsx b/ui/pages/notifications/notification-components/stake/stake.tsx index 7703e6a24bd4..06b215655edb 100644 --- a/ui/pages/notifications/notification-components/stake/stake.tsx +++ b/ui/pages/notifications/notification-components/stake/stake.tsx @@ -1,5 +1,7 @@ import React from 'react'; import { NotificationServicesController } from '@metamask/notification-services-controller'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { t } from '../../../../../app/scripts/translate'; import { CHAIN_IDS } from '../../../../../shared/constants/network'; import { type ExtractedNotification, isOfTypeNodeGuard } from '../node-guard'; diff --git a/ui/pages/notifications/notification-components/swap-completed/swap-completed.tsx b/ui/pages/notifications/notification-components/swap-completed/swap-completed.tsx index 17b1282ef1fe..322900a10238 100644 --- a/ui/pages/notifications/notification-components/swap-completed/swap-completed.tsx +++ b/ui/pages/notifications/notification-components/swap-completed/swap-completed.tsx @@ -3,6 +3,8 @@ import { NotificationServicesController } from '@metamask/notification-services- import { type ExtractedNotification, isOfTypeNodeGuard } from '../node-guard'; import type { NotificationComponent } from '../types/notifications/notifications'; import { CHAIN_IDS } from '../../../../../shared/constants/network'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { t } from '../../../../../app/scripts/translate'; import { diff --git a/ui/pages/onboarding-flow/metametrics/metametrics.test.js b/ui/pages/onboarding-flow/metametrics/metametrics.test.js index ffa66646bc2e..a5b7dc9e1cc8 100644 --- a/ui/pages/onboarding-flow/metametrics/metametrics.test.js +++ b/ui/pages/onboarding-flow/metametrics/metametrics.test.js @@ -7,6 +7,8 @@ import { ONBOARDING_CREATE_PASSWORD_ROUTE } from '../../../helpers/constants/rou import { onboardingMetametricsAgree, noThanks, + // TODO: Remove restricted import + // eslint-disable-next-line import/no-restricted-paths } from '../../../../app/_locales/en/messages.json'; import { setParticipateInMetaMetrics, diff --git a/ui/pages/onboarding-flow/onboarding-app-header/onboarding-app-header.js b/ui/pages/onboarding-flow/onboarding-app-header/onboarding-app-header.js index 6d7cd164a519..84fe343f4a09 100644 --- a/ui/pages/onboarding-flow/onboarding-app-header/onboarding-app-header.js +++ b/ui/pages/onboarding-flow/onboarding-app-header/onboarding-app-header.js @@ -4,6 +4,8 @@ import MetaFoxLogo from '../../../components/ui/metafox-logo'; import Dropdown from '../../../components/ui/dropdown'; import { getCurrentLocale } from '../../../ducks/locale/locale'; import { updateCurrentLocale } from '../../../store/actions'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import locales from '../../../../app/_locales/index.json'; export default function OnboardingAppHeader() { diff --git a/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js b/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js index fffd5c00feda..53cfe99efeb0 100644 --- a/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js +++ b/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js @@ -2,6 +2,8 @@ import React, { useContext, useState, useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { useHistory } from 'react-router-dom'; import { ButtonVariant } from '@metamask/snaps-sdk'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { addUrlProtocolPrefix } from '../../../../app/scripts/lib/util'; import { useSetIsProfileSyncingEnabled, diff --git a/ui/pages/permissions-connect/permissions-connect.component.js b/ui/pages/permissions-connect/permissions-connect.component.js index af84867202a1..e5adf45a43fe 100644 --- a/ui/pages/permissions-connect/permissions-connect.component.js +++ b/ui/pages/permissions-connect/permissions-connect.component.js @@ -3,6 +3,8 @@ import React, { Component } from 'react'; import { Switch, Route } from 'react-router-dom'; import { ethErrors, serializeError } from 'eth-rpc-errors'; import { SubjectType } from '@metamask/permission-controller'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { isEthAddress } from '../../../app/scripts/lib/multichain/address'; import { MILLISECOND } from '../../../shared/constants/time'; import { DEFAULT_ROUTE } from '../../helpers/constants/routes'; @@ -14,6 +16,8 @@ import { CaveatTypes, RestrictedMethods, } from '../../../shared/constants/permissions'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { PermissionNames } from '../../../app/scripts/controllers/permissions'; import ChooseAccount from './choose-account'; import PermissionsRedirect from './redirect'; diff --git a/ui/pages/permissions-connect/permissions-connect.test.tsx b/ui/pages/permissions-connect/permissions-connect.test.tsx index aaabd7621d98..05b1120cf5d8 100644 --- a/ui/pages/permissions-connect/permissions-connect.test.tsx +++ b/ui/pages/permissions-connect/permissions-connect.test.tsx @@ -5,6 +5,8 @@ import thunk from 'redux-thunk'; import { ApprovalType } from '@metamask/controller-utils'; import { BtcAccountType } from '@metamask/keyring-api'; import { fireEvent } from '@testing-library/react'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import messages from '../../../app/_locales/en/messages.json'; import { renderWithProvider } from '../../../test/lib/render-helpers'; import mockState from '../../../test/data/mock-state.json'; diff --git a/ui/pages/routes/routes.component.js b/ui/pages/routes/routes.component.js index 5814d7a5759e..5c91d49c5266 100644 --- a/ui/pages/routes/routes.component.js +++ b/ui/pages/routes/routes.component.js @@ -99,6 +99,8 @@ import { ///: END:ONLY_INCLUDE_IF } from '../../../shared/constants/app'; import { NETWORK_TYPES } from '../../../shared/constants/network'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../app/scripts/lib/util'; import ConfirmationPage from '../confirmations/confirmation'; import OnboardingFlow from '../onboarding-flow/onboarding-flow'; diff --git a/ui/pages/settings/developer-options-tab/developer-options-tab.tsx b/ui/pages/settings/developer-options-tab/developer-options-tab.tsx index 12fd53b60dbb..fa5d58406a14 100644 --- a/ui/pages/settings/developer-options-tab/developer-options-tab.tsx +++ b/ui/pages/settings/developer-options-tab/developer-options-tab.tsx @@ -32,6 +32,8 @@ import { setServiceWorkerKeepAlivePreference, setRedesignedConfirmationsDeveloperEnabled, } from '../../../store/actions'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; import { getIsRedesignedConfirmationsDeveloperEnabled } from '../../confirmations/selectors/confirm'; diff --git a/ui/pages/settings/security-tab/security-tab.component.js b/ui/pages/settings/security-tab/security-tab.component.js index 6ed158844198..f6da9fe2367f 100644 --- a/ui/pages/settings/security-tab/security-tab.component.js +++ b/ui/pages/settings/security-tab/security-tab.component.js @@ -4,6 +4,8 @@ import React, { PureComponent } from 'react'; import { addUrlProtocolPrefix, getEnvironmentType, + // TODO: Remove restricted import + // eslint-disable-next-line import/no-restricted-paths } from '../../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; import { diff --git a/ui/pages/settings/security-tab/security-tab.test.js b/ui/pages/settings/security-tab/security-tab.test.js index 876c43e80e98..905fec684fd5 100644 --- a/ui/pages/settings/security-tab/security-tab.test.js +++ b/ui/pages/settings/security-tab/security-tab.test.js @@ -3,6 +3,8 @@ import userEvent from '@testing-library/user-event'; import React from 'react'; import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; import mockState from '../../../../test/data/mock-state.json'; diff --git a/ui/pages/settings/settings-tab/settings-tab.component.js b/ui/pages/settings/settings-tab/settings-tab.component.js index d798b62f77ba..b998cde80515 100644 --- a/ui/pages/settings/settings-tab/settings-tab.component.js +++ b/ui/pages/settings/settings-tab/settings-tab.component.js @@ -12,6 +12,8 @@ import { } from '../../../helpers/constants/design-system'; import Dropdown from '../../../components/ui/dropdown'; import ToggleButton from '../../../components/ui/toggle-button'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import locales from '../../../../app/_locales/index.json'; import Jazzicon from '../../../components/ui/jazzicon'; import BlockieIdenticon from '../../../components/ui/identicon/blockieIdenticon'; diff --git a/ui/pages/settings/settings.component.js b/ui/pages/settings/settings.component.js index da67815af35c..72a4141512ee 100644 --- a/ui/pages/settings/settings.component.js +++ b/ui/pages/settings/settings.component.js @@ -40,6 +40,8 @@ import { TextVariant, } from '../../helpers/constants/design-system'; import MetafoxLogo from '../../components/ui/metafox-logo'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_POPUP } from '../../../shared/constants/app'; import SettingsTab from './settings-tab'; diff --git a/ui/pages/settings/settings.container.js b/ui/pages/settings/settings.container.js index 5ddc25f147b2..638b6aea23af 100644 --- a/ui/pages/settings/settings.container.js +++ b/ui/pages/settings/settings.container.js @@ -3,6 +3,8 @@ import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; import { getAddressBookEntryOrAccountName } from '../../selectors'; import { ENVIRONMENT_TYPE_POPUP } from '../../../shared/constants/app'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../app/scripts/lib/util'; import { getMostRecentOverviewPage } from '../../ducks/history/history'; import { diff --git a/ui/pages/swaps/prepare-swap-page/review-quote.js b/ui/pages/swaps/prepare-swap-page/review-quote.js index 4695c271cc7c..496ae5ee6d9e 100644 --- a/ui/pages/swaps/prepare-swap-page/review-quote.js +++ b/ui/pages/swaps/prepare-swap-page/review-quote.js @@ -133,6 +133,8 @@ import { calcTokenAmount, toPrecisionWithoutTrailingZeros, } from '../../../../shared/lib/transactions-controller-utils'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { addHexPrefix } from '../../../../app/scripts/lib/util'; import { calcTokenValue, diff --git a/ui/pages/swaps/view-quote/view-quote.js b/ui/pages/swaps/view-quote/view-quote.js index a01184c8dc1a..8dc17ac3c765 100644 --- a/ui/pages/swaps/view-quote/view-quote.js +++ b/ui/pages/swaps/view-quote/view-quote.js @@ -107,6 +107,8 @@ import { calcTokenAmount, toPrecisionWithoutTrailingZeros, } from '../../../../shared/lib/transactions-controller-utils'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { addHexPrefix } from '../../../../app/scripts/lib/util'; import { calcTokenValue, diff --git a/ui/pages/unlock-page/unlock-page.container.js b/ui/pages/unlock-page/unlock-page.container.js index dca1a199d1dd..e632cc0b81f0 100644 --- a/ui/pages/unlock-page/unlock-page.container.js +++ b/ui/pages/unlock-page/unlock-page.container.js @@ -1,6 +1,8 @@ import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; import { compose } from 'redux'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_POPUP } from '../../../shared/constants/app'; import { diff --git a/ui/selectors/custom-gas.js b/ui/selectors/custom-gas.js index adda2204df04..ac1f417e938a 100644 --- a/ui/selectors/custom-gas.js +++ b/ui/selectors/custom-gas.js @@ -1,3 +1,5 @@ +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { addHexPrefix } from '../../app/scripts/lib/util'; import { decEthToConvertedCurrency } from '../../shared/modules/conversion.utils'; import { formatCurrency } from '../helpers/utils/confirm-tx.util'; diff --git a/ui/selectors/institutional/selectors.ts b/ui/selectors/institutional/selectors.ts index 9dd79864ea6c..edaaf5278ae7 100644 --- a/ui/selectors/institutional/selectors.ts +++ b/ui/selectors/institutional/selectors.ts @@ -2,6 +2,8 @@ import { toChecksumAddress } from 'ethereumjs-util'; import { getAccountType, getSelectedInternalAccount } from '../selectors'; import { getProviderConfig } from '../../ducks/metamask/metamask'; import { hexToDecimal } from '../../../shared/modules/conversion.utils'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { normalizeSafeAddress } from '../../../app/scripts/lib/multichain/address'; import { AccountType } from '../../../shared/constants/custody'; diff --git a/ui/selectors/multichain.ts b/ui/selectors/multichain.ts index e22883d83a03..2ef892db3353 100644 --- a/ui/selectors/multichain.ts +++ b/ui/selectors/multichain.ts @@ -16,6 +16,8 @@ import { getNativeCurrency, getProviderConfig, } from '../ducks/metamask/metamask'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { BalancesControllerState } from '../../app/scripts/lib/accounts/BalancesController'; import { MultichainNativeAssets } from '../../shared/constants/multichain/assets'; import { diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index 076525d3a88d..64346a655dfd 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -12,6 +12,8 @@ import { NameType } from '@metamask/name-controller'; import { TransactionStatus } from '@metamask/transaction-controller'; import { isEvmAccountType } from '@metamask/keyring-api'; import { RpcEndpointType } from '@metamask/network-controller'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { addHexPrefix, getEnvironmentType } from '../../app/scripts/lib/util'; import { TEST_CHAINS, @@ -102,6 +104,8 @@ import { import { PRIVACY_POLICY_DATE } from '../helpers/constants/privacy-policy'; import { ENVIRONMENT_TYPE_POPUP } from '../../shared/constants/app'; import { MultichainNativeAssets } from '../../shared/constants/multichain/assets'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { BridgeFeatureFlagsKey } from '../../app/scripts/controllers/bridge/types'; import { getAllUnapprovedTransactions, diff --git a/ui/store/actions.test.js b/ui/store/actions.test.js index 1604f5361eda..68c887c82a82 100644 --- a/ui/store/actions.test.js +++ b/ui/store/actions.test.js @@ -4,7 +4,11 @@ import thunk from 'redux-thunk'; import { EthAccountType } from '@metamask/keyring-api'; import { TransactionStatus } from '@metamask/transaction-controller'; import { NotificationServicesController } from '@metamask/notification-services-controller'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import enLocale from '../../app/_locales/en/messages.json'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import MetaMaskController from '../../app/scripts/metamask-controller'; import { HardwareDeviceNames } from '../../shared/constants/hardware-wallets'; import { GAS_LIMITS } from '../../shared/constants/gas'; diff --git a/ui/store/actions.ts b/ui/store/actions.ts index 82c2eb488ad8..db23a2e5e7a2 100644 --- a/ui/store/actions.ts +++ b/ui/store/actions.ts @@ -47,6 +47,8 @@ import { ORIGIN_METAMASK, POLLING_TOKEN_ENVIRONMENT_TYPES, } from '../../shared/constants/app'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType, addHexPrefix } from '../../app/scripts/lib/util'; import { getMetaMaskAccounts, diff --git a/ui/store/institutional/institution-actions.test.js b/ui/store/institutional/institution-actions.test.js index ec76bf6f29a0..ea75d885d90a 100644 --- a/ui/store/institutional/institution-actions.test.js +++ b/ui/store/institutional/institution-actions.test.js @@ -1,6 +1,8 @@ import sinon from 'sinon'; import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; +// TODO: Remove restricted import +// eslint-disable-next-line import/no-restricted-paths import MetaMaskController from '../../../app/scripts/metamask-controller'; import { setBackgroundConnection } from '../background-connection'; import { mockNetworkState } from '../../../test/stub/networks';