From f988dc1c5ef98ec72212d1f58e736556273b68f7 Mon Sep 17 00:00:00 2001 From: Vladimir Saric <92527393+VSaric@users.noreply.github.com> Date: Mon, 23 Jan 2023 17:19:55 +0100 Subject: [PATCH] Enable the Token Allowance flow by default for all users (#16740) --- .metamaskrc.dist | 1 - app/_locales/ar/messages.json | 4 - app/_locales/de/messages.json | 22 - app/_locales/el/messages.json | 22 - app/_locales/en/messages.json | 22 - app/_locales/es/messages.json | 22 - app/_locales/es_419/messages.json | 7 - app/_locales/fr/messages.json | 22 - app/_locales/hi/messages.json | 22 - app/_locales/id/messages.json | 22 - app/_locales/it/messages.json | 7 - app/_locales/ja/messages.json | 22 - app/_locales/ko/messages.json | 22 - app/_locales/ph/messages.json | 4 - app/_locales/pt/messages.json | 22 - app/_locales/pt_BR/messages.json | 7 - app/_locales/ru/messages.json | 22 - app/_locales/tl/messages.json | 22 - app/_locales/tr/messages.json | 22 - app/_locales/vi/messages.json | 22 - app/_locales/zh_CN/messages.json | 22 - app/_locales/zh_TW/messages.json | 4 - app/scripts/controllers/preferences.js | 12 - app/scripts/metamask-controller.js | 4 - shared/notifications/index.js | 15 - test/e2e/fixture-builder.js | 5 - test/e2e/metamask-ui.spec.js | 195 ----- .../tests/custom-token-add-approve.spec.js | 786 +++++++++++------- .../app/whats-new-popup/whats-new-popup.js | 4 - ui/helpers/constants/settings.js | 7 - ui/helpers/utils/settings-search.test.js | 2 +- .../confirm-approve-content.component.js | 277 +----- .../confirm-approve-content.component.test.js | 34 +- ui/pages/confirm-approve/confirm-approve.js | 42 +- .../experimental-tab.component.js | 40 - .../experimental-tab.container.js | 5 - ui/selectors/selectors.js | 10 - ui/store/actions.js | 14 - 38 files changed, 508 insertions(+), 1308 deletions(-) diff --git a/.metamaskrc.dist b/.metamaskrc.dist index 8dc5610f5..3b105df3c 100644 --- a/.metamaskrc.dist +++ b/.metamaskrc.dist @@ -6,7 +6,6 @@ SWAPS_USE_DEV_APIS= NFTS_V1= PUBNUB_PUB_KEY= PUBNUB_SUB_KEY= -TOKEN_ALLOWANCE_IMPROVEMENTS= PORTFOLIO_URL= TRANSACTION_SECURITY_PROVIDER= diff --git a/app/_locales/ar/messages.json b/app/_locales/ar/messages.json index 500ff79ea..fcd77aac8 100644 --- a/app/_locales/ar/messages.json +++ b/app/_locales/ar/messages.json @@ -12,10 +12,6 @@ "message": "لقد قرأت دولار واحد وأوافق عليه", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1 يمكن الوصول إلى هذا المبلغ الأقصى وإنفاقه حتى", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessingYourCamera": { "message": "جاري استخدام كاميرتك..." }, diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index bd139cdd5..a9e0f83f5 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -110,10 +110,6 @@ "message": "Ich habe die $1 gelesen und stimme ihnen zu", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1 kann bis zu diesem maximalen Betrag abrufen und ausgeben", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessAndSpendNoticeNFT": { "message": "$1 kann auf dieses Asset zugreifen und es ausgeben", "description": "$1 is the url of the site requesting ability to spend" @@ -388,9 +384,6 @@ "approved": { "message": "Genehmigt" }, - "approvedAmountWithColon": { - "message": "Genehmigter Betrag:" - }, "approvedAsset": { "message": "Genehmigtes Asset" }, @@ -1709,12 +1702,6 @@ "message": "Importiert", "description": "status showing that an account has been fully loaded into the keyring" }, - "improvedTokenAllowance": { - "message": "Verbesserte Erfahrung mit der Token-Erlaubnis" - }, - "improvedTokenAllowanceDescription": { - "message": "Aktivieren Sie diese Option, um die verbesserte Token-Erlaubnis zu erhalten, wenn ein Dapp eine ERC20-Genehmigung anfordert." - }, "inYourSettings": { "message": "in Ihren Einstellungen" }, @@ -2398,15 +2385,6 @@ "notifications15Title": { "message": "Ethereum Merge ist da!" }, - "notifications16ActionText": { - "message": "Hier ausprobieren" - }, - "notifications16Description": { - "message": "Wir haben unsere Token-Bestätigung neu gestaltet, um Ihnen zu helfen, fundiertere Entscheidungen zu treffen." - }, - "notifications16Title": { - "message": "Verbesserte Erfahrung mit der Token-Erlaubnis" - }, "notifications17ActionText": { "message": "Sicherheits- und Datenschutzeinstellungen anzeigen" }, diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json index 5e700d84e..3f197f168 100644 --- a/app/_locales/el/messages.json +++ b/app/_locales/el/messages.json @@ -110,10 +110,6 @@ "message": "Έχω διαβάσει και συμφωνώ με το $1", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1 μπορεί να έχει πρόσβαση και να ξοδέψει μέχρι αυτό το μέγιστο ποσό", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessAndSpendNoticeNFT": { "message": "Το $1 ίσως αποκτήσει πρόσβαση και δαπανήσει αυτό το περιουσιακό στοιχείο", "description": "$1 is the url of the site requesting ability to spend" @@ -388,9 +384,6 @@ "approved": { "message": "Εγκρίθηκε" }, - "approvedAmountWithColon": { - "message": "Εγκεκριμένο ποσό:" - }, "approvedAsset": { "message": "Εγκεκριμένο περιουσιακό στοιχείο" }, @@ -1709,12 +1702,6 @@ "message": "Έγινε εισαγωγή", "description": "status showing that an account has been fully loaded into the keyring" }, - "improvedTokenAllowance": { - "message": "Βελτιωμένη εμπειρία χορήγησης tokens" - }, - "improvedTokenAllowanceDescription": { - "message": "Ενεργοποιήστε το για να μεταβείτε στη βελτιωμένη εμπειρία χορήγησης tokens κάθε φορά που μια αποκεντρωμένη εφαρμογή ζητά έγκριση ERC20" - }, "inYourSettings": { "message": "στις Ρυθμίσεις σας" }, @@ -2398,15 +2385,6 @@ "notifications15Title": { "message": "Η συγχώνευση στο Ethereum είναι εδώ!" }, - "notifications16ActionText": { - "message": "Δοκιμάστε το εδώ" - }, - "notifications16Description": { - "message": "Επανασχεδιάσαμε την επιβεβαίωση χορήγησης tokens για να σας βοηθήσουμε να λάβετε πιο συνειδητές αποφάσεις." - }, - "notifications16Title": { - "message": "Βελτιωμένη εμπειρία χορήγησης tokens" - }, "notifications17ActionText": { "message": "Εμφάνιση ρυθμίσεων Ασφάλειας & Απορρήτου" }, diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 0055d80e7..db771ad38 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -110,10 +110,6 @@ "message": "I have read and agree to the $1", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1 may access and spend up to this max amount", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessAndSpendNoticeNFT": { "message": "$1 may access and spend this asset", "description": "$1 is the url of the site requesting ability to spend" @@ -388,9 +384,6 @@ "approved": { "message": "Approved" }, - "approvedAmountWithColon": { - "message": "Approved amount:" - }, "approvedAsset": { "message": "Approved asset" }, @@ -1722,12 +1715,6 @@ "message": "Imported", "description": "status showing that an account has been fully loaded into the keyring" }, - "improvedTokenAllowance": { - "message": "Improved token allowance experience" - }, - "improvedTokenAllowanceDescription": { - "message": "Turn this on to go through the improved token allowance experience whenever a dapp requests an ERC20 approve" - }, "inYourSettings": { "message": "in your Settings" }, @@ -2420,15 +2407,6 @@ "notifications15Title": { "message": "The Ethereum Merge is here!" }, - "notifications16ActionText": { - "message": "Try it out here" - }, - "notifications16Description": { - "message": "We redesigned our token allowance confirmation to help you make more informed decisions." - }, - "notifications16Title": { - "message": "Improved token allowance experience" - }, "notifications17ActionText": { "message": "Show Security & Privacy settings" }, diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index f2a1b8c48..981790fb6 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -110,10 +110,6 @@ "message": "Leí y estoy de acuerdo con $1", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1 puede acceder y gastar hasta este importe máximo", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessAndSpendNoticeNFT": { "message": "$1 puede acceder y gastar este activo", "description": "$1 is the url of the site requesting ability to spend" @@ -388,9 +384,6 @@ "approved": { "message": "Aprobado" }, - "approvedAmountWithColon": { - "message": "Monto aprobado:" - }, "approvedAsset": { "message": "Activo aprobado" }, @@ -1709,12 +1702,6 @@ "message": "Importado", "description": "status showing that an account has been fully loaded into the keyring" }, - "improvedTokenAllowance": { - "message": "Experiencia mejorada de asignación de tokens" - }, - "improvedTokenAllowanceDescription": { - "message": "Actívelo para pasar por la experiencia de asignación de token mejorada cada vez que una dapp solicite una aprobación ERC20" - }, "inYourSettings": { "message": "en su Configuración" }, @@ -2398,15 +2385,6 @@ "notifications15Title": { "message": "¡La Fusión de Ethereum está aquí!" }, - "notifications16ActionText": { - "message": "Inténtelo aquí" - }, - "notifications16Description": { - "message": "Rediseñamos nuestra confirmación de asignación de tokens para ayudarlo a tomar decisiones más informadas." - }, - "notifications16Title": { - "message": "Experiencia mejorada de asignación de tokens" - }, "notifications17ActionText": { "message": "Mostrar configuración de seguridad y privacidad" }, diff --git a/app/_locales/es_419/messages.json b/app/_locales/es_419/messages.json index 610d7b6dc..3ef2f63bc 100644 --- a/app/_locales/es_419/messages.json +++ b/app/_locales/es_419/messages.json @@ -51,10 +51,6 @@ "message": "Leí y estoy de acuerdo con $1", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1 puede acceder y gastar hasta este importe máximo", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessingYourCamera": { "message": "Accediendo a la cámara..." }, @@ -237,9 +233,6 @@ "approved": { "message": "Aprobado" }, - "approvedAmountWithColon": { - "message": "Monto aprobado:" - }, "asset": { "message": "Activo" }, diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index f3825b4fd..8bf8d486a 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -110,10 +110,6 @@ "message": "J’ai lu et j’accepte les $1", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1 peut accéder et dépenser jusqu’à ce montant maximal", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessAndSpendNoticeNFT": { "message": "$1 peut accéder à cet actif et le dépenser", "description": "$1 is the url of the site requesting ability to spend" @@ -388,9 +384,6 @@ "approved": { "message": "Approuvé" }, - "approvedAmountWithColon": { - "message": "Montant approuvé :" - }, "approvedAsset": { "message": "Actif approuvé" }, @@ -1709,12 +1702,6 @@ "message": "Importé", "description": "status showing that an account has been fully loaded into the keyring" }, - "improvedTokenAllowance": { - "message": "Amélioration du processus d’approbation des jetons" - }, - "improvedTokenAllowanceDescription": { - "message": "Activez cette option si vous voulez lancer le processus amélioré d’approbation des jetons chaque fois qu’une dApp demande l’approbation de jetons ERC20" - }, "inYourSettings": { "message": "dans vos paramètres" }, @@ -2398,15 +2385,6 @@ "notifications15Title": { "message": "La fusion Ethereum est en marche !" }, - "notifications16ActionText": { - "message": "Essayez-le" - }, - "notifications16Description": { - "message": "Nous avons amélioré le processus d’approbation des jetons pour vous aider à prendre des décisions plus éclairées." - }, - "notifications16Title": { - "message": "Amélioration du processus d’approbation des jetons" - }, "notifications17ActionText": { "message": "Afficher les paramètres de sécurité et de confidentialité" }, diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index 1f8879cf2..b2d154dd1 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -110,10 +110,6 @@ "message": "मैंने $1 पढ़ लिया है और मैं सहमत हूं", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1 इस अधिकतम राशि तक पहुंच सकते हैं और खर्च कर सकते हैं", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessAndSpendNoticeNFT": { "message": "$1 एक्सेस कर सकता है और इस एसेट को खर्च कर सकता है", "description": "$1 is the url of the site requesting ability to spend" @@ -388,9 +384,6 @@ "approved": { "message": "अनुमोदित" }, - "approvedAmountWithColon": { - "message": "स्वीकृत राशि:" - }, "approvedAsset": { "message": "स्वीकृत एसेट" }, @@ -1709,12 +1702,6 @@ "message": "आयातित", "description": "status showing that an account has been fully loaded into the keyring" }, - "improvedTokenAllowance": { - "message": "बेहतर टोकन भत्ता अनुभव" - }, - "improvedTokenAllowanceDescription": { - "message": "जब भी कोई डैप ERC20 स्वीकृति का अनुरोध करता है तो बेहतर टोकन भत्ता अनुभव प्राप्त करने के लिए इसे चालू करें" - }, "inYourSettings": { "message": "आपके सेटिंग्स में" }, @@ -2398,15 +2385,6 @@ "notifications15Title": { "message": "इथेरियम मर्ज यहाँ है!" }, - "notifications16ActionText": { - "message": "इसे यहां आजमाएं" - }, - "notifications16Description": { - "message": "अधिक सूचित निर्णय लेने में आपकी सहायता करने के लिए हमने अपने टोकन भत्ता पुष्टिकरण को फिर से डिजाइन किया।" - }, - "notifications16Title": { - "message": "बेहतर टोकन भत्ता अनुभव" - }, "notifications17ActionText": { "message": "सुरक्षा और गोपनीयता सेटिंग्स को दिखाएं" }, diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index 2556abda0..1fabd1a34 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -110,10 +110,6 @@ "message": "Saya telah membaca dan menyetujui $1", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1 dapat diakses dan digunakan hingga jumlah maksimum ini", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessAndSpendNoticeNFT": { "message": "$1 dapat mengakses dan membelanjakan aset ini", "description": "$1 is the url of the site requesting ability to spend" @@ -388,9 +384,6 @@ "approved": { "message": "Disetujui" }, - "approvedAmountWithColon": { - "message": "Jumlah yang disetujui:" - }, "approvedAsset": { "message": "Aset yang disetujui" }, @@ -1709,12 +1702,6 @@ "message": "Diimpor", "description": "status showing that an account has been fully loaded into the keyring" }, - "improvedTokenAllowance": { - "message": "Peningkatan pengalaman tunjangan token" - }, - "improvedTokenAllowanceDescription": { - "message": "Aktifkan ini untuk memperoleh peningkatan pengalaman tunjangan token setiap kali aplikasi terdesentralisasi (dapp) meminta persetujuan ERC20" - }, "inYourSettings": { "message": "di Pengaturan Anda" }, @@ -2398,15 +2385,6 @@ "notifications15Title": { "message": "Penggabungan Ethereum telah tiba!" }, - "notifications16ActionText": { - "message": "Cobalah di sini" - }, - "notifications16Description": { - "message": "Kami mendesain ulang konfirmasi tunjangan token kami untuk membantu Anda membuat keputusan yang lebih tepat." - }, - "notifications16Title": { - "message": "Peningkatan pengalaman tunjangan token" - }, "notifications17ActionText": { "message": "Tampilkan pengaturan Keamanan & Privasi" }, diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index 774565740..6fc451f03 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -92,10 +92,6 @@ "message": "Ho letto e accetto i $1", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1 può avere accesso e spendere al massimo", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessAndSpendNoticeNFT": { "message": "$1 può accedere e spendere questa risorsa", "description": "$1 is the url of the site requesting ability to spend" @@ -316,9 +312,6 @@ "approved": { "message": "Approvato" }, - "approvedAmountWithColon": { - "message": "Importo approvato:" - }, "approvedAsset": { "message": "Asset approvato" }, diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index c64e8fcaa..f06f587de 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -110,10 +110,6 @@ "message": "$1を読んで同意しました", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1はアクセスしてこの最大量まで消費できます", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessAndSpendNoticeNFT": { "message": "$1 はこのアセットにアクセスし、使用できます", "description": "$1 is the url of the site requesting ability to spend" @@ -388,9 +384,6 @@ "approved": { "message": "承認済み" }, - "approvedAmountWithColon": { - "message": "承認された金額:" - }, "approvedAsset": { "message": "承認済みのアセット" }, @@ -1709,12 +1702,6 @@ "message": "インポート済み", "description": "status showing that an account has been fully loaded into the keyring" }, - "improvedTokenAllowance": { - "message": "改善されたトークンの許可設定" - }, - "improvedTokenAllowanceDescription": { - "message": "これをオンにすると、DApp が ERC20 の承認を求めた際に、改善されたトークン許可設定が利用できます" - }, "inYourSettings": { "message": "設定で" }, @@ -2398,15 +2385,6 @@ "notifications15Title": { "message": "Ethereum のマージ (Merge) が完了しました!" }, - "notifications16ActionText": { - "message": "こちらでお試しください" - }, - "notifications16Description": { - "message": "より多くの情報に基づき決定を下せるよう、トークン許可設定の確認のデザインを変更しました。" - }, - "notifications16Title": { - "message": "改善されたトークン許可設定" - }, "notifications17ActionText": { "message": "セキュリティおよびプライバシー設定を表示" }, diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index db1d4fc88..b9319686d 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -110,10 +110,6 @@ "message": "$1의 내용을 읽고 이에 동의합니다.", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1의 경우, 이 최대 금액까지 액세스 및 지출할 수 있습니다.", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessAndSpendNoticeNFT": { "message": "$1(은)는 이 자산에 접근하여 사용할 수 있습니다", "description": "$1 is the url of the site requesting ability to spend" @@ -388,9 +384,6 @@ "approved": { "message": "승인됨" }, - "approvedAmountWithColon": { - "message": "승인 금액:" - }, "approvedAsset": { "message": "승인된 자산" }, @@ -1709,12 +1702,6 @@ "message": "가져옴", "description": "status showing that an account has been fully loaded into the keyring" }, - "improvedTokenAllowance": { - "message": "토큰 허용 기능이 개선되었습니다" - }, - "improvedTokenAllowanceDescription": { - "message": "Dapp에서 ERC20 승인을 요청할 때마다 이 기능을 켜시면 토큰 허용 기능을 이용할 수 있습니다" - }, "inYourSettings": { "message": "설정에서" }, @@ -2398,15 +2385,6 @@ "notifications15Title": { "message": "이더리움 머지가 완료되었습니다!" }, - "notifications16ActionText": { - "message": "여기서 체험하세요" - }, - "notifications16Description": { - "message": "토큰 허용 확인 과정을 재설계하여 사용자가 정보에 의한 결정을 할 수 있도록 하였습니다." - }, - "notifications16Title": { - "message": "토큰 허용 경험 개선됨" - }, "notifications17ActionText": { "message": "보안 및 개인정보 설정 표시" }, diff --git a/app/_locales/ph/messages.json b/app/_locales/ph/messages.json index 249835b44..3f5ac76b1 100644 --- a/app/_locales/ph/messages.json +++ b/app/_locales/ph/messages.json @@ -6,10 +6,6 @@ "message": "Nabasa ko at sumasang-ayon ako sa $1", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "Maaaring i-access ng $1 ang max na halagang ito at gumastos hanggang sa max na halagang ito", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessingYourCamera": { "message": "Ina-access ang iyong camera..." }, diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json index 1948422e1..601d77dd3 100644 --- a/app/_locales/pt/messages.json +++ b/app/_locales/pt/messages.json @@ -110,10 +110,6 @@ "message": "Eu li e concordo com os $1", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1 pode acessar e gastar até esse valor máximo", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessAndSpendNoticeNFT": { "message": "$1 pode(m) acessar e usar esse ativo", "description": "$1 is the url of the site requesting ability to spend" @@ -388,9 +384,6 @@ "approved": { "message": "Aprovado" }, - "approvedAmountWithColon": { - "message": "Valor aprovado:" - }, "approvedAsset": { "message": "Ativo aprovado" }, @@ -1709,12 +1702,6 @@ "message": "Importado", "description": "status showing that an account has been fully loaded into the keyring" }, - "improvedTokenAllowance": { - "message": "Experiência aprimorada nas permissões de tokens" - }, - "improvedTokenAllowanceDescription": { - "message": "Ative para ter a experiência aprimorada nas permissões de tokens sempre que um dapp solicitar uma aprovação de ERC20" - }, "inYourSettings": { "message": "em suas Configurações" }, @@ -2398,15 +2385,6 @@ "notifications15Title": { "message": "A fusão do Ethereum chegou!" }, - "notifications16ActionText": { - "message": "Teste aqui" - }, - "notifications16Description": { - "message": "Reprojetamos nossa confirmação de permissões de token para ajudar você a tomar decisões mais informadas." - }, - "notifications16Title": { - "message": "Experiência aprimorada nas permissões de tokens" - }, "notifications17ActionText": { "message": "Mostrar configurações de segurança e privacidade" }, diff --git a/app/_locales/pt_BR/messages.json b/app/_locales/pt_BR/messages.json index 7bb632e69..38d4622bf 100644 --- a/app/_locales/pt_BR/messages.json +++ b/app/_locales/pt_BR/messages.json @@ -51,10 +51,6 @@ "message": "Eu li e concordo com os $1", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1 pode acessar e gastar até esse valor máximo", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessingYourCamera": { "message": "Acessando sua câmera..." }, @@ -237,9 +233,6 @@ "approved": { "message": "Aprovado" }, - "approvedAmountWithColon": { - "message": "Valor aprovado:" - }, "asset": { "message": "Ativo" }, diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index a09e922bf..3e74814de 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -110,10 +110,6 @@ "message": "Я прочитал(-а) $1 и согласен(-на) с ними", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1 может получить доступ и потратить до этой максимальной суммы", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessAndSpendNoticeNFT": { "message": "$1 может получить доступ к этому активу и потратить его", "description": "$1 is the url of the site requesting ability to spend" @@ -388,9 +384,6 @@ "approved": { "message": "Одобрен" }, - "approvedAmountWithColon": { - "message": "Одобренная сумма:" - }, "approvedAsset": { "message": "Одобренный актив" }, @@ -1709,12 +1702,6 @@ "message": "Импортирован", "description": "status showing that an account has been fully loaded into the keyring" }, - "improvedTokenAllowance": { - "message": "Улучшенный опыт предоставления токенов" - }, - "improvedTokenAllowanceDescription": { - "message": "Включите этот параметр, чтобы воспользоваться улучшенным доступом к токенам всякий раз, когда децентрализованное приложение запрашивает одобрение ERC20." - }, "inYourSettings": { "message": "в ваших Настройках" }, @@ -2398,15 +2385,6 @@ "notifications15Title": { "message": "Ethereum Merge уже досутпно!" }, - "notifications16ActionText": { - "message": "Попробуйте это здесь" - }, - "notifications16Description": { - "message": "Мы переработали наше подтверждение допустимых токенов, чтобы помочь вам принимать более обоснованные решения." - }, - "notifications16Title": { - "message": "Улучшенный опыт предоставления токенов" - }, "notifications17ActionText": { "message": "Показать настройки безопасности и конфиденциальности" }, diff --git a/app/_locales/tl/messages.json b/app/_locales/tl/messages.json index b4f49497d..850af882b 100644 --- a/app/_locales/tl/messages.json +++ b/app/_locales/tl/messages.json @@ -110,10 +110,6 @@ "message": "Nabasa ko at sumasang-ayon ako sa $1", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "Maaaring i-access ng $1 ang max na halagang ito at gumastos hanggang sa max na halagang ito", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessAndSpendNoticeNFT": { "message": "$1 maaaring i-access at gamitin ang asset na ito", "description": "$1 is the url of the site requesting ability to spend" @@ -388,9 +384,6 @@ "approved": { "message": "Inaprubahan" }, - "approvedAmountWithColon": { - "message": "Inaprubahang halaga:" - }, "approvedAsset": { "message": "Aprubadong asset" }, @@ -1709,12 +1702,6 @@ "message": "Na-import", "description": "status showing that an account has been fully loaded into the keyring" }, - "improvedTokenAllowance": { - "message": "Pinahusay na karanasan sa allowance ng token" - }, - "improvedTokenAllowanceDescription": { - "message": "I-on ito para dumaan sa pinahusay na karanasan sa allowance ng token tuwing humihiling ang isang dapp na aprubahan ng ERC20" - }, "inYourSettings": { "message": "sa iyong Mga Setting" }, @@ -2398,15 +2385,6 @@ "notifications15Title": { "message": "Narito na ang Ethereum Merge!" }, - "notifications16ActionText": { - "message": "Subukan ito dito" - }, - "notifications16Description": { - "message": "Muli naming idinisenyo ang aming kumpirmasyon ng allowance ng token upang matulungan kang gumawa ng mas matalinong mga desisyon." - }, - "notifications16Title": { - "message": "Pinahusay na karanasan sa allowance ng token" - }, "notifications17ActionText": { "message": "Ipakita ang mga setting ng Seguridad at Pagkapribado" }, diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json index 534e35ce6..cd1749176 100644 --- a/app/_locales/tr/messages.json +++ b/app/_locales/tr/messages.json @@ -110,10 +110,6 @@ "message": "$1 bölümünü okudum ve kabul ediyorum", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1 bu maksimum tutara kadar erişim sağlayabilir ve harcama yapabilir", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessAndSpendNoticeNFT": { "message": "$1 bu varlığa erişebilir ve harcayabilir", "description": "$1 is the url of the site requesting ability to spend" @@ -388,9 +384,6 @@ "approved": { "message": "Onaylandı" }, - "approvedAmountWithColon": { - "message": "Onaylanan tutar:" - }, "approvedAsset": { "message": "Onaylanan varlık" }, @@ -1709,12 +1702,6 @@ "message": "İçe Aktarıldı", "description": "status showing that an account has been fully loaded into the keyring" }, - "improvedTokenAllowance": { - "message": "Gelişmiş token hakediş deneyimi" - }, - "improvedTokenAllowanceDescription": { - "message": "Merkeziyetsiz bir uygulama ERC20 onayı istediğinde gelişmiş token hakediş deneyimini kullanmak için bunu açın" - }, "inYourSettings": { "message": "Ayarlar kısmında" }, @@ -2398,15 +2385,6 @@ "notifications15Title": { "message": "Ethereum Birleşmesi başladı!" }, - "notifications16ActionText": { - "message": "Burada dene" - }, - "notifications16Description": { - "message": "Token hakediş onayımızı daha bilgiye dayalı kararlar almanıza yardımcı olacak şekilde yeniden tasarladık." - }, - "notifications16Title": { - "message": "Gelişmiş token hakedişi deneyimi" - }, "notifications17ActionText": { "message": "Güvenlik ve Gizlilik ayarlarını göster" }, diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index 75ab5e7e5..bf3aa2dc6 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -110,10 +110,6 @@ "message": "Tôi đã đọc và đồng ý với $1", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1 có thể truy cập và chi tiêu đến số tiền tối đa", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessAndSpendNoticeNFT": { "message": "$1 có thể truy cập và chi tiêu tài sản này", "description": "$1 is the url of the site requesting ability to spend" @@ -388,9 +384,6 @@ "approved": { "message": "Đã phê duyệt" }, - "approvedAmountWithColon": { - "message": "Số tiền được duyệt:" - }, "approvedAsset": { "message": "Tài sản được chấp nhận" }, @@ -1709,12 +1702,6 @@ "message": "Đã nhập", "description": "status showing that an account has been fully loaded into the keyring" }, - "improvedTokenAllowance": { - "message": "Trải nghiệm cho phép token được cải thiện" - }, - "improvedTokenAllowanceDescription": { - "message": "Bật tính năng này để có trải nghiệm cho phép token được cải thiện mỗi khi có một dapp yêu cầu phê duyệt ERC20" - }, "inYourSettings": { "message": "trong phần Cài đặt" }, @@ -2398,15 +2385,6 @@ "notifications15Title": { "message": "Hợp nhất Ethereum đã được triển khai!" }, - "notifications16ActionText": { - "message": "Dùng thử tại đây" - }, - "notifications16Description": { - "message": "Chúng tôi đã thiết kế lại xác nhận cho phép token để giúp bạn đưa ra quyết định sáng suốt hơn." - }, - "notifications16Title": { - "message": "Trải nghiệm cho phép token được cải thiện" - }, "notifications17ActionText": { "message": "Hiển thị cài đặt Bảo mật và Quyền riêng tư" }, diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index 290f5a924..43b618451 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -110,10 +110,6 @@ "message": "我已阅读并同意 $1", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1 可以访问并使用此最大金额", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessAndSpendNoticeNFT": { "message": "$1可以访问并使用此资产", "description": "$1 is the url of the site requesting ability to spend" @@ -388,9 +384,6 @@ "approved": { "message": "已批准" }, - "approvedAmountWithColon": { - "message": "已批准金额:" - }, "approvedAsset": { "message": "已获批准的资产" }, @@ -1709,12 +1702,6 @@ "message": "已导入", "description": "status showing that an account has been fully loaded into the keyring" }, - "improvedTokenAllowance": { - "message": "经过改进的代币津贴体验" - }, - "improvedTokenAllowanceDescription": { - "message": "每当分布式应用请求 ERC20 批准时,打开此项以查看经过改进的代币津贴体验" - }, "inYourSettings": { "message": "在设置中" }, @@ -2398,15 +2385,6 @@ "notifications15Title": { "message": "以太坊合并来了!" }, - "notifications16ActionText": { - "message": "在此处尝试" - }, - "notifications16Description": { - "message": "我们重新设计了代币津贴确认,助您作出更明智的决策。" - }, - "notifications16Title": { - "message": "经过改进的代币津贴体验" - }, "notifications17ActionText": { "message": "显示安全和隐私设置" }, diff --git a/app/_locales/zh_TW/messages.json b/app/_locales/zh_TW/messages.json index 9a5ef7a6c..05a5c3cef 100644 --- a/app/_locales/zh_TW/messages.json +++ b/app/_locales/zh_TW/messages.json @@ -6,10 +6,6 @@ "message": "我已閱讀並同意$1", "description": "$1 is the `terms` message" }, - "accessAndSpendNotice": { - "message": "$1 可能會存取並最多花費以下額度", - "description": "$1 is the url of the site requesting ability to spend" - }, "accessingYourCamera": { "message": "正在存取您的攝影鏡頭..." }, diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 2484ef451..7f6eef824 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -66,7 +66,6 @@ export default class PreferencesController { ledgerTransportType: window.navigator.hid ? LedgerTransportTypes.webhid : LedgerTransportTypes.u2f, - improvedTokenAllowanceEnabled: false, transactionSecurityCheckEnabled: false, theme: THEME_TYPE.OS, ...opts.initState, @@ -195,17 +194,6 @@ export default class PreferencesController { this.store.updateState({ theme: val }); } - /** - * Setter for the `improvedTokenAllowanceEnabled` property - * - * @param improvedTokenAllowanceEnabled - */ - setImprovedTokenAllowanceEnabled(improvedTokenAllowanceEnabled) { - this.store.updateState({ - improvedTokenAllowanceEnabled, - }); - } - /** * Setter for the `transactionSecurityCheckEnabled` property * diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 572ae9909..3488d114b 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1802,10 +1802,6 @@ export default class MetamaskController extends EventEmitter { preferencesController, ), setTheme: preferencesController.setTheme.bind(preferencesController), - setImprovedTokenAllowanceEnabled: - preferencesController.setImprovedTokenAllowanceEnabled.bind( - preferencesController, - ), setTransactionSecurityCheckEnabled: preferencesController.setTransactionSecurityCheckEnabled.bind( preferencesController, diff --git a/shared/notifications/index.js b/shared/notifications/index.js index c0406ab4c..9d27aebe8 100644 --- a/shared/notifications/index.js +++ b/shared/notifications/index.js @@ -78,10 +78,6 @@ export const UI_NOTIFICATIONS = { id: 15, date: '2022-09-15', }, - 16: { - id: 16, - date: null, - }, 17: { id: 17, date: null, @@ -232,17 +228,6 @@ export const getTranslatedUINotifications = (t, locale) => { ) : '', }, - 16: { - ...UI_NOTIFICATIONS[16], - title: t('notifications16Title'), - description: t('notifications16Description'), - actionText: t('notifications16ActionText'), - date: UI_NOTIFICATIONS[16].date - ? new Intl.DateTimeFormat(formattedLocale).format( - new Date(UI_NOTIFICATIONS[16].date), - ) - : '', - }, 17: { ...UI_NOTIFICATIONS[17], title: t('notifications17Title'), diff --git a/test/e2e/fixture-builder.js b/test/e2e/fixture-builder.js index fff749f5d..c773dbc45 100644 --- a/test/e2e/fixture-builder.js +++ b/test/e2e/fixture-builder.js @@ -106,11 +106,6 @@ function defaultFixture() { id: 15, isShown: false, }, - 16: { - date: null, - id: 16, - isShown: true, - }, 17: { date: null, id: 17, diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index 14e685c25..1bc3d0e90 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -474,136 +474,6 @@ describe('MetaMask', function () { }); }); - describe('Approves a custom token from dapp', function () { - it('approves an already created token', async function () { - const windowHandles = await driver.getAllWindowHandles(); - const extension = windowHandles[0]; - const dapp = await driver.switchToWindowWithTitle( - 'E2E Test Dapp', - windowHandles, - ); - await driver.closeAllWindowHandlesExcept([extension, dapp]); - await driver.delay(regularDelayMs); - - await driver.switchToWindow(dapp); - await driver.delay(tinyDelayMs); - - await driver.clickElement({ text: 'Approve Tokens', tag: 'button' }); - - await driver.switchToWindow(extension); - await driver.delay(regularDelayMs); - - await driver.wait(async () => { - const pendingTxes = await driver.findElements( - '.transaction-list__pending-transactions .transaction-list-item', - ); - return pendingTxes.length === 1; - }, 10000); - - await driver.waitForSelector({ - // Selects only the very first transaction list item immediately following the 'Pending' header - css: '.transaction-list__pending-transactions .transaction-list__header + .transaction-list-item .list-item__heading', - text: 'Approve TST spend limit', - }); - - await driver.clickElement('.transaction-list-item'); - await driver.delay(regularDelayMs); - }); - - it('displays the token approval data', async function () { - await driver.clickElement({ - text: 'View full transaction details', - css: '.confirm-approve-content__small-blue-text', - }); - const functionType = await driver.findElement( - '.confirm-approve-content__data .confirm-approve-content__small-text', - ); - const functionTypeText = await functionType.getText(); - assert.equal(functionTypeText, 'Function: Approve'); - - const confirmDataDiv = await driver.findElement( - '.confirm-approve-content__data__data-block', - ); - const confirmDataText = await confirmDataDiv.getText(); - assert( - confirmDataText.match( - /0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef4/u, - ), - ); - }); - - it('customizes gas', async function () { - await driver.clickElement('.confirm-approve-content__small-blue-text'); - await driver.delay(regularDelayMs); - await driver.clickElement({ - text: 'Edit suggested gas fee', - tag: 'button', - }); - await driver.delay(regularDelayMs); - - const [gasLimitInput, gasPriceInput] = await driver.findElements( - 'input[type="number"]', - ); - - await gasPriceInput.fill('10'); - await driver.delay(50); - - await gasLimitInput.fill('60001'); - - await driver.delay(veryLargeDelayMs); - - await driver.clickElement({ text: 'Save', tag: 'button' }); - await driver.delay(veryLargeDelayMs); - - const gasFeeInEth = await driver.findElement( - '.confirm-approve-content__transaction-details-content__secondary-fee', - ); - assert.equal(await gasFeeInEth.getText(), '0.0006 ETH'); - }); - - it('edits the permission', async function () { - const editButtons = await driver.findClickableElements( - '.confirm-approve-content__small-blue-text', - ); - await editButtons[2].click(); - - // wait for permission modal to be visible - const permissionModal = await driver.findVisibleElement('span .modal'); - const radioButtons = await driver.findClickableElements( - '.edit-approval-permission__edit-section__radio-button', - ); - await radioButtons[1].click(); - - await driver.fill('input', '5'); - await driver.delay(regularDelayMs); - - await driver.clickElement({ text: 'Save', tag: 'button' }); - await driver.delay(veryLargeDelayMs); - - // wait for permission modal to be removed from DOM. - await permissionModal.waitForElementState('hidden'); - - const permissionInfo = await driver.findElements( - '.confirm-approve-content__medium-text', - ); - const amountDiv = permissionInfo[0]; - assert.equal(await amountDiv.getText(), '5 TST'); - }); - - it('submits the transaction', async function () { - await driver.clickElement({ text: 'Confirm', tag: 'button' }); - await driver.delay(regularDelayMs); - }); - - it('finds the transaction in the transactions list', async function () { - await driver.waitForSelector({ - // Select only the heading of the first entry in the transaction list. - css: '.transaction-list__completed-transactions .transaction-list-item:first-child .list-item__heading', - text: 'Approve TST spend limit', - }); - }); - }); - describe('Transfers a custom token from dapp when no gas value is specified', function () { it('transfers an already created token, without specifying gas', async function () { const windowHandles = await driver.getAllWindowHandles(); @@ -660,69 +530,4 @@ describe('MetaMask', function () { }); }); }); - - describe('Approves a custom token from dapp when no gas value is specified', function () { - it('approves an already created token', async function () { - const windowHandles = await driver.getAllWindowHandles(); - const extension = windowHandles[0]; - const dapp = await driver.switchToWindowWithTitle( - 'E2E Test Dapp', - windowHandles, - ); - await driver.closeAllWindowHandlesExcept([extension, dapp]); - await driver.delay(regularDelayMs); - - await driver.switchToWindow(dapp); - await driver.delay(tinyDelayMs); - - await driver.clickElement({ - text: 'Approve Tokens Without Gas', - tag: 'button', - }); - - await driver.switchToWindow(extension); - await driver.delay(regularDelayMs); - - await driver.wait(async () => { - const pendingTxes = await driver.findElements( - '.transaction-list__pending-transactions .transaction-list-item', - ); - return pendingTxes.length === 1; - }, 10000); - - await driver.waitForSelector({ - // Selects only the very first transaction list item immediately following the 'Pending' header - css: '.transaction-list__pending-transactions .transaction-list__header + .transaction-list-item .list-item__heading', - text: 'Approve TST spend limit', - }); - - await driver.clickElement('.transaction-list-item'); - await driver.delay(regularDelayMs); - }); - - it('shows the correct recipient', async function () { - await driver.clickElement({ - text: 'View full transaction details', - css: '.confirm-approve-content__small-blue-text', - }); - const permissionInfo = await driver.findElements( - '.confirm-approve-content__medium-text', - ); - const recipientDiv = permissionInfo[1]; - assert.equal(await recipientDiv.getText(), '0x2f318C33...C970'); - }); - - it('submits the transaction', async function () { - await driver.delay(veryLargeDelayMs); - await driver.clickElement({ text: 'Confirm', tag: 'button' }); - await driver.delay(regularDelayMs); - }); - - it('finds the transaction in the transactions list', async function () { - await driver.waitForSelector({ - css: '.transaction-list__completed-transactions .transaction-list-item:first-child .list-item__heading', - text: 'Approve TST spend limit', - }); - }); - }); }); diff --git a/test/e2e/tests/custom-token-add-approve.spec.js b/test/e2e/tests/custom-token-add-approve.spec.js index 2815f49a4..d11ce56fb 100644 --- a/test/e2e/tests/custom-token-add-approve.spec.js +++ b/test/e2e/tests/custom-token-add-approve.spec.js @@ -1,362 +1,502 @@ -/* eslint-disable mocha/no-skipped-tests */ const { strict: assert } = require('assert'); -const { - convertToHexValue, - withFixtures, - getWindowHandles, -} = require('../helpers'); +const { convertToHexValue, withFixtures } = require('../helpers'); const FixtureBuilder = require('../fixture-builder'); +const { SMART_CONTRACTS } = require('../seeder/smart-contracts'); -describe.skip('Create token, approve token and approve token without gas', function () { - describe('Add a custom token from a dapp', function () { - const ganacheOptions = { - accounts: [ - { - secretKey: - '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', - balance: convertToHexValue(25000000000000000000), - }, - ], - }; +describe('Create token, approve token and approve token without gas', function () { + const smartContract = SMART_CONTRACTS.HST; + const ganacheOptions = { + accounts: [ + { + secretKey: + '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', + balance: convertToHexValue(25000000000000000000), + }, + ], + }; - it('creates, imports and renders the balance for the new token', async function () { - await withFixtures( - { - dapp: true, - fixtures: new FixtureBuilder() - .withPermissionControllerConnectedToTestDapp() - .build(), - ganacheOptions, - title: this.test.title, - }, - async ({ driver }) => { - await driver.navigate(); - await driver.fill('#password', 'correct horse battery staple'); - await driver.press('#password', driver.Key.ENTER); + it('imports and renders the balance for the new token', async function () { + await withFixtures( + { + dapp: true, + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), + ganacheOptions, + smartContract, + title: this.test.title, + }, + async ({ driver, contractRegistry }) => { + const contractAddress = await contractRegistry.getContractAddress( + smartContract, + ); + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); - // create token - await driver.openNewPage(`http://127.0.0.1:8080/`); - await driver.waitForSelector({ text: 'Create Token', tag: 'button' }); - await driver.clickElement({ text: 'Create Token', tag: 'button' }); + // create token + await driver.openNewPage( + `http://127.0.0.1:8080/?contract=${contractAddress}`, + ); - const windowHandles = await getWindowHandles(driver, 3); - await driver.switchToWindow(windowHandles.popup); - await driver.clickElement({ text: 'Edit', tag: 'button' }); - const inputs = await driver.findElements('input[type="number"]'); - const gasLimitInput = inputs[0]; - const gasPriceInput = inputs[1]; - await gasLimitInput.fill('4700000'); - await gasPriceInput.fill('20'); - await driver.waitForSelector({ text: 'Save', tag: 'button' }); - await driver.clickElement({ text: 'Save', tag: 'button' }); - await driver.clickElement({ text: 'Confirm', tag: 'button' }); + const windowHandles = await driver.getAllWindowHandles(); + const extension = windowHandles[0]; - await driver.switchToWindow(windowHandles.dapp); + // imports custom token from extension + await driver.switchToWindow(extension); + await driver.clickElement(`[data-testid="home__asset-tab"]`); + await driver.clickElement({ tag: 'button', text: 'Assets' }); - const tokenContractAddress = await driver.waitForSelector({ - css: '#tokenAddress', - text: '0x', - }); - const tokenAddress = await tokenContractAddress.getText(); + await driver.clickElement({ text: 'import tokens', tag: 'a' }); + await driver.clickElement({ + text: 'Custom token', + tag: 'button', + }); + await driver.fill('#custom-address', contractAddress); + await driver.waitForSelector('#custom-decimals'); + await driver.delay(2000); - // imports custom token from extension - await driver.switchToWindow(windowHandles.extension); - await driver.clickElement(`[data-testid="home__asset-tab"]`); - await driver.clickElement({ tag: 'button', text: 'Assets' }); + await driver.clickElement({ + text: 'Add custom token', + tag: 'button', + }); - await driver.clickElement({ text: 'import tokens', tag: 'a' }); - await driver.clickElement({ - text: 'Custom token', - tag: 'button', - }); - await driver.waitForSelector('#custom-address'); - await driver.fill('#custom-address', tokenAddress); - await driver.waitForSelector('#custom-symbol'); - await driver.waitForSelector('#custom-decimals'); - await driver.delay(2000); + await driver.delay(2000); + await driver.clickElement({ + text: 'Import tokens', + tag: 'button', + }); - await driver.clickElement({ - text: 'Add custom token', - tag: 'button', - }); - - await driver.delay(2000); - await driver.clickElement({ - text: 'Import tokens', - tag: 'button', - }); - - // renders balance for newly created token - await driver.waitForSelector('.app-header__logo-container'); - await driver.clickElement('.app-header__logo-container'); - await driver.clickElement({ tag: 'button', text: 'Assets' }); - const asset = await driver.waitForSelector({ - css: '.asset-list-item__token-value', - text: '10', - }); - assert.equal(await asset.getText(), '10'); - }, - ); - }); + // renders balance for newly created token + await driver.clickElement('.app-header__logo-container'); + await driver.clickElement({ tag: 'button', text: 'Assets' }); + const asset = await driver.waitForSelector({ + css: '.asset-list-item__token-value', + text: '10', + }); + assert.equal(await asset.getText(), '10'); + }, + ); }); - describe('Approves a custom token from dapp', function () { - let windowHandles; + it('approves an already created token and displays the token approval data', async function () { + await withFixtures( + { + dapp: true, + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), + ganacheOptions, + smartContract, + title: this.test.title, + }, + async ({ driver, contractRegistry }) => { + const contractAddress = await contractRegistry.getContractAddress( + smartContract, + ); + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); - const ganacheOptions = { - accounts: [ - { - secretKey: - '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', - balance: convertToHexValue(25000000000000000000), - }, - ], - }; - it('approves an already created token and displays the token approval data', async function () { - await withFixtures( - { - dapp: true, - fixtures: new FixtureBuilder() - .withPermissionControllerConnectedToTestDapp() - .build(), - ganacheOptions, - title: this.test.title, - }, - async ({ driver }) => { - await driver.navigate(); - await driver.fill('#password', 'correct horse battery staple'); - await driver.press('#password', driver.Key.ENTER); + // create token + await driver.openNewPage( + `http://127.0.0.1:8080/?contract=${contractAddress}`, + ); - await driver.openNewPage(`http://127.0.0.1:8080/`); + let windowHandles = await driver.getAllWindowHandles(); + const extension = windowHandles[0]; - await driver.waitForSelector({ text: 'Create Token', tag: 'button' }); - await driver.clickElement({ text: 'Create Token', tag: 'button' }); - windowHandles = await getWindowHandles(driver, 3); - await driver.switchToWindow(windowHandles.popup); - await driver.clickElement({ text: 'Confirm', tag: 'button' }); - await driver.switchToWindow(windowHandles.dapp); - await driver.waitForSelector({ - text: 'Approve Tokens', - tag: 'button', - }); - await driver.clickElement({ text: 'Approve Tokens', tag: 'button' }); + await driver.findClickableElement('#deployButton'); + // approve token from dapp + await driver.clickElement({ text: 'Approve Tokens', tag: 'button' }); - // displays the token approval data - // switch to popup - windowHandles = await getWindowHandles(driver, 3); - await driver.switchToWindow(windowHandles.popup); + await driver.waitUntilXWindowHandles(3); + windowHandles = await driver.getAllWindowHandles(); + await driver.switchToWindowWithTitle( + 'MetaMask Notification', + windowHandles, + ); - const functionType = await driver.findElement( - '.confirm-approve-content__data .confirm-approve-content__small-text', + await driver.clickElement({ + text: 'Verify contract details', + css: '.token-allowance-container__verify-link', + }); + + const modalTitle = await driver.waitForSelector({ + text: 'Contract details', + tag: 'h5', + }); + + assert.equal(await modalTitle.getText(), 'Contract details'); + + await driver.clickElement({ + text: 'Got it', + tag: 'button', + }); + await driver.clickElement({ + text: 'Use default', + css: '.mm-button-link', + }); + await driver.clickElement({ + text: 'View details', + css: '.token-allowance-container__view-details', + }); + + // checks elements on approve token popup + const functionType = await driver.findElement({ + text: 'Function: Approve', + tag: 'h6', + }); + assert.equal(await functionType.getText(), 'Function: Approve'); + + const confirmDataDiv = await driver.findElement( + '.approve-content-card-container__data__data-block', + ); + const confirmDataText = await confirmDataDiv.getText(); + assert( + confirmDataText.match( + /0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef4/u, + ), + ); + await driver.clickElement({ text: 'Next', tag: 'button' }); + + await driver.findElement({ + text: 'Review your spending cap', + tag: 'div', + }); + + const defaultSpendingCup = await driver.findElement({ + text: '7 TST', + css: '.box--flex-direction-row > h6', + }); + + assert.equal( + await defaultSpendingCup.getText(), + '7 TST', + 'Default value is not correctly set', + ); + + await driver.clickElement({ + text: 'Approve', + tag: 'button', + }); + + await driver.switchToWindow(extension); + await driver.clickElement({ tag: 'button', text: 'Activity' }); + + // check list of pending transactions in extension + await driver.wait(async () => { + const pendingTxes = await driver.findElements( + '.transaction-list-item', ); + return pendingTxes.length === 1; + }, 10000); - await driver.scrollToElement(functionType); - const functionTypeText = await functionType.getText(); - assert.equal(functionTypeText, 'Function: Approve'); - const confirmDataDiv = await driver.findElement( - '.confirm-approve-content__data__data-block', - ); - const confirmDataText = await confirmDataDiv.getText(); - assert( - confirmDataText.match( - /0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef4/u, - ), - ); - await driver.clickElement({ text: 'Confirm', tag: 'button' }); - await driver.switchToWindow(windowHandles.extension); - await driver.clickElement({ tag: 'button', text: 'Activity' }); - - await driver.wait(async () => { - const pendingTxes = await driver.findElements( - '.transaction-list-item', - ); - return pendingTxes.length === 2; - }, 10000); - - await driver.waitForSelector({ - // Selects only the very first transaction list item immediately following the 'Pending' header - css: '.transaction-list__pending-transactions .transaction-list__header + .transaction-list-item .list-item__heading', - text: 'Approve Token spend limit', - }); - }, - ); - }); - - it('customizes gas, edit permissions and checks transaction in transaction list', async function () { - await withFixtures( - { - dapp: true, - fixtures: new FixtureBuilder() - .withPermissionControllerConnectedToTestDapp() - .build(), - ganacheOptions, - title: this.test.title, - }, - async ({ driver }) => { - await driver.navigate(); - await driver.fill('#password', 'correct horse battery staple'); - await driver.press('#password', driver.Key.ENTER); - - await driver.openNewPage(`http://127.0.0.1:8080/`); - - await driver.waitForSelector({ text: 'Create Token', tag: 'button' }); - await driver.clickElement({ text: 'Create Token', tag: 'button' }); - windowHandles = await getWindowHandles(driver, 3); - await driver.switchToWindow(windowHandles.popup); - await driver.clickElement({ text: 'Confirm', tag: 'button' }); - - await driver.switchToWindow(windowHandles.dapp); - - await driver.waitForSelector({ - text: 'Approve Tokens', - tag: 'button', - }); - await driver.clickElement({ text: 'Approve Tokens', tag: 'button' }); - - // switch to popup - windowHandles = await getWindowHandles(driver, 3); - await driver.switchToWindow(windowHandles.popup); - - await driver.clickElement( - '.confirm-approve-content__small-blue-text', - ); - await driver.clickElement({ - text: 'Edit suggested gas fee', - tag: 'button', - }); - const [gasLimitInput, gasPriceInput] = await driver.findElements( - 'input[type="number"]', - ); - await gasPriceInput.clear(); - await gasPriceInput.fill('10'); - await gasLimitInput.clear(); - await gasLimitInput.fill('60001'); - await driver.findClickableElement({ text: 'Save', tag: 'button' }); - await driver.clickElement({ text: 'Save', tag: 'button' }); - - await driver.waitForSelector({ - css: '.confirm-approve-content__transaction-details-content__secondary-fee', - text: '0.0006 ETH', - }); - - // edits the permission - const editButtons = await driver.findClickableElements( - '.confirm-approve-content__small-blue-text', - ); - await editButtons[2].click(); - - // wait for permission modal to be visible - const permissionModal = await driver.findVisibleElement( - 'span .modal', - ); - const radioButtons = await driver.findClickableElements( - '.edit-approval-permission__edit-section__radio-button', - ); - const customSpendLimit = await radioButtons[1]; - await customSpendLimit.click(); - await driver.fill('input', '5'); - await driver.clickElement({ text: 'Save', tag: 'button' }); - - // wait for permission modal to be removed from DOM. - await permissionModal.waitForElementState('hidden'); - const permissionInfo = await driver.findElements( - '.confirm-approve-content__medium-text', - ); - const amountDiv = permissionInfo[0]; - assert.equal(await amountDiv.getText(), '5 TST'); - - // submits the transaction - await driver.clickElement({ text: 'Confirm', tag: 'button' }); - - // finds the transaction in transaction list - await driver.switchToWindow(windowHandles.extension); - await driver.clickElement({ tag: 'button', text: 'Activity' }); - await driver.waitForSelector({ - // Select only the heading of the first entry in the transaction list. - css: '.transaction-list__completed-transactions .transaction-list-item:first-child .list-item__heading', - text: 'Approve Token spend limit', - }); - }, - ); - }); + const approveTokenTask = await driver.waitForSelector({ + // Selects only the very first transaction list item immediately following the 'Pending' header + css: '.transaction-list__completed-transactions .transaction-list-item:first-child .list-item__heading', + text: 'Approve Token spend limit', + }); + assert.equal( + await approveTokenTask.getText(), + 'Approve Token spend limit', + ); + }, + ); }); - describe('Approves a custom token from dapp when no gas value is specified', function () { - let windowHandles; + it('set custom spending cap, customizes gas, edit spending cap and checks transaction in transaction list', async function () { + await withFixtures( + { + dapp: true, + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), + ganacheOptions, + smartContract, + title: this.test.title, + }, + async ({ driver, contractRegistry }) => { + const contractAddress = await contractRegistry.getContractAddress( + smartContract, + ); + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); - const ganacheOptions = { - accounts: [ - { - secretKey: - '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', - balance: convertToHexValue(25000000000000000000), - }, - ], - }; + // create token + await driver.openNewPage( + `http://127.0.0.1:8080/?contract=${contractAddress}`, + ); - it('approves an already created token, shows the correct recipient, submits the transaction and finds the transaction in the transactions list', async function () { - await withFixtures( - { - dapp: true, - fixtures: new FixtureBuilder() - .withPermissionControllerConnectedToTestDapp() - .build(), - ganacheOptions, - title: this.test.title, - }, - async ({ driver }) => { - await driver.navigate(); - await driver.fill('#password', 'correct horse battery staple'); - await driver.press('#password', driver.Key.ENTER); + let windowHandles = await driver.getAllWindowHandles(); + const extension = windowHandles[0]; - await driver.openNewPage(`http://127.0.0.1:8080/`); + await driver.findClickableElement('#deployButton'); - await driver.waitForSelector({ text: 'Create Token', tag: 'button' }); - await driver.clickElement({ text: 'Create Token', tag: 'button' }); - windowHandles = await getWindowHandles(driver, 3); - await driver.switchToWindow(windowHandles.popup); - await driver.clickElement({ text: 'Confirm', tag: 'button' }); + // approve token from dapp + await driver.clickElement({ text: 'Approve Tokens', tag: 'button' }); - await driver.switchToWindow(windowHandles.dapp); + await driver.waitUntilXWindowHandles(3); + windowHandles = await driver.getAllWindowHandles(); + await driver.switchToWindowWithTitle( + 'MetaMask Notification', + windowHandles, + ); - await driver.clickElement({ - text: 'Approve Tokens Without Gas', - tag: 'button', - }); + // set custom spending cap + let setSpendingCap = await driver.findElement( + '[data-testid="custom-spending-cap-input"]', + ); + await setSpendingCap.fill('5'); - await driver.switchToWindow(windowHandles.extension); - await driver.clickElement({ tag: 'button', text: 'Activity' }); + await driver.clickElement({ + text: 'View details', + css: '.token-allowance-container__view-details', + }); + await driver.clickElement({ + text: 'Next', + tag: 'button', + }); - await driver.wait(async () => { - const pendingTxes = await driver.findElements( - '.transaction-list__pending-transactions .transaction-list-item', - ); - return pendingTxes.length === 1; - }, 10000); + let spendingCup = await driver.findElement({ + text: '5 TST', + css: '.box--flex-direction-row > h6', + }); - await driver.waitForSelector({ - // Selects only the very first transaction list item immediately following the 'Pending' header - css: '.transaction-list__pending-transactions .transaction-list__header + .transaction-list-item .list-item__heading', - text: 'Approve Token spend limit', - }); + assert.equal( + await spendingCup.getText(), + '5 TST', + 'Default value is not correctly set', + ); - await driver.clickElement('.transaction-list-item'); + // editing gas fee + const editBtn = await driver.findElements({ + text: 'Edit', + class: 'btn-link > h6', + }); - const permissionInfo = await driver.findElements( - '.confirm-approve-content__medium-text', + editBtn[1].click(); + + await driver.clickElement({ + text: 'Edit suggested gas fee', + tag: 'button', + }); + const [gasLimitInput, gasPriceInput] = await driver.findElements( + 'input[type="number"]', + ); + await gasPriceInput.clear(); + await gasPriceInput.fill('10'); + await gasLimitInput.clear(); + await gasLimitInput.fill('60001'); + await driver.clickElement({ text: 'Save', tag: 'button' }); + + await driver.waitForSelector({ + css: '.box--flex-direction-row > h6', + text: '0.0006 ETH', + }); + + // editing spending cap + await driver.clickElement({ + class: '.review-spending-cap__heading-detail__button', + text: 'Edit', + }); + + setSpendingCap = await driver.findElement( + '[data-testid="custom-spending-cap-input"]', + ); + await setSpendingCap.fill('9'); + + await driver.clickElement({ + text: 'Next', + tag: 'button', + }); + + spendingCup = await driver.findElement({ + text: '9 TST', + css: '.box--flex-direction-row > h6', + }); + assert.equal( + await spendingCup.getText(), + '9 TST', + 'Default value is not correctly set', + ); + + // submits the transaction + await driver.clickElement({ text: 'Approve', tag: 'button' }); + + // finds the transaction in transaction list + await driver.switchToWindow(extension); + await driver.clickElement({ tag: 'button', text: 'Activity' }); + + await driver.wait(async () => { + const pendingTxes = await driver.findElements( + '.transaction-list-item', ); - const recipientDiv = permissionInfo[1]; - assert.equal(await recipientDiv.getText(), '0x2f318C33...C970'); + return pendingTxes.length === 1; + }, 10000); + const approveTokenTask = await driver.waitForSelector({ + // Select only the heading of the first entry in the transaction list. + css: '.transaction-list__completed-transactions .transaction-list-item:first-child .list-item__heading', + text: 'Approve Token spend limit', + }); + assert.equal( + await approveTokenTask.getText(), + 'Approve Token spend limit', + ); + }, + ); + }); - await driver.clickElement({ text: 'Confirm', tag: 'button' }); + it('set maximum spending cap, submits the transaction and finds the transaction in the transactions list', async function () { + await withFixtures( + { + dapp: true, + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), + ganacheOptions, + smartContract, + title: this.test.title, + }, + async ({ driver, contractRegistry }) => { + const contractAddress = await contractRegistry.getContractAddress( + smartContract, + ); + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); - await driver.waitForSelector({ - css: '.transaction-list__completed-transactions .transaction-list-item:first-child .list-item__heading', - text: 'Approve Token spend limit', - }); - }, - ); - }); + // create token + await driver.openNewPage( + `http://127.0.0.1:8080/?contract=${contractAddress}`, + ); + + const windowHandles = await driver.getAllWindowHandles(); + const extension = windowHandles[0]; + + await driver.findClickableElement('#deployButton'); + + // approve token from dapp + await driver.clickElement({ text: 'Approve Tokens', tag: 'button' }); + + await driver.switchToWindow(extension); + await driver.clickElement({ tag: 'button', text: 'Activity' }); + + const pendingTxes = await driver.findElements( + '.transaction-list__pending-transactions .transaction-list-item', + ); + pendingTxes[0].click(); + + // set max spending cap + await driver.clickElement({ + css: '.custom-spending-cap__max', + text: 'Max', + }); + + await driver.clickElement({ + tag: 'button', + text: 'Next', + }); + + // checks the balance + const balance = await driver.findElement({ + css: '.box--display-flex > h6', + text: '10 TST', + }); + + const maxSpendingCap = await driver.findElement({ + text: '10 TST', + css: '.box--flex-direction-row > h6', + }); + + assert.equal( + await maxSpendingCap.getText(), + await balance.getText(), + 'Max spending cap is not set corectly', + ); + + await driver.delay(500); + await driver.clickElement({ + tag: 'button', + text: 'Approve', + }); + + const approveTokenTask = await driver.waitForSelector({ + // Select only the heading of the first entry in the transaction list. + css: '.transaction-list__completed-transactions .transaction-list-item:first-child .list-item__heading', + text: 'Approve Token spend limit', + }); + assert.equal( + await approveTokenTask.getText(), + 'Approve Token spend limit', + ); + }, + ); + }); + + it('approves token without gas, set default spending cap, submits the transaction and finds the transaction in the transactions list', async function () { + await withFixtures( + { + dapp: true, + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), + ganacheOptions, + smartContract, + title: this.test.title, + }, + async ({ driver, contractRegistry }) => { + const contractAddress = await contractRegistry.getContractAddress( + smartContract, + ); + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + await driver.openNewPage( + `http://127.0.0.1:8080/?contract=${contractAddress}`, + ); + const windowHandles = await driver.getAllWindowHandles(); + const extension = windowHandles[0]; + + await driver.findClickableElement('#deployButton'); + // approve token without gas from dapp + await driver.clickElement({ + text: 'Approve Tokens Without Gas', + tag: 'button', + }); + + // switch to extension + await driver.switchToWindow(extension); + await driver.clickElement({ tag: 'button', text: 'Activity' }); + + const pendingTxes = await driver.findElements('.transaction-list-item'); + pendingTxes[0].click(); + // set spending cap + await driver.clickElement({ + text: 'Use default', + css: '.mm-button-link', + }); + await driver.clickElement({ + text: 'Next', + tag: 'button', + }); + + await driver.delay(500); + await driver.clickElement({ text: 'Approve', tag: 'button' }); + + // check transaction in Activity tab + const approveTokenTask = await driver.waitForSelector({ + css: '.transaction-list__completed-transactions .transaction-list-item:first-child .list-item__heading', + text: 'Approve Token spend limit', + }); + assert.equal( + await approveTokenTask.getText(), + 'Approve Token spend limit', + ); + }, + ); }); }); diff --git a/ui/components/app/whats-new-popup/whats-new-popup.js b/ui/components/app/whats-new-popup/whats-new-popup.js index 3c28741cb..3420d03fc 100644 --- a/ui/components/app/whats-new-popup/whats-new-popup.js +++ b/ui/components/app/whats-new-popup/whats-new-popup.js @@ -59,10 +59,6 @@ function getActionFunctionById(id, history) { updateViewedNotifications({ 14: true }); history.push(`${ADVANCED_ROUTE}#backup-userdata`); }, - 16: () => { - updateViewedNotifications({ 16: true }); - history.push(EXPERIMENTAL_ROUTE); - }, 17: () => { updateViewedNotifications({ 17: true }); history.push(SECURITY_ROUTE); diff --git a/ui/helpers/constants/settings.js b/ui/helpers/constants/settings.js index 8baa4ea8e..34e9a8217 100644 --- a/ui/helpers/constants/settings.js +++ b/ui/helpers/constants/settings.js @@ -350,13 +350,6 @@ export const SETTINGS_CONSTANTS = [ route: `${ADVANCED_ROUTE}#restore-userdata`, icon: 'fas fa-upload', }, - { - tabMessage: (t) => t('experimental'), - sectionMessage: (t) => t('improvedTokenAllowance'), - descriptionMessage: (t) => t('improvedTokenAllowanceDescription'), - route: `${EXPERIMENTAL_ROUTE}#improved-token-allowance`, - icon: 'fa fa-flask', - }, { tabMessage: (t) => t('experimental'), sectionMessage: (t) => t('transactionSecurityCheck'), diff --git a/ui/helpers/utils/settings-search.test.js b/ui/helpers/utils/settings-search.test.js index 82a00306f..daaadae9d 100644 --- a/ui/helpers/utils/settings-search.test.js +++ b/ui/helpers/utils/settings-search.test.js @@ -182,7 +182,7 @@ describe('Settings Search Utils', () => { it('should get good experimental section number', () => { expect(getNumberOfSettingsInSection(t, t('experimental'))).toStrictEqual( - 2, + 1, ); }); diff --git a/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js b/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js index 2323b9846..80644b9bc 100644 --- a/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js +++ b/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js @@ -2,16 +2,14 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import copyToClipboard from 'copy-to-clipboard'; -import { getTokenTrackerLink, getAccountLink } from '@metamask/etherscan-link'; +import { getTokenTrackerLink } from '@metamask/etherscan-link'; import UrlIcon from '../../../components/ui/url-icon'; import { addressSummary } from '../../../helpers/utils/util'; import { formatCurrency } from '../../../helpers/utils/confirm-tx.util'; -import { ellipsify } from '../../send/send.utils'; import Typography from '../../../components/ui/typography'; import Box from '../../../components/ui/box'; import Button from '../../../components/ui/button'; import EditGasFeeButton from '../../../components/app/edit-gas-fee-button'; -import Identicon from '../../../components/ui/identicon'; import MultiLayerFeeMessage from '../../../components/app/multilayer-fee-message'; import CopyIcon from '../../../components/ui/icon/copy-icon.component'; import { @@ -36,16 +34,10 @@ export default class ConfirmApproveContent extends Component { }; static propTypes = { - decimals: PropTypes.number, - tokenAmount: PropTypes.string, - customTokenAmount: PropTypes.string, tokenSymbol: PropTypes.string, siteImage: PropTypes.string, showCustomizeGasModal: PropTypes.func, - showEditApprovalPermissionModal: PropTypes.func, origin: PropTypes.string, - setCustomAmount: PropTypes.func, - tokenBalance: PropTypes.string, data: PropTypes.string, toAddress: PropTypes.string, currentCurrency: PropTypes.string, @@ -243,66 +235,6 @@ export default class ConfirmApproveContent extends Component { ); } - renderERC20PermissionContent() { - const { t } = this.context; - const { - customTokenAmount, - tokenAmount, - tokenSymbol, - origin, - toAddress, - isContract, - } = this.props; - - const displayedAddress = isContract - ? `${t('contract')} (${addressSummary(toAddress)})` - : addressSummary(toAddress); - return ( -