mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-25 03:20:23 +01:00
Token allowance flow update (#19666)
This commit is contained in:
parent
f9b1514914
commit
129f6f3f64
10
app/_locales/de/messages.json
generated
10
app/_locales/de/messages.json
generated
@ -2956,9 +2956,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Seed-Phrase anzeigen"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Überprüfen SIe Ihre Ausgabegrenze"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Erlaubnis zum Zugriff auf alle Ihre $1 sowie deren Übertragung entziehen?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3137,6 @@
|
||||
"message": "$1 ohne Ausgabenlimit genehmigen",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Eine Ausgabegrenze für Ihr $1 einrichten",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Einstellungen"
|
||||
},
|
||||
@ -4167,9 +4160,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "Diese URL wird derzeit vom $1-Netzwerk verwendet."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Standardeinstellungen verwenden"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Kontoguthaben-Anfragen sammeln"
|
||||
},
|
||||
|
10
app/_locales/el/messages.json
generated
10
app/_locales/el/messages.json
generated
@ -2956,9 +2956,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Αποκάλυψη φράσης ανάκτησης"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Επανεξετάστε το όριο δαπανών σας"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Ανάκληση άδειας πρόσβασης σε όλα σας τα $1;",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3137,10 +3134,6 @@
|
||||
"message": "Έγκριση $1 χωρίς όριο δαπανών",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Ορίστε ένα ανώτατο όριο δαπανών για το $1",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Ρυθμίσεις"
|
||||
},
|
||||
@ -4164,9 +4157,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "Αυτό το URL χρησιμοποιείται επί του παρόντος από το δίκτυο $1."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Χρήση προκαθορισμένου"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Μαζικά αιτήματα υπολοίπου λογαριασμού"
|
||||
},
|
||||
|
19
app/_locales/en/messages.json
generated
19
app/_locales/en/messages.json
generated
@ -1055,6 +1055,9 @@
|
||||
"customerSupport": {
|
||||
"message": "customer support"
|
||||
},
|
||||
"dappRequestedSpendingCap": {
|
||||
"message": "Site requested spending cap"
|
||||
},
|
||||
"dappSuggested": {
|
||||
"message": "Site suggested"
|
||||
},
|
||||
@ -3544,9 +3547,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Reveal seed phrase"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Review the spending cap for your"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Revoke permission to access and transfer all of your $1?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3766,10 +3766,6 @@
|
||||
"message": "Approve $1 with no spend limit",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Set a spending cap for your $1",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settingAddSnapAccount": {
|
||||
"message": "Add snap account"
|
||||
},
|
||||
@ -4092,6 +4088,9 @@
|
||||
"message": "Only enter a number that you're comfortable with $1 accessing now or in the future. You can always increase the token limit later.",
|
||||
"description": "$1 is origin of the site requesting the token limit"
|
||||
},
|
||||
"spendingCapRequest": {
|
||||
"message": "Spending cap request for your $1"
|
||||
},
|
||||
"srpInputNumberOfWords": {
|
||||
"message": "I have a $1-word phrase",
|
||||
"description": "This is the text for each option in the dropdown where a user selects how many words their secret recovery phrase has during import. The $1 is the number of words (either 12, 15, 18, 21, or 24)."
|
||||
@ -5141,9 +5140,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "This URL is currently used by the $1 network."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Use default"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Batch account balance requests"
|
||||
},
|
||||
@ -5174,6 +5170,9 @@
|
||||
"usePhishingDetectionDescription": {
|
||||
"message": "Display a warning for phishing domains targeting Ethereum users"
|
||||
},
|
||||
"useSiteSuggestion": {
|
||||
"message": "Use site suggestion"
|
||||
},
|
||||
"useTokenDetectionPrivacyDesc": {
|
||||
"message": "Automatically displaying tokens sent to your account involves communication with third party servers to fetch token’s images. Those serves will have access to your IP address."
|
||||
},
|
||||
|
10
app/_locales/es/messages.json
generated
10
app/_locales/es/messages.json
generated
@ -2956,9 +2956,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Revelar frase semilla"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Revise su límite de gasto"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "¿Revocar el permiso para acceder y transferir todos sus $1?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3137,6 @@
|
||||
"message": "Aprobar $1 sin límite preestablecido",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Establecer un límite de gasto para su $1",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Configuración"
|
||||
},
|
||||
@ -4167,9 +4160,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "En este momento, la red $1 está utilizando esta dirección URL."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Uso por defecto"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Solicitudes de saldo de cuenta por lotes"
|
||||
},
|
||||
|
10
app/_locales/fr/messages.json
generated
10
app/_locales/fr/messages.json
generated
@ -2956,9 +2956,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Révéler la phrase mnémonique"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Modifiez votre plafond de dépenses"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Révoquer l’autorisation d’accès et de transfert de tous vos $1 ?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3137,6 @@
|
||||
"message": "Approuver $1 sans limite de dépenses",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Fixez un plafond de dépenses pour vos $1",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Paramètres"
|
||||
},
|
||||
@ -4167,9 +4160,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "Cette URL est actuellement utilisée par le réseau $1."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Utiliser par défaut"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Demandes d’informations concernant le solde de plusieurs comptes"
|
||||
},
|
||||
|
10
app/_locales/hi/messages.json
generated
10
app/_locales/hi/messages.json
generated
@ -2956,9 +2956,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "सीड फ़्रेज़ दिखाएं"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "अपनी खर्च के सीमा की समीक्षा करें"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "आपके सभी $1 को एक्सेस और स्थानांतरित करने की अनुमति निरस्त करें?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3137,6 @@
|
||||
"message": "बिना किसी खर्च सीमा के $1 स्वीकृत करें",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "अपने $1 के लिए खर्च की सीमा को निर्धारित करें",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "सेटिंग"
|
||||
},
|
||||
@ -4167,9 +4160,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "यह URL वर्तमान में $1 नेटवर्क द्वारा उपयोग किया जाता है।"
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "डिफॉल्ट का उपयोग करें"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "खाता के शेष राशि के अनुरोधों को बैच करें"
|
||||
},
|
||||
|
10
app/_locales/id/messages.json
generated
10
app/_locales/id/messages.json
generated
@ -2956,9 +2956,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Ungkap frasa seed"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Tinjau batas pengeluaran Anda"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Cabut izin untuk mengakses dan mentransfer seluruh $1 Anda?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3137,6 @@
|
||||
"message": "Setujui $1 tanpa batas penggunaan",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Tetapkan batas pengeluaran untuk $1",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Pengaturan"
|
||||
},
|
||||
@ -4167,9 +4160,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "URL ini saat ini digunakan oleh jaringan $1."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Gunakan default"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Kelompokkan permintaan saldo akun"
|
||||
},
|
||||
|
10
app/_locales/ja/messages.json
generated
10
app/_locales/ja/messages.json
generated
@ -2956,9 +2956,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "シードフレーズを表示"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "使用上限を確認してください"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "すべての $1 へのアクセスおよび転送許可を取り消しますか?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3137,6 @@
|
||||
"message": "使用限度額なしで $1 を承認",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "$1 の使用上限を設定",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "設定"
|
||||
},
|
||||
@ -4167,9 +4160,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "このURLは現在$1ネットワークで使用されています。"
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "既定値を使用"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "アカウント残高の一括リクエスト"
|
||||
},
|
||||
|
10
app/_locales/ko/messages.json
generated
10
app/_locales/ko/messages.json
generated
@ -2956,9 +2956,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "시드 구문 보기"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "지출 한도 검토"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "모든 $1에 액세스할 수 있는 권한을 철회할까요?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3137,6 @@
|
||||
"message": "$1 무제한 지출 승인",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "$1에 대한 지출 한도 설정",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "설정"
|
||||
},
|
||||
@ -4167,9 +4160,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "이 URL은 현재 $1 네트워크에서 사용됩니다."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "기본값 사용"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "일괄 계정 잔액 요청"
|
||||
},
|
||||
|
10
app/_locales/pt/messages.json
generated
10
app/_locales/pt/messages.json
generated
@ -2956,9 +2956,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Revelar a frase de recuperação"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Revise seu limite de gastos"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Revogar permissão de acesso e transferência de todos os seus $1?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3137,6 @@
|
||||
"message": "Aprovar $1 sem limite de gastos",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Definir um limite de gastos para seu $1",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Definições"
|
||||
},
|
||||
@ -4167,9 +4160,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "O ID da cadeia está sendo usado pela rede $1."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Usar padrão"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Agrupar solicitações de saldo de contas"
|
||||
},
|
||||
|
10
app/_locales/ru/messages.json
generated
10
app/_locales/ru/messages.json
generated
@ -2956,9 +2956,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Показать сид-фразу"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Проверьте свой лимит расходов"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Отозвать разрешение на доступ ко всем вашим $1 и их перевод?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3137,6 @@
|
||||
"message": "Одобрить $1 без ограничений по расходам",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Установить верхний лимит расходов для вашего $1",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Настройки"
|
||||
},
|
||||
@ -4167,9 +4160,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "Это URL-адрес в настоящее время используется сетью $1."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Использовать значения по умолчанию"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Пакетные запросы баланса счета"
|
||||
},
|
||||
|
10
app/_locales/tl/messages.json
generated
10
app/_locales/tl/messages.json
generated
@ -2956,9 +2956,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Ipakita ang seed phrase"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "I-review ang iyong limitasyon sa paggastos"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Bawiin ang pahintulot na i-access at ilipat ang lahat ng iyong $1?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3137,6 @@
|
||||
"message": "Aprubahan ang $1 nang walang limitasyon sa paggastos",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Magtakda ng limitasyon sa paggastos para sa iyong $1",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Mga Setting"
|
||||
},
|
||||
@ -4167,9 +4160,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "Nasa kasalukuyang listahan ng mga network na ang URL."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Gamitin ang default"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Mga kahilingan sa balanse ng batch account"
|
||||
},
|
||||
|
10
app/_locales/tr/messages.json
generated
10
app/_locales/tr/messages.json
generated
@ -2956,9 +2956,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Tohum ifadesini ortaya çıkar"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Harcama üst limitinize göz atın"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Tüm $1 için izin erişim ve transfer izni geri çekilsin mi?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3137,6 @@
|
||||
"message": "$1 için harcama limiti olmadan onay ver",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "$1 için harcama üst limiti belirle",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Ayarlar"
|
||||
},
|
||||
@ -4167,9 +4160,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "Bu URL şu anda $1 ağı tarafından kullanılıyor."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Varsayılanı kullan"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Toplu hesap bakiyesi talepleri"
|
||||
},
|
||||
|
10
app/_locales/vi/messages.json
generated
10
app/_locales/vi/messages.json
generated
@ -2956,9 +2956,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Hiện cụm từ khôi phục bí mật"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Xem lại hạn mức chi tiêu của bạn"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Thu hồi quyền truy cập và chuyển tất cả $1 của bạn?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3137,6 @@
|
||||
"message": "Phê duyệt $1 không có giới hạn chi tiêu",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Đặt hạn mức chi tiêu cho $1 của bạn",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Cài đặt"
|
||||
},
|
||||
@ -4167,9 +4160,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "Mạng $1 hiện đang sử dụng URL này."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Sử dụng mặc định"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Xử lý hàng loạt yêu cầu số dư tài khoản"
|
||||
},
|
||||
|
10
app/_locales/zh_CN/messages.json
generated
10
app/_locales/zh_CN/messages.json
generated
@ -2956,9 +2956,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "显示助记词"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "检查您的支出上限"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "撤销访问和转移您的所有 $1 的权限?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3137,6 @@
|
||||
"message": "批准$1,且无消费限制",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "为 $1 设置支出上限",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "设置"
|
||||
},
|
||||
@ -4167,9 +4160,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "此 URL 目前已被 $1 网络使用。"
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "使用默认值"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "账户余额分批请求"
|
||||
},
|
||||
|
@ -129,10 +129,6 @@ describe('Create token, approve token and approve token without gas', function (
|
||||
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',
|
||||
@ -157,17 +153,17 @@ describe('Create token, approve token and approve token without gas', function (
|
||||
await driver.clickElement({ text: 'Next', tag: 'button' });
|
||||
|
||||
await driver.findElement({
|
||||
text: 'Review the spending cap for your',
|
||||
tag: 'div',
|
||||
text: 'Spending cap request for your ',
|
||||
css: '.box--flex-direction-row',
|
||||
});
|
||||
|
||||
const defaultSpendingCup = await driver.findElement({
|
||||
const defaultSpendingCap = await driver.findElement({
|
||||
text: '7 TST',
|
||||
css: '.box--flex-direction-row > h6',
|
||||
});
|
||||
|
||||
assert.equal(
|
||||
await defaultSpendingCup.getText(),
|
||||
await defaultSpendingCap.getText(),
|
||||
'7 TST',
|
||||
'Default value is not correctly set',
|
||||
);
|
||||
@ -253,13 +249,13 @@ describe('Create token, approve token and approve token without gas', function (
|
||||
tag: 'button',
|
||||
});
|
||||
|
||||
let spendingCup = await driver.findElement({
|
||||
let spendingCap = await driver.findElement({
|
||||
text: '5 TST',
|
||||
css: '.box--flex-direction-row > h6',
|
||||
});
|
||||
|
||||
assert.equal(
|
||||
await spendingCup.getText(),
|
||||
await spendingCap.getText(),
|
||||
'5 TST',
|
||||
'Default value is not correctly set',
|
||||
);
|
||||
@ -309,12 +305,12 @@ describe('Create token, approve token and approve token without gas', function (
|
||||
tag: 'button',
|
||||
});
|
||||
|
||||
spendingCup = await driver.findElement({
|
||||
spendingCap = await driver.findElement({
|
||||
text: '9 TST',
|
||||
css: '.box--flex-direction-row > h6',
|
||||
});
|
||||
assert.equal(
|
||||
await spendingCup.getText(),
|
||||
await spendingCap.getText(),
|
||||
'9 TST',
|
||||
'Default value is not correctly set',
|
||||
);
|
||||
@ -429,7 +425,7 @@ describe('Create token, approve token and approve token without gas', function (
|
||||
);
|
||||
});
|
||||
|
||||
it('approves token without gas, set default spending cap, submits the transaction and finds the transaction in the transactions list', async function () {
|
||||
it('approves token without gas, set site suggested spending cap, submits the transaction and finds the transaction in the transactions list', async function () {
|
||||
await withFixtures(
|
||||
{
|
||||
dapp: true,
|
||||
@ -465,9 +461,16 @@ describe('Create token, approve token and approve token without gas', function (
|
||||
|
||||
const pendingTxes = await driver.findElements('.transaction-list-item');
|
||||
pendingTxes[0].click();
|
||||
// set spending cap
|
||||
|
||||
// set custom spending cap
|
||||
const spendingCap = await driver.findElement(
|
||||
'[data-testid="custom-spending-cap-input"]',
|
||||
);
|
||||
await spendingCap.fill('5');
|
||||
|
||||
// set site suggested spending cap
|
||||
await driver.clickElement({
|
||||
text: 'Use default',
|
||||
text: 'Use site suggestion',
|
||||
css: '.mm-button-link',
|
||||
});
|
||||
await driver.clickElement({
|
||||
|
@ -51,15 +51,6 @@ exports[`CustomSpendingCap should match snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mm-box form-field__heading-detail mm-box--margin-right-0 mm-box--margin-bottom-2 mm-box--text-align-end"
|
||||
>
|
||||
<button
|
||||
class="box mm-text mm-button-base mm-button-link mm-button-link--size-auto mm-text--body-md box--display-inline-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-primary-default box--background-color-transparent"
|
||||
>
|
||||
Use default
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
class="form-field__input"
|
||||
@ -67,7 +58,7 @@ exports[`CustomSpendingCap should match snapshot 1`] = `
|
||||
id="custom-spending-cap"
|
||||
placeholder="Enter a number"
|
||||
type="text"
|
||||
value="10"
|
||||
value="7"
|
||||
/>
|
||||
|
||||
</div>
|
||||
@ -85,7 +76,7 @@ exports[`CustomSpendingCap should match snapshot 1`] = `
|
||||
class="box custom-spending-cap__description box--flex-direction-row"
|
||||
>
|
||||
<h6
|
||||
class="box mm-text mm-text--body-sm box--padding-top-2 box--padding-bottom-2 box--flex-direction-row box--color-text-default"
|
||||
class="box mm-text mm-text--body-sm box--padding-top-2 box--flex-direction-row box--color-text-default"
|
||||
>
|
||||
<span>
|
||||
|
||||
@ -93,7 +84,7 @@ exports[`CustomSpendingCap should match snapshot 1`] = `
|
||||
<h6
|
||||
class="box mm-text custom-spending-cap__input-value-and-token-name mm-text--body-sm-bold box--flex-direction-row box--color-text-default"
|
||||
>
|
||||
10
|
||||
7
|
||||
|
||||
TST
|
||||
</h6>
|
||||
@ -101,6 +92,13 @@ exports[`CustomSpendingCap should match snapshot 1`] = `
|
||||
|
||||
</span>
|
||||
</h6>
|
||||
<a
|
||||
class="box mm-text mm-button-base mm-button-base--size-sm mm-button-link mm-text--body-md box--margin-bottom-2 box--display-inline-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-primary-default box--background-color-transparent"
|
||||
href="https://support.metamask.io/hc/en-us/articles/6055177143579-How-to-customize-token-approvals-with-a-spending-cap"
|
||||
target="_blank"
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useState, useContext, useEffect, useRef } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import BigNumber from 'bignumber.js';
|
||||
@ -21,7 +21,6 @@ import {
|
||||
BackgroundColor,
|
||||
TextColor,
|
||||
} from '../../../helpers/constants/design-system';
|
||||
import { getCustomTokenAmount } from '../../../selectors';
|
||||
import { setCustomTokenAmount } from '../../../ducks/app/app';
|
||||
import { calcTokenAmount } from '../../../../shared/lib/transactions-controller-utils';
|
||||
import { hexToDecimal } from '../../../../shared/modules/conversion.utils';
|
||||
@ -34,6 +33,7 @@ import { Numeric } from '../../../../shared/modules/Numeric';
|
||||
import { estimateGas } from '../../../store/actions';
|
||||
import { getCustomTxParamsData } from '../../../pages/confirm-approve/confirm-approve.util';
|
||||
import { useGasFeeContext } from '../../../contexts/gasFee';
|
||||
import ZENDESK_URLS from '../../../helpers/constants/zendesk-url';
|
||||
import { CustomSpendingCapTooltip } from './custom-spending-cap-tooltip';
|
||||
|
||||
export default function CustomSpendingCap({
|
||||
@ -45,18 +45,17 @@ export default function CustomSpendingCap({
|
||||
passTheErrorText,
|
||||
decimals,
|
||||
setInputChangeInProgress,
|
||||
customSpendingCap,
|
||||
setCustomSpendingCap,
|
||||
}) {
|
||||
const t = useContext(I18nContext);
|
||||
const dispatch = useDispatch();
|
||||
const { updateTransaction } = useGasFeeContext();
|
||||
const inputRef = useRef(null);
|
||||
|
||||
const value = useSelector(getCustomTokenAmount);
|
||||
|
||||
const [error, setError] = useState('');
|
||||
const [showUseDefaultButton, setShowUseDefaultButton] = useState(
|
||||
value !== String(dappProposedValue) && true,
|
||||
);
|
||||
const [showUseSiteSuggestionButton, setShowUseSiteSuggestionButton] =
|
||||
useState(customSpendingCap !== String(dappProposedValue) && true);
|
||||
const inputLogicEmptyStateText = t('inputLogicEmptyState');
|
||||
|
||||
const replaceCommaToDot = (inputValue) => {
|
||||
@ -102,7 +101,7 @@ export default function CustomSpendingCap({
|
||||
};
|
||||
|
||||
const [customSpendingCapText, setCustomSpendingCapText] = useState(
|
||||
getInputTextLogic(value).description,
|
||||
getInputTextLogic(customSpendingCap).description,
|
||||
);
|
||||
|
||||
const handleChange = async (valueInput) => {
|
||||
@ -139,37 +138,42 @@ export default function CustomSpendingCap({
|
||||
setError(spendingCapError);
|
||||
}
|
||||
}
|
||||
|
||||
setCustomSpendingCap(String(valueInput));
|
||||
dispatch(setCustomTokenAmount(String(valueInput)));
|
||||
|
||||
try {
|
||||
const newData = getCustomTxParamsData(txParams.data, {
|
||||
customPermissionAmount: valueInput,
|
||||
decimals,
|
||||
});
|
||||
const { from, to, value: txValue } = txParams;
|
||||
const estimatedGasLimit = await estimateGas({
|
||||
from,
|
||||
to,
|
||||
value: txValue,
|
||||
data: newData,
|
||||
});
|
||||
if (estimatedGasLimit) {
|
||||
await updateTransaction({
|
||||
gasLimit: hexToDecimal(addHexPrefix(estimatedGasLimit)),
|
||||
if (String(valueInput) !== '') {
|
||||
try {
|
||||
const newData = getCustomTxParamsData(txParams.data, {
|
||||
customPermissionAmount: valueInput,
|
||||
decimals,
|
||||
});
|
||||
const { from, to, value: txValue } = txParams;
|
||||
const estimatedGasLimit = await estimateGas({
|
||||
from,
|
||||
to,
|
||||
value: txValue,
|
||||
data: newData,
|
||||
});
|
||||
if (estimatedGasLimit) {
|
||||
await updateTransaction({
|
||||
gasLimit: hexToDecimal(addHexPrefix(estimatedGasLimit)),
|
||||
});
|
||||
}
|
||||
} catch (exp) {
|
||||
console.error('Error in trying to update gas limit', exp);
|
||||
}
|
||||
} catch (exp) {
|
||||
console.error('Error in trying to update gas limit', exp);
|
||||
}
|
||||
|
||||
setInputChangeInProgress(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (value !== String(dappProposedValue)) {
|
||||
setShowUseDefaultButton(true);
|
||||
if (customSpendingCap === String(dappProposedValue)) {
|
||||
setShowUseSiteSuggestionButton(false);
|
||||
} else {
|
||||
setShowUseSiteSuggestionButton(true);
|
||||
}
|
||||
}, [value, dappProposedValue]);
|
||||
}, [customSpendingCap, dappProposedValue]);
|
||||
|
||||
useEffect(() => {
|
||||
passTheErrorText(error);
|
||||
@ -185,7 +189,7 @@ export default function CustomSpendingCap({
|
||||
}, [inputRef.current]);
|
||||
|
||||
const chooseTooltipContentText = decConversionGreaterThan(
|
||||
value,
|
||||
customSpendingCap,
|
||||
currentTokenBalance,
|
||||
)
|
||||
? t('warningTooltipText', [
|
||||
@ -221,7 +225,7 @@ export default function CustomSpendingCap({
|
||||
>
|
||||
<label
|
||||
htmlFor={
|
||||
decConversionGreaterThan(value, currentTokenBalance)
|
||||
decConversionGreaterThan(customSpendingCap, currentTokenBalance)
|
||||
? 'custom-spending-cap-input-value'
|
||||
: 'custom-spending-cap'
|
||||
}
|
||||
@ -231,18 +235,23 @@ export default function CustomSpendingCap({
|
||||
dataTestId="custom-spending-cap-input"
|
||||
wrappingLabelProps={{ as: 'div' }}
|
||||
id={
|
||||
decConversionGreaterThan(value, currentTokenBalance)
|
||||
decConversionGreaterThan(customSpendingCap, currentTokenBalance)
|
||||
? 'custom-spending-cap-input-value'
|
||||
: 'custom-spending-cap'
|
||||
}
|
||||
TooltipCustomComponent={
|
||||
<CustomSpendingCapTooltip
|
||||
tooltipContentText={
|
||||
replaceCommaToDot(value) ? chooseTooltipContentText : ''
|
||||
replaceCommaToDot(customSpendingCap)
|
||||
? chooseTooltipContentText
|
||||
: ''
|
||||
}
|
||||
tooltipIcon={
|
||||
replaceCommaToDot(value)
|
||||
? decConversionGreaterThan(value, currentTokenBalance)
|
||||
replaceCommaToDot(customSpendingCap)
|
||||
? decConversionGreaterThan(
|
||||
customSpendingCap,
|
||||
currentTokenBalance,
|
||||
)
|
||||
: ''
|
||||
}
|
||||
/>
|
||||
@ -251,18 +260,18 @@ export default function CustomSpendingCap({
|
||||
titleText={t('customSpendingCap')}
|
||||
placeholder={t('enterANumber')}
|
||||
error={error}
|
||||
value={value}
|
||||
value={customSpendingCap}
|
||||
titleDetail={
|
||||
showUseDefaultButton && (
|
||||
showUseSiteSuggestionButton && (
|
||||
<ButtonLink
|
||||
size={Size.auto}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setShowUseDefaultButton(false);
|
||||
setShowUseSiteSuggestionButton(false);
|
||||
handleChange(dappProposedValue);
|
||||
}}
|
||||
>
|
||||
{t('useDefault')}
|
||||
{t('useSiteSuggestion')}
|
||||
</ButtonLink>
|
||||
)
|
||||
}
|
||||
@ -298,12 +307,19 @@ export default function CustomSpendingCap({
|
||||
variant={TextVariant.bodySm}
|
||||
as="h6"
|
||||
paddingTop={2}
|
||||
paddingBottom={2}
|
||||
>
|
||||
{replaceCommaToDot(value)
|
||||
{replaceCommaToDot(customSpendingCap)
|
||||
? customSpendingCapText
|
||||
: inputLogicEmptyStateText}
|
||||
</Text>
|
||||
<ButtonLink
|
||||
size={Size.SM}
|
||||
href={ZENDESK_URLS.TOKEN_ALLOWANCE_WITH_SPENDING_CAP}
|
||||
target="_blank"
|
||||
marginBottom={2}
|
||||
>
|
||||
{t('learnMoreUpperCase')}
|
||||
</ButtonLink>
|
||||
</Box>
|
||||
</label>
|
||||
</Box>
|
||||
@ -345,4 +361,12 @@ CustomSpendingCap.propTypes = {
|
||||
* Updating input state to changing
|
||||
*/
|
||||
setInputChangeInProgress: PropTypes.func.isRequired,
|
||||
/**
|
||||
* Custom token amount or The dapp suggested amount
|
||||
*/
|
||||
customSpendingCap: PropTypes.string,
|
||||
/**
|
||||
* State method to update the custom token value
|
||||
*/
|
||||
setCustomSpendingCap: PropTypes.func.isRequired,
|
||||
};
|
||||
|
@ -23,6 +23,9 @@ export default {
|
||||
decimals: {
|
||||
control: 'text',
|
||||
},
|
||||
customSpendingCap: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
},
|
||||
args: {
|
||||
tokenName: 'DAI',
|
||||
@ -30,6 +33,7 @@ export default {
|
||||
dappProposedValue: '7',
|
||||
siteOrigin: 'Uniswap.org',
|
||||
decimals: '4',
|
||||
customSpendingCap: '7',
|
||||
},
|
||||
};
|
||||
|
||||
@ -38,3 +42,13 @@ export const DefaultStory = (args) => {
|
||||
};
|
||||
|
||||
DefaultStory.storyName = 'Default';
|
||||
|
||||
export const CustomSpendingCapStory = (args) => {
|
||||
return <CustomSpendingCap {...args} />;
|
||||
};
|
||||
CustomSpendingCapStory.storyName = 'CustomSpendingCapStory';
|
||||
|
||||
CustomSpendingCapStory.args = {
|
||||
...DefaultStory.args,
|
||||
customSpendingCap: '8',
|
||||
};
|
||||
|
@ -26,6 +26,8 @@ const props = {
|
||||
decimals: '4',
|
||||
passTheErrorText: () => undefined,
|
||||
setInputChangeInProgress: () => undefined,
|
||||
customSpendingCap: '7',
|
||||
setCustomSpendingCap: () => undefined,
|
||||
};
|
||||
|
||||
describe('CustomSpendingCap', () => {
|
||||
|
@ -63,7 +63,7 @@ export default function ReviewSpendingCap({
|
||||
as="h6"
|
||||
display={DISPLAY.INLINE_BLOCK}
|
||||
>
|
||||
{t('customSpendingCap')}
|
||||
{t('dappRequestedSpendingCap')}
|
||||
</Text>
|
||||
<Box marginLeft={2} display={DISPLAY.INLINE_BLOCK}>
|
||||
<Tooltip
|
||||
|
@ -28,6 +28,8 @@ const ZENDESK_URLS = {
|
||||
'https://metamask.zendesk.com/hc/en-us/articles/360059952212-MetaMask-is-a-non-custodial-wallet',
|
||||
SPEEDUP_CANCEL:
|
||||
'https://metamask.zendesk.com/hc/en-us/articles/360015489251-How-to-speed-up-or-cancel-a-pending-transaction',
|
||||
TOKEN_ALLOWANCE_WITH_SPENDING_CAP:
|
||||
'https://support.metamask.io/hc/en-us/articles/6055177143579-How-to-customize-token-approvals-with-a-spending-cap',
|
||||
TOKEN_SAFETY_PRACTICES:
|
||||
'https://metamask.zendesk.com/hc/en-us/articles/4403988839451',
|
||||
UNKNOWN_NETWORK:
|
||||
|
@ -0,0 +1,489 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TokenAllowancePage should match snapshot 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="box token-allowance-container page-container box--flex-direction-row"
|
||||
>
|
||||
<div
|
||||
class="box box--flex-direction-row"
|
||||
>
|
||||
<div
|
||||
class="confirm-page-container-navigation"
|
||||
style="display: none;"
|
||||
>
|
||||
<div
|
||||
class="confirm-page-container-navigation__container"
|
||||
data-testid="navigation-container"
|
||||
style="visibility: hidden;"
|
||||
>
|
||||
<button
|
||||
class="confirm-page-container-navigation__arrow"
|
||||
data-testid="first-page"
|
||||
>
|
||||
<i
|
||||
class="fa fa-angle-double-left fa-2x"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
class="confirm-page-container-navigation__arrow"
|
||||
data-testid="previous-page"
|
||||
>
|
||||
<i
|
||||
class="fa fa-angle-left fa-2x"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="confirm-page-container-navigation__textcontainer"
|
||||
>
|
||||
<div
|
||||
class="confirm-page-container-navigation__navtext"
|
||||
>
|
||||
0
|
||||
|
||||
of
|
||||
|
||||
0
|
||||
</div>
|
||||
<div
|
||||
class="confirm-page-container-navigation__longtext"
|
||||
>
|
||||
requests waiting to be acknowledged
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="confirm-page-container-navigation__container"
|
||||
style="visibility: hidden;"
|
||||
>
|
||||
<button
|
||||
class="confirm-page-container-navigation__arrow"
|
||||
data-testid="next-page"
|
||||
>
|
||||
<i
|
||||
class="fa fa-angle-right fa-2x"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
class="confirm-page-container-navigation__arrow"
|
||||
data-testid="last-page"
|
||||
>
|
||||
<i
|
||||
class="fa fa-angle-double-right fa-2x"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="box box--padding-right-4 box--padding-left-4 box--display-flex box--flex-direction-row box--justify-content-space-between box--align-items-center"
|
||||
>
|
||||
<div
|
||||
class="box box--flex-direction-row"
|
||||
/>
|
||||
<div
|
||||
class="box box--flex-direction-row box--text-align-end"
|
||||
>
|
||||
<h6
|
||||
class="box mm-text mm-text--body-sm mm-text--font-weight-bold box--flex-direction-row box--color-text-muted"
|
||||
>
|
||||
1
|
||||
|
||||
of
|
||||
2
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="box network-account-balance-header box--padding-4 box--display-flex box--flex-direction-row box--justify-content-space-between box--align-items-center"
|
||||
>
|
||||
<div
|
||||
class="box box--display-flex box--gap-2 box--flex-direction-row box--align-items-center"
|
||||
>
|
||||
<div
|
||||
class="box box--display-flex box--flex-direction-row box--align-items-center"
|
||||
>
|
||||
<div
|
||||
class=""
|
||||
>
|
||||
<div
|
||||
class="identicon"
|
||||
style="height: 32px; width: 32px; border-radius: 16px;"
|
||||
>
|
||||
<div
|
||||
style="border-radius: 50px; overflow: hidden; padding: 0px; margin: 0px; width: 32px; height: 32px; display: inline-block; background: rgb(250, 58, 0);"
|
||||
>
|
||||
<svg
|
||||
height="32"
|
||||
width="32"
|
||||
x="0"
|
||||
y="0"
|
||||
>
|
||||
<rect
|
||||
fill="#18CDF2"
|
||||
height="32"
|
||||
transform="translate(-1.04839350379394 -3.3042840694604987) rotate(328.9 16 16)"
|
||||
width="32"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
<rect
|
||||
fill="#035E56"
|
||||
height="32"
|
||||
transform="translate(-18.298461708832043 10.5924618717486) rotate(176.2 16 16)"
|
||||
width="32"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
<rect
|
||||
fill="#F26602"
|
||||
height="32"
|
||||
transform="translate(16.667842018223922 -14.205139722997082) rotate(468.9 16 16)"
|
||||
width="32"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="network-account-balance-header__network-account__ident-icon-ethereum--gray"
|
||||
>
|
||||
<span
|
||||
class="icon-with-fallback__fallback"
|
||||
>
|
||||
M
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="box box--display-flex box--flex-direction-column box--align-items-flex-start"
|
||||
>
|
||||
<h6
|
||||
class="box mm-text mm-text--body-sm box--flex-direction-row box--color-text-alternative"
|
||||
>
|
||||
mainnet
|
||||
</h6>
|
||||
<h6
|
||||
class="box mm-text mm-text--body-sm mm-text--font-weight-bold box--flex-direction-row box--color-text-default"
|
||||
>
|
||||
Account 1
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="box box--display-flex box--flex-direction-column box--align-items-flex-end"
|
||||
>
|
||||
<h6
|
||||
class="box mm-text mm-text--body-sm box--flex-direction-row box--color-text-alternative"
|
||||
>
|
||||
Balance
|
||||
</h6>
|
||||
<h6
|
||||
align="end"
|
||||
class="box mm-text mm-text--body-sm mm-text--font-weight-bold box--flex-direction-row box--color-text-default"
|
||||
>
|
||||
10
|
||||
|
||||
TST
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="box box--display-flex box--flex-direction-row box--justify-content-center"
|
||||
>
|
||||
<div
|
||||
class="box token-allowance-container__icon-display-content box--margin-top-6 box--margin-right-12 box--margin-bottom-8 box--margin-left-12 box--padding-top-2 box--padding-right-4 box--padding-bottom-2 box--padding-left-2 box--display-flex box--flex-direction-row box--align-items-center box--border-style-solid box--border-color-border-muted box--border-width-1"
|
||||
>
|
||||
<div
|
||||
class=""
|
||||
>
|
||||
<img
|
||||
alt="https://metamask.github.io"
|
||||
class="url-icon token-allowance-container__icon-display-content__siteimage-identicon"
|
||||
src="https://metamask.github.io/test-dapp/metamask-fox.svg"
|
||||
/>
|
||||
</div>
|
||||
<h6
|
||||
class="box mm-text mm-text--body-sm box--margin-left-1 box--flex-direction-row box--color-text-alternative"
|
||||
>
|
||||
https://metamask.github.io
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="box box--margin-right-4 box--margin-left-4 box--flex-direction-row"
|
||||
>
|
||||
<h3
|
||||
align="center"
|
||||
class="box mm-text mm-text--heading-md box--flex-direction-row box--color-text-default"
|
||||
>
|
||||
<span>
|
||||
|
||||
Spending cap request for your
|
||||
<div
|
||||
class="box box--margin-top-4 box--flex-direction-row"
|
||||
>
|
||||
<div
|
||||
class="box contract-token-values box--display-flex box--gap-2 box--flex-direction-row box--justify-content-center box--align-items-center"
|
||||
>
|
||||
<div
|
||||
class=""
|
||||
>
|
||||
<div
|
||||
class="identicon"
|
||||
style="height: 24px; width: 24px; border-radius: 12px;"
|
||||
>
|
||||
<div
|
||||
style="border-radius: 50px; overflow: hidden; padding: 0px; margin: 0px; width: 24px; height: 24px; display: inline-block; background: rgb(242, 206, 2);"
|
||||
>
|
||||
<svg
|
||||
height="24"
|
||||
width="24"
|
||||
x="0"
|
||||
y="0"
|
||||
>
|
||||
<rect
|
||||
fill="#186FF2"
|
||||
height="24"
|
||||
transform="translate(4.5535541527659795 -0.012406777909352561) rotate(501.9 12 12)"
|
||||
width="24"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
<rect
|
||||
fill="#F97101"
|
||||
height="24"
|
||||
transform="translate(-10.003810991077078 6.326210026231173) rotate(323.7 12 12)"
|
||||
width="24"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
<rect
|
||||
fill="#FB1832"
|
||||
height="24"
|
||||
transform="translate(-22.151479903389234 -4.322407331572157) rotate(370.5 12 12)"
|
||||
width="24"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2
|
||||
class="box box--flex-direction-row typography typography--h2 typography--weight-bold typography--style-normal typography--color-text-alternative"
|
||||
>
|
||||
TST
|
||||
</h2>
|
||||
<div>
|
||||
<div
|
||||
aria-describedby="tippy-tooltip-1"
|
||||
class=""
|
||||
data-original-title="Copy to clipboard"
|
||||
data-tooltipped=""
|
||||
style="display: inline;"
|
||||
tabindex="0"
|
||||
>
|
||||
<button
|
||||
aria-label="Copy to clipboard"
|
||||
class="box mm-button-icon mm-button-icon--size-lg box--display-inline-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-icon-muted box--background-color-transparent box--rounded-lg"
|
||||
>
|
||||
<span
|
||||
class="box mm-icon mm-icon--size-lg box--display-inline-block box--flex-direction-row box--color-inherit"
|
||||
style="mask-image: url('./images/icons/copy.svg');"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
aria-describedby="tippy-tooltip-2"
|
||||
class=""
|
||||
data-original-title="Open in block explorer"
|
||||
data-tooltipped=""
|
||||
style="display: inline;"
|
||||
tabindex="0"
|
||||
>
|
||||
<button
|
||||
aria-label="Open in block explorer"
|
||||
class="box mm-button-icon mm-button-icon--size-lg box--display-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-icon-muted box--background-color-transparent box--rounded-lg"
|
||||
>
|
||||
<span
|
||||
class="box mm-icon mm-icon--size-lg box--display-inline-block box--flex-direction-row box--color-inherit"
|
||||
style="mask-image: url('./images/icons/export.svg');"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</span>
|
||||
</h3>
|
||||
</div>
|
||||
<div
|
||||
class="box box--margin-top-1 box--display-flex box--flex-direction-row box--justify-content-center"
|
||||
>
|
||||
<a
|
||||
class="button btn-link token-allowance-container__verify-link"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<h6
|
||||
class="box mm-text mm-text--body-sm box--flex-direction-row box--color-primary-default"
|
||||
>
|
||||
Verify third-party details
|
||||
</h6>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
class="box box--margin-4 box--sm:margin-4 box--md:margin-3 box--lg:margin-4 box--flex-direction-row"
|
||||
>
|
||||
<div
|
||||
class="box custom-spending-cap box--padding-top-2 box--padding-right-6 box--padding-left-6 box--display-flex box--gap-2 box--flex-direction-column box--align-items-flex-start box--background-color-background-alternative box--rounded-sm"
|
||||
>
|
||||
<div
|
||||
class="box custom-spending-cap__input box--display-block box--flex-direction-row box--justify-content-center"
|
||||
>
|
||||
<label
|
||||
for="custom-spending-cap"
|
||||
>
|
||||
<div
|
||||
class="form-field"
|
||||
>
|
||||
<div
|
||||
class="mm-box"
|
||||
>
|
||||
<div
|
||||
class="form-field__heading"
|
||||
>
|
||||
<div
|
||||
class="mm-box form-field__heading-title mm-box--display-flex mm-box--align-items-baseline"
|
||||
>
|
||||
<h6
|
||||
class="box mm-text mm-text--body-sm-bold box--display-inline-block box--flex-direction-row box--color-text-default"
|
||||
for="custom-spending-cap"
|
||||
tag="label"
|
||||
>
|
||||
Custom spending cap
|
||||
</h6>
|
||||
|
||||
<div
|
||||
class="box box--display-inline-block box--flex-direction-row"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
aria-describedby="tippy-tooltip-3"
|
||||
class=""
|
||||
data-original-title="null"
|
||||
data-tooltipped=""
|
||||
style="display: inline;"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="box mm-icon mm-icon--size-inherit box--display-inline-block box--flex-direction-row box--color-inherit"
|
||||
style="mask-image: url('./images/icons/question.svg');"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
class="form-field__input"
|
||||
data-testid="custom-spending-cap-input"
|
||||
id="custom-spending-cap"
|
||||
placeholder="Enter a number"
|
||||
type="text"
|
||||
value="7"
|
||||
/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="box custom-spending-cap__max box--margin-left-auto box--padding-right-4 box--padding-bottom-2 box--flex-direction-row box--text-align-end box--width-max"
|
||||
>
|
||||
<button
|
||||
class="box mm-text mm-button-base mm-button-link mm-button-link--size-auto mm-text--body-md box--display-inline-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-primary-default box--background-color-transparent"
|
||||
>
|
||||
Max
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="box custom-spending-cap__description box--flex-direction-row"
|
||||
>
|
||||
<h6
|
||||
class="box mm-text mm-text--body-sm box--padding-top-2 box--flex-direction-row box--color-text-default"
|
||||
>
|
||||
<span>
|
||||
|
||||
This allows the third party to spend
|
||||
<h6
|
||||
class="box mm-text custom-spending-cap__input-value-and-token-name mm-text--body-sm-bold box--flex-direction-row box--color-text-default"
|
||||
>
|
||||
7
|
||||
|
||||
TST
|
||||
</h6>
|
||||
from your current balance.
|
||||
|
||||
</span>
|
||||
</h6>
|
||||
<a
|
||||
class="box mm-text mm-button-base mm-button-base--size-sm mm-button-link mm-text--body-md box--margin-bottom-2 box--display-inline-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-primary-default box--background-color-transparent"
|
||||
href="https://support.metamask.io/hc/en-us/articles/6055177143579-How-to-customize-token-approvals-with-a-spending-cap"
|
||||
target="_blank"
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="box box--display-flex box--flex-direction-row box--justify-content-center"
|
||||
>
|
||||
<a
|
||||
class="button btn-link token-allowance-container__view-details"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<h6
|
||||
class="box mm-text mm-text--body-sm box--margin-right-1 box--flex-direction-row box--color-primary-default"
|
||||
>
|
||||
View details
|
||||
</h6>
|
||||
<i
|
||||
class="fa fa-sm fa-angle-down"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
class="page-container__footer"
|
||||
>
|
||||
<footer>
|
||||
<button
|
||||
class="button btn--rounded btn-secondary page-container__footer-button page-container__footer-button__cancel"
|
||||
data-testid="page-container-footer-cancel"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Reject
|
||||
</button>
|
||||
<button
|
||||
class="button btn--rounded btn-primary page-container__footer-button"
|
||||
data-testid="page-container-footer-next"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -29,7 +29,6 @@ import {
|
||||
transactionFeeSelector,
|
||||
getKnownMethodData,
|
||||
getRpcPrefsForCurrentProvider,
|
||||
getCustomTokenAmount,
|
||||
getUnapprovedTxCount,
|
||||
getUnapprovedTransactions,
|
||||
getUseCurrencyRateCheck,
|
||||
@ -101,6 +100,9 @@ export default function TokenAllowance({
|
||||
const { hostname } = new URL(origin);
|
||||
const thisOriginIsAllowedToSkipFirstPage = ALLOWED_HOSTS.includes(hostname);
|
||||
|
||||
const [customSpendingCap, setCustomSpendingCap] = useState(
|
||||
dappProposedTokenAmount,
|
||||
);
|
||||
const [showContractDetails, setShowContractDetails] = useState(false);
|
||||
const [inputChangeInProgress, setInputChangeInProgress] = useState(false);
|
||||
const [showFullTxDetails, setShowFullTxDetails] = useState(false);
|
||||
@ -122,24 +124,20 @@ export default function TokenAllowance({
|
||||
const unapprovedTxCount = useSelector(getUnapprovedTxCount);
|
||||
const unapprovedTxs = useSelector(getUnapprovedTransactions);
|
||||
const useCurrencyRateCheck = useSelector(getUseCurrencyRateCheck);
|
||||
let customTokenAmount = useSelector(getCustomTokenAmount);
|
||||
if (thisOriginIsAllowedToSkipFirstPage && dappProposedTokenAmount) {
|
||||
customTokenAmount = dappProposedTokenAmount;
|
||||
}
|
||||
|
||||
const replaceCommaToDot = (inputValue) => {
|
||||
return inputValue.replace(/,/gu, '.');
|
||||
};
|
||||
|
||||
let customPermissionAmount = NUM_W_OPT_DECIMAL_COMMA_OR_DOT_REGEX.test(
|
||||
customTokenAmount,
|
||||
customSpendingCap,
|
||||
)
|
||||
? replaceCommaToDot(customTokenAmount).toString()
|
||||
? replaceCommaToDot(customSpendingCap).toString()
|
||||
: '0';
|
||||
|
||||
const maxTokenAmount = calcTokenAmount(MAX_TOKEN_ALLOWANCE_AMOUNT, decimals);
|
||||
if (customTokenAmount.length > 1 && Number(customTokenAmount)) {
|
||||
const customSpendLimitNumber = new BigNumber(customTokenAmount);
|
||||
if (customSpendingCap.length > 1 && Number(customSpendingCap)) {
|
||||
const customSpendLimitNumber = new BigNumber(customSpendingCap);
|
||||
if (customSpendLimitNumber.greaterThan(maxTokenAmount)) {
|
||||
customPermissionAmount = 0;
|
||||
}
|
||||
@ -170,7 +168,7 @@ export default function TokenAllowance({
|
||||
const { balanceError } = useGasFeeContext();
|
||||
|
||||
const disableNextButton =
|
||||
isFirstPage && (customTokenAmount === '' || errorText !== '');
|
||||
isFirstPage && (customSpendingCap === '' || errorText !== '');
|
||||
|
||||
const disableApproveButton = !isFirstPage && balanceError;
|
||||
|
||||
@ -212,9 +210,9 @@ export default function TokenAllowance({
|
||||
fullTxData.originalApprovalAmount = dappProposedTokenAmount;
|
||||
}
|
||||
|
||||
if (customTokenAmount) {
|
||||
fullTxData.customTokenAmount = customTokenAmount;
|
||||
fullTxData.finalApprovalAmount = customTokenAmount;
|
||||
if (customSpendingCap) {
|
||||
fullTxData.customTokenAmount = customSpendingCap;
|
||||
fullTxData.finalApprovalAmount = customSpendingCap;
|
||||
} else if (dappProposedTokenAmount !== undefined) {
|
||||
fullTxData.finalApprovalAmount = dappProposedTokenAmount;
|
||||
}
|
||||
@ -255,7 +253,7 @@ export default function TokenAllowance({
|
||||
);
|
||||
};
|
||||
|
||||
const isEmpty = customTokenAmount === '';
|
||||
const isEmpty = customSpendingCap === '';
|
||||
|
||||
const renderContractTokenValues = (
|
||||
<Box marginTop={4} key={tokenAddress}>
|
||||
@ -359,17 +357,12 @@ export default function TokenAllowance({
|
||||
<Box marginLeft={4} marginRight={4}>
|
||||
<Text variant={TextVariant.headingMd} align={TextAlign.Center}>
|
||||
{isFirstPage ? (
|
||||
t('setSpendingCap', [renderContractTokenValues])
|
||||
t('spendingCapRequest', [renderContractTokenValues])
|
||||
) : (
|
||||
<Box>
|
||||
{customTokenAmount === '0' || isEmpty ? (
|
||||
t('revokeSpendingCap', [renderContractTokenValues])
|
||||
) : (
|
||||
<Box>
|
||||
{t('reviewSpendingCap')}
|
||||
{renderContractTokenValues}
|
||||
</Box>
|
||||
)}
|
||||
{customSpendingCap === '0' || isEmpty
|
||||
? t('revokeSpendingCap', [renderContractTokenValues])
|
||||
: t('spendingCapRequest', [renderContractTokenValues])}
|
||||
</Box>
|
||||
)}
|
||||
</Text>
|
||||
@ -405,15 +398,17 @@ export default function TokenAllowance({
|
||||
passTheErrorText={(value) => setErrorText(value)}
|
||||
decimals={decimals}
|
||||
setInputChangeInProgress={setInputChangeInProgress}
|
||||
customSpendingCap={customSpendingCap}
|
||||
setCustomSpendingCap={setCustomSpendingCap}
|
||||
/>
|
||||
) : (
|
||||
<ReviewSpendingCap
|
||||
tokenName={tokenSymbol}
|
||||
currentTokenBalance={currentTokenBalance}
|
||||
tokenValue={
|
||||
isNaN(parseFloat(customTokenAmount))
|
||||
isNaN(parseFloat(customSpendingCap))
|
||||
? dappProposedTokenAmount
|
||||
: replaceCommaToDot(customTokenAmount)
|
||||
: replaceCommaToDot(customSpendingCap)
|
||||
}
|
||||
onEdit={() => handleBackClick()}
|
||||
/>
|
||||
|
@ -187,12 +187,20 @@ describe('TokenAllowancePage', () => {
|
||||
store = configureMockStore()(state);
|
||||
});
|
||||
|
||||
it('should render title "Set a spending cap for your" in token allowance page', () => {
|
||||
it('should match snapshot', () => {
|
||||
const { container } = renderWithProvider(
|
||||
<TokenAllowance {...props} />,
|
||||
store,
|
||||
);
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render title "Spending cap request for your" in token allowance page', () => {
|
||||
const { getByText } = renderWithProvider(
|
||||
<TokenAllowance {...props} />,
|
||||
store,
|
||||
);
|
||||
expect(getByText('Set a spending cap for your')).toBeInTheDocument();
|
||||
expect(getByText('Spending cap request for your')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render reject button', () => {
|
||||
@ -215,37 +223,55 @@ describe('TokenAllowancePage', () => {
|
||||
expect(getByText('Function: Approve')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should click Use default and set input value to default', () => {
|
||||
const { getByText, getByTestId } = renderWithProvider(
|
||||
it('should load the page with dappProposedAmount prefilled and "Use site suggestion" should not be displayed', () => {
|
||||
const { queryByText, getByTestId } = renderWithProvider(
|
||||
<TokenAllowance {...props} />,
|
||||
store,
|
||||
);
|
||||
|
||||
act(() => {
|
||||
const useDefault = getByText('Use default');
|
||||
fireEvent.click(useDefault);
|
||||
const useSiteSuggestion = queryByText('Use site suggestion');
|
||||
expect(useSiteSuggestion).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
const input = getByTestId('custom-spending-cap-input');
|
||||
expect(input.value).toBe('1');
|
||||
expect(input.value).toBe('7');
|
||||
});
|
||||
|
||||
it('should call back button when button is clicked and return to previous page', () => {
|
||||
it('should click Use site suggestion and set input value to default', () => {
|
||||
const { getByText, getByTestId } = renderWithProvider(
|
||||
<TokenAllowance {...props} />,
|
||||
store,
|
||||
);
|
||||
|
||||
const textField = getByTestId('custom-spending-cap-input');
|
||||
expect(textField.value).toBe('7');
|
||||
fireEvent.change(textField, { target: { value: '1' } });
|
||||
expect(textField.value).toBe('1');
|
||||
|
||||
act(() => {
|
||||
const useSiteSuggestion = getByText('Use site suggestion');
|
||||
expect(useSiteSuggestion).toBeInTheDocument();
|
||||
fireEvent.click(useSiteSuggestion);
|
||||
});
|
||||
|
||||
expect(textField.value).toBe('7');
|
||||
});
|
||||
|
||||
it('should call back button when button is clicked and return to previous page', () => {
|
||||
const { getByText } = renderWithProvider(
|
||||
<TokenAllowance {...props} />,
|
||||
store,
|
||||
);
|
||||
|
||||
const nextButton = getByText('Next');
|
||||
fireEvent.click(nextButton);
|
||||
|
||||
expect(getByText('Site requested spending cap')).toBeInTheDocument();
|
||||
|
||||
const backButton = getByText('< Back');
|
||||
fireEvent.click(backButton);
|
||||
|
||||
expect(getByText('Set a spending cap for your')).toBeInTheDocument();
|
||||
expect(getByText('Spending cap request for your')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should click Verify third-party details and show popup Third-party details, then close popup', () => {
|
||||
@ -265,14 +291,11 @@ describe('TokenAllowancePage', () => {
|
||||
});
|
||||
|
||||
it('should show ledger info text if the sending address is ledger', () => {
|
||||
const { queryByText, getByText, getByTestId } = renderWithProvider(
|
||||
const { queryByText, getByText } = renderWithProvider(
|
||||
<TokenAllowance {...props} fromAddressIsLedger />,
|
||||
store,
|
||||
);
|
||||
|
||||
const textField = getByTestId('custom-spending-cap-input');
|
||||
fireEvent.change(textField, { target: { value: '1' } });
|
||||
|
||||
expect(queryByText('Prior to clicking confirm:')).toBeNull();
|
||||
|
||||
const nextButton = getByText('Next');
|
||||
@ -282,14 +305,11 @@ describe('TokenAllowancePage', () => {
|
||||
});
|
||||
|
||||
it('should not show ledger info text if the sending address is not ledger', () => {
|
||||
const { queryByText, getByText, getByTestId } = renderWithProvider(
|
||||
const { queryByText, getByText } = renderWithProvider(
|
||||
<TokenAllowance {...props} fromAddressIsLedger={false} />,
|
||||
store,
|
||||
);
|
||||
|
||||
const textField = getByTestId('custom-spending-cap-input');
|
||||
fireEvent.change(textField, { target: { value: '1' } });
|
||||
|
||||
expect(queryByText('Prior to clicking confirm:')).toBeNull();
|
||||
|
||||
const nextButton = getByText('Next');
|
||||
|
Loading…
Reference in New Issue
Block a user