mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-22 01:13:22 +01:00
feat(878): implement network txn toggle and new style (#20363)
* feat(878): implement new incoming transaction toggle networks for setting and onboarding * Update state snapshots * feat(878): change gaps, migration types based on comment --------- Co-authored-by: Mark Stacey <markjstacey@gmail.com>
This commit is contained in:
parent
a478f675f1
commit
00d155ce2f
@ -239,6 +239,7 @@ module.exports = {
|
||||
'app/scripts/controllers/app-state.test.js',
|
||||
'app/scripts/controllers/mmi-controller.test.js',
|
||||
'app/scripts/controllers/permissions/**/*.test.js',
|
||||
'app/scripts/controllers/preferences.test.js',
|
||||
'app/scripts/lib/**/*.test.js',
|
||||
'app/scripts/migrations/*.test.js',
|
||||
'app/scripts/platforms/*.test.js',
|
||||
@ -268,6 +269,7 @@ module.exports = {
|
||||
'app/scripts/controllers/app-state.test.js',
|
||||
'app/scripts/controllers/mmi-controller.test.js',
|
||||
'app/scripts/controllers/permissions/**/*.test.js',
|
||||
'app/scripts/controllers/preferences.test.js',
|
||||
'app/scripts/lib/**/*.test.js',
|
||||
'app/scripts/migrations/*.test.js',
|
||||
'app/scripts/platforms/*.test.js',
|
||||
|
@ -8,6 +8,7 @@ module.exports = {
|
||||
'./app/scripts/controllers/app-state.test.js',
|
||||
'./app/scripts/controllers/permissions/**/*.test.js',
|
||||
'./app/scripts/controllers/mmi-controller.test.js',
|
||||
'./app/scripts/controllers/preferences.test.js',
|
||||
'./app/scripts/constants/error-utils.test.js',
|
||||
'./development/fitness-functions/**/*.test.ts',
|
||||
'./test/e2e/helpers.test.js',
|
||||
|
@ -2,6 +2,7 @@ import { draftTransactionInitialState } from '../ui/ducks/send';
|
||||
import { KeyringType } from '../shared/constants/keyring';
|
||||
import { NetworkType } from '@metamask/controller-utils';
|
||||
import { NetworkStatus } from '@metamask/network-controller';
|
||||
import { CHAIN_IDS } from '../shared/constants/network';
|
||||
|
||||
const state = {
|
||||
invalidCustomNetwork: {
|
||||
@ -529,6 +530,12 @@ const state = {
|
||||
preferences: {
|
||||
useNativeCurrencyAsPrimaryCurrency: true,
|
||||
},
|
||||
incomingTransactionsPreferences: {
|
||||
[CHAIN_IDS.MAINNET]: true,
|
||||
[CHAIN_IDS.GOERLI]: false,
|
||||
[CHAIN_IDS.OPTIMISM_TESTNET]: false,
|
||||
[CHAIN_IDS.AVALANCHE_TESTNET]: true,
|
||||
},
|
||||
firstTimeFlowType: 'create',
|
||||
completedOnboarding: true,
|
||||
knownMethodData: {
|
||||
|
4
app/_locales/de/messages.json
generated
4
app/_locales/de/messages.json
generated
@ -3019,10 +3019,6 @@
|
||||
"onboardingPinExtensionTitle": {
|
||||
"message": "Ihre MetaMask Installation ist abgeschlossen!"
|
||||
},
|
||||
"onboardingShowIncomingTransactionsDescription": {
|
||||
"message": "Die Anzeige der eingehenden Transaktionen in Ihrer Wallet beruht auf der Kommunikation mit $1. Etherscan hat Zugriff auf Ihre Ethereum-Adresse und Ihre IP-Adresse. $2 anzeigen.",
|
||||
"description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key."
|
||||
},
|
||||
"onboardingUsePhishingDetectionDescription": {
|
||||
"message": "Phishing-Warnungen basieren auf der Kommunikation mit $1. jsDeliver hat Zugriff auf Ihre IP-Adresse. $2 ansehen.",
|
||||
"description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link"
|
||||
|
4
app/_locales/el/messages.json
generated
4
app/_locales/el/messages.json
generated
@ -3019,10 +3019,6 @@
|
||||
"onboardingPinExtensionTitle": {
|
||||
"message": "Η εγκατάσταση του MetaMask ολοκληρώθηκε!"
|
||||
},
|
||||
"onboardingShowIncomingTransactionsDescription": {
|
||||
"message": "Η εμφάνιση των εισερχόμενων συναλλαγών στο πορτοφόλι σας βασίζεται σε επικοινωνία με το $1. Το Etherscan θα έχει πρόσβαση στη διεύθυνση Ethereum σας και τη διεύθυνση IP σας. Δείτε $2.",
|
||||
"description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key."
|
||||
},
|
||||
"onboardingUsePhishingDetectionDescription": {
|
||||
"message": "Οι ειδοποιήσεις ανίχνευσης Απάτης Ηλεκτρονικού Ψαρέματος βασίζονται στην επικοινωνία με το $1. Το jsDeliver θα έχει πρόσβαση στη διεύθυνση IP σας. Δείτε $2.",
|
||||
"description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link"
|
||||
|
4
app/_locales/en/messages.json
generated
4
app/_locales/en/messages.json
generated
@ -3022,10 +3022,6 @@
|
||||
"onboardingPinExtensionTitle": {
|
||||
"message": "Your MetaMask install is complete!"
|
||||
},
|
||||
"onboardingShowIncomingTransactionsDescription": {
|
||||
"message": "Showing incoming transactions in your wallet relies on communication with $1. Etherscan will have access to your Ethereum address and your IP address. View $2.",
|
||||
"description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key."
|
||||
},
|
||||
"onboardingUsePhishingDetectionDescription": {
|
||||
"message": "Phishing detection alerts rely on communication with $1. jsDeliver will have access to your IP address. View $2.",
|
||||
"description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link"
|
||||
|
4
app/_locales/es/messages.json
generated
4
app/_locales/es/messages.json
generated
@ -3019,10 +3019,6 @@
|
||||
"onboardingPinExtensionTitle": {
|
||||
"message": "¡Su instalación de MetaMask ha finalizado!"
|
||||
},
|
||||
"onboardingShowIncomingTransactionsDescription": {
|
||||
"message": "Mostrar las transacciones entrantes en su cartera depende de la comunicación con $1. Etherscan tendrá acceso a su dirección de Ethereum y a su dirección IP. Ver 2$.",
|
||||
"description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key."
|
||||
},
|
||||
"onboardingUsePhishingDetectionDescription": {
|
||||
"message": "Las alertas de detección de phishing se basan en la comunicación con $1. jsDeliver tendrá acceso a su dirección IP. Ver 2$.",
|
||||
"description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link"
|
||||
|
8
app/_locales/es_419/messages.json
generated
8
app/_locales/es_419/messages.json
generated
@ -1623,14 +1623,6 @@
|
||||
"onboardingPinExtensionTitle": {
|
||||
"message": "¡Su instalación de MetaMask ha finalizado!"
|
||||
},
|
||||
"onboardingShowIncomingTransactionsDescription": {
|
||||
"message": "Mostrar las transacciones entrantes en su cartera depende de la comunicación con $1. Etherscan tendrá acceso a su dirección de Ethereum y a su dirección IP. Ver $2.",
|
||||
"description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key."
|
||||
},
|
||||
"onboardingUsePhishingDetectionDescription": {
|
||||
"message": "Las alertas de detección de phishing se basan en la comunicación con $1. jsDeliver tendrá acceso a su dirección IP. Ver $2.",
|
||||
"description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link"
|
||||
},
|
||||
"onlyAddTrustedNetworks": {
|
||||
"message": "Un proveedor de red malintencionado puede mentir sobre el estado de la cadena de bloques y registrar su actividad de red. Agregue solo redes personalizadas de confianza."
|
||||
},
|
||||
|
4
app/_locales/fr/messages.json
generated
4
app/_locales/fr/messages.json
generated
@ -3019,10 +3019,6 @@
|
||||
"onboardingPinExtensionTitle": {
|
||||
"message": "Votre installation de MetaMask est terminée !"
|
||||
},
|
||||
"onboardingShowIncomingTransactionsDescription": {
|
||||
"message": "L’affichage des transactions entrantes dans votre portefeuille repose sur la communication avec $1. Etherscan aura accès à votre adresse Ethereum et à votre adresse IP. Voir $2.",
|
||||
"description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key."
|
||||
},
|
||||
"onboardingUsePhishingDetectionDescription": {
|
||||
"message": "Les alertes de détection d’hameçonnage reposent sur la communication avec $1. jsDeliver aura accès à votre adresse IP. Voir $2.",
|
||||
"description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link"
|
||||
|
4
app/_locales/hi/messages.json
generated
4
app/_locales/hi/messages.json
generated
@ -3019,10 +3019,6 @@
|
||||
"onboardingPinExtensionTitle": {
|
||||
"message": "आपका MetaMask इंस्टॉल पूरा हो गया है!"
|
||||
},
|
||||
"onboardingShowIncomingTransactionsDescription": {
|
||||
"message": "आपके वॉलेट में आने वाले लेन-देन को दिखाना $1 के साथ संचार पर निर्भर करता है। Etherscan की पहुंच आपके Ethereum और आपके IP पते तक होगी। $2 देखें।",
|
||||
"description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key."
|
||||
},
|
||||
"onboardingUsePhishingDetectionDescription": {
|
||||
"message": "फिशिंग डिटेक्शन अलर्ट $1 के साथ संचार पर निर्भर करते हैं। jsDeliver की पहुंच आपके IP पते तक होगी। $2 देखें।",
|
||||
"description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link"
|
||||
|
4
app/_locales/id/messages.json
generated
4
app/_locales/id/messages.json
generated
@ -3019,10 +3019,6 @@
|
||||
"onboardingPinExtensionTitle": {
|
||||
"message": "Pemasangan MetaMask Anda selesai!"
|
||||
},
|
||||
"onboardingShowIncomingTransactionsDescription": {
|
||||
"message": "Menampilkan transaksi masuk di dompet Anda bergantung pada komunikasi dengan $1. Etherscan akan mendapat akses ke alamat Ethereum dan alamat IP Anda. Lihat $2.",
|
||||
"description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key."
|
||||
},
|
||||
"onboardingUsePhishingDetectionDescription": {
|
||||
"message": "Peringatan deteksi pengelabuan bergantung pada komunikasi dengan $1. jsDeliver akan mendapat akses ke alamat IP Anda. Lihat $2.",
|
||||
"description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link"
|
||||
|
4
app/_locales/ja/messages.json
generated
4
app/_locales/ja/messages.json
generated
@ -3019,10 +3019,6 @@
|
||||
"onboardingPinExtensionTitle": {
|
||||
"message": "MetaMaskのインストールが完了しました!"
|
||||
},
|
||||
"onboardingShowIncomingTransactionsDescription": {
|
||||
"message": "ウォレットに受け取ったトランザクションを表示するには、$1との通信が必要です。EtherscanはユーザーのイーサリアムアドレスとIPアドレスにアクセスできます。$2をご覧ください。",
|
||||
"description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key."
|
||||
},
|
||||
"onboardingUsePhishingDetectionDescription": {
|
||||
"message": "フィッシング検出アラートには$1との通信が必要です。jsDeliverはユーザーのIPアドレスにアクセスします。$2をご覧ください。",
|
||||
"description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link"
|
||||
|
4
app/_locales/ko/messages.json
generated
4
app/_locales/ko/messages.json
generated
@ -3019,10 +3019,6 @@
|
||||
"onboardingPinExtensionTitle": {
|
||||
"message": "MetaMask 설치가 완료되었습니다!"
|
||||
},
|
||||
"onboardingShowIncomingTransactionsDescription": {
|
||||
"message": "지갑에 들어오는 거래를 표시하려면 $1 링크와의 통신이 필요합니다. Etherscan은 이더리움 주소와 IP 주소에 액세스할 수 있습니다. $2 보기.",
|
||||
"description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key."
|
||||
},
|
||||
"onboardingUsePhishingDetectionDescription": {
|
||||
"message": "피싱 감지 경보는 $1과(와)의 통신에 의존합니다. jsDeliver는 귀하의 IP 주소에 액세스할 수 있습니다. $2 보기.",
|
||||
"description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link"
|
||||
|
4
app/_locales/pt/messages.json
generated
4
app/_locales/pt/messages.json
generated
@ -3019,10 +3019,6 @@
|
||||
"onboardingPinExtensionTitle": {
|
||||
"message": "Sua instalação da MetaMask está concluída!"
|
||||
},
|
||||
"onboardingShowIncomingTransactionsDescription": {
|
||||
"message": "A exibição de transações recebidas na sua carteira depende de comunicação com $1. O Etherscan terá acesso ao seu endereço Ethereum e ao seu endereço IP. Veja $2.",
|
||||
"description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key."
|
||||
},
|
||||
"onboardingUsePhishingDetectionDescription": {
|
||||
"message": "Os alertas de detecção de phishing dependem de comunicação com $1. O jsDeliver terá acesso ao seu endereço IP. Veja $2.",
|
||||
"description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link"
|
||||
|
4
app/_locales/pt_BR/messages.json
generated
4
app/_locales/pt_BR/messages.json
generated
@ -1623,10 +1623,6 @@
|
||||
"onboardingPinExtensionTitle": {
|
||||
"message": "Sua instalação da MetaMask está concluída!"
|
||||
},
|
||||
"onboardingShowIncomingTransactionsDescription": {
|
||||
"message": "A exibição de transações recebidas na sua carteira depende de comunicação com $1. O Etherscan terá acesso ao seu endereço Ethereum e ao seu endereço IP. Veja $2.",
|
||||
"description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key."
|
||||
},
|
||||
"onboardingUsePhishingDetectionDescription": {
|
||||
"message": "Os alertas de detecção de phishing dependem de comunicação com $1. O jsDeliver terá acesso ao seu endereço IP. Veja $2.",
|
||||
"description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link"
|
||||
|
4
app/_locales/ru/messages.json
generated
4
app/_locales/ru/messages.json
generated
@ -3019,10 +3019,6 @@
|
||||
"onboardingPinExtensionTitle": {
|
||||
"message": "Установка MetaMask завершена!"
|
||||
},
|
||||
"onboardingShowIncomingTransactionsDescription": {
|
||||
"message": "Отображение входящих транзакций в вашем кошельке зависит от связи с $1. Etherscan получит доступ к вашему адресу Ethereum и вашему IP-адресу. Посмотрите $2.",
|
||||
"description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key."
|
||||
},
|
||||
"onboardingUsePhishingDetectionDescription": {
|
||||
"message": "Оповещения об обнаружении фишинга зависят от связи с $1. jsDeliver получит доступ к вашему IP-адресу. Посмотрите $ 2.",
|
||||
"description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link"
|
||||
|
4
app/_locales/tl/messages.json
generated
4
app/_locales/tl/messages.json
generated
@ -3019,10 +3019,6 @@
|
||||
"onboardingPinExtensionTitle": {
|
||||
"message": "Ang pag-install ng iyong MetaMask ay kumpleto na!"
|
||||
},
|
||||
"onboardingShowIncomingTransactionsDescription": {
|
||||
"message": "Ang pagpapakita ng mga papasok na transaksyon sa iyong wallet ay umaasa sa pakikipag-ugnayan sa $1. Magkakaroon ng access ang Etherscan sa iyong Ethereum address at iyong IP address. Tingnan ang $2.",
|
||||
"description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key."
|
||||
},
|
||||
"onboardingUsePhishingDetectionDescription": {
|
||||
"message": "Ang mga alerto sa pagtuklas ng phishing ay umaasa sa komunikasyon sa $1. Ang jsDeliver ay magkakaroon ng access sa iyong IP address. Tingnan ang $2.",
|
||||
"description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link"
|
||||
|
4
app/_locales/tr/messages.json
generated
4
app/_locales/tr/messages.json
generated
@ -3019,10 +3019,6 @@
|
||||
"onboardingPinExtensionTitle": {
|
||||
"message": "MetaMask kurulumunuz tamamlandı!"
|
||||
},
|
||||
"onboardingShowIncomingTransactionsDescription": {
|
||||
"message": "Cüzdanınıza gelen işlemlerin gösterilmesi $1 ile iletişime bağlıdır. Etherscan, Ethereum adresinize ve IP adresinize erişim sağlayacaktır. Şunu görüntüleyin: $2.",
|
||||
"description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key."
|
||||
},
|
||||
"onboardingUsePhishingDetectionDescription": {
|
||||
"message": "Kimlik avı tespiti uyarıları $1 ile iletişime bağlıdır. jsDeliver IP adresinize erişim sağlayacaktır. Şunu görüntüleyin: $2.",
|
||||
"description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link"
|
||||
|
4
app/_locales/vi/messages.json
generated
4
app/_locales/vi/messages.json
generated
@ -3019,10 +3019,6 @@
|
||||
"onboardingPinExtensionTitle": {
|
||||
"message": "Quá trình cài đặt MetaMask đã hoàn tất!"
|
||||
},
|
||||
"onboardingShowIncomingTransactionsDescription": {
|
||||
"message": "Việc hiển thị các giao dịch đến trong ví của bạn tùy thuộc vào quá trình truyền tin với $1. Etherscan sẽ có quyền truy cập vào địa chỉ Ethereum và địa chỉ IP của bạn. Xem $2.",
|
||||
"description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key."
|
||||
},
|
||||
"onboardingUsePhishingDetectionDescription": {
|
||||
"message": "Thông báo phát hiện dấu hiệu lừa đảo tùy thuộc vào quá trình truyền tin với $1. jsDeliver sẽ có quyền truy cập vào địa chỉ IP của bạn. Xem $2.",
|
||||
"description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link"
|
||||
|
4
app/_locales/zh_CN/messages.json
generated
4
app/_locales/zh_CN/messages.json
generated
@ -3019,10 +3019,6 @@
|
||||
"onboardingPinExtensionTitle": {
|
||||
"message": "您的 MetaMask 安装完成!"
|
||||
},
|
||||
"onboardingShowIncomingTransactionsDescription": {
|
||||
"message": "在您的钱包中显示传入的交易依赖于与 $1 的通信。Etherscan 将有权访问您的以太坊地址和 IP 地址。查看 $2。",
|
||||
"description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key."
|
||||
},
|
||||
"onboardingUsePhishingDetectionDescription": {
|
||||
"message": "网络钓鱼检测警报依赖于与 $1 的通信。jsDeliver 将有权访问您的 IP 地址。查看 $2。",
|
||||
"description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link"
|
||||
|
@ -225,6 +225,7 @@ describe('DetectTokensController', function () {
|
||||
tokenListController,
|
||||
onInfuraIsBlocked: sinon.stub(),
|
||||
onInfuraIsUnblocked: sinon.stub(),
|
||||
networkConfigurations: {},
|
||||
});
|
||||
preferences.setAddresses([
|
||||
'0x7e57e2',
|
||||
|
@ -53,6 +53,7 @@ describe('MMIController', function () {
|
||||
onInfuraIsBlocked: jest.fn(),
|
||||
onInfuraIsUnblocked: jest.fn(),
|
||||
provider: {},
|
||||
networkConfigurations: {},
|
||||
}),
|
||||
appStateController: new AppStateController({
|
||||
addUnlockListener: jest.fn(),
|
||||
|
@ -1,6 +1,9 @@
|
||||
import { ObservableStore } from '@metamask/obs-store';
|
||||
import { normalize as normalizeAddress } from 'eth-sig-util';
|
||||
import { IPFS_DEFAULT_GATEWAY_URL } from '../../../shared/constants/network';
|
||||
import {
|
||||
CHAIN_IDS,
|
||||
IPFS_DEFAULT_GATEWAY_URL,
|
||||
} from '../../../shared/constants/network';
|
||||
import { LedgerTransportTypes } from '../../../shared/constants/hardware-wallets';
|
||||
import { ThemeType } from '../../../shared/constants/preferences';
|
||||
import { shouldShowLineaMainnet } from '../../../shared/modules/network.utils';
|
||||
@ -8,6 +11,17 @@ import { shouldShowLineaMainnet } from '../../../shared/modules/network.utils';
|
||||
import { KEYRING_SNAPS_REGISTRY_URL } from '../../../shared/constants/app';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
const mainNetworks = {
|
||||
[CHAIN_IDS.MAINNET]: true,
|
||||
[CHAIN_IDS.LINEA_MAINNET]: true,
|
||||
};
|
||||
|
||||
const testNetworks = {
|
||||
[CHAIN_IDS.GOERLI]: true,
|
||||
[CHAIN_IDS.SEPOLIA]: true,
|
||||
[CHAIN_IDS.LINEA_GOERLI]: true,
|
||||
};
|
||||
|
||||
export default class PreferencesController {
|
||||
/**
|
||||
*
|
||||
@ -25,6 +39,13 @@ export default class PreferencesController {
|
||||
* @property {string} store.selectedAddress A hex string that matches the currently selected address in the app
|
||||
*/
|
||||
constructor(opts = {}) {
|
||||
const addedNonMainNetwork = Object.values(
|
||||
opts.networkConfigurations,
|
||||
).reduce((acc, element) => {
|
||||
acc[element.chainId] = true;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const initState = {
|
||||
useBlockie: false,
|
||||
useNonceField: false,
|
||||
@ -51,8 +72,11 @@ export default class PreferencesController {
|
||||
// Feature flag toggling is available in the global namespace
|
||||
// for convenient testing of pre-release features, and should never
|
||||
// perform sensitive operations.
|
||||
featureFlags: {
|
||||
showIncomingTransactions: true,
|
||||
featureFlags: {},
|
||||
incomingTransactionsPreferences: {
|
||||
...mainNetworks,
|
||||
...addedNonMainNetwork,
|
||||
...testNetworks,
|
||||
},
|
||||
knownMethodData: {},
|
||||
currentLocale: opts.initLangCode,
|
||||
@ -84,6 +108,7 @@ export default class PreferencesController {
|
||||
};
|
||||
|
||||
this.network = opts.network;
|
||||
|
||||
this._onInfuraIsBlocked = opts.onInfuraIsBlocked;
|
||||
this._onInfuraIsUnblocked = opts.onInfuraIsUnblocked;
|
||||
this.store = new ObservableStore(initState);
|
||||
@ -448,7 +473,7 @@ export default class PreferencesController {
|
||||
* found in the settings page.
|
||||
*
|
||||
* @param {string} preference - The preference to enable or disable.
|
||||
* @param {boolean} value - Indicates whether or not the preference should be enabled or disabled.
|
||||
* @param {boolean |object} value - Indicates whether or not the preference should be enabled or disabled.
|
||||
* @returns {Promise<object>} Promises a new object; the updated preferences object.
|
||||
*/
|
||||
async setPreference(preference, value) {
|
||||
@ -550,6 +575,18 @@ export default class PreferencesController {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A setter for the incomingTransactions in preference to be updated
|
||||
*
|
||||
* @param {string} chainId - chainId of the network
|
||||
* @param {bool} value - preference of certain network, true to be enabled
|
||||
*/
|
||||
setIncomingTransactionsPreferences(chainId, value) {
|
||||
const previousValue = this.store.getState().incomingTransactionsPreferences;
|
||||
const updatedValue = { ...previousValue, [chainId]: value };
|
||||
this.store.updateState({ incomingTransactionsPreferences: updatedValue });
|
||||
}
|
||||
|
||||
getRpcMethodPreferences() {
|
||||
return this.store.getState().disabledRpcMethodPreferences;
|
||||
}
|
||||
@ -570,6 +607,7 @@ export default class PreferencesController {
|
||||
}
|
||||
this.store.updateState({ snapRegistryList: snapRegistry });
|
||||
}
|
||||
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
//
|
||||
|
@ -1,67 +1,85 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import sinon from 'sinon';
|
||||
/**
|
||||
* @jest-environment node
|
||||
*/
|
||||
import { ControllerMessenger } from '@metamask/base-controller';
|
||||
import { TokenListController } from '@metamask/assets-controllers';
|
||||
import { CHAIN_IDS } from '../../../shared/constants/network';
|
||||
import PreferencesController from './preferences';
|
||||
|
||||
describe('preferences controller', function () {
|
||||
const NETWORK_CONFIGURATION_DATA = {
|
||||
'test-networkConfigurationId-1': {
|
||||
rpcUrl: 'https://testrpc.com',
|
||||
chainId: CHAIN_IDS.GOERLI,
|
||||
nickname: '0X5',
|
||||
rpcPrefs: { blockExplorerUrl: 'https://etherscan.io' },
|
||||
},
|
||||
'test-networkConfigurationId-2': {
|
||||
rpcUrl: 'http://localhost:8545',
|
||||
chainId: '0x539',
|
||||
ticker: 'ETH',
|
||||
nickname: 'Localhost 8545',
|
||||
rpcPrefs: {},
|
||||
},
|
||||
};
|
||||
describe('preferences controller', () => {
|
||||
let preferencesController;
|
||||
let tokenListController;
|
||||
|
||||
beforeEach(function () {
|
||||
beforeEach(() => {
|
||||
const tokenListMessenger = new ControllerMessenger().getRestricted({
|
||||
name: 'TokenListController',
|
||||
});
|
||||
tokenListController = new TokenListController({
|
||||
chainId: '1',
|
||||
preventPollingOnNetworkRestart: false,
|
||||
onNetworkStateChange: sinon.spy(),
|
||||
onPreferencesStateChange: sinon.spy(),
|
||||
onNetworkStateChange: jest.fn(),
|
||||
onPreferencesStateChange: jest.fn(),
|
||||
messenger: tokenListMessenger,
|
||||
});
|
||||
|
||||
preferencesController = new PreferencesController({
|
||||
initLangCode: 'en_US',
|
||||
tokenListController,
|
||||
onInfuraIsBlocked: sinon.spy(),
|
||||
onInfuraIsUnblocked: sinon.spy(),
|
||||
onInfuraIsBlocked: jest.fn(),
|
||||
onInfuraIsUnblocked: jest.fn(),
|
||||
networkConfigurations: NETWORK_CONFIGURATION_DATA,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
describe('useBlockie', function () {
|
||||
it('defaults useBlockie to false', function () {
|
||||
assert.equal(preferencesController.store.getState().useBlockie, false);
|
||||
describe('useBlockie', () => {
|
||||
it('defaults useBlockie to false', () => {
|
||||
expect(preferencesController.store.getState().useBlockie).toStrictEqual(
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
it('setUseBlockie to true', function () {
|
||||
it('setUseBlockie to true', () => {
|
||||
preferencesController.setUseBlockie(true);
|
||||
assert.equal(preferencesController.store.getState().useBlockie, true);
|
||||
expect(preferencesController.store.getState().useBlockie).toStrictEqual(
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setCurrentLocale', function () {
|
||||
it('checks the default currentLocale', function () {
|
||||
describe('setCurrentLocale', () => {
|
||||
it('checks the default currentLocale', () => {
|
||||
const { currentLocale } = preferencesController.store.getState();
|
||||
assert.equal(currentLocale, 'en_US');
|
||||
expect(currentLocale).toStrictEqual('en_US');
|
||||
});
|
||||
|
||||
it('sets current locale in preferences controller', function () {
|
||||
it('sets current locale in preferences controller', () => {
|
||||
preferencesController.setCurrentLocale('ja');
|
||||
const { currentLocale } = preferencesController.store.getState();
|
||||
assert.equal(currentLocale, 'ja');
|
||||
expect(currentLocale).toStrictEqual('ja');
|
||||
});
|
||||
});
|
||||
|
||||
describe('setAddresses', function () {
|
||||
it('should keep a map of addresses to names and addresses in the store', function () {
|
||||
describe('setAddresses', () => {
|
||||
it('should keep a map of addresses to names and addresses in the store', () => {
|
||||
preferencesController.setAddresses(['0xda22le', '0x7e57e2']);
|
||||
|
||||
const { identities } = preferencesController.store.getState();
|
||||
assert.deepEqual(identities, {
|
||||
expect(identities).toStrictEqual({
|
||||
'0xda22le': {
|
||||
name: 'Account 1',
|
||||
address: '0xda22le',
|
||||
@ -73,12 +91,12 @@ describe('preferences controller', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('should replace its list of addresses', function () {
|
||||
it('should replace its list of addresses', () => {
|
||||
preferencesController.setAddresses(['0xda22le', '0x7e57e2']);
|
||||
preferencesController.setAddresses(['0xda22le77', '0x7e57e277']);
|
||||
|
||||
const { identities } = preferencesController.store.getState();
|
||||
assert.deepEqual(identities, {
|
||||
expect(identities).toStrictEqual({
|
||||
'0xda22le77': {
|
||||
name: 'Account 1',
|
||||
address: '0xda22le77',
|
||||
@ -91,237 +109,235 @@ describe('preferences controller', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeAddress', function () {
|
||||
it('should remove an address from state', function () {
|
||||
describe('removeAddress', () => {
|
||||
it('should remove an address from state', () => {
|
||||
preferencesController.setAddresses(['0xda22le', '0x7e57e2']);
|
||||
|
||||
preferencesController.removeAddress('0xda22le');
|
||||
|
||||
assert.equal(
|
||||
expect(
|
||||
preferencesController.store.getState().identities['0xda22le'],
|
||||
undefined,
|
||||
);
|
||||
).toStrictEqual(undefined);
|
||||
});
|
||||
|
||||
it('should switch accounts if the selected address is removed', function () {
|
||||
it('should switch accounts if the selected address is removed', () => {
|
||||
preferencesController.setAddresses(['0xda22le', '0x7e57e2']);
|
||||
|
||||
preferencesController.setSelectedAddress('0x7e57e2');
|
||||
preferencesController.removeAddress('0x7e57e2');
|
||||
|
||||
assert.equal(preferencesController.getSelectedAddress(), '0xda22le');
|
||||
expect(preferencesController.getSelectedAddress()).toStrictEqual(
|
||||
'0xda22le',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setAccountLabel', function () {
|
||||
it('should update a label for the given account', function () {
|
||||
describe('setAccountLabel', () => {
|
||||
it('should update a label for the given account', () => {
|
||||
preferencesController.setAddresses(['0xda22le', '0x7e57e2']);
|
||||
|
||||
assert.deepEqual(
|
||||
expect(
|
||||
preferencesController.store.getState().identities['0xda22le'],
|
||||
{
|
||||
name: 'Account 1',
|
||||
address: '0xda22le',
|
||||
},
|
||||
);
|
||||
).toStrictEqual({
|
||||
name: 'Account 1',
|
||||
address: '0xda22le',
|
||||
});
|
||||
|
||||
preferencesController.setAccountLabel('0xda22le', 'Dazzle');
|
||||
assert.deepEqual(
|
||||
expect(
|
||||
preferencesController.store.getState().identities['0xda22le'],
|
||||
{
|
||||
name: 'Dazzle',
|
||||
address: '0xda22le',
|
||||
},
|
||||
);
|
||||
).toStrictEqual({
|
||||
name: 'Dazzle',
|
||||
address: '0xda22le',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('setPasswordForgotten', function () {
|
||||
it('should default to false', function () {
|
||||
const state = preferencesController.store.getState();
|
||||
assert.equal(state.forgottenPassword, false);
|
||||
describe('setPasswordForgotten', () => {
|
||||
it('should default to false', () => {
|
||||
expect(
|
||||
preferencesController.store.getState().forgottenPassword,
|
||||
).toStrictEqual(false);
|
||||
});
|
||||
|
||||
it('should set the forgottenPassword property in state', function () {
|
||||
assert.equal(
|
||||
preferencesController.store.getState().forgottenPassword,
|
||||
false,
|
||||
);
|
||||
|
||||
it('should set the forgottenPassword property in state', () => {
|
||||
preferencesController.setPasswordForgotten(true);
|
||||
|
||||
assert.equal(
|
||||
expect(
|
||||
preferencesController.store.getState().forgottenPassword,
|
||||
true,
|
||||
);
|
||||
).toStrictEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setUsePhishDetect', function () {
|
||||
it('should default to true', function () {
|
||||
const state = preferencesController.store.getState();
|
||||
assert.equal(state.usePhishDetect, true);
|
||||
});
|
||||
|
||||
it('should set the usePhishDetect property in state', function () {
|
||||
assert.equal(preferencesController.store.getState().usePhishDetect, true);
|
||||
preferencesController.setUsePhishDetect(false);
|
||||
assert.equal(
|
||||
describe('setUsePhishDetect', () => {
|
||||
it('should default to true', () => {
|
||||
expect(
|
||||
preferencesController.store.getState().usePhishDetect,
|
||||
false,
|
||||
);
|
||||
).toStrictEqual(true);
|
||||
});
|
||||
|
||||
it('should set the usePhishDetect property in state', () => {
|
||||
preferencesController.setUsePhishDetect(false);
|
||||
expect(
|
||||
preferencesController.store.getState().usePhishDetect,
|
||||
).toStrictEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setUseMultiAccountBalanceChecker', function () {
|
||||
it('should default to true', function () {
|
||||
const state = preferencesController.store.getState();
|
||||
assert.equal(state.useMultiAccountBalanceChecker, true);
|
||||
describe('setUseMultiAccountBalanceChecker', () => {
|
||||
it('should default to true', () => {
|
||||
expect(
|
||||
preferencesController.store.getState().useMultiAccountBalanceChecker,
|
||||
).toStrictEqual(true);
|
||||
});
|
||||
|
||||
it('should set the setUseMultiAccountBalanceChecker property in state', function () {
|
||||
assert.equal(
|
||||
preferencesController.store.getState().useMultiAccountBalanceChecker,
|
||||
true,
|
||||
);
|
||||
|
||||
it('should set the setUseMultiAccountBalanceChecker property in state', () => {
|
||||
preferencesController.setUseMultiAccountBalanceChecker(false);
|
||||
|
||||
assert.equal(
|
||||
expect(
|
||||
preferencesController.store.getState().useMultiAccountBalanceChecker,
|
||||
false,
|
||||
);
|
||||
).toStrictEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setUseTokenDetection', function () {
|
||||
it('should default to false', function () {
|
||||
const state = preferencesController.store.getState();
|
||||
assert.equal(state.useTokenDetection, false);
|
||||
describe('setUseTokenDetection', () => {
|
||||
it('should default to false', () => {
|
||||
expect(
|
||||
preferencesController.store.getState().useTokenDetection,
|
||||
).toStrictEqual(false);
|
||||
});
|
||||
|
||||
it('should set the useTokenDetection property in state', function () {
|
||||
assert.equal(
|
||||
preferencesController.store.getState().useTokenDetection,
|
||||
false,
|
||||
);
|
||||
it('should set the useTokenDetection property in state', () => {
|
||||
preferencesController.setUseTokenDetection(true);
|
||||
assert.equal(
|
||||
expect(
|
||||
preferencesController.store.getState().useTokenDetection,
|
||||
true,
|
||||
);
|
||||
).toStrictEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setUseNftDetection', function () {
|
||||
it('should default to false', function () {
|
||||
const state = preferencesController.store.getState();
|
||||
assert.equal(state.useNftDetection, false);
|
||||
describe('setUseNftDetection', () => {
|
||||
it('should default to false', () => {
|
||||
expect(
|
||||
preferencesController.store.getState().useNftDetection,
|
||||
).toStrictEqual(false);
|
||||
});
|
||||
|
||||
it('should set the useNftDetection property in state', function () {
|
||||
assert.equal(
|
||||
preferencesController.store.getState().useNftDetection,
|
||||
false,
|
||||
);
|
||||
it('should set the useNftDetection property in state', () => {
|
||||
preferencesController.setOpenSeaEnabled(true);
|
||||
preferencesController.setUseNftDetection(true);
|
||||
assert.equal(
|
||||
expect(
|
||||
preferencesController.store.getState().useNftDetection,
|
||||
true,
|
||||
);
|
||||
).toStrictEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setUse4ByteResolution', function () {
|
||||
it('should default to true', function () {
|
||||
const state = preferencesController.store.getState();
|
||||
assert.equal(state.use4ByteResolution, true);
|
||||
expect(
|
||||
preferencesController.store.getState().use4ByteResolution,
|
||||
).toStrictEqual(true);
|
||||
});
|
||||
|
||||
it('should set the use4ByteResolution property in state', function () {
|
||||
assert.equal(
|
||||
preferencesController.store.getState().use4ByteResolution,
|
||||
true,
|
||||
);
|
||||
preferencesController.setUse4ByteResolution(false);
|
||||
assert.equal(
|
||||
expect(
|
||||
preferencesController.store.getState().use4ByteResolution,
|
||||
false,
|
||||
);
|
||||
).toStrictEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setOpenSeaEnabled', function () {
|
||||
it('should default to false', function () {
|
||||
const state = preferencesController.store.getState();
|
||||
assert.equal(state.openSeaEnabled, false);
|
||||
});
|
||||
|
||||
it('should set the openSeaEnabled property in state', function () {
|
||||
assert.equal(
|
||||
describe('setOpenSeaEnabled', () => {
|
||||
it('should default to false', () => {
|
||||
expect(
|
||||
preferencesController.store.getState().openSeaEnabled,
|
||||
false,
|
||||
);
|
||||
).toStrictEqual(false);
|
||||
});
|
||||
|
||||
it('should set the openSeaEnabled property in state', () => {
|
||||
preferencesController.setOpenSeaEnabled(true);
|
||||
assert.equal(preferencesController.store.getState().openSeaEnabled, true);
|
||||
expect(
|
||||
preferencesController.store.getState().openSeaEnabled,
|
||||
).toStrictEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setAdvancedGasFee', function () {
|
||||
it('should default to null', function () {
|
||||
const state = preferencesController.store.getState();
|
||||
assert.equal(state.advancedGasFee, null);
|
||||
describe('setAdvancedGasFee', () => {
|
||||
it('should default to null', () => {
|
||||
expect(
|
||||
preferencesController.store.getState().advancedGasFee,
|
||||
).toStrictEqual(null);
|
||||
});
|
||||
|
||||
it('should set the setAdvancedGasFee property in state', function () {
|
||||
const state = preferencesController.store.getState();
|
||||
assert.equal(state.advancedGasFee, null);
|
||||
it('should set the setAdvancedGasFee property in state', () => {
|
||||
preferencesController.setAdvancedGasFee({
|
||||
maxBaseFee: '1.5',
|
||||
priorityFee: '2',
|
||||
});
|
||||
assert.equal(
|
||||
expect(
|
||||
preferencesController.store.getState().advancedGasFee.maxBaseFee,
|
||||
'1.5',
|
||||
);
|
||||
assert.equal(
|
||||
).toStrictEqual('1.5');
|
||||
expect(
|
||||
preferencesController.store.getState().advancedGasFee.priorityFee,
|
||||
'2',
|
||||
);
|
||||
).toStrictEqual('2');
|
||||
});
|
||||
});
|
||||
|
||||
describe('setTheme', function () {
|
||||
it('should default to value "OS"', function () {
|
||||
const state = preferencesController.store.getState();
|
||||
assert.equal(state.theme, 'os');
|
||||
describe('setTheme', () => {
|
||||
it('should default to value "OS"', () => {
|
||||
expect(preferencesController.store.getState().theme).toStrictEqual('os');
|
||||
});
|
||||
|
||||
it('should set the setTheme property in state', function () {
|
||||
const state = preferencesController.store.getState();
|
||||
assert.equal(state.theme, 'os');
|
||||
it('should set the setTheme property in state', () => {
|
||||
preferencesController.setTheme('dark');
|
||||
assert.equal(preferencesController.store.getState().theme, 'dark');
|
||||
expect(preferencesController.store.getState().theme).toStrictEqual(
|
||||
'dark',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setUseCurrencyRateCheck', function () {
|
||||
it('should default to false', function () {
|
||||
const state = preferencesController.store.getState();
|
||||
assert.equal(state.useCurrencyRateCheck, true);
|
||||
describe('setUseCurrencyRateCheck', () => {
|
||||
it('should default to false', () => {
|
||||
expect(
|
||||
preferencesController.store.getState().useCurrencyRateCheck,
|
||||
).toStrictEqual(true);
|
||||
});
|
||||
|
||||
it('should set the useCurrencyRateCheck property in state', function () {
|
||||
assert.equal(
|
||||
preferencesController.store.getState().useCurrencyRateCheck,
|
||||
true,
|
||||
);
|
||||
it('should set the useCurrencyRateCheck property in state', () => {
|
||||
preferencesController.setUseCurrencyRateCheck(false);
|
||||
assert.equal(
|
||||
expect(
|
||||
preferencesController.store.getState().useCurrencyRateCheck,
|
||||
).toStrictEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setIncomingTransactionsPreferences', () => {
|
||||
const addedNonTestNetworks = Object.keys(NETWORK_CONFIGURATION_DATA);
|
||||
|
||||
it('should have default value combined', () => {
|
||||
const state = preferencesController.store.getState();
|
||||
expect(state.incomingTransactionsPreferences).toStrictEqual({
|
||||
[CHAIN_IDS.MAINNET]: true,
|
||||
[CHAIN_IDS.LINEA_MAINNET]: true,
|
||||
[NETWORK_CONFIGURATION_DATA[addedNonTestNetworks[0]].chainId]: true,
|
||||
[NETWORK_CONFIGURATION_DATA[addedNonTestNetworks[1]].chainId]: true,
|
||||
[CHAIN_IDS.GOERLI]: true,
|
||||
[CHAIN_IDS.SEPOLIA]: true,
|
||||
[CHAIN_IDS.LINEA_GOERLI]: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should update incomingTransactionsPreferences with given value set', () => {
|
||||
preferencesController.setIncomingTransactionsPreferences(
|
||||
[CHAIN_IDS.LINEA_MAINNET],
|
||||
false,
|
||||
);
|
||||
const state = preferencesController.store.getState();
|
||||
expect(state.incomingTransactionsPreferences).toStrictEqual({
|
||||
[CHAIN_IDS.MAINNET]: true,
|
||||
[CHAIN_IDS.LINEA_MAINNET]: false,
|
||||
[NETWORK_CONFIGURATION_DATA[addedNonTestNetworks[0]].chainId]: true,
|
||||
[NETWORK_CONFIGURATION_DATA[addedNonTestNetworks[1]].chainId]: true,
|
||||
[CHAIN_IDS.GOERLI]: true,
|
||||
[CHAIN_IDS.SEPOLIA]: true,
|
||||
[CHAIN_IDS.LINEA_GOERLI]: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -228,8 +228,9 @@ export default class TransactionController extends EventEmitter {
|
||||
getNetworkState: () => this._getNetworkState(),
|
||||
isEnabled: () =>
|
||||
Boolean(
|
||||
this.preferencesStore.getState().featureFlags
|
||||
?.showIncomingTransactions && this._hasCompletedOnboarding(),
|
||||
this.preferencesStore.getState().incomingTransactionsPreferences?.[
|
||||
this._getChainId()
|
||||
] && this._hasCompletedOnboarding(),
|
||||
),
|
||||
lastFetchedBlockNumbers: opts.initState?.lastFetchedBlockNumbers || {},
|
||||
remoteTransactionSource: new EtherscanRemoteTransactionSource({
|
||||
|
@ -131,7 +131,6 @@ const jsonData = JSON.stringify({
|
||||
advancedGasFee: null,
|
||||
featureFlags: {
|
||||
sendHexData: true,
|
||||
showIncomingTransactions: true,
|
||||
},
|
||||
knownMethodData: {},
|
||||
currentLocale: 'en',
|
||||
|
@ -415,6 +415,7 @@ export default class MetamaskController extends EventEmitter {
|
||||
),
|
||||
tokenListController: this.tokenListController,
|
||||
provider: this.provider,
|
||||
networkConfigurations: this.networkController.state.networkConfigurations,
|
||||
});
|
||||
|
||||
const tokensControllerMessenger = this.controllerMessenger.getRestricted({
|
||||
@ -1975,10 +1976,10 @@ export default class MetamaskController extends EventEmitter {
|
||||
|
||||
this.preferencesController.store.subscribe(async (state) => {
|
||||
const { selectedAddress, currentLocale } = state;
|
||||
|
||||
const { chainId } = this.networkController.state.providerConfig;
|
||||
await updateCurrentLocale(currentLocale);
|
||||
|
||||
if (state?.featureFlags?.showIncomingTransactions) {
|
||||
if (state.incomingTransactionsPreferences?.[chainId]) {
|
||||
this.txController.startIncomingTransactionPolling();
|
||||
} else {
|
||||
this.txController.stopIncomingTransactionPolling();
|
||||
@ -2280,6 +2281,10 @@ export default class MetamaskController extends EventEmitter {
|
||||
setCurrentLocale: preferencesController.setCurrentLocale.bind(
|
||||
preferencesController,
|
||||
),
|
||||
setIncomingTransactionsPreferences:
|
||||
preferencesController.setIncomingTransactionsPreferences.bind(
|
||||
preferencesController,
|
||||
),
|
||||
markPasswordForgotten: this.markPasswordForgotten.bind(this),
|
||||
unMarkPasswordForgotten: this.unMarkPasswordForgotten.bind(this),
|
||||
getRequestAccountTabIds: this.getRequestAccountTabIds,
|
||||
|
@ -1686,24 +1686,24 @@ describe('MetaMaskController', function () {
|
||||
controllerMessengerSpy = ControllerMessenger.prototype;
|
||||
});
|
||||
|
||||
it('starts incoming transaction polling if show incoming transactions enabled', async function () {
|
||||
it('starts incoming transaction polling if incomingTransactionsPreferences is enabled for that chainId', async function () {
|
||||
assert(txControllerStub.startIncomingTransactionPolling.notCalled);
|
||||
|
||||
await preferencesControllerSpy.store.subscribe.lastCall.args[0]({
|
||||
featureFlags: {
|
||||
showIncomingTransactions: true,
|
||||
incomingTransactionsPreferences: {
|
||||
[MAINNET_CHAIN_ID]: true,
|
||||
},
|
||||
});
|
||||
|
||||
assert(txControllerStub.startIncomingTransactionPolling.calledOnce);
|
||||
});
|
||||
|
||||
it('stops incoming transaction polling if show incoming transactions disabled', async function () {
|
||||
it('stops incoming transaction polling if incomingTransactionsPreferences is disabled for that chainIdd', async function () {
|
||||
assert(txControllerStub.stopIncomingTransactionPolling.notCalled);
|
||||
|
||||
await preferencesControllerSpy.store.subscribe.lastCall.args[0]({
|
||||
featureFlags: {
|
||||
showIncomingTransactions: false,
|
||||
incomingTransactionsPreferences: {
|
||||
[MAINNET_CHAIN_ID]: false,
|
||||
},
|
||||
});
|
||||
|
||||
|
141
app/scripts/migrations/096.test.ts
Normal file
141
app/scripts/migrations/096.test.ts
Normal file
@ -0,0 +1,141 @@
|
||||
import { CHAIN_IDS } from '../../../shared/constants/network';
|
||||
import { migrate, version } from './096';
|
||||
|
||||
const oldVersion = 95;
|
||||
describe('migration #96', () => {
|
||||
it('updates the version metadata', async () => {
|
||||
const oldStorage = {
|
||||
meta: { version: oldVersion },
|
||||
data: {},
|
||||
};
|
||||
|
||||
const newStorage = await migrate(oldStorage);
|
||||
|
||||
expect(newStorage.meta).toStrictEqual({ version });
|
||||
});
|
||||
|
||||
it('returns the state unaltered if it has no PreferencesController property', async () => {
|
||||
const oldData = {
|
||||
some: 'data',
|
||||
};
|
||||
const oldStorage = {
|
||||
meta: { version: oldVersion },
|
||||
data: oldData,
|
||||
};
|
||||
|
||||
const newStorage = await migrate(oldStorage);
|
||||
|
||||
expect(newStorage.data).toStrictEqual(oldData);
|
||||
});
|
||||
|
||||
it('returns the state unaltered if it has no NetworkController property', async () => {
|
||||
const oldData = {
|
||||
PreferencesController: 'data',
|
||||
};
|
||||
const oldStorage = {
|
||||
meta: { version: oldVersion },
|
||||
data: oldData,
|
||||
};
|
||||
|
||||
const newStorage = await migrate(oldStorage);
|
||||
|
||||
expect(newStorage.data).toStrictEqual(oldData);
|
||||
});
|
||||
|
||||
it('returns the state unaltered if the PreferencesController object has no featureFlags property', async () => {
|
||||
const oldData = {
|
||||
PreferencesController: 'data',
|
||||
NetworkController: 'data',
|
||||
};
|
||||
const oldStorage = {
|
||||
meta: { version: oldVersion },
|
||||
data: oldData,
|
||||
};
|
||||
|
||||
const newStorage = await migrate(oldStorage);
|
||||
|
||||
expect(newStorage.data).toStrictEqual(oldData);
|
||||
});
|
||||
|
||||
it('returns the state unaltered if the NetworkController object has no networkConfigurations property', async () => {
|
||||
const oldData = {
|
||||
PreferencesController: {
|
||||
featureFlags: {
|
||||
showIncomingTransactions: true,
|
||||
},
|
||||
},
|
||||
NetworkController: 'data',
|
||||
};
|
||||
const oldStorage = {
|
||||
meta: { version: oldVersion },
|
||||
data: oldData,
|
||||
};
|
||||
|
||||
const newStorage = await migrate(oldStorage);
|
||||
|
||||
expect(newStorage.data).toStrictEqual(oldData);
|
||||
});
|
||||
|
||||
it('rewrites PreferencesController and delete showIncomingTransactions', async () => {
|
||||
const showIncomingTransactionsValue = false;
|
||||
const networkConfigurations = {
|
||||
'network-configuration-id-1': {
|
||||
chainId: '0xa4b1',
|
||||
nickname: 'Arbitrum One',
|
||||
rpcPrefs: {
|
||||
blockExplorerUrl: 'https://explorer.arbitrum.io',
|
||||
},
|
||||
rpcUrl:
|
||||
'https://arbitrum-mainnet.infura.io/v3/373266a93aab4acda48f89d4fe77c748',
|
||||
ticker: 'ETH',
|
||||
},
|
||||
'network-configuration-id-2': {
|
||||
chainId: '0x4e454152',
|
||||
nickname: 'Aurora Mainnet',
|
||||
rpcPrefs: {
|
||||
blockExplorerUrl: 'https://aurorascan.dev/',
|
||||
},
|
||||
rpcUrl:
|
||||
'https://aurora-mainnet.infura.io/v3/373266a93aab4acda48f89d4fe77c748',
|
||||
ticker: 'Aurora ETH',
|
||||
},
|
||||
};
|
||||
const oldData = {
|
||||
PreferencesController: {
|
||||
featureFlags: {
|
||||
showIncomingTransactions: showIncomingTransactionsValue,
|
||||
},
|
||||
},
|
||||
NetworkController: {
|
||||
networkConfigurations,
|
||||
},
|
||||
};
|
||||
const oldStorage = {
|
||||
meta: { version: oldVersion },
|
||||
data: oldData,
|
||||
};
|
||||
const newStorage = await migrate(oldStorage);
|
||||
expect(newStorage).toStrictEqual({
|
||||
meta: {
|
||||
version,
|
||||
},
|
||||
data: {
|
||||
PreferencesController: {
|
||||
featureFlags: {},
|
||||
incomingTransactionsPreferences: {
|
||||
[CHAIN_IDS.MAINNET]: showIncomingTransactionsValue,
|
||||
[CHAIN_IDS.LINEA_MAINNET]: showIncomingTransactionsValue,
|
||||
[networkConfigurations['network-configuration-id-1'].chainId]:
|
||||
showIncomingTransactionsValue,
|
||||
[networkConfigurations['network-configuration-id-2'].chainId]:
|
||||
showIncomingTransactionsValue,
|
||||
[CHAIN_IDS.GOERLI]: showIncomingTransactionsValue,
|
||||
[CHAIN_IDS.SEPOLIA]: showIncomingTransactionsValue,
|
||||
[CHAIN_IDS.LINEA_GOERLI]: showIncomingTransactionsValue,
|
||||
},
|
||||
},
|
||||
NetworkController: { networkConfigurations },
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
84
app/scripts/migrations/096.ts
Normal file
84
app/scripts/migrations/096.ts
Normal file
@ -0,0 +1,84 @@
|
||||
import { cloneDeep, fromPairs, map } from 'lodash';
|
||||
import { hasProperty, isObject } from '@metamask/utils';
|
||||
import { CHAIN_IDS } from '../../../shared/constants/network';
|
||||
|
||||
type VersionedData = {
|
||||
meta: { version: number };
|
||||
data: Record<string, any>;
|
||||
};
|
||||
|
||||
export const version = 96;
|
||||
|
||||
/**
|
||||
* This migration will operate the following:
|
||||
*
|
||||
* - Delete `showIncomingTransactions` from `featureFlags` in PreferencesController
|
||||
* - Create a new object under PreferencesController named as `incomingTransactionsPreferences`
|
||||
* 1. which will collect all added networks including localhost
|
||||
* 2. then append the test networks
|
||||
* 3. each of them would become a key coming with the value Ture/False from `showIncomingTransactions`
|
||||
*
|
||||
* @param originalVersionedData - Versioned MetaMask extension state, exactly what we persist to dist.
|
||||
* @param originalVersionedData.meta - State metadata.
|
||||
* @param originalVersionedData.meta.version - The current state version.
|
||||
* @param originalVersionedData.data - The persisted MetaMask state, keyed by controller.
|
||||
* @returns Updated versioned MetaMask extension state.
|
||||
*/
|
||||
export async function migrate(
|
||||
originalVersionedData: VersionedData,
|
||||
): Promise<VersionedData> {
|
||||
const versionedData = cloneDeep(originalVersionedData);
|
||||
versionedData.meta.version = version;
|
||||
transformState(versionedData.data);
|
||||
return versionedData;
|
||||
}
|
||||
|
||||
interface NetworkConfiguration {
|
||||
chainId: Record<string, any>;
|
||||
}
|
||||
|
||||
function transformState(state: Record<string, unknown>) {
|
||||
if (
|
||||
!hasProperty(state, 'PreferencesController') ||
|
||||
!isObject(state.PreferencesController) ||
|
||||
!isObject(state.NetworkController) ||
|
||||
!hasProperty(state.PreferencesController, 'featureFlags') ||
|
||||
!hasProperty(state.NetworkController, 'networkConfigurations')
|
||||
) {
|
||||
return state;
|
||||
}
|
||||
const { PreferencesController, NetworkController } = state;
|
||||
const { featureFlags }: Record<string, any> = PreferencesController;
|
||||
const { showIncomingTransactions }: any = featureFlags;
|
||||
const { networkConfigurations }: Record<string, any> = NetworkController;
|
||||
|
||||
const addedNetwork: Record<string, any>[] =
|
||||
Object.values<NetworkConfiguration>(networkConfigurations).map(
|
||||
(network) => network.chainId,
|
||||
);
|
||||
|
||||
const mainNetworks = [CHAIN_IDS.MAINNET, CHAIN_IDS.LINEA_MAINNET];
|
||||
const testNetworks = [
|
||||
CHAIN_IDS.GOERLI,
|
||||
CHAIN_IDS.SEPOLIA,
|
||||
CHAIN_IDS.LINEA_GOERLI,
|
||||
];
|
||||
const allSavedNetworks: Record<string, any> = [
|
||||
...mainNetworks,
|
||||
...addedNetwork,
|
||||
...testNetworks,
|
||||
];
|
||||
|
||||
const incomingTransactionsPreferences = fromPairs(
|
||||
map(allSavedNetworks, (element) => [element, showIncomingTransactions]),
|
||||
);
|
||||
|
||||
if (featureFlags?.showIncomingTransactions !== undefined) {
|
||||
delete featureFlags.showIncomingTransactions;
|
||||
}
|
||||
|
||||
state.PreferencesController.incomingTransactionsPreferences =
|
||||
incomingTransactionsPreferences;
|
||||
|
||||
return state;
|
||||
}
|
@ -100,6 +100,7 @@ import * as m092point1 from './092.1';
|
||||
import * as m093 from './093';
|
||||
import * as m094 from './094';
|
||||
import * as m095 from './095';
|
||||
import * as m096 from './096';
|
||||
|
||||
const migrations = [
|
||||
m002,
|
||||
@ -197,5 +198,6 @@ const migrations = [
|
||||
m093,
|
||||
m094,
|
||||
m095,
|
||||
m096,
|
||||
];
|
||||
export default migrations;
|
||||
|
@ -7,6 +7,7 @@ module.exports = {
|
||||
'<rootDir>/app/scripts/controllers/transactions/etherscan.ts',
|
||||
'<rootDir>/app/scripts/controllers/transactions/EtherscanRemoteTransactionSource.ts',
|
||||
'<rootDir>/app/scripts/controllers/transactions/IncomingTransactionHelper.ts',
|
||||
'<rootDir>/app/scripts/controllers/preferences.js',
|
||||
'<rootDir>/app/scripts/flask/**/*.js',
|
||||
'<rootDir>/app/scripts/lib/**/*.(js|ts)',
|
||||
'<rootDir>/app/scripts/lib/createRPCMethodTrackingMiddleware.js',
|
||||
@ -45,6 +46,7 @@ module.exports = {
|
||||
'<rootDir>/app/scripts/controllers/transactions/IncomingTransactionHelper.test.ts',
|
||||
'<rootDir>/app/scripts/controllers/mmi-controller.test.js',
|
||||
'<rootDir>/app/scripts/controllers/permissions/**/*.test.js',
|
||||
'<rootDir>/app/scripts/controllers/preferences.test.js',
|
||||
'<rootDir>/app/scripts/controllers/sign.test.ts',
|
||||
'<rootDir>/app/scripts/controllers/decrypt-message.test.ts',
|
||||
'<rootDir>/app/scripts/flask/**/*.test.js',
|
||||
|
@ -111,9 +111,7 @@
|
||||
"alertEnabledness": {
|
||||
"unconnectedAccount": true
|
||||
},
|
||||
"featureFlags": {
|
||||
"showIncomingTransactions": true
|
||||
},
|
||||
"featureFlags": {},
|
||||
"network": "5",
|
||||
"providerConfig": {
|
||||
"type": "rpc",
|
||||
|
@ -107,9 +107,7 @@
|
||||
"alertEnabledness": {
|
||||
"unconnectedAccount": true
|
||||
},
|
||||
"featureFlags": {
|
||||
"showIncomingTransactions": true
|
||||
},
|
||||
"featureFlags": {},
|
||||
"networkId": "5",
|
||||
"providerConfig": {
|
||||
"type": "rpc",
|
||||
@ -220,7 +218,15 @@
|
||||
}
|
||||
},
|
||||
"cachedBalances": {},
|
||||
"incomingTransactions": {},
|
||||
"incomingTransactionsPreferences": {
|
||||
"0x1": true,
|
||||
"0xe708": false,
|
||||
"0xfa": true,
|
||||
"0x5": false,
|
||||
"0xaa36a7": true,
|
||||
"0xe704": true
|
||||
},
|
||||
|
||||
"unapprovedTxs": {
|
||||
"8393540981007587": {
|
||||
"chainId": "0x5",
|
||||
|
@ -250,9 +250,7 @@ function defaultFixture() {
|
||||
advancedGasFee: null,
|
||||
currentLocale: 'en',
|
||||
dismissSeedBackUpReminder: true,
|
||||
featureFlags: {
|
||||
showIncomingTransactions: true,
|
||||
},
|
||||
featureFlags: {},
|
||||
forgottenPassword: false,
|
||||
identities: {
|
||||
'0x5cfe73b6021e818b776b421b1c4db2474086a7e1': {
|
||||
@ -322,6 +320,7 @@ function defaultFixture() {
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function onboardingFixture() {
|
||||
return {
|
||||
data: {
|
||||
@ -380,9 +379,7 @@ function onboardingFixture() {
|
||||
advancedGasFee: null,
|
||||
currentLocale: 'en',
|
||||
dismissSeedBackUpReminder: false,
|
||||
featureFlags: {
|
||||
showIncomingTransactions: true,
|
||||
},
|
||||
featureFlags: {},
|
||||
forgottenPassword: false,
|
||||
identities: {},
|
||||
infuraBlocked: false,
|
||||
|
@ -16,9 +16,7 @@
|
||||
"advancedGasFee": null,
|
||||
"currentLocale": "en",
|
||||
"dismissSeedBackUpReminder": true,
|
||||
"featureFlags": {
|
||||
"showIncomingTransactions": true
|
||||
},
|
||||
"featureFlags": {},
|
||||
"forgottenPassword": false,
|
||||
"frequentRpcListDetail": [
|
||||
{
|
||||
|
@ -10,6 +10,7 @@ const {
|
||||
importWrongSRPOnboardingFlow,
|
||||
testSRPDropdownIterations,
|
||||
assertAccountBalanceForDOM,
|
||||
defaultGanacheOptions,
|
||||
} = require('../helpers');
|
||||
const FixtureBuilder = require('../fixture-builder');
|
||||
|
||||
@ -19,12 +20,12 @@ describe('MetaMask onboarding', function () {
|
||||
'test test test test test test test test test test test test';
|
||||
const wrongTestPassword = 'test test test test';
|
||||
|
||||
const ganacheOptions = {
|
||||
const ganacheOptions2 = {
|
||||
accounts: [
|
||||
{
|
||||
secretKey:
|
||||
'0x53CB0AB5226EEBF4D872113D98332C1555DC304443BEE1CF759D15798D3C55A9',
|
||||
balance: convertToHexValue(25000000000000000000),
|
||||
balance: convertToHexValue(10000000000000000000),
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -33,7 +34,7 @@ describe('MetaMask onboarding', function () {
|
||||
await withFixtures(
|
||||
{
|
||||
fixtures: new FixtureBuilder({ onboarding: true }).build(),
|
||||
ganacheOptions,
|
||||
ganacheOptions: defaultGanacheOptions,
|
||||
title: this.test.title,
|
||||
failOnConsoleError: false,
|
||||
},
|
||||
@ -54,7 +55,7 @@ describe('MetaMask onboarding', function () {
|
||||
await withFixtures(
|
||||
{
|
||||
fixtures: new FixtureBuilder({ onboarding: true }).build(),
|
||||
ganacheOptions,
|
||||
ganacheOptions: defaultGanacheOptions,
|
||||
title: this.test.title,
|
||||
failOnConsoleError: false,
|
||||
},
|
||||
@ -79,7 +80,7 @@ describe('MetaMask onboarding', function () {
|
||||
await withFixtures(
|
||||
{
|
||||
fixtures: new FixtureBuilder({ onboarding: true }).build(),
|
||||
ganacheOptions,
|
||||
ganacheOptions: defaultGanacheOptions,
|
||||
title: this.test.title,
|
||||
failOnConsoleError: false,
|
||||
},
|
||||
@ -101,7 +102,7 @@ describe('MetaMask onboarding', function () {
|
||||
await withFixtures(
|
||||
{
|
||||
fixtures: new FixtureBuilder({ onboarding: true }).build(),
|
||||
ganacheOptions,
|
||||
ganacheOptions: defaultGanacheOptions,
|
||||
title: this.test.title,
|
||||
failOnConsoleError: false,
|
||||
},
|
||||
@ -141,7 +142,7 @@ describe('MetaMask onboarding', function () {
|
||||
await withFixtures(
|
||||
{
|
||||
fixtures: new FixtureBuilder({ onboarding: true }).build(),
|
||||
ganacheOptions,
|
||||
ganacheOptions: defaultGanacheOptions,
|
||||
title: this.test.title,
|
||||
failOnConsoleError: false,
|
||||
},
|
||||
@ -162,11 +163,11 @@ describe('MetaMask onboarding', function () {
|
||||
);
|
||||
|
||||
// Check that the error message is displayed for the password fields
|
||||
const passwordErrorIsDisplayed = await driver.isElementPresent({
|
||||
text: "Passwords don't match",
|
||||
css: 'h6',
|
||||
});
|
||||
assert.equal(passwordErrorIsDisplayed, true);
|
||||
await driver.isElementPresent(
|
||||
{ text: "Passwords don't match", tag: 'h6' },
|
||||
true,
|
||||
);
|
||||
|
||||
// Check that the "Confirm Password" button is disabled
|
||||
const confirmPasswordButton = await driver.findElement(
|
||||
'[data-testid="create-password-wallet"]',
|
||||
@ -180,7 +181,7 @@ describe('MetaMask onboarding', function () {
|
||||
await withFixtures(
|
||||
{
|
||||
fixtures: new FixtureBuilder({ onboarding: true }).build(),
|
||||
ganacheOptions,
|
||||
ganacheOptions: defaultGanacheOptions,
|
||||
title: this.test.title,
|
||||
failOnConsoleError: false,
|
||||
},
|
||||
@ -204,7 +205,7 @@ describe('MetaMask onboarding', function () {
|
||||
await withFixtures(
|
||||
{
|
||||
fixtures: new FixtureBuilder({ onboarding: true }).build(),
|
||||
ganacheOptions,
|
||||
ganacheOptions: defaultGanacheOptions,
|
||||
title: this.test.title,
|
||||
failOnConsoleError: false,
|
||||
},
|
||||
@ -238,16 +239,6 @@ describe('MetaMask onboarding', function () {
|
||||
);
|
||||
});
|
||||
|
||||
const ganacheOptions2 = {
|
||||
accounts: [
|
||||
{
|
||||
secretKey:
|
||||
'0x53CB0AB5226EEBF4D872113D98332C1555DC304443BEE1CF759D15798D3C55A9',
|
||||
balance: convertToHexValue(10000000000000000000),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
it(`User can add custom network during onboarding`, async function () {
|
||||
const networkName = 'Localhost 8546';
|
||||
const networkUrl = 'http://127.0.0.1:8546';
|
||||
@ -258,7 +249,7 @@ describe('MetaMask onboarding', function () {
|
||||
{
|
||||
fixtures: new FixtureBuilder({ onboarding: true }).build(),
|
||||
ganacheOptions: {
|
||||
...ganacheOptions,
|
||||
...defaultGanacheOptions,
|
||||
concurrent: { port, chainId, ganacheOptions2 },
|
||||
},
|
||||
title: this.test.title,
|
||||
|
@ -109,7 +109,8 @@
|
||||
"useCurrencyRateCheck": "boolean",
|
||||
"openSeaEnabled": "boolean",
|
||||
"advancedGasFee": "object",
|
||||
"featureFlags": { "showIncomingTransactions": true },
|
||||
"featureFlags": {},
|
||||
"incomingTransactionsPreferences": "object",
|
||||
"knownMethodData": "object",
|
||||
"currentLocale": "en",
|
||||
"identities": "object",
|
||||
|
@ -20,7 +20,8 @@
|
||||
"pendingTokens": "object",
|
||||
"customNonceValue": "",
|
||||
"useBlockie": false,
|
||||
"featureFlags": { "showIncomingTransactions": true },
|
||||
"featureFlags": {},
|
||||
"incomingTransactionsPreferences": "object",
|
||||
"welcomeScreenSeen": false,
|
||||
"currentLocale": "en",
|
||||
"preferences": {
|
||||
|
@ -66,7 +66,7 @@
|
||||
"advancedGasFee": "object",
|
||||
"currentLocale": "en",
|
||||
"dismissSeedBackUpReminder": "boolean",
|
||||
"featureFlags": { "showIncomingTransactions": true },
|
||||
"featureFlags": {},
|
||||
"forgottenPassword": false,
|
||||
"identities": "object",
|
||||
"infuraBlocked": "boolean",
|
||||
|
@ -66,7 +66,7 @@
|
||||
"advancedGasFee": "object",
|
||||
"currentLocale": "en",
|
||||
"dismissSeedBackUpReminder": "boolean",
|
||||
"featureFlags": { "showIncomingTransactions": true },
|
||||
"featureFlags": {},
|
||||
"forgottenPassword": false,
|
||||
"identities": "object",
|
||||
"infuraBlocked": "boolean",
|
||||
|
@ -6,23 +6,22 @@ exports[`IncomingTransactionToggle should render existing incoming transaction p
|
||||
class="mm-box mm-incoming-transaction-toggle"
|
||||
>
|
||||
<p
|
||||
class="mm-box mm-text mm-text--body-lg-medium mm-text--font-weight-bold mm-box--color-text-default"
|
||||
class="mm-box mm-text mm-text--body-md-medium mm-box--color-text-default"
|
||||
>
|
||||
Show incoming transactions
|
||||
</p>
|
||||
<p
|
||||
class="mm-box mm-text mm-text--body-md mm-box--color-text-alternative"
|
||||
class="mm-box mm-text mm-text--body-sm mm-box--color-text-alternative"
|
||||
>
|
||||
This relies on each network which will have access to your Ethereum address and your IP address.
|
||||
</p>
|
||||
<div
|
||||
class="mm-box mm-box--margin-top-3 mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
class="mm-box mm-box--margin-top-3 mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
data-testid="incoming-transaction-toggle-enable-all"
|
||||
>
|
||||
<p
|
||||
class="mm-box mm-text mm-text--body-md mm-box--color-text-default"
|
||||
class="mm-box mm-text mm-text--body-sm-bold mm-box--color-text-default"
|
||||
>
|
||||
|
||||
Enable for all networks
|
||||
</p>
|
||||
<label
|
||||
|
@ -0,0 +1,26 @@
|
||||
import { StoryFn } from '@storybook/react';
|
||||
import React from 'react';
|
||||
import IncomingTransactionToggle from './incoming-transaction-toggle';
|
||||
import { ALL_NETWORKS_DATA, INCOMING_DATA } from './mock-data';
|
||||
|
||||
const IncomingTransactionToggleStory = {
|
||||
title: 'Components/App/IncomingTransactionToggle',
|
||||
component: IncomingTransactionToggle,
|
||||
argTypes: {},
|
||||
};
|
||||
|
||||
export const DefaultStory: StoryFn<typeof IncomingTransactionToggle> = () => {
|
||||
return (
|
||||
<IncomingTransactionToggle
|
||||
setIncomingTransactionsPreferences={(chainId, value) => {
|
||||
console.log(chainId, value);
|
||||
}}
|
||||
allNetworks={ALL_NETWORKS_DATA}
|
||||
incomingTransactionsPreferences={INCOMING_DATA}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
DefaultStory.storyName = 'Default';
|
||||
|
||||
export default IncomingTransactionToggleStory;
|
@ -6,81 +6,9 @@ import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||
import mockState from '../../../../test/data/mock-state.json';
|
||||
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
||||
import IncomingTransactionToggle from './incoming-transaction-toggle';
|
||||
import { ALL_NETWORKS_DATA, INCOMING_DATA } from './mock-data';
|
||||
|
||||
const mockTrackEvent = jest.fn();
|
||||
const ALL_NETWORKS_DATA = [
|
||||
{
|
||||
chainId: '0x1',
|
||||
nickname: 'Ethereum Mainnet',
|
||||
rpcUrl: 'https://mainnet.infura.io/v3/6c21df2a8dcb4a77b9bbcc1b65ee9ded',
|
||||
rpcPrefs: {
|
||||
imageUrl: './images/eth_logo.png',
|
||||
},
|
||||
providerType: 'mainnet',
|
||||
ticker: 'ETH',
|
||||
id: 'mainnet',
|
||||
removable: false,
|
||||
},
|
||||
{
|
||||
chainId: '0xe708',
|
||||
nickname: 'Linea Mainnet',
|
||||
rpcUrl:
|
||||
'https://linea-mainnet.infura.io/v3/6c21df2a8dcb4a77b9bbcc1b65ee9ded',
|
||||
rpcPrefs: {
|
||||
imageUrl: './images/linea-logo-mainnet.png',
|
||||
},
|
||||
providerType: 'linea-mainnet',
|
||||
id: 'linea-mainnet',
|
||||
removable: false,
|
||||
},
|
||||
{
|
||||
chainId: '0xfa',
|
||||
nickname: 'FANTOM',
|
||||
rpcPrefs: {},
|
||||
rpcUrl: 'http://ftmscan.com5',
|
||||
ticker: 'FTM',
|
||||
},
|
||||
{
|
||||
chainId: '0x5',
|
||||
nickname: 'Goerli',
|
||||
rpcUrl: 'https://goerli.infura.io/v3/6c21df2a8dcb4a77b9bbcc1b65ee9ded',
|
||||
providerType: 'goerli',
|
||||
ticker: 'GoerliETH',
|
||||
id: 'goerli',
|
||||
removable: false,
|
||||
},
|
||||
{
|
||||
chainId: '0xaa36a7',
|
||||
nickname: 'Sepolia',
|
||||
rpcUrl: 'https://sepolia.infura.io/v3/6c21df2a8dcb4a77b9bbcc1b65ee9ded',
|
||||
providerType: 'sepolia',
|
||||
ticker: 'SepoliaETH',
|
||||
id: 'sepolia',
|
||||
removable: false,
|
||||
},
|
||||
{
|
||||
chainId: '0xe704',
|
||||
nickname: 'Linea Goerli',
|
||||
rpcUrl:
|
||||
'https://linea-goerli.infura.io/v3/6c21df2a8dcb4a77b9bbcc1b65ee9ded',
|
||||
rpcPrefs: {
|
||||
imageUrl: './images/linea-logo-testnet.png',
|
||||
},
|
||||
providerType: 'linea-goerli',
|
||||
ticker: 'LineaETH',
|
||||
id: 'linea-goerli',
|
||||
removable: false,
|
||||
},
|
||||
];
|
||||
|
||||
const INCOMING_DATA = {
|
||||
'0x1': true,
|
||||
'0xe708': false,
|
||||
'0xfa': true,
|
||||
'0x5': false,
|
||||
'0xaa36a7': true,
|
||||
'0xe704': true,
|
||||
};
|
||||
|
||||
describe('IncomingTransactionToggle', () => {
|
||||
const mockStore = configureMockState([thunk])(mockState);
|
||||
|
@ -10,7 +10,6 @@ import {
|
||||
FlexDirection,
|
||||
JustifyContent,
|
||||
TextVariant,
|
||||
FontWeight,
|
||||
TextColor,
|
||||
} from '../../../helpers/constants/design-system';
|
||||
|
||||
@ -19,9 +18,9 @@ import { TEST_CHAINS } from '../../../../shared/constants/network';
|
||||
import NetworkToggle from './network-toggle';
|
||||
|
||||
interface IncomingTransactionToggleProps {
|
||||
wrapperRef: PolymorphicRef<any>;
|
||||
wrapperRef?: PolymorphicRef<any>;
|
||||
incomingTransactionsPreferences: Record<string, boolean>;
|
||||
allNetworks: [Record<string, any>];
|
||||
allNetworks: Record<string, any>[];
|
||||
setIncomingTransactionsPreferences: (
|
||||
chainId: string,
|
||||
isAllEnabledValue: boolean,
|
||||
@ -74,11 +73,11 @@ const IncomingTransactionToggle = ({
|
||||
|
||||
return (
|
||||
<Box ref={wrapperRef} className="mm-incoming-transaction-toggle">
|
||||
<Text variant={TextVariant.bodyLgMedium} fontWeight={FontWeight.Bold}>
|
||||
<Text variant={TextVariant.bodyMdMedium}>
|
||||
{t('showIncomingTransactions')}
|
||||
</Text>
|
||||
|
||||
<Text variant={TextVariant.bodyMd} color={TextColor.textAlternative}>
|
||||
<Text variant={TextVariant.bodySm} color={TextColor.textAlternative}>
|
||||
{t('showIncomingTransactionsInformation')}
|
||||
</Text>
|
||||
<Box
|
||||
@ -86,9 +85,12 @@ const IncomingTransactionToggle = ({
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Row}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
gap={4}
|
||||
data-testid="incoming-transaction-toggle-enable-all"
|
||||
>
|
||||
<Text variant={TextVariant.bodyMd}> {t('enableForAllNetworks')}</Text>
|
||||
<Text variant={TextVariant.bodySmBold}>
|
||||
{t('enableForAllNetworks')}
|
||||
</Text>
|
||||
<ToggleButton
|
||||
value={isAllEnabled}
|
||||
onToggle={(value) => toggleAllEnabled(!value)}
|
||||
|
73
ui/components/app/incoming-trasaction-toggle/mock-data.ts
Normal file
73
ui/components/app/incoming-trasaction-toggle/mock-data.ts
Normal file
@ -0,0 +1,73 @@
|
||||
export const ALL_NETWORKS_DATA = [
|
||||
{
|
||||
chainId: '0x1',
|
||||
nickname: 'Ethereum Mainnet',
|
||||
rpcUrl: 'https://mainnet.infura.io/v3/6c21df2a8dcb4a77b9bbcc1b65ee9ded',
|
||||
rpcPrefs: {
|
||||
imageUrl: './images/eth_logo.png',
|
||||
},
|
||||
providerType: 'mainnet',
|
||||
ticker: 'ETH',
|
||||
id: 'mainnet',
|
||||
removable: false,
|
||||
},
|
||||
{
|
||||
chainId: '0xe708',
|
||||
nickname: 'Linea Mainnet',
|
||||
rpcUrl:
|
||||
'https://linea-mainnet.infura.io/v3/6c21df2a8dcb4a77b9bbcc1b65ee9ded',
|
||||
rpcPrefs: {
|
||||
imageUrl: './images/linea-logo-mainnet.png',
|
||||
},
|
||||
providerType: 'linea-mainnet',
|
||||
id: 'linea-mainnet',
|
||||
removable: false,
|
||||
},
|
||||
{
|
||||
chainId: '0xfa',
|
||||
nickname: 'FANTOM',
|
||||
rpcPrefs: {},
|
||||
rpcUrl: 'http://ftmscan.com5',
|
||||
ticker: 'FTM',
|
||||
},
|
||||
{
|
||||
chainId: '0x5',
|
||||
nickname: 'Goerli',
|
||||
rpcUrl: 'https://goerli.infura.io/v3/6c21df2a8dcb4a77b9bbcc1b65ee9ded',
|
||||
providerType: 'goerli',
|
||||
ticker: 'GoerliETH',
|
||||
id: 'goerli',
|
||||
removable: false,
|
||||
},
|
||||
{
|
||||
chainId: '0xaa36a7',
|
||||
nickname: 'Sepolia',
|
||||
rpcUrl: 'https://sepolia.infura.io/v3/6c21df2a8dcb4a77b9bbcc1b65ee9ded',
|
||||
providerType: 'sepolia',
|
||||
ticker: 'SepoliaETH',
|
||||
id: 'sepolia',
|
||||
removable: false,
|
||||
},
|
||||
{
|
||||
chainId: '0xe704',
|
||||
nickname: 'Linea Goerli',
|
||||
rpcUrl:
|
||||
'https://linea-goerli.infura.io/v3/6c21df2a8dcb4a77b9bbcc1b65ee9ded',
|
||||
rpcPrefs: {
|
||||
imageUrl: './images/linea-logo-testnet.png',
|
||||
},
|
||||
providerType: 'linea-goerli',
|
||||
ticker: 'LineaETH',
|
||||
id: 'linea-goerli',
|
||||
removable: false,
|
||||
},
|
||||
];
|
||||
|
||||
export const INCOMING_DATA = {
|
||||
'0x1': true,
|
||||
'0xe708': false,
|
||||
'0xfa': true,
|
||||
'0x5': false,
|
||||
'0xaa36a7': true,
|
||||
'0xe704': true,
|
||||
};
|
@ -74,7 +74,6 @@ const customStore = ({
|
||||
// pendingTransactions
|
||||
featureFlags: {
|
||||
...testData?.metamask?.featureFlags,
|
||||
showIncomingTransactions: pendingCount > 0,
|
||||
},
|
||||
incomingTransactions: {
|
||||
...testData?.metamask?.incomingTransactions,
|
||||
|
@ -21,28 +21,11 @@ import {
|
||||
Box,
|
||||
} from '../../component-library';
|
||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||
import { getAvatarNetworkColor } from '../../../helpers/utils/accounts';
|
||||
import Tooltip from '../../ui/tooltip/tooltip';
|
||||
import {
|
||||
GOERLI_DISPLAY_NAME,
|
||||
LINEA_GOERLI_DISPLAY_NAME,
|
||||
SEPOLIA_DISPLAY_NAME,
|
||||
} from '../../../../shared/constants/network';
|
||||
|
||||
const MAXIMUM_CHARACTERS_WITHOUT_TOOLTIP = 20;
|
||||
|
||||
function getAvatarNetworkColor(name) {
|
||||
switch (name) {
|
||||
case GOERLI_DISPLAY_NAME:
|
||||
return BackgroundColor.goerli;
|
||||
case LINEA_GOERLI_DISPLAY_NAME:
|
||||
return BackgroundColor.lineaGoerli;
|
||||
case SEPOLIA_DISPLAY_NAME:
|
||||
return BackgroundColor.sepolia;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export const NetworkListItem = ({
|
||||
name,
|
||||
iconSrc,
|
||||
|
@ -1,7 +1,6 @@
|
||||
.toggle-button {
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
|
||||
$self: &;
|
||||
|
||||
&__status {
|
||||
|
@ -1,4 +1,10 @@
|
||||
import { InvisibleCharacter } from '../../components/component-library';
|
||||
import {
|
||||
GOERLI_DISPLAY_NAME,
|
||||
LINEA_GOERLI_DISPLAY_NAME,
|
||||
SEPOLIA_DISPLAY_NAME,
|
||||
} from '../../../shared/constants/network';
|
||||
import { BackgroundColor } from '../constants/design-system';
|
||||
|
||||
export function getAccountNameErrorMessage(
|
||||
accounts,
|
||||
@ -41,3 +47,16 @@ export function getAccountNameErrorMessage(
|
||||
|
||||
return { isValidAccountName, errorMessage };
|
||||
}
|
||||
|
||||
export function getAvatarNetworkColor(name) {
|
||||
switch (name) {
|
||||
case GOERLI_DISPLAY_NAME:
|
||||
return BackgroundColor.goerli;
|
||||
case LINEA_GOERLI_DISPLAY_NAME:
|
||||
return BackgroundColor.lineaGoerli;
|
||||
case SEPOLIA_DISPLAY_NAME:
|
||||
return BackgroundColor.sepolia;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
@ -1,47 +1,79 @@
|
||||
import { getAccountNameErrorMessage } from './accounts';
|
||||
import {
|
||||
GOERLI_DISPLAY_NAME,
|
||||
LINEA_GOERLI_DISPLAY_NAME,
|
||||
MAINNET_DISPLAY_NAME,
|
||||
SEPOLIA_DISPLAY_NAME,
|
||||
} from '../../../shared/constants/network';
|
||||
import { BackgroundColor } from '../constants/design-system';
|
||||
import { getAccountNameErrorMessage, getAvatarNetworkColor } from './accounts';
|
||||
|
||||
const mockAccounts = [{ name: 'Account 1' }, { name: 'Account 2' }];
|
||||
|
||||
const mockLocalization = { t: jest.fn().mockReturnValue('Account') };
|
||||
|
||||
describe('Accounts', () => {
|
||||
it('does not allow duplicate names', () => {
|
||||
const { isValidAccountName } = getAccountNameErrorMessage(
|
||||
mockAccounts,
|
||||
mockLocalization,
|
||||
'Account 2',
|
||||
'Account 3',
|
||||
);
|
||||
expect(isValidAccountName).toBe(false);
|
||||
describe('#getAccountNameErrorMessage', () => {
|
||||
it('does not allow duplicate names', () => {
|
||||
const { isValidAccountName } = getAccountNameErrorMessage(
|
||||
mockAccounts,
|
||||
mockLocalization,
|
||||
'Account 2',
|
||||
'Account 3',
|
||||
);
|
||||
expect(isValidAccountName).toBe(false);
|
||||
});
|
||||
|
||||
it('does not allow reserved name patterns', () => {
|
||||
const { isValidAccountName } = getAccountNameErrorMessage(
|
||||
mockAccounts,
|
||||
mockLocalization,
|
||||
'Account 7',
|
||||
'Account 3',
|
||||
);
|
||||
expect(isValidAccountName).toBe(false);
|
||||
});
|
||||
|
||||
it('does not allow reserved name patterns in lowercase', () => {
|
||||
const { isValidAccountName } = getAccountNameErrorMessage(
|
||||
mockAccounts,
|
||||
mockLocalization,
|
||||
'account 7',
|
||||
'Account 3',
|
||||
);
|
||||
expect(isValidAccountName).toBe(false);
|
||||
});
|
||||
|
||||
it('allows proposed name in lowercase', () => {
|
||||
const { isValidAccountName } = getAccountNameErrorMessage(
|
||||
mockAccounts,
|
||||
mockLocalization,
|
||||
'account 3',
|
||||
'Account 3',
|
||||
);
|
||||
expect(isValidAccountName).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('does not allow reserved name patterns', () => {
|
||||
const { isValidAccountName } = getAccountNameErrorMessage(
|
||||
mockAccounts,
|
||||
mockLocalization,
|
||||
'Account 7',
|
||||
'Account 3',
|
||||
);
|
||||
expect(isValidAccountName).toBe(false);
|
||||
});
|
||||
|
||||
it('does not allow reserved name patterns in lowercase', () => {
|
||||
const { isValidAccountName } = getAccountNameErrorMessage(
|
||||
mockAccounts,
|
||||
mockLocalization,
|
||||
'account 7',
|
||||
'Account 3',
|
||||
);
|
||||
expect(isValidAccountName).toBe(false);
|
||||
});
|
||||
|
||||
it('allows proposed name in lowercase', () => {
|
||||
const { isValidAccountName } = getAccountNameErrorMessage(
|
||||
mockAccounts,
|
||||
mockLocalization,
|
||||
'account 3',
|
||||
'Account 3',
|
||||
);
|
||||
expect(isValidAccountName).toBe(true);
|
||||
describe('#getAvatarNetworkColor', () => {
|
||||
it('should return goerli', () => {
|
||||
expect(getAvatarNetworkColor(GOERLI_DISPLAY_NAME)).toStrictEqual(
|
||||
BackgroundColor.goerli,
|
||||
);
|
||||
});
|
||||
it('should return lineaGoerli', () => {
|
||||
expect(getAvatarNetworkColor(LINEA_GOERLI_DISPLAY_NAME)).toStrictEqual(
|
||||
BackgroundColor.lineaGoerli,
|
||||
);
|
||||
});
|
||||
it('should return sepolia', () => {
|
||||
expect(getAvatarNetworkColor(SEPOLIA_DISPLAY_NAME)).toStrictEqual(
|
||||
BackgroundColor.sepolia,
|
||||
);
|
||||
});
|
||||
it('should return undefined', () => {
|
||||
expect(getAvatarNetworkColor(MAINNET_DISPLAY_NAME)).toStrictEqual(
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -71,8 +71,6 @@ const t = (key) => {
|
||||
return 'Reveal Secret Recovery Phrase';
|
||||
case 'showIncomingTransactions':
|
||||
return 'Show incoming transactions';
|
||||
case 'showIncomingTransactionsDescription':
|
||||
return 'Select this to use Etherscan to show incoming transactions in the transactions list';
|
||||
case 'usePhishingDetection':
|
||||
return 'Use phishing detection';
|
||||
case 'usePhishingDetectionDescription':
|
||||
|
@ -19,7 +19,7 @@ import {
|
||||
ONBOARDING_PIN_EXTENSION_ROUTE,
|
||||
ONBOARDING_METAMETRICS,
|
||||
} from '../../helpers/constants/routes';
|
||||
import { NETWORK_TYPES } from '../../../shared/constants/network';
|
||||
import { CHAIN_IDS, NETWORK_TYPES } from '../../../shared/constants/network';
|
||||
import {
|
||||
createNewVaultAndGetSeedPhrase,
|
||||
unlockAndGetSeedPhrase,
|
||||
@ -41,6 +41,9 @@ describe('Onboarding Flow', () => {
|
||||
type: NETWORK_TYPES.GOERLI,
|
||||
chainId: '0x0',
|
||||
},
|
||||
incomingTransactionsPreferences: {
|
||||
[CHAIN_IDS.MAINNET]: true,
|
||||
},
|
||||
},
|
||||
localeMessages: {
|
||||
currentLocale: 'en',
|
||||
|
@ -23,9 +23,7 @@
|
||||
|
||||
&__settings {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
max-width: 620px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
|
@ -27,10 +27,9 @@ import {
|
||||
} from '../../../helpers/constants/design-system';
|
||||
import { ONBOARDING_PIN_EXTENSION_ROUTE } from '../../../helpers/constants/routes';
|
||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||
import { getCurrentNetwork } from '../../../selectors';
|
||||
import { getAllNetworks, getCurrentNetwork } from '../../../selectors';
|
||||
import {
|
||||
setCompletedOnboarding,
|
||||
setFeatureFlag,
|
||||
setIpfsGateway,
|
||||
setUseCurrencyRateCheck,
|
||||
setUseMultiAccountBalanceChecker,
|
||||
@ -40,19 +39,23 @@ import {
|
||||
setUseAddressBarEnsResolution,
|
||||
showModal,
|
||||
toggleNetworkMenu,
|
||||
setIncomingTransactionsPreferences,
|
||||
} from '../../../store/actions';
|
||||
import IncomingTransactionToggle from '../../../components/app/incoming-trasaction-toggle/incoming-transaction-toggle';
|
||||
import { Setting } from './setting';
|
||||
|
||||
export default function PrivacySettings() {
|
||||
const t = useI18nContext();
|
||||
const dispatch = useDispatch();
|
||||
const history = useHistory();
|
||||
const { incomingTransactionsPreferences } = useSelector(
|
||||
(state) => state.metamask,
|
||||
);
|
||||
|
||||
const [usePhishingDetection, setUsePhishingDetection] = useState(true);
|
||||
const [turnOn4ByteResolution, setTurnOn4ByteResolution] = useState(true);
|
||||
const [turnOnTokenDetection, setTurnOnTokenDetection] = useState(true);
|
||||
const [turnOnCurrencyRateCheck, setTurnOnCurrencyRateCheck] = useState(true);
|
||||
const [showIncomingTransactions, setShowIncomingTransactions] =
|
||||
useState(true);
|
||||
const [
|
||||
isMultiAccountBalanceCheckerEnabled,
|
||||
setMultiAccountBalanceCheckerEnabled,
|
||||
@ -63,11 +66,9 @@ export default function PrivacySettings() {
|
||||
const trackEvent = useContext(MetaMetricsContext);
|
||||
|
||||
const currentNetwork = useSelector(getCurrentNetwork);
|
||||
const allNetworks = useSelector(getAllNetworks);
|
||||
|
||||
const handleSubmit = () => {
|
||||
dispatch(
|
||||
setFeatureFlag('showIncomingTransactions', showIncomingTransactions),
|
||||
);
|
||||
dispatch(setUsePhishDetect(usePhishingDetection));
|
||||
dispatch(setUse4ByteResolution(turnOn4ByteResolution));
|
||||
dispatch(setUseTokenDetection(turnOnTokenDetection));
|
||||
@ -87,7 +88,7 @@ export default function PrivacySettings() {
|
||||
category: MetaMetricsEventCategory.Onboarding,
|
||||
event: MetaMetricsEventName.OnboardingWalletAdvancedSettings,
|
||||
properties: {
|
||||
show_incoming_tx: showIncomingTransactions,
|
||||
show_incoming_tx: incomingTransactionsPreferences,
|
||||
use_phising_detection: usePhishingDetection,
|
||||
turnon_token_detection: turnOnTokenDetection,
|
||||
},
|
||||
@ -124,28 +125,12 @@ export default function PrivacySettings() {
|
||||
className="privacy-settings__settings"
|
||||
data-testid="privacy-settings-settings"
|
||||
>
|
||||
<Setting
|
||||
value={showIncomingTransactions}
|
||||
setValue={setShowIncomingTransactions}
|
||||
title={t('showIncomingTransactions')}
|
||||
description={t('onboardingShowIncomingTransactionsDescription', [
|
||||
<a
|
||||
key="etherscan"
|
||||
href="https://etherscan.io/"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{t('etherscan')}
|
||||
</a>,
|
||||
<a
|
||||
href="https://etherscan.io/privacyPolicy"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
key="privacyMsg"
|
||||
>
|
||||
{t('privacyMsg')}
|
||||
</a>,
|
||||
])}
|
||||
<IncomingTransactionToggle
|
||||
allNetworks={allNetworks}
|
||||
setIncomingTransactionsPreferences={(chainId, value) =>
|
||||
dispatch(setIncomingTransactionsPreferences(chainId, value))
|
||||
}
|
||||
incomingTransactionsPreferences={incomingTransactionsPreferences}
|
||||
/>
|
||||
<Setting
|
||||
value={usePhishingDetection}
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
renderWithProvider,
|
||||
setBackgroundConnection,
|
||||
} from '../../../../test/jest';
|
||||
import { CHAIN_IDS } from '../../../../shared/constants/network';
|
||||
import PrivacySettings from './privacy-settings';
|
||||
|
||||
describe('Privacy Settings Onboarding View', () => {
|
||||
@ -15,6 +16,13 @@ describe('Privacy Settings Onboarding View', () => {
|
||||
providerConfig: {
|
||||
type: 'test',
|
||||
},
|
||||
incomingTransactionsPreferences: {
|
||||
[CHAIN_IDS.MAINNET]: true,
|
||||
[CHAIN_IDS.LINEA_MAINNET]: false,
|
||||
[CHAIN_IDS.GOERLI]: false,
|
||||
[CHAIN_IDS.SEPOLIA]: false,
|
||||
[CHAIN_IDS.LINEA_GOERLI]: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -30,6 +38,7 @@ describe('Privacy Settings Onboarding View', () => {
|
||||
.mockImplementation(() => Promise.resolve());
|
||||
const setUseMultiAccountBalanceCheckerStub = jest.fn();
|
||||
const setUseAddressBarEnsResolutionStub = jest.fn();
|
||||
const setIncomingTransactionsPreferencesStub = jest.fn();
|
||||
|
||||
setBackgroundConnection({
|
||||
setFeatureFlag: setFeatureFlagStub,
|
||||
@ -41,6 +50,7 @@ describe('Privacy Settings Onboarding View', () => {
|
||||
completeOnboarding: completeOnboardingStub,
|
||||
setUseMultiAccountBalanceChecker: setUseMultiAccountBalanceCheckerStub,
|
||||
setUseAddressBarEnsResolution: setUseAddressBarEnsResolutionStub,
|
||||
setIncomingTransactionsPreferences: setIncomingTransactionsPreferencesStub,
|
||||
});
|
||||
|
||||
it('should update preferences', () => {
|
||||
@ -49,28 +59,28 @@ describe('Privacy Settings Onboarding View', () => {
|
||||
store,
|
||||
);
|
||||
// All settings are initialized toggled to true
|
||||
expect(setFeatureFlagStub).toHaveBeenCalledTimes(0);
|
||||
expect(setUsePhishDetectStub).toHaveBeenCalledTimes(0);
|
||||
expect(setUse4ByteResolutionStub).toHaveBeenCalledTimes(0);
|
||||
expect(setUseTokenDetectionStub).toHaveBeenCalledTimes(0);
|
||||
expect(setUseMultiAccountBalanceCheckerStub).toHaveBeenCalledTimes(0);
|
||||
expect(setUseCurrencyRateCheckStub).toHaveBeenCalledTimes(0);
|
||||
expect(setUseAddressBarEnsResolutionStub).toHaveBeenCalledTimes(0);
|
||||
expect(setIncomingTransactionsPreferencesStub).toHaveBeenCalledTimes(0);
|
||||
|
||||
const toggles = container.querySelectorAll('input[type=checkbox]');
|
||||
const submitButton = getByText('Done');
|
||||
|
||||
// toggle to false
|
||||
fireEvent.click(toggles[0]);
|
||||
fireEvent.click(toggles[1]);
|
||||
fireEvent.click(toggles[2]);
|
||||
fireEvent.click(toggles[3]);
|
||||
fireEvent.click(toggles[4]);
|
||||
fireEvent.click(toggles[5]);
|
||||
fireEvent.click(toggles[6]);
|
||||
fireEvent.click(toggles[7]);
|
||||
fireEvent.click(toggles[8]);
|
||||
fireEvent.click(toggles[9]);
|
||||
fireEvent.click(toggles[10]);
|
||||
fireEvent.click(toggles[11]);
|
||||
|
||||
fireEvent.click(submitButton);
|
||||
|
||||
expect(setFeatureFlagStub).toHaveBeenCalledTimes(1);
|
||||
expect(setIncomingTransactionsPreferencesStub).toHaveBeenCalledTimes(1);
|
||||
expect(setUsePhishDetectStub).toHaveBeenCalledTimes(1);
|
||||
expect(setUse4ByteResolutionStub).toHaveBeenCalledTimes(1);
|
||||
expect(setUseTokenDetectionStub).toHaveBeenCalledTimes(1);
|
||||
@ -78,7 +88,12 @@ describe('Privacy Settings Onboarding View', () => {
|
||||
expect(setUseCurrencyRateCheckStub).toHaveBeenCalledTimes(1);
|
||||
expect(setUseAddressBarEnsResolutionStub).toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(setFeatureFlagStub.mock.calls[0][1]).toStrictEqual(false);
|
||||
expect(setIncomingTransactionsPreferencesStub).toHaveBeenCalledWith(
|
||||
CHAIN_IDS.MAINNET,
|
||||
false,
|
||||
expect.anything(),
|
||||
);
|
||||
|
||||
expect(setUsePhishDetectStub.mock.calls[0][0]).toStrictEqual(false);
|
||||
expect(setUse4ByteResolutionStub.mock.calls[0][0]).toStrictEqual(false);
|
||||
expect(setUseTokenDetectionStub.mock.calls[0][0]).toStrictEqual(false);
|
||||
@ -89,35 +104,6 @@ describe('Privacy Settings Onboarding View', () => {
|
||||
expect(setUseAddressBarEnsResolutionStub.mock.calls[0][0]).toStrictEqual(
|
||||
false,
|
||||
);
|
||||
|
||||
// toggle back to true
|
||||
fireEvent.click(toggles[0]);
|
||||
fireEvent.click(toggles[1]);
|
||||
fireEvent.click(toggles[2]);
|
||||
fireEvent.click(toggles[3]);
|
||||
fireEvent.click(toggles[4]);
|
||||
fireEvent.click(toggles[5]);
|
||||
fireEvent.click(toggles[6]);
|
||||
fireEvent.click(submitButton);
|
||||
expect(setFeatureFlagStub).toHaveBeenCalledTimes(2);
|
||||
expect(setUsePhishDetectStub).toHaveBeenCalledTimes(2);
|
||||
expect(setUse4ByteResolutionStub).toHaveBeenCalledTimes(2);
|
||||
expect(setUseTokenDetectionStub).toHaveBeenCalledTimes(2);
|
||||
expect(setUseMultiAccountBalanceCheckerStub).toHaveBeenCalledTimes(2);
|
||||
expect(setUseCurrencyRateCheckStub).toHaveBeenCalledTimes(2);
|
||||
expect(setUseAddressBarEnsResolutionStub).toHaveBeenCalledTimes(2);
|
||||
|
||||
expect(setFeatureFlagStub.mock.calls[1][1]).toStrictEqual(true);
|
||||
expect(setUsePhishDetectStub.mock.calls[1][0]).toStrictEqual(true);
|
||||
expect(setUse4ByteResolutionStub.mock.calls[1][0]).toStrictEqual(true);
|
||||
expect(setUseTokenDetectionStub.mock.calls[1][0]).toStrictEqual(true);
|
||||
expect(setUseMultiAccountBalanceCheckerStub.mock.calls[1][0]).toStrictEqual(
|
||||
true,
|
||||
);
|
||||
expect(setUseCurrencyRateCheckStub.mock.calls[1][0]).toStrictEqual(true);
|
||||
expect(setUseAddressBarEnsResolutionStub.mock.calls[1][0]).toStrictEqual(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
describe('IPFS', () => {
|
||||
|
@ -7,7 +7,6 @@ import {
|
||||
TextVariant,
|
||||
AlignItems,
|
||||
Display,
|
||||
FontWeight,
|
||||
} from '../../../helpers/constants/design-system';
|
||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||
|
||||
@ -30,10 +29,8 @@ export const Setting = ({
|
||||
className="privacy-settings__setting__wrapper"
|
||||
>
|
||||
<div className="privacy-settings__setting">
|
||||
<Text variant={TextVariant.bodyLgMedium} fontWeight={FontWeight.Bold}>
|
||||
{title}
|
||||
</Text>
|
||||
<Text variant={TextVariant.bodyMd} as="div">
|
||||
<Text variant={TextVariant.bodyMdMedium}>{title}</Text>
|
||||
<Text variant={TextVariant.bodySm} as="div">
|
||||
{description}
|
||||
</Text>
|
||||
</div>
|
||||
|
@ -70,7 +70,7 @@ exports[`AdvancedTab Component should match snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
data-testid="advanced-setting-hex-data"
|
||||
>
|
||||
<div
|
||||
@ -136,7 +136,7 @@ exports[`AdvancedTab Component should match snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
data-testid="advanced-setting-show-testnet-conversion"
|
||||
>
|
||||
<div
|
||||
@ -202,7 +202,7 @@ exports[`AdvancedTab Component should match snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
data-testid="advanced-setting-show-testnet-conversion"
|
||||
>
|
||||
<div
|
||||
@ -268,7 +268,7 @@ exports[`AdvancedTab Component should match snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
data-testid="advanced-setting-custom-nonce"
|
||||
>
|
||||
<div
|
||||
@ -520,7 +520,7 @@ exports[`AdvancedTab Component should match snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
data-testid="advanced-setting-dismiss-reminder"
|
||||
>
|
||||
<div
|
||||
|
@ -262,6 +262,7 @@ export default class AdvancedTab extends PureComponent {
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Row}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
gap={4}
|
||||
data-testid="advanced-setting-hex-data"
|
||||
>
|
||||
<div className="settings-page__content-item">
|
||||
@ -294,6 +295,7 @@ export default class AdvancedTab extends PureComponent {
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Row}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
gap={4}
|
||||
data-testid="advanced-setting-show-testnet-conversion"
|
||||
>
|
||||
<div className="settings-page__content-item">
|
||||
@ -329,6 +331,7 @@ export default class AdvancedTab extends PureComponent {
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Row}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
gap={4}
|
||||
>
|
||||
<div className="settings-page__content-item">
|
||||
<span>{t('showTestnetNetworks')}</span>
|
||||
@ -361,6 +364,7 @@ export default class AdvancedTab extends PureComponent {
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Row}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
gap={4}
|
||||
>
|
||||
<div className="settings-page__content-item">
|
||||
<span>{t('nonceField')}</span>
|
||||
@ -551,6 +555,7 @@ export default class AdvancedTab extends PureComponent {
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Row}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
gap={4}
|
||||
>
|
||||
<div className="settings-page__content-item">
|
||||
<span>{t('dismissReminderField')}</span>
|
||||
|
@ -273,8 +273,6 @@
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
|
||||
@include screen-sm-max {
|
||||
height: initial;
|
||||
|
@ -47,7 +47,7 @@ exports[`Security Tab should match snapshot 1`] = `
|
||||
class="settings-page__content-padded"
|
||||
>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
@ -124,7 +124,7 @@ exports[`Security Tab should match snapshot 1`] = `
|
||||
class="settings-page__content-padded"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-row"
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
@ -139,58 +139,54 @@ exports[`Security Tab should match snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
class="settings-page__content-item-col"
|
||||
data-testid="4byte-resolution-container"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item-col"
|
||||
data-testid="4byte-resolution-container"
|
||||
<label
|
||||
class="toggle-button toggle-button--on"
|
||||
tabindex="0"
|
||||
>
|
||||
<label
|
||||
class="toggle-button toggle-button--on"
|
||||
tabindex="0"
|
||||
<div
|
||||
style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;"
|
||||
>
|
||||
<div
|
||||
style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;"
|
||||
style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(242, 244, 246);"
|
||||
>
|
||||
<div
|
||||
style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(242, 244, 246);"
|
||||
>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;"
|
||||
/>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgba(255, 255, 255, 0.6); bottom: 0px; margin-top: auto; margin-bottom: auto; padding-right: 5px; line-height: 0; width: 26px; height: 20px; opacity: 0;"
|
||||
/>
|
||||
</div>
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;"
|
||||
/>
|
||||
<div
|
||||
style="position: absolute; height: 100%; top: 0px; left: 0px; display: flex; flex: 1; align-self: stretch; align-items: center; justify-content: flex-start;"
|
||||
>
|
||||
<div
|
||||
style="width: 18px; height: 18px; display: flex; align-self: center; box-shadow: none; border-radius: 50%; box-sizing: border-box; position: relative; background-color: rgb(3, 125, 214); left: 18px;"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px;"
|
||||
type="checkbox"
|
||||
value="true"
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgba(255, 255, 255, 0.6); bottom: 0px; margin-top: auto; margin-bottom: auto; padding-right: 5px; line-height: 0; width: 26px; height: 20px; opacity: 0;"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="toggle-button__status"
|
||||
style="position: absolute; height: 100%; top: 0px; left: 0px; display: flex; flex: 1; align-self: stretch; align-items: center; justify-content: flex-start;"
|
||||
>
|
||||
<span
|
||||
class="toggle-button__label-off"
|
||||
>
|
||||
Off
|
||||
</span>
|
||||
<span
|
||||
class="toggle-button__label-on"
|
||||
>
|
||||
On
|
||||
</span>
|
||||
<div
|
||||
style="width: 18px; height: 18px; display: flex; align-self: center; box-shadow: none; border-radius: 50%; box-sizing: border-box; position: relative; background-color: rgb(3, 125, 214); left: 18px;"
|
||||
/>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<input
|
||||
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px;"
|
||||
type="checkbox"
|
||||
value="true"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="toggle-button__status"
|
||||
>
|
||||
<span
|
||||
class="toggle-button__label-off"
|
||||
>
|
||||
Off
|
||||
</span>
|
||||
<span
|
||||
class="toggle-button__label-on"
|
||||
>
|
||||
On
|
||||
</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -203,7 +199,7 @@ exports[`Security Tab should match snapshot 1`] = `
|
||||
class="settings-page__content-padded"
|
||||
>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
@ -297,44 +293,27 @@ exports[`Security Tab should match snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
class="mm-box mm-incoming-transaction-toggle"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
<p
|
||||
class="mm-box mm-text mm-text--body-md-medium mm-box--color-text-default"
|
||||
>
|
||||
<span>
|
||||
Show incoming transactions
|
||||
</span>
|
||||
<div
|
||||
class="settings-page__content-description"
|
||||
Show incoming transactions
|
||||
</p>
|
||||
<p
|
||||
class="mm-box mm-text mm-text--body-sm mm-box--color-text-alternative"
|
||||
>
|
||||
This relies on each network which will have access to your Ethereum address and your IP address.
|
||||
</p>
|
||||
<div
|
||||
class="mm-box mm-box--margin-top-3 mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
data-testid="incoming-transaction-toggle-enable-all"
|
||||
>
|
||||
<p
|
||||
class="mm-box mm-text mm-text--body-sm-bold mm-box--color-text-default"
|
||||
>
|
||||
<span>
|
||||
|
||||
This relies on
|
||||
<a
|
||||
href="https://etherscan.io/privacyPolicy"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Etherscan
|
||||
</a>
|
||||
which will have access to your Ethereum address and your IP address.
|
||||
<a
|
||||
href="https://consensys.net/privacy-policy/"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Privacy policy
|
||||
</a>
|
||||
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="settings-page__content-item-col"
|
||||
data-testid="showIncomingTransactions"
|
||||
>
|
||||
Enable for all networks
|
||||
</p>
|
||||
<label
|
||||
class="toggle-button toggle-button--off"
|
||||
tabindex="0"
|
||||
@ -381,75 +360,24 @@ exports[`Security Tab should match snapshot 1`] = `
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
class="settings-page__security-tab-sub-header"
|
||||
>
|
||||
Network provider
|
||||
</span>
|
||||
<div
|
||||
class="settings-page__content-padded"
|
||||
>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--flex-direction-column"
|
||||
data-testid="advanced-setting-choose-your-network"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
class="mm-box network-toggle-wrapper mm-box--margin-top-6 mm-box--margin-bottom-6 mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
data-testid="network-toggle-0x1"
|
||||
>
|
||||
<span>
|
||||
Choose your network
|
||||
</span>
|
||||
<div
|
||||
class="settings-page__content-description"
|
||||
class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--align-items-center mm-box--width-full mm-box--background-color-transparent"
|
||||
>
|
||||
<span>
|
||||
|
||||
We use Infura as our remote procedure call (RPC) provider to offer the most reliable and private access to Ethereum data we can. You can choose your own RPC, but remember that any RPC will receive your IP address and Ethereum wallet to make transactions. Read our
|
||||
<a
|
||||
href="https://consensys.net/privacy-policy/"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Privacy policy
|
||||
</a>
|
||||
to learn more about how Infura handles data.
|
||||
|
||||
</span>
|
||||
<div
|
||||
class="mm-box mm-text mm-avatar-base mm-avatar-base--size-sm mm-avatar-network mm-text--body-sm mm-text--text-transform-uppercase mm-box--display-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-full mm-box--border-color-transparent box--border-style-solid box--border-width-1"
|
||||
>
|
||||
C
|
||||
</div>
|
||||
<p
|
||||
class="mm-box mm-text mm-text--body-md mm-text--ellipsis mm-box--margin-left-2 mm-box--color-text-default mm-box--background-color-transparent"
|
||||
>
|
||||
Custom Mainnet RPC
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="settings-page__content-item-col"
|
||||
>
|
||||
<button
|
||||
class="mm-box mm-text mm-button-base mm-button-base--size-md settings-page__button mm-button-primary mm-text--body-md-medium mm-box--padding-0 mm-box--padding-right-4 mm-box--padding-left-4 mm-box--display-inline-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-primary-inverse mm-box--background-color-primary-default mm-box--rounded-pill"
|
||||
type="secondary"
|
||||
>
|
||||
Add custom network
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--flex-direction-column"
|
||||
data-testid="setting-ipfs-gateway"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
>
|
||||
<span>
|
||||
IPFS gateway
|
||||
</span>
|
||||
<div
|
||||
class="settings-page__content-description"
|
||||
>
|
||||
MetaMask uses third-party services to show images of your NFTs stored on IPFS, display information related to ENS addresses entered in your browser's address bar, and fetch icons for different tokens. Your IP address may be exposed to these services when you’re using them.
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="settings-page__content-item-col"
|
||||
data-testid="ipfsToggle"
|
||||
>
|
||||
<label
|
||||
class="toggle-button toggle-button--on"
|
||||
tabindex="0"
|
||||
@ -496,6 +424,389 @@ exports[`Security Tab should match snapshot 1`] = `
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="mm-box network-toggle-wrapper mm-box--margin-top-6 mm-box--margin-bottom-6 mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
data-testid="network-toggle-0xe708"
|
||||
>
|
||||
<div
|
||||
class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--align-items-center mm-box--width-full mm-box--background-color-transparent"
|
||||
>
|
||||
<div
|
||||
class="mm-box mm-text mm-avatar-base mm-avatar-base--size-sm mm-avatar-network mm-text--body-sm mm-text--text-transform-uppercase mm-box--display-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-full mm-box--border-color-transparent box--border-style-solid box--border-width-1"
|
||||
>
|
||||
<img
|
||||
alt="Linea Mainnet logo"
|
||||
class="mm-avatar-network__network-image"
|
||||
src="./images/linea-logo-mainnet.png"
|
||||
/>
|
||||
</div>
|
||||
<p
|
||||
class="mm-box mm-text mm-text--body-md mm-text--ellipsis mm-box--margin-left-2 mm-box--color-text-default mm-box--background-color-transparent"
|
||||
>
|
||||
Linea Mainnet
|
||||
</p>
|
||||
</div>
|
||||
<label
|
||||
class="toggle-button toggle-button--off"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;"
|
||||
>
|
||||
<div
|
||||
style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(242, 244, 246);"
|
||||
>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;"
|
||||
/>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgba(255, 255, 255, 0.6); bottom: 0px; margin-top: auto; margin-bottom: auto; padding-right: 5px; line-height: 0; width: 26px; height: 20px; opacity: 1;"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style="position: absolute; height: 100%; top: 0px; left: 0px; display: flex; flex: 1; align-self: stretch; align-items: center; justify-content: flex-start;"
|
||||
>
|
||||
<div
|
||||
style="width: 18px; height: 18px; display: flex; align-self: center; box-shadow: none; border-radius: 50%; box-sizing: border-box; position: relative; background-color: rgb(106, 115, 125); left: 3px;"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px;"
|
||||
type="checkbox"
|
||||
value="false"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="toggle-button__status"
|
||||
>
|
||||
<span
|
||||
class="toggle-button__label-off"
|
||||
>
|
||||
Off
|
||||
</span>
|
||||
<span
|
||||
class="toggle-button__label-on"
|
||||
>
|
||||
On
|
||||
</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="mm-box network-toggle-wrapper mm-box--margin-top-6 mm-box--margin-bottom-6 mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
data-testid="network-toggle-0x5"
|
||||
>
|
||||
<div
|
||||
class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--align-items-center mm-box--width-full mm-box--background-color-transparent"
|
||||
>
|
||||
<div
|
||||
class="mm-box mm-text mm-avatar-base mm-avatar-base--size-sm mm-avatar-network mm-text--body-sm mm-text--text-transform-uppercase mm-box--display-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-full mm-box--border-color-transparent box--border-style-solid box--border-width-1"
|
||||
>
|
||||
G
|
||||
</div>
|
||||
<p
|
||||
class="mm-box mm-text mm-text--body-md mm-text--ellipsis mm-box--margin-left-2 mm-box--color-text-default mm-box--background-color-transparent"
|
||||
>
|
||||
Goerli
|
||||
</p>
|
||||
</div>
|
||||
<label
|
||||
class="toggle-button toggle-button--off"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;"
|
||||
>
|
||||
<div
|
||||
style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(242, 244, 246);"
|
||||
>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;"
|
||||
/>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgba(255, 255, 255, 0.6); bottom: 0px; margin-top: auto; margin-bottom: auto; padding-right: 5px; line-height: 0; width: 26px; height: 20px; opacity: 1;"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style="position: absolute; height: 100%; top: 0px; left: 0px; display: flex; flex: 1; align-self: stretch; align-items: center; justify-content: flex-start;"
|
||||
>
|
||||
<div
|
||||
style="width: 18px; height: 18px; display: flex; align-self: center; box-shadow: none; border-radius: 50%; box-sizing: border-box; position: relative; background-color: rgb(106, 115, 125); left: 3px;"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px;"
|
||||
type="checkbox"
|
||||
value="false"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="toggle-button__status"
|
||||
>
|
||||
<span
|
||||
class="toggle-button__label-off"
|
||||
>
|
||||
Off
|
||||
</span>
|
||||
<span
|
||||
class="toggle-button__label-on"
|
||||
>
|
||||
On
|
||||
</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="mm-box network-toggle-wrapper mm-box--margin-top-6 mm-box--margin-bottom-6 mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
data-testid="network-toggle-0xaa36a7"
|
||||
>
|
||||
<div
|
||||
class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--align-items-center mm-box--width-full mm-box--background-color-transparent"
|
||||
>
|
||||
<div
|
||||
class="mm-box mm-text mm-avatar-base mm-avatar-base--size-sm mm-avatar-network mm-text--body-sm mm-text--text-transform-uppercase mm-box--display-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-full mm-box--border-color-transparent box--border-style-solid box--border-width-1"
|
||||
>
|
||||
S
|
||||
</div>
|
||||
<p
|
||||
class="mm-box mm-text mm-text--body-md mm-text--ellipsis mm-box--margin-left-2 mm-box--color-text-default mm-box--background-color-transparent"
|
||||
>
|
||||
Sepolia
|
||||
</p>
|
||||
</div>
|
||||
<label
|
||||
class="toggle-button toggle-button--on"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;"
|
||||
>
|
||||
<div
|
||||
style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(242, 244, 246);"
|
||||
>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;"
|
||||
/>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgba(255, 255, 255, 0.6); bottom: 0px; margin-top: auto; margin-bottom: auto; padding-right: 5px; line-height: 0; width: 26px; height: 20px; opacity: 0;"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style="position: absolute; height: 100%; top: 0px; left: 0px; display: flex; flex: 1; align-self: stretch; align-items: center; justify-content: flex-start;"
|
||||
>
|
||||
<div
|
||||
style="width: 18px; height: 18px; display: flex; align-self: center; box-shadow: none; border-radius: 50%; box-sizing: border-box; position: relative; background-color: rgb(3, 125, 214); left: 18px;"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px;"
|
||||
type="checkbox"
|
||||
value="true"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="toggle-button__status"
|
||||
>
|
||||
<span
|
||||
class="toggle-button__label-off"
|
||||
>
|
||||
Off
|
||||
</span>
|
||||
<span
|
||||
class="toggle-button__label-on"
|
||||
>
|
||||
On
|
||||
</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="mm-box network-toggle-wrapper mm-box--margin-top-6 mm-box--margin-bottom-6 mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
data-testid="network-toggle-0xe704"
|
||||
>
|
||||
<div
|
||||
class="mm-box mm-box--display-flex mm-box--gap-2 mm-box--align-items-center mm-box--width-full mm-box--background-color-transparent"
|
||||
>
|
||||
<div
|
||||
class="mm-box mm-text mm-avatar-base mm-avatar-base--size-sm mm-avatar-network mm-text--body-sm mm-text--text-transform-uppercase mm-box--display-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-full mm-box--border-color-transparent box--border-style-solid box--border-width-1"
|
||||
>
|
||||
<img
|
||||
alt="Linea Goerli logo"
|
||||
class="mm-avatar-network__network-image"
|
||||
src="./images/linea-logo-testnet.png"
|
||||
/>
|
||||
</div>
|
||||
<p
|
||||
class="mm-box mm-text mm-text--body-md mm-text--ellipsis mm-box--margin-left-2 mm-box--color-text-default mm-box--background-color-transparent"
|
||||
>
|
||||
Linea Goerli
|
||||
</p>
|
||||
</div>
|
||||
<label
|
||||
class="toggle-button toggle-button--on"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;"
|
||||
>
|
||||
<div
|
||||
style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(242, 244, 246);"
|
||||
>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;"
|
||||
/>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgba(255, 255, 255, 0.6); bottom: 0px; margin-top: auto; margin-bottom: auto; padding-right: 5px; line-height: 0; width: 26px; height: 20px; opacity: 0;"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style="position: absolute; height: 100%; top: 0px; left: 0px; display: flex; flex: 1; align-self: stretch; align-items: center; justify-content: flex-start;"
|
||||
>
|
||||
<div
|
||||
style="width: 18px; height: 18px; display: flex; align-self: center; box-shadow: none; border-radius: 50%; box-sizing: border-box; position: relative; background-color: rgb(3, 125, 214); left: 18px;"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px;"
|
||||
type="checkbox"
|
||||
value="true"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="toggle-button__status"
|
||||
>
|
||||
<span
|
||||
class="toggle-button__label-off"
|
||||
>
|
||||
Off
|
||||
</span>
|
||||
<span
|
||||
class="toggle-button__label-on"
|
||||
>
|
||||
On
|
||||
</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
class="settings-page__security-tab-sub-header"
|
||||
>
|
||||
Network provider
|
||||
</span>
|
||||
<div
|
||||
class="settings-page__content-padded"
|
||||
>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-column"
|
||||
data-testid="advanced-setting-choose-your-network"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
>
|
||||
<span>
|
||||
Choose your network
|
||||
</span>
|
||||
<div
|
||||
class="settings-page__content-description"
|
||||
>
|
||||
<span>
|
||||
|
||||
We use Infura as our remote procedure call (RPC) provider to offer the most reliable and private access to Ethereum data we can. You can choose your own RPC, but remember that any RPC will receive your IP address and Ethereum wallet to make transactions. Read our
|
||||
<a
|
||||
href="https://consensys.net/privacy-policy/"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Privacy policy
|
||||
</a>
|
||||
to learn more about how Infura handles data.
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="settings-page__content-item-col"
|
||||
>
|
||||
<button
|
||||
class="mm-box mm-text mm-button-base mm-button-base--size-md settings-page__button mm-button-primary mm-text--body-md-medium mm-box--padding-0 mm-box--padding-right-4 mm-box--padding-left-4 mm-box--display-inline-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-primary-inverse mm-box--background-color-primary-default mm-box--rounded-pill"
|
||||
type="secondary"
|
||||
>
|
||||
Add custom network
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-column"
|
||||
data-testid="setting-ipfs-gateway"
|
||||
>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
>
|
||||
<span>
|
||||
IPFS gateway
|
||||
</span>
|
||||
<div
|
||||
class="settings-page__content-description"
|
||||
>
|
||||
MetaMask uses third-party services to show images of your NFTs stored on IPFS, display information related to ENS addresses entered in your browser's address bar, and fetch icons for different tokens. Your IP address may be exposed to these services when you’re using them.
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="settings-page__content-item-col"
|
||||
data-testid="ipfsToggle"
|
||||
>
|
||||
<label
|
||||
class="toggle-button toggle-button--on"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;"
|
||||
>
|
||||
<div
|
||||
style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(242, 244, 246);"
|
||||
>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;"
|
||||
/>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgba(255, 255, 255, 0.6); bottom: 0px; margin-top: auto; margin-bottom: auto; padding-right: 5px; line-height: 0; width: 26px; height: 20px; opacity: 0;"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style="position: absolute; height: 100%; top: 0px; left: 0px; display: flex; flex: 1; align-self: stretch; align-items: center; justify-content: flex-start;"
|
||||
>
|
||||
<div
|
||||
style="width: 18px; height: 18px; display: flex; align-self: center; box-shadow: none; border-radius: 50%; box-sizing: border-box; position: relative; background-color: rgb(3, 125, 214); left: 18px;"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px;"
|
||||
type="checkbox"
|
||||
value="true"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="toggle-button__status"
|
||||
>
|
||||
<span
|
||||
class="toggle-button__label-off"
|
||||
>
|
||||
Off
|
||||
</span>
|
||||
<span
|
||||
class="toggle-button__label-on"
|
||||
>
|
||||
On
|
||||
</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
>
|
||||
@ -524,7 +835,7 @@ exports[`Security Tab should match snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--margin-top-3 mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
class="mm-box settings-page__content-row mm-box--margin-top-3 mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
id="ens-domains"
|
||||
>
|
||||
<div>
|
||||
@ -626,7 +937,7 @@ exports[`Security Tab should match snapshot 1`] = `
|
||||
class="settings-page__content-padded"
|
||||
>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
data-testid="advanced-setting-gas-fee-estimation"
|
||||
id="advanced-settings-autodetect-tokens"
|
||||
>
|
||||
@ -706,7 +1017,7 @@ exports[`Security Tab should match snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
@ -772,7 +1083,7 @@ exports[`Security Tab should match snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
@ -787,62 +1098,58 @@ exports[`Security Tab should match snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
class="settings-page__content-item-col"
|
||||
data-testid="enableOpenSeaAPI"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item-col"
|
||||
data-testid="enableOpenSeaAPI"
|
||||
<label
|
||||
class="toggle-button toggle-button--on"
|
||||
tabindex="0"
|
||||
>
|
||||
<label
|
||||
class="toggle-button toggle-button--on"
|
||||
tabindex="0"
|
||||
<div
|
||||
style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;"
|
||||
>
|
||||
<div
|
||||
style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;"
|
||||
style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(242, 244, 246);"
|
||||
>
|
||||
<div
|
||||
style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(242, 244, 246);"
|
||||
>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;"
|
||||
/>
|
||||
<div
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgba(255, 255, 255, 0.6); bottom: 0px; margin-top: auto; margin-bottom: auto; padding-right: 5px; line-height: 0; width: 26px; height: 20px; opacity: 0;"
|
||||
/>
|
||||
</div>
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 1; width: 26px; height: 20px; left: 4px;"
|
||||
/>
|
||||
<div
|
||||
style="position: absolute; height: 100%; top: 0px; left: 0px; display: flex; flex: 1; align-self: stretch; align-items: center; justify-content: flex-start;"
|
||||
>
|
||||
<div
|
||||
style="width: 18px; height: 18px; display: flex; align-self: center; box-shadow: none; border-radius: 50%; box-sizing: border-box; position: relative; background-color: rgb(3, 125, 214); left: 18px;"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px;"
|
||||
type="checkbox"
|
||||
value="true"
|
||||
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgba(255, 255, 255, 0.6); bottom: 0px; margin-top: auto; margin-bottom: auto; padding-right: 5px; line-height: 0; width: 26px; height: 20px; opacity: 0;"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="toggle-button__status"
|
||||
style="position: absolute; height: 100%; top: 0px; left: 0px; display: flex; flex: 1; align-self: stretch; align-items: center; justify-content: flex-start;"
|
||||
>
|
||||
<span
|
||||
class="toggle-button__label-off"
|
||||
>
|
||||
Off
|
||||
</span>
|
||||
<span
|
||||
class="toggle-button__label-on"
|
||||
>
|
||||
On
|
||||
</span>
|
||||
<div
|
||||
style="width: 18px; height: 18px; display: flex; align-self: center; box-shadow: none; border-radius: 50%; box-sizing: border-box; position: relative; background-color: rgb(3, 125, 214); left: 18px;"
|
||||
/>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<input
|
||||
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px;"
|
||||
type="checkbox"
|
||||
value="true"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="toggle-button__status"
|
||||
>
|
||||
<span
|
||||
class="toggle-button__label-off"
|
||||
>
|
||||
Off
|
||||
</span>
|
||||
<span
|
||||
class="toggle-button__label-on"
|
||||
>
|
||||
On
|
||||
</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
@ -939,7 +1246,7 @@ exports[`Security Tab should match snapshot 1`] = `
|
||||
class="settings-page__content-padded"
|
||||
>
|
||||
<div
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
|
||||
>
|
||||
<div
|
||||
class="settings-page__content-item"
|
||||
|
@ -17,7 +17,6 @@ import {
|
||||
COINGECKO_LINK,
|
||||
CONSENSYS_PRIVACY_LINK,
|
||||
CRYPTOCOMPARE_LINK,
|
||||
ETHERSCAN_PRIVACY_LINK,
|
||||
PRIVACY_POLICY_LINK,
|
||||
} from '../../../../shared/lib/ui-utils';
|
||||
import SRPQuiz from '../../../components/app/srp-quiz-modal/SRPQuiz';
|
||||
@ -42,6 +41,8 @@ import {
|
||||
handleSettingsRefs,
|
||||
} from '../../../helpers/utils/settings-search';
|
||||
|
||||
import IncomingTransactionToggle from '../../../components/app/incoming-trasaction-toggle/incoming-transaction-toggle';
|
||||
|
||||
export default class SecurityTab extends PureComponent {
|
||||
static contextTypes = {
|
||||
t: PropTypes.func,
|
||||
@ -57,8 +58,9 @@ export default class SecurityTab extends PureComponent {
|
||||
setUseNftDetection: PropTypes.func,
|
||||
participateInMetaMetrics: PropTypes.bool.isRequired,
|
||||
setParticipateInMetaMetrics: PropTypes.func.isRequired,
|
||||
showIncomingTransactions: PropTypes.bool.isRequired,
|
||||
setShowIncomingTransactionsFeatureFlag: PropTypes.func.isRequired,
|
||||
incomingTransactionsPreferences: PropTypes.object.isRequired,
|
||||
allNetworks: PropTypes.array.isRequired,
|
||||
setIncomingTransactionsPreferences: PropTypes.func.isRequired,
|
||||
setUsePhishDetect: PropTypes.func.isRequired,
|
||||
usePhishDetect: PropTypes.bool.isRequired,
|
||||
setUse4ByteResolution: PropTypes.func.isRequired,
|
||||
@ -170,55 +172,19 @@ export default class SecurityTab extends PureComponent {
|
||||
}
|
||||
|
||||
renderIncomingTransactionsOptIn() {
|
||||
const { t } = this.context;
|
||||
const { showIncomingTransactions, setShowIncomingTransactionsFeatureFlag } =
|
||||
this.props;
|
||||
const {
|
||||
incomingTransactionsPreferences,
|
||||
allNetworks,
|
||||
setIncomingTransactionsPreferences,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Box
|
||||
ref={this.settingsRefs[1]}
|
||||
className="settings-page__content-row"
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Row}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
>
|
||||
<div className="settings-page__content-item">
|
||||
<span>{t('showIncomingTransactions')}</span>
|
||||
<div className="settings-page__content-description">
|
||||
{t('showIncomingTransactionsDescription', [
|
||||
// TODO: Update to use real link
|
||||
<a
|
||||
href={ETHERSCAN_PRIVACY_LINK}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
key="etherscan-privacy-link"
|
||||
>
|
||||
{t('etherscan')}
|
||||
</a>,
|
||||
// TODO: Update to use real link
|
||||
<a
|
||||
href={CONSENSYS_PRIVACY_LINK}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
key="ic-consensys-privacy-link"
|
||||
>
|
||||
{t('privacyMsg')}
|
||||
</a>,
|
||||
])}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="settings-page__content-item-col"
|
||||
data-testid="showIncomingTransactions"
|
||||
>
|
||||
<ToggleButton
|
||||
value={showIncomingTransactions}
|
||||
onToggle={(value) => setShowIncomingTransactionsFeatureFlag(!value)}
|
||||
offLabel={t('off')}
|
||||
onLabel={t('on')}
|
||||
/>
|
||||
</div>
|
||||
</Box>
|
||||
<IncomingTransactionToggle
|
||||
wrapperRef={this.settingsRefs[1]}
|
||||
allNetworks={allNetworks}
|
||||
setIncomingTransactionsPreferences={setIncomingTransactionsPreferences}
|
||||
incomingTransactionsPreferences={incomingTransactionsPreferences}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -233,6 +199,7 @@ export default class SecurityTab extends PureComponent {
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Row}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
gap={4}
|
||||
>
|
||||
<div className="settings-page__content-item">
|
||||
<span>{t('usePhishingDetection')}</span>
|
||||
@ -260,27 +227,33 @@ export default class SecurityTab extends PureComponent {
|
||||
const { t } = this.context;
|
||||
const { use4ByteResolution, setUse4ByteResolution } = this.props;
|
||||
return (
|
||||
<div ref={this.settingsRefs[3]} className="settings-page__content-row">
|
||||
<Box
|
||||
ref={this.settingsRefs[3]}
|
||||
className="settings-page__content-row"
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Row}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
gap={4}
|
||||
>
|
||||
<div className="settings-page__content-item">
|
||||
<span>{t('use4ByteResolution')}</span>
|
||||
<div className="settings-page__content-description">
|
||||
{t('use4ByteResolutionDescription')}
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-page__content-item">
|
||||
<div
|
||||
className="settings-page__content-item-col"
|
||||
data-testid="4byte-resolution-container"
|
||||
>
|
||||
<ToggleButton
|
||||
value={use4ByteResolution}
|
||||
onToggle={(value) => setUse4ByteResolution(!value)}
|
||||
offLabel={t('off')}
|
||||
onLabel={t('on')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="settings-page__content-item-col"
|
||||
data-testid="4byte-resolution-container"
|
||||
>
|
||||
<ToggleButton
|
||||
value={use4ByteResolution}
|
||||
onToggle={(value) => setUse4ByteResolution(!value)}
|
||||
offLabel={t('off')}
|
||||
onLabel={t('on')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@ -296,6 +269,7 @@ export default class SecurityTab extends PureComponent {
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Row}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
gap={4}
|
||||
>
|
||||
<div className="settings-page__content-item">
|
||||
<span>{t('participateInMetaMetrics')}</span>
|
||||
@ -329,6 +303,7 @@ export default class SecurityTab extends PureComponent {
|
||||
data-testid="advanced-setting-choose-your-network"
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Column}
|
||||
gap={4}
|
||||
>
|
||||
<div className="settings-page__content-item">
|
||||
<span>{t('chooseYourNetwork')}</span>
|
||||
@ -408,34 +383,43 @@ export default class SecurityTab extends PureComponent {
|
||||
data-testid="setting-ipfs-gateway"
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Column}
|
||||
gap={4}
|
||||
>
|
||||
<div className="settings-page__content-item">
|
||||
<span>{t('ipfsGateway')}</span>
|
||||
<div className="settings-page__content-description">
|
||||
{t('ipfsGatewayDescription')}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="settings-page__content-item-col"
|
||||
data-testid="ipfsToggle"
|
||||
<Box
|
||||
className="settings-page__content-row"
|
||||
gap={4}
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Row}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
>
|
||||
<ToggleButton
|
||||
value={this.state.ipfsToggle}
|
||||
onToggle={(value) => {
|
||||
if (value) {
|
||||
// turning from true to false
|
||||
this.props.setIpfsGateway('');
|
||||
} else {
|
||||
// turning from false to true
|
||||
handleIpfsGatewayChange(this.state.ipfsGateway);
|
||||
}
|
||||
<div className="settings-page__content-item">
|
||||
<span>{t('ipfsGateway')}</span>
|
||||
<div className="settings-page__content-description">
|
||||
{t('ipfsGatewayDescription')}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="settings-page__content-item-col"
|
||||
data-testid="ipfsToggle"
|
||||
>
|
||||
<ToggleButton
|
||||
value={this.state.ipfsToggle}
|
||||
onToggle={(value) => {
|
||||
if (value) {
|
||||
// turning from true to false
|
||||
this.props.setIpfsGateway('');
|
||||
} else {
|
||||
// turning from false to true
|
||||
handleIpfsGatewayChange(this.state.ipfsGateway);
|
||||
}
|
||||
|
||||
this.setState({ ipfsToggle: !value });
|
||||
}}
|
||||
offLabel={t('off')}
|
||||
onLabel={t('on')}
|
||||
/>
|
||||
</div>
|
||||
this.setState({ ipfsToggle: !value });
|
||||
}}
|
||||
offLabel={t('off')}
|
||||
onLabel={t('on')}
|
||||
/>
|
||||
</div>
|
||||
</Box>
|
||||
{this.state.ipfsToggle && (
|
||||
<div className="settings-page__content-item">
|
||||
<span>{t('addIPFSGateway')}</span>
|
||||
@ -456,6 +440,7 @@ export default class SecurityTab extends PureComponent {
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Row}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
gap={4}
|
||||
ref={this.settingsRefs[10]}
|
||||
marginTop={3}
|
||||
id="ens-domains"
|
||||
@ -531,6 +516,7 @@ export default class SecurityTab extends PureComponent {
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Row}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
gap={4}
|
||||
id="advanced-settings-autodetect-tokens"
|
||||
>
|
||||
<div className="settings-page__content-item">
|
||||
@ -584,6 +570,7 @@ export default class SecurityTab extends PureComponent {
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Row}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
gap={4}
|
||||
>
|
||||
<div className="settings-page__content-item">
|
||||
<span>{t('useMultiAccountBalanceChecker')}</span>
|
||||
@ -625,6 +612,7 @@ export default class SecurityTab extends PureComponent {
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Row}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
gap={4}
|
||||
>
|
||||
<div className="settings-page__content-item">
|
||||
<span>{t('currencyRateCheckToggle')}</span>
|
||||
@ -673,7 +661,7 @@ export default class SecurityTab extends PureComponent {
|
||||
);
|
||||
}
|
||||
|
||||
renderOpenSeaEnabledToggle() {
|
||||
renderDisplayNftMediaToggle() {
|
||||
const { t } = this.context;
|
||||
const {
|
||||
openSeaEnabled,
|
||||
@ -689,6 +677,7 @@ export default class SecurityTab extends PureComponent {
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Row}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
gap={4}
|
||||
>
|
||||
<div className="settings-page__content-item">
|
||||
<span>{t('displayNftMedia')}</span>
|
||||
@ -696,32 +685,31 @@ export default class SecurityTab extends PureComponent {
|
||||
{t('displayNftMediaDescription')}
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-page__content-item">
|
||||
<div
|
||||
className="settings-page__content-item-col"
|
||||
data-testid="enableOpenSeaAPI"
|
||||
>
|
||||
<ToggleButton
|
||||
value={openSeaEnabled}
|
||||
onToggle={(value) => {
|
||||
this.context.trackEvent({
|
||||
category: MetaMetricsEventCategory.Settings,
|
||||
event: 'Enabled/Disable OpenSea',
|
||||
properties: {
|
||||
action: 'Enabled/Disable OpenSea',
|
||||
legacy_event: true,
|
||||
},
|
||||
});
|
||||
// value is positive when being toggled off
|
||||
if (value && useNftDetection) {
|
||||
setUseNftDetection(false);
|
||||
}
|
||||
setOpenSeaEnabled(!value);
|
||||
}}
|
||||
offLabel={t('off')}
|
||||
onLabel={t('on')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="settings-page__content-item-col"
|
||||
data-testid="enableOpenSeaAPI"
|
||||
>
|
||||
<ToggleButton
|
||||
value={openSeaEnabled}
|
||||
onToggle={(value) => {
|
||||
this.context.trackEvent({
|
||||
category: MetaMetricsEventCategory.Settings,
|
||||
event: 'Enabled/Disable OpenSea',
|
||||
properties: {
|
||||
action: 'Enabled/Disable OpenSea',
|
||||
legacy_event: true,
|
||||
},
|
||||
});
|
||||
// value is positive when being toggled off
|
||||
if (value && useNftDetection) {
|
||||
setUseNftDetection(false);
|
||||
}
|
||||
setOpenSeaEnabled(!value);
|
||||
}}
|
||||
offLabel={t('off')}
|
||||
onLabel={t('on')}
|
||||
/>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
@ -742,6 +730,7 @@ export default class SecurityTab extends PureComponent {
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Row}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
gap={4}
|
||||
>
|
||||
<div className="settings-page__content-item">
|
||||
<span>{t('useNftDetection')}</span>
|
||||
@ -837,7 +826,7 @@ export default class SecurityTab extends PureComponent {
|
||||
<div className="settings-page__content-padded">
|
||||
{this.renderAutoDetectTokensToggle()}
|
||||
{this.renderBatchAccountBalanceRequestsToggle()}
|
||||
{this.renderOpenSeaEnabledToggle()}
|
||||
{this.renderDisplayNftMediaToggle()}
|
||||
{this.renderNftDetectionToggle()}
|
||||
</div>
|
||||
<span className="settings-page__security-tab-sub-header">
|
||||
|
@ -2,7 +2,7 @@ import { connect } from 'react-redux';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { compose } from 'redux';
|
||||
import {
|
||||
setFeatureFlag,
|
||||
setIncomingTransactionsPreferences,
|
||||
setIpfsGateway,
|
||||
setParticipateInMetaMetrics,
|
||||
setUseCurrencyRateCheck,
|
||||
@ -14,6 +14,7 @@ import {
|
||||
setUseNftDetection,
|
||||
setUse4ByteResolution,
|
||||
} from '../../../store/actions';
|
||||
import { getAllNetworks } from '../../../selectors';
|
||||
import SecurityTab from './security-tab.component';
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
@ -21,8 +22,9 @@ const mapStateToProps = (state) => {
|
||||
appState: { warning },
|
||||
metamask,
|
||||
} = state;
|
||||
|
||||
const {
|
||||
featureFlags: { showIncomingTransactions } = {},
|
||||
incomingTransactionsPreferences,
|
||||
participateInMetaMetrics,
|
||||
usePhishDetect,
|
||||
useTokenDetection,
|
||||
@ -35,9 +37,12 @@ const mapStateToProps = (state) => {
|
||||
use4ByteResolution,
|
||||
} = metamask;
|
||||
|
||||
const allNetworks = getAllNetworks(state);
|
||||
|
||||
return {
|
||||
warning,
|
||||
showIncomingTransactions,
|
||||
incomingTransactionsPreferences,
|
||||
allNetworks,
|
||||
participateInMetaMetrics,
|
||||
usePhishDetect,
|
||||
useTokenDetection,
|
||||
@ -53,10 +58,10 @@ const mapStateToProps = (state) => {
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
setIncomingTransactionsPreferences: (chainId, value) =>
|
||||
dispatch(setIncomingTransactionsPreferences(chainId, value)),
|
||||
setParticipateInMetaMetrics: (val) =>
|
||||
dispatch(setParticipateInMetaMetrics(val)),
|
||||
setShowIncomingTransactionsFeatureFlag: (shouldShow) =>
|
||||
dispatch(setFeatureFlag('showIncomingTransactions', shouldShow)),
|
||||
setUsePhishDetect: (val) => dispatch(setUsePhishDetect(val)),
|
||||
setUseCurrencyRateCheck: (val) => dispatch(setUseCurrencyRateCheck(val)),
|
||||
setUseTokenDetection: (value) => {
|
||||
|
@ -20,7 +20,6 @@ jest.mock('../../../../app/scripts/lib/util', () => {
|
||||
});
|
||||
|
||||
describe('Security Tab', () => {
|
||||
delete mockState.metamask.featureFlags; // Unset featureFlags in order to test the default value
|
||||
mockState.appState.warning = 'warning'; // This tests an otherwise untested render branch
|
||||
|
||||
const mockStore = configureMockStore([thunk])(mockState);
|
||||
@ -91,10 +90,6 @@ describe('Security Tab', () => {
|
||||
expect(await toggleCheckbox('currencyRateCheckToggle', true)).toBe(true);
|
||||
});
|
||||
|
||||
it('toggles incoming txs', async () => {
|
||||
expect(await toggleCheckbox('showIncomingTransactions', false)).toBe(true);
|
||||
});
|
||||
|
||||
it('should toggle token detection', async () => {
|
||||
expect(await toggleCheckbox('autoDetectTokens', true)).toBe(true);
|
||||
});
|
||||
|
@ -80,11 +80,11 @@ const getStateTree = ({
|
||||
},
|
||||
unapprovedMsgs,
|
||||
selectedAddress: SENDERS.ONE,
|
||||
featureFlags: {
|
||||
showIncomingTransactions: true,
|
||||
},
|
||||
featureFlags: {},
|
||||
transactions: [...incomingTxList],
|
||||
incomingTransactions: [...incomingTxList],
|
||||
currentNetworkTxList: [...txList],
|
||||
incomingTransactionsPreferences: {},
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -26,9 +26,8 @@ const INVALID_INITIAL_TRANSACTION_TYPES = [
|
||||
];
|
||||
|
||||
export const incomingTxListSelector = (state) => {
|
||||
const { showIncomingTransactions } = state.metamask.featureFlags;
|
||||
|
||||
if (!showIncomingTransactions) {
|
||||
const { incomingTransactionsPreferences } = state.metamask;
|
||||
if (!incomingTransactionsPreferences) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
@ -113,9 +113,7 @@ describe('Transaction Selectors', () => {
|
||||
nickname: 'mainnet',
|
||||
chainId: CHAIN_IDS.MAINNET,
|
||||
},
|
||||
featureFlags: {
|
||||
showIncomingTransactions: false,
|
||||
},
|
||||
featureFlags: {},
|
||||
selectedAddress: '0xAddress',
|
||||
currentNetworkTxList: [
|
||||
{
|
||||
@ -178,9 +176,7 @@ describe('Transaction Selectors', () => {
|
||||
chainId: CHAIN_IDS.MAINNET,
|
||||
},
|
||||
selectedAddress: '0xAddress',
|
||||
featureFlags: {
|
||||
showIncomingTransactions: false,
|
||||
},
|
||||
featureFlags: {},
|
||||
currentNetworkTxList: [tx1, tx2],
|
||||
},
|
||||
};
|
||||
@ -262,9 +258,7 @@ describe('Transaction Selectors', () => {
|
||||
chainId: CHAIN_IDS.MAINNET,
|
||||
},
|
||||
selectedAddress: '0xAddress',
|
||||
featureFlags: {
|
||||
showIncomingTransactions: false,
|
||||
},
|
||||
featureFlags: {},
|
||||
currentNetworkTxList: [
|
||||
submittedTx,
|
||||
unapprovedTx,
|
||||
|
@ -2693,7 +2693,7 @@ interface TemporaryFeatureFlagDef {
|
||||
[feature: string]: boolean;
|
||||
}
|
||||
interface TemporaryPreferenceFlagDef {
|
||||
[preference: string]: boolean;
|
||||
[preference: string]: boolean | object;
|
||||
}
|
||||
|
||||
export function setFeatureFlag(
|
||||
@ -2729,7 +2729,7 @@ export function setFeatureFlag(
|
||||
|
||||
export function setPreference(
|
||||
preference: string,
|
||||
value: boolean | string,
|
||||
value: boolean | string | object,
|
||||
): ThunkAction<
|
||||
Promise<TemporaryPreferenceFlagDef>,
|
||||
MetaMaskReduxState,
|
||||
@ -2744,13 +2744,11 @@ export function setPreference(
|
||||
[preference, value],
|
||||
(err, updatedPreferences) => {
|
||||
dispatch(hideLoadingIndication());
|
||||
|
||||
if (err) {
|
||||
dispatch(displayWarning(err));
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(updatedPreferences as TemporaryPreferenceFlagDef);
|
||||
},
|
||||
);
|
||||
@ -2789,6 +2787,21 @@ export function setAutoLockTimeLimit(value: boolean) {
|
||||
return setPreference('autoLockTimeLimit', value);
|
||||
}
|
||||
|
||||
export function setIncomingTransactionsPreferences(
|
||||
chainId: string,
|
||||
value: boolean,
|
||||
): ThunkAction<void, MetaMaskReduxState, unknown, AnyAction> {
|
||||
return async (dispatch: MetaMaskReduxDispatch) => {
|
||||
dispatch(showLoadingIndication());
|
||||
log.debug(`background.setIncomingTransactionsPreferences`);
|
||||
await submitRequestToBackground('setIncomingTransactionsPreferences', [
|
||||
chainId,
|
||||
value,
|
||||
]);
|
||||
dispatch(hideLoadingIndication());
|
||||
};
|
||||
}
|
||||
|
||||
export function setCompletedOnboarding(): ThunkAction<
|
||||
void,
|
||||
MetaMaskReduxState,
|
||||
|
@ -206,9 +206,7 @@ describe('#updateCustodyState', () => {
|
||||
nickname: 'mainnet',
|
||||
chainId: '0x1',
|
||||
},
|
||||
featureFlags: {
|
||||
showIncomingTransactions: false,
|
||||
},
|
||||
featureFlags: {},
|
||||
selectedAddress: '0xAddress',
|
||||
};
|
||||
|
||||
@ -232,9 +230,7 @@ describe('#updateCustodyState', () => {
|
||||
nickname: 'mainnet',
|
||||
chainId: '0x1',
|
||||
},
|
||||
featureFlags: {
|
||||
showIncomingTransactions: false,
|
||||
},
|
||||
featureFlags: {},
|
||||
selectedAddress: '0xAddress',
|
||||
currentNetworkTxList: [
|
||||
{
|
||||
@ -287,9 +283,7 @@ describe('#updateCustodyState', () => {
|
||||
nickname: 'mainnet',
|
||||
chainId: '0x1',
|
||||
},
|
||||
featureFlags: {
|
||||
showIncomingTransactions: false,
|
||||
},
|
||||
featureFlags: {},
|
||||
selectedAddress: '0xAddress',
|
||||
currentNetworkTxList: [
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user