diff --git a/.circleci/config.yml b/.circleci/config.yml index 8473915d8a41..1755e91b46a1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -246,6 +246,8 @@ workflows: - test-e2e-firefox - test-e2e-chrome-snaps - test-e2e-firefox-snaps + - test-e2e-chrome-snaps-flask + - test-e2e-firefox-snaps-flask - test-storybook - benchmark: requires: diff --git a/.circleci/scripts/chrome-install.sh b/.circleci/scripts/chrome-install.sh index cba84785f3af..2cf0bdb0e393 100755 --- a/.circleci/scripts/chrome-install.sh +++ b/.circleci/scripts/chrome-install.sh @@ -7,12 +7,12 @@ set -o pipefail sudo apt-get update # To get the latest version, see -CHROME_VERSION='114.0.5735.133-1' +CHROME_VERSION='116.0.5845.179-1' CHROME_BINARY="google-chrome-stable_${CHROME_VERSION}_amd64.deb" CHROME_BINARY_URL="https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/${CHROME_BINARY}" # To retrieve this checksum, run the `wget` and `shasum` commands below -CHROME_BINARY_SHA512SUM='0b1a18c44efb72ed3e69a5f78419ff5fa973df42b18a8becfcc3d4f6825957c637e9396d07756f910f2d9c7c85a3e2b64cc30cca18182ae8811feadd609f159d' +CHROME_BINARY_SHA512SUM='cbdad3f5c928ef79a46a3619054b3c4a73a99f942f9bf4ea75d37d6434912da5c01f6ee30718a58e869ff6b57b10bb7fea1cf91885a25aac290a50a2ee3c03c4' wget -O "${CHROME_BINARY}" -t 5 "${CHROME_BINARY_URL}" diff --git a/.eslintrc.js b/.eslintrc.js index e09e9badbac0..392547014375 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -241,6 +241,7 @@ module.exports = { 'app/scripts/controllers/permissions/**/*.test.js', 'app/scripts/controllers/preferences.test.js', 'app/scripts/lib/**/*.test.js', + 'app/scripts/metamask-controller.test.js', 'app/scripts/migrations/*.test.js', 'app/scripts/platforms/*.test.js', 'development/**/*.test.js', @@ -271,6 +272,7 @@ module.exports = { 'app/scripts/controllers/permissions/**/*.test.js', 'app/scripts/controllers/preferences.test.js', 'app/scripts/lib/**/*.test.js', + 'app/scripts/metamask-controller.test.js', 'app/scripts/migrations/*.test.js', 'app/scripts/platforms/*.test.js', 'development/**/*.test.js', diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index f945eb7b7553..e5c1eb06b588 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -42,7 +42,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -53,7 +53,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v2 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -67,4 +67,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 diff --git a/.mocharc.js b/.mocharc.js index 5998b524ecab..8b78cbf360e3 100644 --- a/.mocharc.js +++ b/.mocharc.js @@ -10,6 +10,7 @@ module.exports = { './app/scripts/controllers/mmi-controller.test.js', './app/scripts/controllers/preferences.test.js', './app/scripts/constants/error-utils.test.js', + './app/scripts/metamask-controller.test.js', './development/fitness-functions/**/*.test.ts', './test/e2e/helpers.test.js', ], diff --git a/.storybook/initial-states/transactions.js b/.storybook/initial-states/transactions.js index 70885e4a606d..cc0f0e1be3c6 100644 --- a/.storybook/initial-states/transactions.js +++ b/.storybook/initial-states/transactions.js @@ -72,37 +72,6 @@ export const MOCK_TRANSACTION_BY_TYPE = { }, type: 'cancel', }, - [ - { - op: 'add', - path: '/nonceDetails', - value: { - params: { - highestLocallyConfirmed: 81, - highestSuggested: 81, - nextNetworkNonce: 81, - }, - local: { - name: 'local', - nonce: 83, - details: { - startPoint: 81, - highest: 83, - }, - }, - network: { - name: 'network', - nonce: 81, - details: { - blockNumber: '0xa3e3ac', - baseCount: 81, - }, - }, - }, - note: 'transactions#approveTransaction', - timestamp: 1653527035723, - }, - ], [ { op: 'add', @@ -172,29 +141,6 @@ export const MOCK_TRANSACTION_BY_TYPE = { }, ], ], - nonceDetails: { - params: { - highestLocallyConfirmed: 81, - highestSuggested: 81, - nextNetworkNonce: 81, - }, - local: { - name: 'local', - nonce: 83, - details: { - startPoint: 81, - highest: 83, - }, - }, - network: { - name: 'network', - nonce: 81, - details: { - blockNumber: '0xa3e3ac', - baseCount: 81, - }, - }, - }, r: '0xb66eff07d9061c42e47ccf5f6a52b6626ef4d5b10e50d8aa6b8f20ae645fe347', s: '0x3a2da8d56beff82a2d59e807f7d578f0c3b4b99cd6d3735c72c133d06fe02a9d', v: '0x2b', @@ -402,37 +348,6 @@ export const MOCK_TRANSACTION_BY_TYPE = { type: 'retry', estimatedBaseFee: 'd', }, - [ - { - op: 'add', - path: '/nonceDetails', - value: { - params: { - highestLocallyConfirmed: 7, - highestSuggested: 7, - nextNetworkNonce: 7, - }, - local: { - name: 'local', - nonce: 10, - details: { - startPoint: 7, - highest: 10, - }, - }, - network: { - name: 'network', - nonce: 7, - details: { - blockNumber: '0xa3d235', - baseCount: 7, - }, - }, - }, - note: 'transactions#approveTransaction', - timestamp: 1653459456415, - }, - ], [ { op: 'add', @@ -497,29 +412,6 @@ export const MOCK_TRANSACTION_BY_TYPE = { }, ], ], - nonceDetails: { - params: { - highestLocallyConfirmed: 7, - highestSuggested: 7, - nextNetworkNonce: 7, - }, - local: { - name: 'local', - nonce: 10, - details: { - startPoint: 7, - highest: 10, - }, - }, - network: { - name: 'network', - nonce: 7, - details: { - blockNumber: '0xa3d235', - baseCount: 7, - }, - }, - }, r: '0xde2e3131fb55b1edd182de128453521c86eed588f92058b61b3ce56cdfb33a26', s: '0x64ee1eef8d0fa1b35e122658554d16645366e8977253fc1c47d030f28736409b', v: '0x00', @@ -778,33 +670,6 @@ export const MOCK_TRANSACTION_BY_TYPE = { note: 'transactions#approveTransaction', timestamp: 1653457117294, }, - { - op: 'add', - path: '/nonceDetails', - value: { - params: { - highestLocallyConfirmed: 5, - highestSuggested: 5, - nextNetworkNonce: 5, - }, - local: { - name: 'local', - nonce: 5, - details: { - startPoint: 5, - highest: 5, - }, - }, - network: { - name: 'network', - nonce: 5, - details: { - blockNumber: '0xa3d19b', - baseCount: 5, - }, - }, - }, - }, ], [ { @@ -883,29 +748,6 @@ export const MOCK_TRANSACTION_BY_TYPE = { maxPriorityFeePerGas: '0x4a817c800', }, estimatedBaseFee: '14', - nonceDetails: { - params: { - highestLocallyConfirmed: 5, - highestSuggested: 5, - nextNetworkNonce: 5, - }, - local: { - name: 'local', - nonce: 5, - details: { - startPoint: 5, - highest: 5, - }, - }, - network: { - name: 'network', - nonce: 5, - details: { - blockNumber: '0xa3d19b', - baseCount: 5, - }, - }, - }, r: '0xfdd2cb46203b5e7bba99cc56a37da3e5e3f36163a5bd9c51cddfd8d7028f5dd0', s: '0x54c35cfa10b3350a3fd3a0e7b4aeb0b603d528c07a8cfdf4a78505d9864edef4', v: '0x00', @@ -949,29 +791,6 @@ export const MOCK_TRANSACTION_BY_TYPE = { maxPriorityFeePerGas: '0x3B9ACA00', }, estimatedBaseFee: '3ba182755', - nonceDetails: { - params: { - highestLocallyConfirmed: 87, - highestSuggested: 87, - nextNetworkNonce: 87, - }, - local: { - name: 'local', - nonce: 87, - details: { - startPoint: 87, - highest: 87, - }, - }, - network: { - name: 'network', - nonce: 87, - details: { - blockNumber: '0xa28e38', - baseCount: 87, - }, - }, - }, r: '0xd13310569a8d5876e37788183034bfe4bc3b49c0663c5fd9b2bf13adf9b4791c', s: '0x7a83d8840e7edcdf4fdedfd2bc1ce19775e54fd17f29ede5165591a1cf3febea', v: '0x00', @@ -1156,33 +975,6 @@ export const MOCK_TRANSACTION_BY_TYPE = { note: 'transactions#approveTransaction', timestamp: 1653457091939, }, - { - op: 'add', - path: '/nonceDetails', - value: { - params: { - highestLocallyConfirmed: 4, - highestSuggested: 4, - nextNetworkNonce: 4, - }, - local: { - name: 'local', - nonce: 4, - details: { - startPoint: 4, - highest: 4, - }, - }, - network: { - name: 'network', - nonce: 4, - details: { - blockNumber: '0xa3d198', - baseCount: 4, - }, - }, - }, - }, ], [ { @@ -1370,29 +1162,6 @@ export const MOCK_TRANSACTION_BY_TYPE = { maxPriorityFeePerGas: '0x4a817c800', }, estimatedBaseFee: '16', - nonceDetails: { - params: { - highestLocallyConfirmed: 4, - highestSuggested: 4, - nextNetworkNonce: 4, - }, - local: { - name: 'local', - nonce: 4, - details: { - startPoint: 4, - highest: 4, - }, - }, - network: { - name: 'network', - nonce: 4, - details: { - blockNumber: '0xa3d198', - baseCount: 4, - }, - }, - }, r: '0xb0f36e4392f9d302351789aef355a2e95b979bcdd99d19026c533152563d3bce', s: '0x08e59de373e65c9c54e6a8052585461e81409d33178464f9b72f4cc36ac75d40', v: '0x01', @@ -1591,33 +1360,6 @@ export const MOCK_TRANSACTION_BY_TYPE = { note: 'transactions#approveTransaction', timestamp: 1653457330354, }, - { - op: 'add', - path: '/nonceDetails', - value: { - params: { - highestLocallyConfirmed: 6, - highestSuggested: 6, - nextNetworkNonce: 6, - }, - local: { - name: 'local', - nonce: 6, - details: { - startPoint: 6, - highest: 6, - }, - }, - network: { - name: 'network', - nonce: 6, - details: { - blockNumber: '0xa3d1a8', - baseCount: 6, - }, - }, - }, - }, ], [ { @@ -1829,29 +1571,6 @@ export const MOCK_TRANSACTION_BY_TYPE = { maxPriorityFeePerGas: '0x59682f00', }, estimatedBaseFee: 'd', - nonceDetails: { - params: { - highestLocallyConfirmed: 6, - highestSuggested: 6, - nextNetworkNonce: 6, - }, - local: { - name: 'local', - nonce: 6, - details: { - startPoint: 6, - highest: 6, - }, - }, - network: { - name: 'network', - nonce: 6, - details: { - blockNumber: '0xa3d1a8', - baseCount: 6, - }, - }, - }, r: '0x58294750acbe46cb0dd15ef615a244be49af61f0d799cce68bbbd3d4e7c75cdc', s: '0x3993c38f6e168065d9b20a0b4254697d47db114f57243f56c22f228c7a173f9c', v: '0x01', diff --git a/.storybook/test-data.js b/.storybook/test-data.js index d7c7db0d5caa..7acce27bc431 100644 --- a/.storybook/test-data.js +++ b/.storybook/test-data.js @@ -626,34 +626,7 @@ const state = { path: '/txParams/nonce', timestamp: 1629582711220, value: '0x15b', - }, - { - op: 'add', - path: '/nonceDetails', - value: { - local: { - details: { - highest: 347, - startPoint: 347, - }, - name: 'local', - nonce: 347, - }, - network: { - details: { - baseCount: 347, - blockNumber: '0x9c2682', - }, - name: 'network', - nonce: 347, - }, - params: { - highestLocallyConfirmed: 327, - highestSuggested: 347, - nextNetworkNonce: 347, - }, - }, - }, + } ], [ { @@ -901,29 +874,6 @@ const state = { id: 7900715443136469, loadingDefaults: false, metamaskNetworkId: '56', - nonceDetails: { - local: { - details: { - highest: 347, - startPoint: 347, - }, - name: 'local', - nonce: 347, - }, - network: { - details: { - baseCount: 347, - blockNumber: '0x9c2682', - }, - name: 'network', - nonce: 347, - }, - params: { - highestLocallyConfirmed: 327, - highestSuggested: 347, - nextNetworkNonce: 347, - }, - }, origin: 'metamask', r: '0x90a4dfb0646eef9815454d0ab543b5844acb8772101084565155c93ecce8ed69', rawTx: diff --git a/CHANGELOG.md b/CHANGELOG.md index c3c65908cd0a..5283ec097070 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [11.2.0] +### Added +- Adds Swaps support for the zkSync Era network ([#20809](https://github.com/MetaMask/metamask-extension/pull/20809)) + +### Changed +- Increase account list height, so that it uses all available screen space and displays more accounts ([#20745](https://github.com/MetaMask/metamask-extension/pull/20745)) +- Update Snaps What's New text translations in 14 languages ([#20734](https://github.com/MetaMask/metamask-extension/pull/20734)) +- Remove hover background on Account Picker ([#20794](https://github.com/MetaMask/metamask-extension/pull/20794)) +- Show the first letter or number in a Snap's name as the icon, and not a symbol character, if there is no icon ([#20851](https://github.com/MetaMask/metamask-extension/pull/20851)) +- Set initial background color to system theme ([#20858](https://github.com/MetaMask/metamask-extension/pull/20858)) +- Increase network list height, so that it uses all available screen space and displays more networks ([#20801](https://github.com/MetaMask/metamask-extension/pull/20801)) +- Improve visual spacing and borders on connected sites in the snap details page ([#20854](https://github.com/MetaMask/metamask-extension/pull/20854)) +- [FLASK] Bump snaps packages ([#20567](https://github.com/MetaMask/metamask-extension/pull/20567)) +- [MMI] Added code fences to hide emojis just for MMI build ([#20754](https://github.com/MetaMask/metamask-extension/pull/20754)) +- [MMI] Show the NFT tab content for mmi ([#20830](https://github.com/MetaMask/metamask-extension/pull/20830)) +- [MMI] Changed the wrong privacy policy URL to the good one ([#20884](https://github.com/MetaMask/metamask-extension/pull/20884)) +- [MMI] Shows Stake & Portfolio buttons and hides the Buy and Bridge buttons ([#20767](https://github.com/MetaMask/metamask-extension/pull/20767)) + +### Fixed +- Ensure all NFT lists are sorted by the NFT's id ([#20796](https://github.com/MetaMask/metamask-extension/pull/20796)) +- Fix custom amount editing on token approval screens ([#20804](https://github.com/MetaMask/metamask-extension/pull/20804)) + ## [11.1.2] ### Fixed - Prevent crashes for users that have NFTs without an image and/r limited image data ([#21176](https://github.com/MetaMask/metamask-extension/pull/21176)) @@ -4044,7 +4066,8 @@ Update styles and spacing on the critical error page ([#20350](https://github.c ### Uncategorized - Added the ability to restore accounts from seed words. -[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v11.1.2...HEAD +[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v11.2.0...HEAD +[11.2.0]: https://github.com/MetaMask/metamask-extension/compare/v11.1.2...v11.2.0 [11.1.2]: https://github.com/MetaMask/metamask-extension/compare/v11.1.1...v11.1.2 [11.1.1]: https://github.com/MetaMask/metamask-extension/compare/v11.1.0...v11.1.1 [11.1.0]: https://github.com/MetaMask/metamask-extension/compare/v11.0.0...v11.1.0 diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index 4ee978a1c49c..851cdaeb7c49 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -371,9 +371,6 @@ "amount": { "message": "Betrag" }, - "apiUrl": { - "message": "API-URL" - }, "appDescription": { "message": "Ethereum Browsererweiterung", "description": "The description of the application" @@ -981,9 +978,6 @@ "custodian": { "message": "Verwahrer" }, - "custodianAccount": { - "message": "Verwahrungskonto" - }, "custodianAccountAddedDesc": { "message": "Sie können jetzt Verwahrungskonten in MetaMask Institutional verwenden." }, @@ -2331,9 +2325,6 @@ "missingSettingRequest": { "message": "Hier anfragen" }, - "mmiAddToken": { - "message": "Die Seite bei $1 möchte das folgende Verwahrungstoken in MetaMask Institutional autorisieren." - }, "mmiBuiltAroundTheWorld": { "message": "MetaMask Institutional ist weltweit konzipiert und aufgebaut." }, @@ -2879,6 +2870,21 @@ "notificationsMarkAllAsRead": { "message": "Alle als gelesen markieren" }, + "notificationsOpenBetaSnapsActionText": { + "message": "Mehr erfahren" + }, + "notificationsOpenBetaSnapsDescriptionOne": { + "message": "🎉 Wir freuen uns sehr, die Open-Beta-Version von MetaMask Snaps zu präsentieren!" + }, + "notificationsOpenBetaSnapsDescriptionThree": { + "message": "Personalisieren Sie Ihre Wallet mit Snaps, die von der Entwickler-Community erstellt wurden!" + }, + "notificationsOpenBetaSnapsDescriptionTwo": { + "message": "Snaps helfen Ihnen dabei, mehr aus MetaMask zu machen – wie z. B. Verbindungen mit anderen Netzwerken herzustellen, Transaktionseinblicke zu erlangen und benutzerdefinierte Benachrichtigungen zu erhalten." + }, + "notificationsOpenBetaSnapsTitle": { + "message": "Wir stellen vor: MetaMask Snaps" + }, "numberOfNewTokensDetectedPlural": { "message": "$1 neue Tokens in diesem Konto gefunden.", "description": "$1 is the number of new tokens detected" @@ -4060,6 +4066,10 @@ "snapsNoInsight": { "message": "Der Snap brachte keine Einsicht." }, + "snapsPrivacyWarningSecondMessage": { + "message": "Alle Daten, die Sie mit Drittanbieterdiensten teilen, werden direkt von diesen Drittanbieterdiensten im Einklang mit deren Datenschutzerklärung erfasst. Für weitere Informationen lesen Sie bitte die jeweiligen Datenschutzerklärungen.", + "description": "Second part of a message in popup modal displayed when installing a snap for the first time." + }, "snapsSettingsDescription": { "message": "Verwalten Sie Ihre Snaps." }, diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json index 8b26d947bbc3..9ba54b66e1d7 100644 --- a/app/_locales/el/messages.json +++ b/app/_locales/el/messages.json @@ -371,9 +371,6 @@ "amount": { "message": "Ποσό" }, - "apiUrl": { - "message": "API URL" - }, "appDescription": { "message": "Ένα Πορτοφόλι Ethereum στο Πρόγραμμα Περιήγησής σας", "description": "The description of the application" @@ -981,9 +978,6 @@ "custodian": { "message": "Θεματοφύλακας" }, - "custodianAccount": { - "message": "Λογαριασμός θεματοφύλακα" - }, "custodianAccountAddedDesc": { "message": "Μπορείτε τώρα να χρησιμοποιήσετε τους λογαριασμούς θεματοφύλακά σας στο MetaMask Institutional." }, @@ -2331,9 +2325,6 @@ "missingSettingRequest": { "message": "Υποβάλετε αίτημα εδώ" }, - "mmiAddToken": { - "message": "Η σελίδα στο $1 θα ήθελε να εξουσιοδοτήσει το ακόλουθο token θεματοφύλακα στο MetaMask Institutional" - }, "mmiBuiltAroundTheWorld": { "message": "Το MetaMask Institutional έχει σχεδιαστεί και λειτουργεί σε όλο τον κόσμο." }, @@ -2879,6 +2870,21 @@ "notificationsMarkAllAsRead": { "message": "Επισήμανση όλων ως αναγνωσμένων" }, + "notificationsOpenBetaSnapsActionText": { + "message": "Μάθετε περισσότερα" + }, + "notificationsOpenBetaSnapsDescriptionOne": { + "message": "🎉 Είμαστε ενθουσιασμένοι που ανακοινώνουμε την δοκιμαστική έναρξη του MetaMask Snaps!" + }, + "notificationsOpenBetaSnapsDescriptionThree": { + "message": "Εξατομικεύστε το πορτοφόλι σας με snaps που δημιουργήθηκαν από την κοινότητα προγραμματιστών!" + }, + "notificationsOpenBetaSnapsDescriptionTwo": { + "message": "Τα Snaps σάς βοηθούν να κάνετε περισσότερα με το MetaMask — όπως τη σύνδεση σε περισσότερα δίκτυα, τη προβολή πληροφοριών συναλλαγών και τη λήψη προσαρμοσμένων ειδοποιήσεων." + }, + "notificationsOpenBetaSnapsTitle": { + "message": "Παρουσιάζουμε τα MetaMask Snaps" + }, "numberOfNewTokensDetectedPlural": { "message": "$1 νέα tokens βρέθηκαν σε αυτόν τον λογαριασμό", "description": "$1 is the number of new tokens detected" @@ -4060,6 +4066,10 @@ "snapsNoInsight": { "message": "Το snap δεν επέστρεψε καμία πληροφορία" }, + "snapsPrivacyWarningSecondMessage": { + "message": "Οποιεσδήποτε πληροφορίες μοιράζεστε με τις Υπηρεσίες Τρίτων θα συλλέγονται απευθείας από τις εν λόγω Υπηρεσίες Τρίτων σύμφωνα με τις πολιτικές απορρήτου τους. Ανατρέξτε στις πολιτικές απορρήτου τους για περισσότερες πληροφορίες.", + "description": "Second part of a message in popup modal displayed when installing a snap for the first time." + }, "snapsSettingsDescription": { "message": "Διαχειριστείτε τα Snaps σας" }, diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 5f82f40cc16b..6eeddd86044e 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -351,9 +351,15 @@ "message": "All of your NFTs from $1", "description": "$1 is a link to contract on the block explorer when we're not able to retrieve a erc721 or erc1155 name" }, + "allow": { + "message": "Allow" + }, "allowExternalExtensionTo": { "message": "Allow this external extension to:" }, + "allowMmiToConnectToCustodian": { + "message": "This will allow MMI to connect to $1 to import your accounts." + }, "allowSpendToken": { "message": "Give permission to access your $1?", "description": "$1 is the symbol of the token that are requesting to spend" @@ -371,9 +377,6 @@ "amount": { "message": "Amount" }, - "apiUrl": { - "message": "API URL" - }, "appDescription": { "message": "An Ethereum Wallet in your Browser", "description": "The description of the application" @@ -732,6 +735,15 @@ "confirm": { "message": "Confirm" }, + "confirmConnectCustodianRedirect": { + "message": "We will redirect you to $1 upon clicking continue." + }, + "confirmConnectCustodianText": { + "message": "To connect your accounts log into your $1 account and click on the 'connect to MMI' button." + }, + "confirmConnectionTitle": { + "message": "Confirm connection to $1" + }, "confirmPassword": { "message": "Confirm password" }, @@ -765,6 +777,9 @@ "connectCustodialAccountTitle": { "message": "Custodial Accounts" }, + "connectCustodianAccounts": { + "message": "Connect $1 accounts" + }, "connectManually": { "message": "Manually connect to current site" }, @@ -981,14 +996,11 @@ "custodian": { "message": "Custodian" }, - "custodianAccount": { - "message": "Custodian account" - }, "custodianAccountAddedDesc": { - "message": "You can now use your custodian accounts in MetaMask Institutional." + "message": "You can now use your accounts in MetaMask Institutional." }, "custodianAccountAddedTitle": { - "message": "Selected custodian accounts have been added." + "message": "Selected $1 accounts have been added." }, "custodianReplaceRefreshTokenChangedFailed": { "message": "Please go to $1 and click the 'Connect to MMI' button within their user interface to connect your accounts to MMI again." @@ -2343,9 +2355,6 @@ "missingSettingRequest": { "message": "Request here" }, - "mmiAddToken": { - "message": "The page at $1 would like to authorise the following custodian token in MetaMask Institutional" - }, "mmiBuiltAroundTheWorld": { "message": "MetaMask Institutional is designed and built around the world." }, @@ -2437,6 +2446,9 @@ "networkNameTestnet": { "message": "Testnet" }, + "networkNameZkSyncEra": { + "message": "zkSync Era" + }, "networkProvider": { "message": "Network provider" }, @@ -3232,6 +3244,14 @@ "message": "Allow the snap to derive arbitrary keys unique to this snap, without exposing them. These keys are separate from your MetaMask account(s) and not related to your private keys or Secret Recovery Phrase. Other snaps cannot access this information.", "description": "An extended description for the `snap_getEntropy` permission" }, + "permission_getLocale": { + "message": "View your preferred language.", + "description": "The description for the `snap_getLocale` permission" + }, + "permission_getLocaleDescription": { + "message": "Let this Snap access your preferred language from your MetaMask settings. This can be used to localize and display the Snap's content using your language.", + "description": "An extended description for the `snap_getLocale` permission" + }, "permission_lifecycleHooks": { "message": "Use lifecycle hooks.", "description": "The description for the `endowment:lifecycle-hooks` permission" @@ -4278,7 +4298,7 @@ "message": "Stake" }, "stakeDescription": { - "message": "Hold up your crypto and earn potential profits" + "message": "Stake your crypto to earn rewards" }, "stateLogError": { "message": "Error in retrieving state logs." diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index 32066acf8b21..69914a0c3d90 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -371,9 +371,6 @@ "amount": { "message": "Importe" }, - "apiUrl": { - "message": "URL de la API" - }, "appDescription": { "message": "Un monedero de Ethereum en el explorador", "description": "The description of the application" @@ -981,9 +978,6 @@ "custodian": { "message": "Custodio" }, - "custodianAccount": { - "message": "Cuenta custodiada" - }, "custodianAccountAddedDesc": { "message": "Ahora ya puede usar sus cuentas custodiadas en MetaMask Institutional." }, @@ -2331,9 +2325,6 @@ "missingSettingRequest": { "message": "Solicítelo aquí" }, - "mmiAddToken": { - "message": "A la página de $1 le gustaría autorizar el siguiente token custodiado en MetaMask Institutional" - }, "mmiBuiltAroundTheWorld": { "message": "MetaMask Institutional está diseñado y construido en todo el mundo." }, @@ -2879,6 +2870,21 @@ "notificationsMarkAllAsRead": { "message": "Marcar todo como leído" }, + "notificationsOpenBetaSnapsActionText": { + "message": "Conozca más" + }, + "notificationsOpenBetaSnapsDescriptionOne": { + "message": "🎉 ¡Nos complace anunciar la versión Beta abierta de MetaMask Snaps!" + }, + "notificationsOpenBetaSnapsDescriptionThree": { + "message": "¡Personalice su monedero con snaps creados por la comunidad de desarrolladores!" + }, + "notificationsOpenBetaSnapsDescriptionTwo": { + "message": "Los snaps lo ayudan a hacer más con MetaMask, como conectarlo a más redes, ver información sobre transacciones y recibir notificaciones personalizadas." + }, + "notificationsOpenBetaSnapsTitle": { + "message": "Presentamos MetaMask Snaps" + }, "numberOfNewTokensDetectedPlural": { "message": "$1 nuevos tokens encontrados en esta cuenta", "description": "$1 is the number of new tokens detected" @@ -4060,6 +4066,10 @@ "snapsNoInsight": { "message": "El snap no devolvió ninguna información" }, + "snapsPrivacyWarningSecondMessage": { + "message": "Cualquier información que comparta con Servicios de terceros será recopilada directamente por dichos Servicios de terceros de acuerdo con sus políticas de privacidad. Consulte sus políticas de privacidad para obtener más información.", + "description": "Second part of a message in popup modal displayed when installing a snap for the first time." + }, "snapsSettingsDescription": { "message": "Administre sus snaps" }, diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index 7c1eb5b70e3c..423f49b172b1 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -371,9 +371,6 @@ "amount": { "message": "Montant" }, - "apiUrl": { - "message": "URL de l’API" - }, "appDescription": { "message": "Extension Ethereum pour navigateur", "description": "The description of the application" @@ -981,9 +978,6 @@ "custodian": { "message": "Dépôt" }, - "custodianAccount": { - "message": "Compte de dépôt" - }, "custodianAccountAddedDesc": { "message": "Vous pouvez maintenant utiliser vos comptes de dépôt dans MetaMask Institutional." }, @@ -2331,9 +2325,6 @@ "missingSettingRequest": { "message": "Demandez ici" }, - "mmiAddToken": { - "message": "La page à $1 souhaite autoriser le jeton de dépôt suivant dans MetaMask institutionnel" - }, "mmiBuiltAroundTheWorld": { "message": "MetaMask Institutional est conçu et établi dans le monde entier." }, @@ -2879,6 +2870,21 @@ "notificationsMarkAllAsRead": { "message": "Marquer tout comme lu" }, + "notificationsOpenBetaSnapsActionText": { + "message": "En savoir plus" + }, + "notificationsOpenBetaSnapsDescriptionOne": { + "message": "🎉 Nous sommes ravis d’annoncer le lancement de la version bêta publique de MetaMask Snaps !" + }, + "notificationsOpenBetaSnapsDescriptionThree": { + "message": "Personnalisez votre portefeuille avec des snaps conçus par la communauté de développeurs !" + }, + "notificationsOpenBetaSnapsDescriptionTwo": { + "message": "Les snaps vous aident à profiter pleinement de MetaMask, par exemple vous connecter à plus de réseaux, voir un aperçu des transactions et recevoir des notifications personnalisées." + }, + "notificationsOpenBetaSnapsTitle": { + "message": "Présentation de MetaMask Snaps" + }, "numberOfNewTokensDetectedPlural": { "message": "$1 nouveaux jetons trouvés dans ce compte", "description": "$1 is the number of new tokens detected" @@ -4060,6 +4066,10 @@ "snapsNoInsight": { "message": "Le snap n’a renvoyé aucun aperçu" }, + "snapsPrivacyWarningSecondMessage": { + "message": "Toute information que vous partagez avec des services tiers sera collectée directement par ces services tiers conformément à leur politique de confidentialité. Pour plus d’informations, veuillez consulter leur politique de confidentialité.", + "description": "Second part of a message in popup modal displayed when installing a snap for the first time." + }, "snapsSettingsDescription": { "message": "Gérez vos Snaps" }, diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index d40befd3313f..b1cbf1c5464c 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -371,9 +371,6 @@ "amount": { "message": "अमाउंट" }, - "apiUrl": { - "message": "API URL" - }, "appDescription": { "message": "आपके ब्राउज़र में एक Ethereum वॉलेट", "description": "The description of the application" @@ -981,9 +978,6 @@ "custodian": { "message": "कस्टोडियन" }, - "custodianAccount": { - "message": "कस्टोडियन अकाउंट" - }, "custodianAccountAddedDesc": { "message": "अब आप MetaMask Institutional में अपने कस्टोडियन एकाउंट्स का इस्तेमाल कर सकते हैं।" }, @@ -2331,9 +2325,6 @@ "missingSettingRequest": { "message": "यहां रिक्वेस्ट करें" }, - "mmiAddToken": { - "message": "$1 पर मौजूद पेज MetaMask Institutional में निम्नलिखित कस्टोडियन टोकन को अधिकृत करना चाहता है" - }, "mmiBuiltAroundTheWorld": { "message": "MetaMask Institutional को दुनिया भर में डिजाइन किया और बनाया गया है।" }, @@ -2879,6 +2870,21 @@ "notificationsMarkAllAsRead": { "message": "सभी को पढ़ा हुआ चिन्हित करें" }, + "notificationsOpenBetaSnapsActionText": { + "message": "ज्यादा जानें।" + }, + "notificationsOpenBetaSnapsDescriptionOne": { + "message": "🎉 MetaMask Snaps के Open Beta की घोषणा करते हुए हमें खुशी का अनुभव हो रहा है!" + }, + "notificationsOpenBetaSnapsDescriptionThree": { + "message": "डेवलेपर कम्युनिटी द्वारा तैयार किए गए Snaps के साथ अपने वॉलेट को निजीकृत करें!" + }, + "notificationsOpenBetaSnapsDescriptionTwo": { + "message": "Snaps की मदद से आप MetaMask के साथ और भी बहुत कुछ कर सकते हैं - जैसे, ज़्यादा नेटवर्कों से जुड़ना, ट्रांजेक्शन से संबंधित जानकारी देखना और कस्टम नोटिफ़िकेशन्स पाना।" + }, + "notificationsOpenBetaSnapsTitle": { + "message": "पेश हैं MetaMask Snaps" + }, "numberOfNewTokensDetectedPlural": { "message": "इस अकाउंट में $1 के नए टोकन पाए गए", "description": "$1 is the number of new tokens detected" @@ -4060,6 +4066,10 @@ "snapsNoInsight": { "message": "Snap ने कोई इनसाइट नहीं लौटाई" }, + "snapsPrivacyWarningSecondMessage": { + "message": "थर्ड पार्टी सेवाओं के साथ आप जो भी सूचना शेयर करते हैं, उसे उन थर्ड पार्टी सेवाओं द्वारा उनकी अपनी गोपनीयता नीतियों के अनुसार सीधे एकत्र की जाएगी। अधिक जानकारी के लिए कृपया उनकी गोपनीयता नीतियां देखें।", + "description": "Second part of a message in popup modal displayed when installing a snap for the first time." + }, "snapsSettingsDescription": { "message": "अपने Snaps प्रबंधित करें" }, diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index 420e21ab98e4..beda6288f89f 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -371,9 +371,6 @@ "amount": { "message": "Jumlah" }, - "apiUrl": { - "message": "URL API" - }, "appDescription": { "message": "Dompet Ethereum pada Browser Anda", "description": "The description of the application" @@ -981,9 +978,6 @@ "custodian": { "message": "Kustodian" }, - "custodianAccount": { - "message": "Akun kustodian" - }, "custodianAccountAddedDesc": { "message": "Saat ini Anda dapat menggunakan akun kustodian di MetaMask Institutional." }, @@ -2331,9 +2325,6 @@ "missingSettingRequest": { "message": "Minta di sini" }, - "mmiAddToken": { - "message": "Halaman di $1 ingin mengotorisasi token kustodian berikut di MetaMask Institutional" - }, "mmiBuiltAroundTheWorld": { "message": "MetaMask Institutional dirancang dan dibangun di seluruh dunia." }, @@ -2879,6 +2870,21 @@ "notificationsMarkAllAsRead": { "message": "Tandai semua telah dibaca" }, + "notificationsOpenBetaSnapsActionText": { + "message": "Selengkapnya" + }, + "notificationsOpenBetaSnapsDescriptionOne": { + "message": "🎉 Kami sangat gembira mengumumkan versi Open Beta dari MetaMask Snap!" + }, + "notificationsOpenBetaSnapsDescriptionThree": { + "message": "Personalisasikan dompet Anda dengan snap yang dibuat oleh komunitas pengembang!" + }, + "notificationsOpenBetaSnapsDescriptionTwo": { + "message": "Snap membantu Anda melakukan lebih banyak hal dengan MetaMask — seperti terhubung ke lebih banyak jaringan, melihat wawasan transaksi, dan mendapatkan notifikasi khusus." + }, + "notificationsOpenBetaSnapsTitle": { + "message": "Memperkenalkan MetaMask Snap" + }, "numberOfNewTokensDetectedPlural": { "message": "$1 token baru ditemukan di akun ini", "description": "$1 is the number of new tokens detected" @@ -4060,6 +4066,10 @@ "snapsNoInsight": { "message": "Snap tidak mengembalikan wawasan apa pun" }, + "snapsPrivacyWarningSecondMessage": { + "message": "Setiap informasi yang Anda bagikan kepada Layanan Pihak Ketiga akan dikumpulkan langsung oleh Layanan Pihak Ketiga tersebut sesuai dengan kebijakan privasinya. Baca kebijakan privasinya untuk informasi lebih lanjut.", + "description": "Second part of a message in popup modal displayed when installing a snap for the first time." + }, "snapsSettingsDescription": { "message": "Kelola Snap Anda" }, diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index 0d2f80a2bc10..ec33d33bef47 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -371,9 +371,6 @@ "amount": { "message": "金額" }, - "apiUrl": { - "message": "API URL" - }, "appDescription": { "message": "ブラウザにあるイーサリアムウォレット", "description": "The description of the application" @@ -981,9 +978,6 @@ "custodian": { "message": "カストディアン" }, - "custodianAccount": { - "message": "カストディアンアカウント" - }, "custodianAccountAddedDesc": { "message": "カストディアンアカウントをMetaMask Institutionalで使えるようになりました。" }, @@ -2331,9 +2325,6 @@ "missingSettingRequest": { "message": "ここからリクエスト" }, - "mmiAddToken": { - "message": "$1のページがMetaMask Institutionalで次のカストディアントークンの承認を求めています" - }, "mmiBuiltAroundTheWorld": { "message": "MetaMaskは、世界中でデザイン・開発されています。" }, @@ -2879,6 +2870,21 @@ "notificationsMarkAllAsRead": { "message": "すべて既読にする" }, + "notificationsOpenBetaSnapsActionText": { + "message": "詳細" + }, + "notificationsOpenBetaSnapsDescriptionOne": { + "message": "🎉 MetaMask Snapsのオープンベータについてお知らせします!" + }, + "notificationsOpenBetaSnapsDescriptionThree": { + "message": "開発者コミュニティによって開発されたsnapで、ウォレットをカスタマイズできます!" + }, + "notificationsOpenBetaSnapsDescriptionTwo": { + "message": "Snapsを使えば、他のネットワークへの接続やトランザクションインサイトの表示、カスタム通知の取得など、MetaMaskでより多くのことができるようになります。" + }, + "notificationsOpenBetaSnapsTitle": { + "message": "MetaMask Snapsのご紹介" + }, "numberOfNewTokensDetectedPlural": { "message": "$1種類の新しいトークンがこのアカウントで見つかりました", "description": "$1 is the number of new tokens detected" @@ -4060,6 +4066,10 @@ "snapsNoInsight": { "message": "snapがインサイトを返しませんでした" }, + "snapsPrivacyWarningSecondMessage": { + "message": "サードパーティサービスと共有する情報は、当該サードパーティサービスにより、それぞれのプライバシーポリシーに従い直接収集されます。詳細は、各サードパーティサービスのプライバシーポリシーをご覧ください。", + "description": "Second part of a message in popup modal displayed when installing a snap for the first time." + }, "snapsSettingsDescription": { "message": "Snapsの管理" }, diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index db35ac06a4af..f98405e900d7 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -371,9 +371,6 @@ "amount": { "message": "금액" }, - "apiUrl": { - "message": "API URL" - }, "appDescription": { "message": "브라우저의 이더리움 지갑", "description": "The description of the application" @@ -981,9 +978,6 @@ "custodian": { "message": "수탁자" }, - "custodianAccount": { - "message": "수탁 계정" - }, "custodianAccountAddedDesc": { "message": "이제 MetaMask Institutional에서 수탁 계정을 사용할 수 있습니다." }, @@ -1159,6 +1153,9 @@ "message": "$1 설명", "description": "$1 represents the name of the snap" }, + "desktopApp": { + "message": "데스크톱 앱" + }, "desktopConnectionCriticalErrorDescription": { "message": "이는 간헐적인 오류일 수 있습니다. 확장 프로그램을 다시 시작하거나 MetaMask 데스크톱을 비활성화해 보세요." }, @@ -2328,9 +2325,6 @@ "missingSettingRequest": { "message": "여기에서 요청하세요" }, - "mmiAddToken": { - "message": "$1의 페이지는 다음과 같은 MetaMask 기관 수탁 토큰을 승인하려고 합니다" - }, "mmiBuiltAroundTheWorld": { "message": "MetaMask Institutional은 전 세계적으로 설계 및 구축되었습니다." }, @@ -2756,6 +2750,9 @@ "notifications23ActionText": { "message": "보안 경고 활성화" }, + "notifications23DescriptionOne": { + "message": "이더리움 메인넷에서 Blockaid가 제공하는 보안 경고를 통해 개인정보를 보호하면서 사기를 피하세요." + }, "notifications23DescriptionTwo": { "message": "요청을 승인하기 전에 항상 직접 확인하세요." }, @@ -2852,6 +2849,14 @@ "notifications9Title": { "message": "👓 사용자가 트랜잭션을 이해하기 쉽게 도와드립니다." }, + "notificationsDropLedgerFirefoxDescription": { + "message": "Firefox에서 더 이상 U2F를 지원하지 않아 Firefox를 이용한 MetaMask에서 Ledger를 이용할 수 없습니다. 대신 Google Chrome에서 MetaMask를 이용해 보세요.", + "description": "Description of a notification in the 'See What's New' popup. Describes that ledger will not longer be supported for firefox users and they should use MetaMask on chrome for ledger support instead." + }, + "notificationsDropLedgerFirefoxTitle": { + "message": "Firefox의 Ledger 지원 중단", + "description": "Title for a notification in the 'See What's New' popup. Tells firefox users that ledger support is being dropped." + }, "notificationsEmptyText": { "message": "설치한 스냅에서 알림을 찾을 수 있는 곳입니다." }, @@ -2865,6 +2870,21 @@ "notificationsMarkAllAsRead": { "message": "모두 읽음으로 표시" }, + "notificationsOpenBetaSnapsActionText": { + "message": "자세히 알아보기" + }, + "notificationsOpenBetaSnapsDescriptionOne": { + "message": "🎉 MetaMask Snaps의 오픈 베타가 시작되었습니다!" + }, + "notificationsOpenBetaSnapsDescriptionThree": { + "message": "개발자 커뮤니티가 구축한 스냅으로 지갑을 개별 맞춤하세요!" + }, + "notificationsOpenBetaSnapsDescriptionTwo": { + "message": "스냅은 추가 네트워크 연결, 트랜잭션 인사이트 확인, 커스텀 알림 받기 등 사용자가 MetaMask에서 더욱 다양한 기능을 사용할 수 있도록 합니다." + }, + "notificationsOpenBetaSnapsTitle": { + "message": "MetaMask Snaps 소개" + }, "numberOfNewTokensDetectedPlural": { "message": "계정에서 $1개의 새로운 토큰이 발견됨", "description": "$1 is the number of new tokens detected" @@ -3650,9 +3670,16 @@ "securityAlerts": { "message": "보안 경고" }, + "securityAlertsDescription": { + "message": "이 기능은 개인정보를 보호하면서 트랜잭션 및 서명 요청을 적극적으로 검토하여 이더리움 메인넷에서 악의적인 활동이 있는 경우 경고합니다. 사용자 데이터는 이 서비스를 제공하는 제삼자와 공유되지 않습니다. 요청을 승인하기 전에 항상 직접 확인하세요. 이 기능이 모든 악의적인 활동 탐지를 보장하는 것은 아닙니다." + }, "securityAndPrivacy": { "message": "보안 및 프라이버시" }, + "securityProviderPoweredBy": { + "message": "$1 제공", + "description": "The security provider that is providing data" + }, "seeDetails": { "message": "세부 정보 보기" }, @@ -4039,6 +4066,10 @@ "snapsNoInsight": { "message": "스냅이 인사이트를 가져오지 못했습니다" }, + "snapsPrivacyWarningSecondMessage": { + "message": "타사와 공유하는 모든 정보는 해당 타사의 개인정보 처리방침에 따라 직접 수집됩니다. 더 자세한 내용은 해당 회사의 개인정보 처리방침을 참고하시기 바랍니다.", + "description": "Second part of a message in popup modal displayed when installing a snap for the first time." + }, "snapsSettingsDescription": { "message": "스냅 관리" }, diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json index 55d976198132..92ff97f1b260 100644 --- a/app/_locales/pt/messages.json +++ b/app/_locales/pt/messages.json @@ -371,9 +371,6 @@ "amount": { "message": "Valor" }, - "apiUrl": { - "message": "URL da API" - }, "appDescription": { "message": "Uma carteira de Ethereum no seu navegador", "description": "The description of the application" @@ -981,9 +978,6 @@ "custodian": { "message": "Custodiante" }, - "custodianAccount": { - "message": "Conta custodiante" - }, "custodianAccountAddedDesc": { "message": "Agora você pode usar suas contas de custódia no MetaMask Institutional." }, @@ -2331,9 +2325,6 @@ "missingSettingRequest": { "message": "Solicite aqui" }, - "mmiAddToken": { - "message": "A página em $1 gostaria de autorizar o seguinte token de custodiante na MetaMask Institutional" - }, "mmiBuiltAroundTheWorld": { "message": "O MetaMask Institutional é projetado e desenvolvido ao redor do mundo." }, @@ -2879,6 +2870,21 @@ "notificationsMarkAllAsRead": { "message": "Marcar todas como lidas" }, + "notificationsOpenBetaSnapsActionText": { + "message": "Saiba mais" + }, + "notificationsOpenBetaSnapsDescriptionOne": { + "message": "🎉 Estamos empolgados de anunciar o Beta Aberto do MetaMask Snaps!" + }, + "notificationsOpenBetaSnapsDescriptionThree": { + "message": "Personalize sua carteira com snaps criados pela comunidade de desenvolvedores!" + }, + "notificationsOpenBetaSnapsDescriptionTwo": { + "message": "Os snaps ajudam a fazer mais com a MetaMask, como conectar-se a mais redes, ver insights de transações e receber notificações personalizadas." + }, + "notificationsOpenBetaSnapsTitle": { + "message": "Apresentamos o MetaMask Snaps" + }, "numberOfNewTokensDetectedPlural": { "message": "$1 novos tokens encontrados nesta conta", "description": "$1 is the number of new tokens detected" @@ -4060,6 +4066,10 @@ "snapsNoInsight": { "message": "O snap não retornou nenhum insight" }, + "snapsPrivacyWarningSecondMessage": { + "message": "Informações compartilhadas com Serviços de Terceiros serão coletadas diretamente por eles, de acordo com políticas de privacidade próprias. Por favor, consulte-as para obter mais informações.", + "description": "Second part of a message in popup modal displayed when installing a snap for the first time." + }, "snapsSettingsDescription": { "message": "Gerencie seus snaps" }, diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index 51f7b1e92d77..7becb2d165ab 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -371,9 +371,6 @@ "amount": { "message": "Сумма" }, - "apiUrl": { - "message": "URL API" - }, "appDescription": { "message": "Кошелек Ethereum в вашем браузере", "description": "The description of the application" @@ -981,9 +978,6 @@ "custodian": { "message": "Депозитарий" }, - "custodianAccount": { - "message": "Депозитарный счет" - }, "custodianAccountAddedDesc": { "message": "Теперь вы можете использовать свои депозитарные счета в MetaMask Institutional." }, @@ -2331,9 +2325,6 @@ "missingSettingRequest": { "message": "Запросите здесь" }, - "mmiAddToken": { - "message": "Страница в $1 хочет авторизовать следующий токен депозитария в MetaMask Institutional" - }, "mmiBuiltAroundTheWorld": { "message": "MetaMask Institutional разработан и создан с учетом потребностей в разных частях мира." }, @@ -2879,6 +2870,21 @@ "notificationsMarkAllAsRead": { "message": "Отметить все как прочитанные" }, + "notificationsOpenBetaSnapsActionText": { + "message": "Подробнее" + }, + "notificationsOpenBetaSnapsDescriptionOne": { + "message": "🎉 Мы рады объявить об открытой бета-версии MetaMask Snaps!" + }, + "notificationsOpenBetaSnapsDescriptionThree": { + "message": "Персонализируйте свой кошелек с помощью snaps, созданных сообществом разработчиков!" + }, + "notificationsOpenBetaSnapsDescriptionTwo": { + "message": "Snaps помогают вам делать больше с MetaMask — например, подключаться к большему количеству сетей, просматривать статистику транзакций и получать настраиваемые уведомления." + }, + "notificationsOpenBetaSnapsTitle": { + "message": "Представляем MetaMask Snaps" + }, "numberOfNewTokensDetectedPlural": { "message": "$1 новых токена(-ов) найдены в этом счете", "description": "$1 is the number of new tokens detected" @@ -4060,6 +4066,10 @@ "snapsNoInsight": { "message": "Этот snap не выдал никакой аналитики" }, + "snapsPrivacyWarningSecondMessage": { + "message": "Любая информация, которую вы передаете Сторонним службам, будет собираться непосредственно этими Сторонними службами в соответствии с их политикой конфиденциальности. Пожалуйста, обратитесь к их политике конфиденциальности для получения дополнительной информации.", + "description": "Second part of a message in popup modal displayed when installing a snap for the first time." + }, "snapsSettingsDescription": { "message": "Управление вашим Snaps" }, diff --git a/app/_locales/tl/messages.json b/app/_locales/tl/messages.json index a9648e6dc1ff..45135ff62f6d 100644 --- a/app/_locales/tl/messages.json +++ b/app/_locales/tl/messages.json @@ -371,9 +371,6 @@ "amount": { "message": "Halaga" }, - "apiUrl": { - "message": "API URL" - }, "appDescription": { "message": "Ethereum Wallet sa iyong Browser", "description": "The description of the application" @@ -981,9 +978,6 @@ "custodian": { "message": "Tagapangalaga" }, - "custodianAccount": { - "message": "Account ng tagapangalaga" - }, "custodianAccountAddedDesc": { "message": "Maaari mo na ngayong gamitin ang iyong mga custodian account sa MetaMask Institutional." }, @@ -2331,9 +2325,6 @@ "missingSettingRequest": { "message": "Humiling dito" }, - "mmiAddToken": { - "message": "Ang pahina sa $1 ay nais pahintulutan ang sumusunod na tagapangalaga na token sa MetaMask Institutional" - }, "mmiBuiltAroundTheWorld": { "message": "Ang MetaMask Institutional ay dinisenyo at binuo sa buong mundo." }, @@ -2879,6 +2870,21 @@ "notificationsMarkAllAsRead": { "message": "Markahan ang lahat bilang nabasa na" }, + "notificationsOpenBetaSnapsActionText": { + "message": "Matuto pa" + }, + "notificationsOpenBetaSnapsDescriptionOne": { + "message": "🎉 Nasasabik kaming ianunsiyo ang Open Beta ng MetaMask Snaps!" + }, + "notificationsOpenBetaSnapsDescriptionThree": { + "message": "Ipersonalisa ang iyong wallet gamit ang mga snap na binuo ng developer community!" + }, + "notificationsOpenBetaSnapsDescriptionTwo": { + "message": "Ang Snaps ay makakatulong sa iyo na maraming magawa sa MetaMask -- tulad ng kumonekta sa maraming network, tingnan ang mga insight sa transaksyon, at makakuha ng custom na notipikasyon." + }, + "notificationsOpenBetaSnapsTitle": { + "message": "Ipinakikilala ang MetaMask Snaps" + }, "numberOfNewTokensDetectedPlural": { "message": "$1 (na) bagong token ang nakita sa account na ito", "description": "$1 is the number of new tokens detected" @@ -4060,6 +4066,10 @@ "snapsNoInsight": { "message": "Ang snap ay hindi nagbalik ng anumang insight" }, + "snapsPrivacyWarningSecondMessage": { + "message": "Ang anumang impormasyong ibinabahagi mo sa mga Serbisyo ng Third Party ay direktang kokolektahin ng mga Serbisyo ng Third Party na iyon alinsunod sa kanilang mga patakaran sa pagkapribado. Pakitingnan ang kanilang mga patakaran sa pagkapribado para sa higit pang impormasyon.", + "description": "Second part of a message in popup modal displayed when installing a snap for the first time." + }, "snapsSettingsDescription": { "message": "Pamahalaan ang iyong mga Snap" }, diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json index d5f858d14c34..0543827c83c4 100644 --- a/app/_locales/tr/messages.json +++ b/app/_locales/tr/messages.json @@ -371,9 +371,6 @@ "amount": { "message": "Tutar" }, - "apiUrl": { - "message": "API URL" - }, "appDescription": { "message": "Tarayıcında bir Ethereum Cüzdanı", "description": "The description of the application" @@ -981,9 +978,6 @@ "custodian": { "message": "Saklayıcı Kurum" }, - "custodianAccount": { - "message": "Saklayıcı kurum hesabı" - }, "custodianAccountAddedDesc": { "message": "Artık saklayıcı kurum hesaplarınızı MetaMask Institutional'da kullanabilirsiniz." }, @@ -2331,9 +2325,6 @@ "missingSettingRequest": { "message": "Buradan talep et" }, - "mmiAddToken": { - "message": "$1 alanındaki sayfa MetaMask Institutional'daki aşağıdaki saklayıcı kurum tokenine yetki vermek istiyor" - }, "mmiBuiltAroundTheWorld": { "message": "MetaMask Institutional dünya çapında tasarlanmış ve yapılmıştır." }, @@ -2879,6 +2870,21 @@ "notificationsMarkAllAsRead": { "message": "Tümünü okundu olarak işaretle" }, + "notificationsOpenBetaSnapsActionText": { + "message": "Daha fazla bilgi edinin" + }, + "notificationsOpenBetaSnapsDescriptionOne": { + "message": "MetaMask Snaps'in Açık Beta sürümünü duyurmaktan heyecan duyuyoruz!" + }, + "notificationsOpenBetaSnapsDescriptionThree": { + "message": "Geliştirici topluluğu tarafından oluşturulan snap'lerle cüzdanınızı kişiselleştirin!" + }, + "notificationsOpenBetaSnapsDescriptionTwo": { + "message": "Snap'ler MetaMask ile daha fazla ağa bağlanma, işlem içgörülerini görme ve kişisel bildirimler alma gibi daha çok şey yapmanıza yardımcı olur." + }, + "notificationsOpenBetaSnapsTitle": { + "message": "MetaMask Snaps tanıtımı" + }, "numberOfNewTokensDetectedPlural": { "message": "Bu hesapta $1 yeni token bulundu", "description": "$1 is the number of new tokens detected" @@ -4060,6 +4066,10 @@ "snapsNoInsight": { "message": "Snap herhangi bir ayrıntıya ulaşamadı" }, + "snapsPrivacyWarningSecondMessage": { + "message": "Üçüncü Taraf Hizmetleri ile paylaştığınız tüm bilgiler söz konusu Üçüncü Taraf Hizmetlerinin gizlilik politikalarına göre doğrudan üçüncü taraflar tarafından toplanacaktır. Daha fazla bilgi için lütfen üçüncü tarafların gizlilik politikalarına bakın.", + "description": "Second part of a message in popup modal displayed when installing a snap for the first time." + }, "snapsSettingsDescription": { "message": "Snaplerini yönet" }, diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index 004878d5b896..699efc6a3830 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -371,9 +371,6 @@ "amount": { "message": "Số tiền" }, - "apiUrl": { - "message": "URL API" - }, "appDescription": { "message": "Ví Ethereum trên trình duyệt của bạn", "description": "The description of the application" @@ -981,9 +978,6 @@ "custodian": { "message": "Lưu ký" }, - "custodianAccount": { - "message": "Tài khoản lưu ký" - }, "custodianAccountAddedDesc": { "message": "Giờ đây bạn có thể sử dụng tài khoản lưu ký của mình trong MetaMask Institutional." }, @@ -2331,9 +2325,6 @@ "missingSettingRequest": { "message": "Yêu cầu tại đây" }, - "mmiAddToken": { - "message": "Trang tại $1 muốn ủy quyền token lưu ký sau trong MetaMask Institutional" - }, "mmiBuiltAroundTheWorld": { "message": "MetaMask Institutional được thiết kế và xây dựng trên khắp thế giới." }, @@ -2879,6 +2870,21 @@ "notificationsMarkAllAsRead": { "message": "Đánh dấu đã đọc tất cả" }, + "notificationsOpenBetaSnapsActionText": { + "message": "Tìm hiểu thêm" + }, + "notificationsOpenBetaSnapsDescriptionOne": { + "message": "Chúng tôi vui mừng thông báo về phiên bản Open Beta của MetaMask Snaps!" + }, + "notificationsOpenBetaSnapsDescriptionThree": { + "message": "Cá nhân hóa ví của bạn bằng các snap do cộng đồng nhà lập trình xây dựng!" + }, + "notificationsOpenBetaSnapsDescriptionTwo": { + "message": "Snap giúp bạn làm được nhiều việc hơn với MetaMask — chẳng hạn như kết nối với nhiều mạng hơn, xem thông tin chuyên sâu về giao dịch và nhận thông báo tùy chỉnh." + }, + "notificationsOpenBetaSnapsTitle": { + "message": "Giới thiệu MetaMask Snaps" + }, "numberOfNewTokensDetectedPlural": { "message": "Tìm thấy $1 token mới trong tài khoản này", "description": "$1 is the number of new tokens detected" @@ -4060,6 +4066,10 @@ "snapsNoInsight": { "message": "Snap không trả về bất kỳ thông tin chi tiết nào" }, + "snapsPrivacyWarningSecondMessage": { + "message": "Mọi thông tin mà bạn chia sẻ với Dịch vụ bên thứ ba sẽ được Dịch vụ bên thứ ba đó thu thập trực tiếp theo chính sách quyền riêng tư của họ. Vui lòng tham khảo chính sách quyền riêng tư của họ để biết thêm thông tin.", + "description": "Second part of a message in popup modal displayed when installing a snap for the first time." + }, "snapsSettingsDescription": { "message": "Quản lý Snap" }, diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index 5bbe9036bd2f..e94f426e1398 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -371,9 +371,6 @@ "amount": { "message": "数额" }, - "apiUrl": { - "message": "API URL" - }, "appDescription": { "message": "浏览器中的以太坊钱包", "description": "The description of the application" @@ -981,9 +978,6 @@ "custodian": { "message": "托管人" }, - "custodianAccount": { - "message": "托管账户" - }, "custodianAccountAddedDesc": { "message": "您现在可以在 MetaMask Institutional 使用您的托管账户。 " }, @@ -1223,7 +1217,7 @@ "message": "您的 MetaMask Extension 需要升级。" }, "desktopOutdatedExtensionErrorTitle": { - "message": "MetaMask Extension 已过期" + "message": "MetaMask Extension 已过时" }, "desktopPageDescription": { "message": "如果配对成功,扩展程序将重新启动,您必须重新输入密码。" @@ -2331,9 +2325,6 @@ "missingSettingRequest": { "message": "在这里请求" }, - "mmiAddToken": { - "message": "$1的页面想在 MetaMask Institutional 中授权以下托管代币" - }, "mmiBuiltAroundTheWorld": { "message": "MetaMask Institutional 面向全球各地设计并建立。" }, @@ -2879,6 +2870,21 @@ "notificationsMarkAllAsRead": { "message": "将所有标记为已读" }, + "notificationsOpenBetaSnapsActionText": { + "message": "了解详情" + }, + "notificationsOpenBetaSnapsDescriptionOne": { + "message": "🎉 我们很高兴宣布推出 MetaMask Snaps 公开测试版!" + }, + "notificationsOpenBetaSnapsDescriptionThree": { + "message": "使用开发者社群构建的 snap,个性化您的钱包!" + }, + "notificationsOpenBetaSnapsDescriptionTwo": { + "message": "Snaps 可以帮助您利用 MetaMask 做更多事情,例如连接到更多网络、查看交易见解,以及获取自定义通知。" + }, + "notificationsOpenBetaSnapsTitle": { + "message": "介绍 MetaMask Snaps" + }, "numberOfNewTokensDetectedPlural": { "message": "在此账户中找到$1枚新代币", "description": "$1 is the number of new tokens detected" @@ -4060,6 +4066,10 @@ "snapsNoInsight": { "message": "Snap 没有返回任何洞察" }, + "snapsPrivacyWarningSecondMessage": { + "message": "您与第三方服务分享的任何信息,将由这些第三方服务根据其隐私政策直接收集。请参阅其隐私政策以了解更多信息。", + "description": "Second part of a message in popup modal displayed when installing a snap for the first time." + }, "snapsSettingsDescription": { "message": "管理您的 Snaps" }, diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index 9603542dac85..4a50e61cf60b 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -28,9 +28,11 @@ export default class AppStateController extends EventEmitter { preferencesStore, qrHardwareStore, messenger, + extension, } = opts; super(); + this.extension = extension; this.onInactiveTimeout = onInactiveTimeout || (() => undefined); this.store = new ObservableStore({ timeoutMinutes: DEFAULT_AUTO_LOCK_TIME_LIMIT, @@ -249,7 +251,7 @@ export default class AppStateController extends EventEmitter { if (this.timer) { clearTimeout(this.timer); } else if (isManifestV3) { - chrome.alarms.clear(AUTO_LOCK_TIMEOUT_ALARM); + this.extension.alarms.clear(AUTO_LOCK_TIMEOUT_ALARM); } if (!timeoutMinutes) { @@ -257,14 +259,14 @@ export default class AppStateController extends EventEmitter { } if (isManifestV3) { - chrome.alarms.create(AUTO_LOCK_TIMEOUT_ALARM, { + this.extension.alarms.create(AUTO_LOCK_TIMEOUT_ALARM, { delayInMinutes: timeoutMinutes, periodInMinutes: timeoutMinutes, }); - chrome.alarms.onAlarm.addListener((alarmInfo) => { + this.extension.alarms.onAlarm.addListener((alarmInfo) => { if (alarmInfo.name === AUTO_LOCK_TIMEOUT_ALARM) { this.onInactiveTimeout(); - chrome.alarms.clear(AUTO_LOCK_TIMEOUT_ALARM); + this.extension.alarms.clear(AUTO_LOCK_TIMEOUT_ALARM); } }); } else { diff --git a/app/scripts/controllers/metametrics.js b/app/scripts/controllers/metametrics.js index 20a7cdcb5493..d92e1ce5f808 100644 --- a/app/scripts/controllers/metametrics.js +++ b/app/scripts/controllers/metametrics.js @@ -176,20 +176,23 @@ export default class MetaMetricsController { // tracked if the event isn't progressed within that amount of time. if (isManifestV3) { /* eslint-disable no-undef */ - chrome.alarms.getAll((alarms) => { + this.extension.alarms.getAll((alarms) => { const hasAlarm = checkAlarmExists( alarms, METAMETRICS_FINALIZE_EVENT_FRAGMENT_ALARM, ); if (!hasAlarm) { - chrome.alarms.create(METAMETRICS_FINALIZE_EVENT_FRAGMENT_ALARM, { - delayInMinutes: 1, - periodInMinutes: 1, - }); + this.extension.alarms.create( + METAMETRICS_FINALIZE_EVENT_FRAGMENT_ALARM, + { + delayInMinutes: 1, + periodInMinutes: 1, + }, + ); } }); - chrome.alarms.onAlarm.addListener((alarmInfo) => { + this.extension.alarms.onAlarm.addListener((alarmInfo) => { if (alarmInfo.name === METAMETRICS_FINALIZE_EVENT_FRAGMENT_ALARM) { this.finalizeAbandonedFragments(); } diff --git a/app/scripts/controllers/mmi-controller.js b/app/scripts/controllers/mmi-controller.js index 355d4ad27352..bdf84c5f8877 100644 --- a/app/scripts/controllers/mmi-controller.js +++ b/app/scripts/controllers/mmi-controller.js @@ -345,7 +345,7 @@ export default class MMIController extends EventEmitter { // FIXME: status maps are not a thing anymore this.custodyController.storeCustodyStatusMap( - custodian.name, + custodian.envName, keyring.getStatusMap(), ); diff --git a/app/scripts/controllers/swaps.js b/app/scripts/controllers/swaps.js index 2d35c97f1327..1e9fe2c44eb6 100644 --- a/app/scripts/controllers/swaps.js +++ b/app/scripts/controllers/swaps.js @@ -172,11 +172,12 @@ export default class SwapsController { } async fetchSwapsNetworkConfig(chainId) { - const response = await fetchWithCache( - getBaseApi('network', chainId), - { method: 'GET' }, - { cacheRefreshTime: 600000 }, - ); + const response = await fetchWithCache({ + url: getBaseApi('network', chainId), + fetchOptions: { method: 'GET' }, + cacheOptions: { cacheRefreshTime: 600000 }, + functionName: 'fetchSwapsNetworkConfig', + }); const { refreshRates, parameters = {} } = response || {}; if ( !refreshRates || diff --git a/app/scripts/controllers/transactions/README.md b/app/scripts/controllers/transactions/README.md index 7f9787b1b920..09ba59e806e3 100644 --- a/app/scripts/controllers/transactions/README.md +++ b/app/scripts/controllers/transactions/README.md @@ -59,29 +59,7 @@ txMeta = { "value": "0x3b9aca00" }] ], // I've removed most of history for this - "origin": "MetaMask", //debug - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 0, - "highestSuggested": 0, - "nextNetworkNonce": 0 - }, - "local": { - "name": "local", - "nonce": 0, - "details": { - "startPoint": 0, - "highest": 0 - } - }, - "network": { - "name": "network", - "nonce": 0, - "details": { - "baseCount": 0 - } - } - }, + "origin": "MetaMask", "rawTx": "0xf86980843b9aca00827b0c948acce2391c0d510a6c5e5d8f819a678f79b7e67580808602c5b5de66eea05c01a320b96ac730cb210ca56d2cb71fa360e1fc2c21fa5cf333687d18eb323fa02ed05987a6e5fd0f2459fcff80710b76b83b296454ad9a37594a0ccb4643ea90", // used for rebroadcast "hash": "0xa45ba834b97c15e6ff4ed09badd04ecd5ce884b455eb60192cdc73bcc583972a", "submittedTime": 1524094077902 // time of the attempt to submit the raw tx to the network, used in the ui to show the retry button diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index d5e98ba70ca0..872bfd4401c8 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -345,6 +345,9 @@ export default class TransactionController extends EventEmitter { this._requestTransactionApproval(txMeta, { shouldShowRequest: false, }).catch((error) => { + if (error.code === errorCodes.provider.userRejectedRequest) { + return; + } log.error('Error during persisted transaction approval', error); }); }); @@ -1857,11 +1860,6 @@ export default class TransactionController extends EventEmitter { customNonceValue === 0 ? customNonceValue : customNonceValue || nonce; txMeta.txParams.nonce = addHexPrefix(customOrNonce.toString(16)); - // add nonce debugging information to txMeta - txMeta.nonceDetails = nonceLock.nonceDetails; - if (customNonceValue) { - txMeta.nonceDetails.customNonceValue = customNonceValue; - } this.txStateManager.updateTransaction( txMeta, 'transactions#approveTransaction', diff --git a/app/scripts/lib/rpc-method-middleware/handlers/switch-ethereum-chain.js b/app/scripts/lib/rpc-method-middleware/handlers/switch-ethereum-chain.js index e2137da871b7..b074a3d7fde9 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/switch-ethereum-chain.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/switch-ethereum-chain.js @@ -20,6 +20,8 @@ const switchEthereumChain = { hookNames: { getCurrentChainId: true, findNetworkConfigurationBy: true, + findNetworkClientIdByChainId: true, + setNetworkClientIdForDomain: true, setProviderType: true, setActiveNetwork: true, requestUserApproval: true, @@ -53,6 +55,8 @@ async function switchEthereumChainHandler( { getCurrentChainId, findNetworkConfigurationBy, + findNetworkClientIdByChainId, + setNetworkClientIdForDomain, setProviderType, setActiveNetwork, requestUserApproval, @@ -99,7 +103,6 @@ async function switchEthereumChainHandler( }), ); } - const requestData = findExistingNetwork(_chainId, findNetworkConfigurationBy); if (requestData) { const currentChainId = getCurrentChainId(); @@ -122,6 +125,8 @@ async function switchEthereumChainHandler( } else { await setActiveNetwork(approvedRequestData.id); } + const networkClientId = findNetworkClientIdByChainId(_chainId); + setNetworkClientIdForDomain(req.origin, networkClientId); res.result = null; } catch (error) { return end(error); diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index edc7925e2220..077d0329049d 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -198,6 +198,7 @@ export const SENTRY_BACKGROUND_STATE = { usePhishDetect: true, useTokenDetection: true, }, + SelectedNetworkController: { domains: true, perDomainNetwork: false }, SignatureController: { unapprovedMsgCount: true, unapprovedMsgs: false, diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 52fc263aa53e..ee08fe92682b 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -53,6 +53,11 @@ import { SubjectType, } from '@metamask/subject-metadata-controller'; import SmartTransactionsController from '@metamask/smart-transactions-controller'; +import { + SelectedNetworkController, + createSelectedNetworkMiddleware, +} from '@metamask/selected-network-controller'; + ///: BEGIN:ONLY_INCLUDE_IN(snaps) import { encrypt, decrypt } from '@metamask/browser-passworder'; import { RateLimitController } from '@metamask/rate-limit-controller'; @@ -301,6 +306,21 @@ export default class MetamaskController extends EventEmitter { // next, we will initialize the controllers // controller initialization order matters + this.selectedNetworkController = new SelectedNetworkController({ + messenger: this.controllerMessenger.getRestricted({ + name: 'SelectedNetworkController', + allowedActions: [ + 'SelectedNetworkController:getState', + 'SelectedNetworkController:getNetworkClientIdForDomain', + 'SelectedNetworkController:setNetworkClientIdForDomain', + ], + allowedEvents: [ + 'SelectedNetworkController:stateChange', + 'NetworkController:stateChange', + ], + }), + }); + this.approvalController = new ApprovalController({ messenger: this.controllerMessenger.getRestricted({ name: 'ApprovalController', @@ -623,6 +643,7 @@ export default class MetamaskController extends EventEmitter { `${this.approvalController.name}:acceptRequest`, ], }), + extension: this.extension, }); const currencyRateMessenger = this.controllerMessenger.getRestricted({ @@ -826,7 +847,12 @@ export default class MetamaskController extends EventEmitter { ///: BEGIN:ONLY_INCLUDE_IN(keyring-snaps) additionalKeyrings.push( (() => { - const builder = () => new SnapKeyring(this.snapController); + const builder = () => + new SnapKeyring(this.snapController, { + saveState: async () => { + await this.keyringController.persistAllKeyrings(); + }, + }); builder.type = SnapKeyring.type; return builder; })(), @@ -1666,6 +1692,7 @@ export default class MetamaskController extends EventEmitter { SmartTransactionsController: this.smartTransactionsController, NftController: this.nftController, PhishingController: this.phishingController, + SelectedNetworkController: this.selectedNetworkController, ///: BEGIN:ONLY_INCLUDE_IN(snaps) SnapController: this.snapController, CronjobController: this.cronjobController, @@ -1710,6 +1737,7 @@ export default class MetamaskController extends EventEmitter { TokensController: this.tokensController, SmartTransactionsController: this.smartTransactionsController, NftController: this.nftController, + SelectedNetworkController: this.selectedNetworkController, ///: BEGIN:ONLY_INCLUDE_IN(snaps) SnapController: this.snapController, CronjobController: this.cronjobController, @@ -1835,18 +1863,15 @@ export default class MetamaskController extends EventEmitter { * Initialize the snap keyring if it is not present. */ async getSnapKeyring() { - if (!this.snapKeyring) { - let [snapKeyring] = this.coreKeyringController.getKeyringsByType( + let [snapKeyring] = this.coreKeyringController.getKeyringsByType( + KeyringType.snap, + ); + if (!snapKeyring) { + snapKeyring = await this.coreKeyringController.addNewKeyring( KeyringType.snap, ); - if (!snapKeyring) { - snapKeyring = await this.keyringController.addNewKeyring( - KeyringType.snap, - ); - } - this.snapKeyring = snapKeyring; } - return this.snapKeyring; + return snapKeyring; } ///: END:ONLY_INCLUDE_IN @@ -1887,6 +1912,17 @@ export default class MetamaskController extends EventEmitter { return this.controllerMessenger.call('SnapController:handleRequest', args); } + /** + * Gets the currently selected locale from the PreferencesController. + * + * @returns The currently selected locale. + */ + getLocale() { + const { currentLocale } = this.preferencesController.store.getState(); + + return currentLocale; + } + /** * Constructor helper for getting Snap permission specifications. */ @@ -1896,6 +1932,7 @@ export default class MetamaskController extends EventEmitter { ...buildSnapRestrictedMethodSpecifications({ encrypt, decrypt, + getLocale: this.getLocale.bind(this), clearSnapState: this.controllerMessenger.call.bind( this.controllerMessenger, 'SnapController:clearSnapState', @@ -1942,9 +1979,6 @@ export default class MetamaskController extends EventEmitter { ///: END:ONLY_INCLUDE_IN ///: BEGIN:ONLY_INCLUDE_IN(keyring-snaps) getSnapKeyring: this.getSnapKeyring.bind(this), - saveSnapKeyring: async () => { - await this.keyringController.persistAllKeyrings(); - }, ///: END:ONLY_INCLUDE_IN ///: BEGIN:ONLY_INCLUDE_IN(snaps) }), @@ -4044,8 +4078,15 @@ export default class MetamaskController extends EventEmitter { setupProviderEngine({ origin, subjectType, sender, tabId }) { // setup json rpc engine stack const engine = new JsonRpcEngine(); + const { blockTracker, provider } = this; + // append origin to each request + engine.push(createOriginMiddleware({ origin })); + + // append selectedNetworkClientId to each request + engine.push(createSelectedNetworkMiddleware(this.controllerMessenger)); + // create filter polyfill middleware const filterMiddleware = createFilterMiddleware({ provider, blockTracker }); @@ -4062,9 +4103,6 @@ export default class MetamaskController extends EventEmitter { engine.push(createDupeReqFilterMiddleware()); } - // append origin to each request - engine.push(createOriginMiddleware({ origin })); - // append tabId to each request if it exists if (tabId) { engine.push(createTabIdMiddleware({ tabId })); @@ -4182,7 +4220,15 @@ export default class MetamaskController extends EventEmitter { setActiveNetwork: this.networkController.setActiveNetwork.bind( this.networkController, ), + findNetworkClientIdByChainId: + this.networkController.findNetworkClientIdByChainId.bind( + this.networkController, + ), findNetworkConfigurationBy: this.findNetworkConfigurationBy.bind(this), + setNetworkClientIdForDomain: + this.selectedNetworkController.setNetworkClientIdForDomain.bind( + this.selectedNetworkController, + ), setProviderType: this.networkController.setProviderType.bind( this.networkController, ), @@ -4267,6 +4313,7 @@ export default class MetamaskController extends EventEmitter { // forward to metamask primary provider engine.push(providerAsMiddleware(provider)); + return engine; } diff --git a/app/scripts/metamask-controller.test.js b/app/scripts/metamask-controller.test.js index 6e387de1d0e4..c8e6c070e14d 100644 --- a/app/scripts/metamask-controller.test.js +++ b/app/scripts/metamask-controller.test.js @@ -1,11 +1,10 @@ -import { strict as assert } from 'assert'; -import sinon from 'sinon'; +/** + * @jest-environment node + */ import { cloneDeep } from 'lodash'; import nock from 'nock'; import { obj as createThoughStream } from 'through2'; import EthQuery from 'eth-query'; -import proxyquire from 'proxyquire'; -import browser from 'webextension-polyfill'; import { wordlist as englishWordlist } from '@metamask/scure-bip39/dist/wordlists/english'; import { ListNames, @@ -25,7 +24,7 @@ import { HardwareDeviceNames } from '../../shared/constants/hardware-wallets'; import { KeyringType } from '../../shared/constants/keyring'; import { deferredPromise } from './lib/util'; import TransactionController from './controllers/transactions'; -import PreferencesController from './controllers/preferences'; +import MetaMaskController from './metamask-controller'; const Ganache = require('../../test/e2e/ganache'); @@ -35,16 +34,24 @@ const browserPolyfillMock = { runtime: { id: 'fake-extension-id', onInstalled: { - addListener: () => undefined, + addListener: jest.fn(), }, onMessageExternal: { - addListener: () => undefined, + addListener: jest.fn(), }, - getPlatformInfo: async () => 'mac', + getPlatformInfo: jest.fn().mockResolvedValue('mac'), }, storage: { session: { - set: () => undefined, + set: jest.fn(), + }, + }, + alarms: { + getAll: jest.fn(), + create: jest.fn(), + clear: jest.fn(), + onAlarm: { + addListener: jest.fn(), }, }, }; @@ -72,42 +79,29 @@ const createLoggerMiddlewareMock = () => (req, res, next) => { next(); }; -const MOCK_TOKEN_BALANCE = '888'; - -function MockEthContract() { - return () => { - return { - at: () => { - return { - balanceOf: () => MOCK_TOKEN_BALANCE, - }; - }, - }; - }; -} - -function MockPreferencesController(...args) { - const controller = new PreferencesController(...args); - - sinon.stub(controller.store, 'subscribe'); - - return controller; -} - -// TODO, Feb 24, 2023: -// ethjs-contract is being added to proxyquire, but we might want to discontinue proxyquire -// this is for expediency as we resolve a bug for v10.26.0. The proper solution here would have -// us set up the test infrastructure for a mocked provider. Github ticket for that is: -// https://github.com/MetaMask/metamask-extension/issues/17890 -const MetaMaskController = proxyquire('./metamask-controller', { - './lib/createLoggerMiddleware': { default: createLoggerMiddlewareMock }, - 'ethjs-contract': MockEthContract, - './controllers/preferences': { default: MockPreferencesController }, -}).default; +jest.mock('./lib/createLoggerMiddleware', () => createLoggerMiddlewareMock); +jest.mock( + './controllers/preferences', + () => + function (...args) { + const PreferencesController = jest.requireActual( + './controllers/preferences', + ).default; + const controller = new PreferencesController(...args); + // jest.spyOn gets hoisted to the top of this function before controller is initialized. + // This forces us to replace the function directly with a jest stub instead. + // eslint-disable-next-line jest/prefer-spy-on + controller.store.subscribe = jest.fn(); + return controller; + }, +); -const MetaMaskControllerMV3 = proxyquire('./metamask-controller', { - '../../shared/modules/mv3.utils': { isManifestV3: true }, -}).default; +const mockIsManifestV3 = jest.fn().mockReturnValue(false); +jest.mock('../../shared/modules/mv3.utils', () => ({ + get isManifestV3() { + return mockIsManifestV3(); + }, +})); const currentNetworkId = '5'; const DEFAULT_LABEL = 'Account 1'; @@ -210,14 +204,12 @@ const firstTimeState = { const noop = () => undefined; -describe('MetaMaskController', function () { - const sandbox = sinon.createSandbox(); - - before(async function () { +describe('MetaMaskController', () => { + beforeAll(async () => { await ganacheServer.start(); }); - beforeEach(function () { + beforeEach(() => { nock('https://min-api.cryptocompare.com') .persist() .get(/.*/u) @@ -254,59 +246,54 @@ describe('MetaMaskController', function () { }, ]), ); - - sandbox.replace(browser, 'runtime', { - sendMessage: sandbox.stub().rejects(), - }); - - browserPolyfillMock.storage.session.set = sandbox.spy(); }); - afterEach(function () { + afterEach(() => { + jest.clearAllMocks(); nock.cleanAll(); - sandbox.restore(); }); - after(async function () { + afterAll(async () => { await ganacheServer.quit(); }); - describe('Phishing Detection Mock', function () { - it('should be updated to use v1 of the API', function () { + describe('Phishing Detection Mock', () => { + it('should be updated to use v1 of the API', () => { // Update the fixture above if this test fails - assert.equal( - METAMASK_STALELIST_URL, + expect(METAMASK_STALELIST_URL).toStrictEqual( 'https://phishing-detection.metafi.codefi.network/v1/stalelist', ); - assert.equal( - METAMASK_HOTLIST_DIFF_URL, + expect(METAMASK_HOTLIST_DIFF_URL).toStrictEqual( 'https://phishing-detection.metafi.codefi.network/v1/diffsSince', ); }); }); - describe('MetaMaskController Behaviour', function () { + describe('MetaMaskController Behaviour', () => { let metamaskController; - beforeEach(function () { - sandbox.spy(MetaMaskController.prototype, 'resetStates'); + beforeEach(() => { + jest.spyOn(MetaMaskController.prototype, 'resetStates'); - sandbox.stub( - TransactionController.prototype, - 'updateIncomingTransactions', - ); + jest + .spyOn(TransactionController.prototype, 'updateIncomingTransactions') + .mockReturnValue(); - sandbox.stub( - TransactionController.prototype, - 'startIncomingTransactionPolling', - ); + jest + .spyOn( + TransactionController.prototype, + 'startIncomingTransactionPolling', + ) + .mockReturnValue(); - sandbox.stub( - TransactionController.prototype, - 'stopIncomingTransactionPolling', - ); + jest + .spyOn( + TransactionController.prototype, + 'stopIncomingTransactionPolling', + ) + .mockReturnValue(); - sandbox.spy(ControllerMessenger.prototype, 'subscribe'); + jest.spyOn(ControllerMessenger.prototype, 'subscribe'); metamaskController = new MetaMaskController({ showUserConfirmation: noop, @@ -330,29 +317,28 @@ describe('MetaMaskController', function () { isFirstMetaMaskControllerSetup: true, }); - // add sinon method spies - sandbox.spy( + jest.spyOn( metamaskController.keyringController, 'createNewVaultAndKeychain', ); - sandbox.spy( + jest.spyOn( metamaskController.coreKeyringController, 'createNewVaultAndRestore', ); }); - describe('should reset states on first time profile load', function () { - it('in mv2, it should reset state without attempting to call browser storage', function () { - assert.equal(metamaskController.resetStates.callCount, 1); - assert.equal(browserPolyfillMock.storage.session.set.callCount, 0); + describe('should reset states on first time profile load', () => { + it('in mv2, it should reset state without attempting to call browser storage', () => { + expect(metamaskController.resetStates).toHaveBeenCalledTimes(1); + expect(browserPolyfillMock.storage.session.set).not.toHaveBeenCalled(); }); }); - describe('#importAccountWithStrategy', function () { + describe('#importAccountWithStrategy', () => { const importPrivkey = '4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553'; - beforeEach(async function () { + beforeEach(async () => { const password = 'a-fake-password'; await metamaskController.createNewVaultAndRestore(password, TEST_SEED); await metamaskController.importAccountWithStrategy('privateKey', [ @@ -360,7 +346,7 @@ describe('MetaMaskController', function () { ]); }); - it('adds private key to keyrings in core KeyringController', async function () { + it('adds private key to keyrings in core KeyringController', async () => { const simpleKeyrings = metamaskController.coreKeyringController.getKeyringsByType( KeyringType.imported, @@ -369,25 +355,23 @@ describe('MetaMaskController', function () { const privKeyHex = await simpleKeyrings[0].exportAccount( pubAddressHexArr[0], ); - assert.equal(privKeyHex, importPrivkey); - assert.equal( - pubAddressHexArr[0], + expect(privKeyHex).toStrictEqual(importPrivkey); + expect(pubAddressHexArr[0]).toStrictEqual( '0xe18035bf8712672935fdb4e5e431b1a0183d2dfc', ); }); - it('adds 1 account', async function () { + it('adds 1 account', async () => { const keyringAccounts = await metamaskController.keyringController.getAccounts(); - assert.equal( - keyringAccounts[keyringAccounts.length - 1], + expect(keyringAccounts[keyringAccounts.length - 1]).toStrictEqual( '0xe18035bf8712672935fdb4e5e431b1a0183d2dfc', ); }); }); - describe('submitPassword', function () { - it('removes any identities that do not correspond to known accounts.', async function () { + describe('submitPassword', () => { + it('removes any identities that do not correspond to known accounts.', async () => { const password = 'password'; await metamaskController.createNewVaultAndKeychain(password); @@ -402,80 +386,62 @@ describe('MetaMaskController', function () { await metamaskController.coreKeyringController.getAccounts(); identities.forEach((identity) => { - assert.ok( - addresses.includes(identity), - `addresses should include all IDs: ${identity}`, - ); + expect(addresses).toContain(identity); }); addresses.forEach((address) => { - assert.ok( - identities.includes(address), - `identities should include all Addresses: ${address}`, - ); + expect(identities).toContain(address); }); }); }); - describe('setLocked', function () { - it('should lock KeyringController', async function () { - sandbox.spy(metamaskController.coreKeyringController, 'setLocked'); + describe('setLocked', () => { + it('should lock KeyringController', async () => { + jest.spyOn(metamaskController.coreKeyringController, 'setLocked'); await metamaskController.setLocked(); - assert(metamaskController.coreKeyringController.setLocked.called); - assert.equal( + expect( + metamaskController.coreKeyringController.setLocked, + ).toHaveBeenCalled(); + expect( metamaskController.coreKeyringController.state.isUnlocked, - false, - ); + ).toStrictEqual(false); }); }); - describe('#createNewVaultAndKeychain', function () { - it('can only create new vault on keyringController once', async function () { - const selectStub = sandbox.stub( - metamaskController, - 'selectFirstIdentity', - ); + describe('#createNewVaultAndKeychain', () => { + it('can only create new vault on keyringController once', async () => { + jest.spyOn(metamaskController, 'selectFirstIdentity').mockReturnValue(); const password = 'a-fake-password'; await metamaskController.createNewVaultAndKeychain(password); await metamaskController.createNewVaultAndKeychain(password); - assert( - metamaskController.keyringController.createNewVaultAndKeychain - .calledOnce, - ); - - selectStub.reset(); + expect( + metamaskController.keyringController.createNewVaultAndKeychain, + ).toHaveBeenCalledTimes(1); }); }); - describe('#createNewVaultAndRestore', function () { - it('should be able to call newVaultAndRestore despite a mistake.', async function () { + describe('#createNewVaultAndRestore', () => { + it('should be able to call newVaultAndRestore despite a mistake.', async () => { const password = 'what-what-what'; - sandbox.stub(metamaskController, 'getBalance'); - metamaskController.getBalance.callsFake(() => { - return Promise.resolve('0x0'); - }); + jest.spyOn(metamaskController, 'getBalance').mockResolvedValue('0x0'); await metamaskController .createNewVaultAndRestore(password, TEST_SEED.slice(0, -1)) .catch(() => null); await metamaskController.createNewVaultAndRestore(password, TEST_SEED); - assert( - metamaskController.coreKeyringController.createNewVaultAndRestore - .calledTwice, - ); + expect( + metamaskController.coreKeyringController.createNewVaultAndRestore, + ).toHaveBeenCalledTimes(2); }); - it('should clear previous identities after vault restoration', async function () { - sandbox.stub(metamaskController, 'getBalance'); - metamaskController.getBalance.callsFake(() => { - return Promise.resolve('0x0'); - }); + it('should clear previous identities after vault restoration', async () => { + jest.spyOn(metamaskController, 'getBalance').mockResolvedValue('0x0'); let startTime = Date.now(); await metamaskController.createNewVaultAndRestore( @@ -487,13 +453,12 @@ describe('MetaMaskController', function () { const firstVaultIdentities = cloneDeep( metamaskController.getState().identities, ); - assert.ok( + expect( firstVaultIdentities[TEST_ADDRESS].lastSelected >= startTime && firstVaultIdentities[TEST_ADDRESS].lastSelected <= endTime, - `'${firstVaultIdentities[TEST_ADDRESS].lastSelected}' expected to be between '${startTime}' and '${endTime}'`, - ); + ).toStrictEqual(true); delete firstVaultIdentities[TEST_ADDRESS].lastSelected; - assert.deepEqual(firstVaultIdentities, { + expect(firstVaultIdentities).toStrictEqual({ [TEST_ADDRESS]: { address: TEST_ADDRESS, name: DEFAULT_LABEL }, }); @@ -506,7 +471,7 @@ describe('MetaMaskController', function () { metamaskController.getState().identities, ); delete labelledFirstVaultIdentities[TEST_ADDRESS].lastSelected; - assert.deepEqual(labelledFirstVaultIdentities, { + expect(labelledFirstVaultIdentities).toStrictEqual({ [TEST_ADDRESS]: { address: TEST_ADDRESS, name: 'Account Foo' }, }); @@ -520,13 +485,12 @@ describe('MetaMaskController', function () { const secondVaultIdentities = cloneDeep( metamaskController.getState().identities, ); - assert.ok( + expect( secondVaultIdentities[TEST_ADDRESS_ALT].lastSelected >= startTime && secondVaultIdentities[TEST_ADDRESS_ALT].lastSelected <= endTime, - `'${secondVaultIdentities[TEST_ADDRESS_ALT].lastSelected}' expected to be between '${startTime}' and '${endTime}'`, - ); + ).toStrictEqual(true); delete secondVaultIdentities[TEST_ADDRESS_ALT].lastSelected; - assert.deepEqual(secondVaultIdentities, { + expect(secondVaultIdentities).toStrictEqual({ [TEST_ADDRESS_ALT]: { address: TEST_ADDRESS_ALT, name: DEFAULT_LABEL, @@ -534,17 +498,22 @@ describe('MetaMaskController', function () { }); }); - it('should restore any consecutive accounts with balances without extra zero balance accounts', async function () { - sandbox.stub(metamaskController, 'getBalance'); - metamaskController.getBalance.withArgs(TEST_ADDRESS).callsFake(() => { - return Promise.resolve('0x14ced5122ce0a000'); - }); - metamaskController.getBalance.withArgs(TEST_ADDRESS_2).callsFake(() => { - return Promise.resolve('0x0'); - }); - metamaskController.getBalance.withArgs(TEST_ADDRESS_3).callsFake(() => { - return Promise.resolve('0x14ced5122ce0a000'); - }); + it('should restore any consecutive accounts with balances without extra zero balance accounts', async () => { + jest + .spyOn(metamaskController, 'getBalance') + .mockImplementation((address) => { + switch (address) { + case TEST_ADDRESS: + case TEST_ADDRESS_3: + return Promise.resolve('0x14ced5122ce0a000'); + case TEST_ADDRESS_2: + return Promise.resolve('0x0'); + default: + return Promise.reject( + new Error('unexpected argument to mocked getBalance'), + ); + } + }); const startTime = Date.now(); await metamaskController.createNewVaultAndRestore( @@ -553,19 +522,19 @@ describe('MetaMaskController', function () { ); const identities = cloneDeep(metamaskController.getState().identities); - assert.ok( + expect( identities[TEST_ADDRESS].lastSelected >= startTime && identities[TEST_ADDRESS].lastSelected <= Date.now(), - ); + ).toStrictEqual(true); delete identities[TEST_ADDRESS].lastSelected; - assert.deepEqual(identities, { + expect(identities).toStrictEqual({ [TEST_ADDRESS]: { address: TEST_ADDRESS, name: DEFAULT_LABEL }, }); }); }); - describe('#getBalance', function () { - it('should return the balance known by accountTracker', async function () { + describe('#getBalance', () => { + it('should return the balance known by accountTracker', async () => { const accounts = {}; const balance = '0x14ced5122ce0a000'; accounts[TEST_ADDRESS] = { balance }; @@ -574,14 +543,14 @@ describe('MetaMaskController', function () { const gotten = await metamaskController.getBalance(TEST_ADDRESS); - assert.equal(balance, gotten); + expect(balance).toStrictEqual(gotten); }); - it('should ask the network for a balance when not known by accountTracker', async function () { + it('should ask the network for a balance when not known by accountTracker', async () => { const accounts = {}; const balance = '0x14ced5122ce0a000'; const ethQuery = new EthQuery(); - sinon.stub(ethQuery, 'getBalance').callsFake((_, callback) => { + jest.spyOn(ethQuery, 'getBalance').mockImplementation((_, callback) => { callback(undefined, balance); }); @@ -592,22 +561,22 @@ describe('MetaMaskController', function () { ethQuery, ); - assert.equal(balance, gotten); + expect(balance).toStrictEqual(gotten); }); }); - describe('#getApi', function () { - it('getState', function () { + describe('#getApi', () => { + it('getState', () => { const getApi = metamaskController.getApi(); const state = getApi.getState(); - assert.deepEqual(state, metamaskController.getState()); + expect(state).toStrictEqual(metamaskController.getState()); }); }); - describe('#selectFirstIdentity', function () { + describe('#selectFirstIdentity', () => { let identities, address; - beforeEach(function () { + beforeEach(() => { address = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'; identities = { '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': { @@ -625,36 +594,35 @@ describe('MetaMaskController', function () { metamaskController.selectFirstIdentity(); }); - it('changes preferences controller select address', function () { + it('changes preferences controller select address', () => { const preferenceControllerState = metamaskController.preferencesController.store.getState(); - assert.equal(preferenceControllerState.selectedAddress, address); + expect(preferenceControllerState.selectedAddress).toStrictEqual( + address, + ); }); - it('changes metamask controller selected address', function () { + it('changes metamask controller selected address', () => { const metamaskState = metamaskController.getState(); - assert.equal(metamaskState.selectedAddress, address); + expect(metamaskState.selectedAddress).toStrictEqual(address); }); }); - describe('connectHardware', function () { - it('should throw if it receives an unknown device name', async function () { - try { - await metamaskController.connectHardware( - 'Some random device name', - 0, - `m/44/0'/0'`, - ); - } catch (e) { - assert.equal( - e.message, - 'MetamaskController:getKeyringForDevice - Unknown device', - ); - } + describe('connectHardware', () => { + it('should throw if it receives an unknown device name', async () => { + const result = metamaskController.connectHardware( + 'Some random device name', + 0, + `m/44/0'/0'`, + ); + + await expect(result).rejects.toThrow( + 'MetamaskController:getKeyringForDevice - Unknown device', + ); }); - it('should add the Trezor Hardware keyring', async function () { - sinon.spy(metamaskController.keyringController, 'addNewKeyring'); + it('should add the Trezor Hardware keyring', async () => { + jest.spyOn(metamaskController.keyringController, 'addNewKeyring'); await metamaskController .connectHardware(HardwareDeviceNames.trezor, 0) .catch(() => null); @@ -662,15 +630,14 @@ describe('MetaMaskController', function () { await metamaskController.coreKeyringController.getKeyringsByType( KeyringType.trezor, ); - assert.deepEqual( - metamaskController.keyringController.addNewKeyring.getCall(0).args, - [KeyringType.trezor], - ); - assert.equal(keyrings.length, 1); + expect( + metamaskController.keyringController.addNewKeyring, + ).toHaveBeenCalledWith(KeyringType.trezor); + expect(keyrings).toHaveLength(1); }); - it('should add the Ledger Hardware keyring', async function () { - sinon.spy(metamaskController.keyringController, 'addNewKeyring'); + it('should add the Ledger Hardware keyring', async () => { + jest.spyOn(metamaskController.keyringController, 'addNewKeyring'); await metamaskController .connectHardware(HardwareDeviceNames.ledger, 0) .catch(() => null); @@ -678,16 +645,15 @@ describe('MetaMaskController', function () { await metamaskController.coreKeyringController.getKeyringsByType( KeyringType.ledger, ); - assert.deepEqual( - metamaskController.keyringController.addNewKeyring.getCall(0).args, - [KeyringType.ledger], - ); - assert.equal(keyrings.length, 1); + expect( + metamaskController.keyringController.addNewKeyring, + ).toHaveBeenCalledWith(KeyringType.ledger); + expect(keyrings).toHaveLength(1); }); }); - describe('getPrimaryKeyringMnemonic', function () { - it('should return a mnemonic as a Uint8Array', function () { + describe('getPrimaryKeyringMnemonic', () => { + it('should return a mnemonic as a Uint8Array', () => { const mockMnemonic = 'above mercy benefit hospital call oval domain student sphere interest argue shock'; const mnemonicIndices = mockMnemonic @@ -701,56 +667,50 @@ describe('MetaMaskController', function () { type: 'HD Key Tree', mnemonic: uint8ArrayMnemonic, }; - sinon - .stub(metamaskController.coreKeyringController, 'getKeyringsByType') - .returns([mockHDKeyring]); + jest + .spyOn(metamaskController.coreKeyringController, 'getKeyringsByType') + .mockReturnValue([mockHDKeyring]); const recoveredMnemonic = metamaskController.getPrimaryKeyringMnemonic(); - assert.equal(recoveredMnemonic, uint8ArrayMnemonic); + expect(recoveredMnemonic).toStrictEqual(uint8ArrayMnemonic); }); }); - describe('checkHardwareStatus', function () { - it('should throw if it receives an unknown device name', async function () { - try { - await metamaskController.checkHardwareStatus( - 'Some random device name', - `m/44/0'/0'`, - ); - } catch (e) { - assert.equal( - e.message, - 'MetamaskController:getKeyringForDevice - Unknown device', - ); - } + describe('checkHardwareStatus', () => { + it('should throw if it receives an unknown device name', async () => { + const result = metamaskController.checkHardwareStatus( + 'Some random device name', + `m/44/0'/0'`, + ); + await expect(result).rejects.toThrow( + 'MetamaskController:getKeyringForDevice - Unknown device', + ); }); - it('should be locked by default', async function () { + it('should be locked by default', async () => { await metamaskController .connectHardware(HardwareDeviceNames.trezor, 0) .catch(() => null); const status = await metamaskController.checkHardwareStatus( HardwareDeviceNames.trezor, ); - assert.equal(status, false); + expect(status).toStrictEqual(false); }); }); - describe('forgetDevice', function () { - it('should throw if it receives an unknown device name', async function () { - try { - await metamaskController.forgetDevice('Some random device name'); - } catch (e) { - assert.equal( - e.message, - 'MetamaskController:getKeyringForDevice - Unknown device', - ); - } + describe('forgetDevice', () => { + it('should throw if it receives an unknown device name', async () => { + const result = metamaskController.forgetDevice( + 'Some random device name', + ); + await expect(result).rejects.toThrow( + 'MetamaskController:getKeyringForDevice - Unknown device', + ); }); - it('should wipe all the keyring info', async function () { + it('should wipe all the keyring info', async () => { await metamaskController .connectHardware(HardwareDeviceNames.trezor, 0) .catch(() => null); @@ -760,44 +720,35 @@ describe('MetaMaskController', function () { KeyringType.trezor, ); - assert.deepEqual(keyrings[0].accounts, []); - assert.deepEqual(keyrings[0].page, 0); - assert.deepEqual(keyrings[0].isUnlocked(), false); + expect(keyrings[0].accounts).toStrictEqual([]); + expect(keyrings[0].page).toStrictEqual(0); + expect(keyrings[0].isUnlocked()).toStrictEqual(false); }); }); - describe('unlockHardwareWalletAccount', function () { - let accountToUnlock; - let windowOpenStub; - let addNewAccountStub; - let getAccountsStub; - beforeEach(async function () { - accountToUnlock = 10; - windowOpenStub = sinon.stub(window, 'open'); - windowOpenStub.returns(noop); - - addNewAccountStub = sinon.stub( - metamaskController.keyringController, - 'addNewAccount', - ); - addNewAccountStub.returns('0x123'); + describe('unlockHardwareWalletAccount', () => { + const accountToUnlock = 10; + beforeEach(async () => { + jest.spyOn(window, 'open').mockReturnValue(); + jest + .spyOn(metamaskController.keyringController, 'addNewAccount') + .mockReturnValue('0x123'); + + jest + .spyOn(metamaskController.keyringController, 'getAccounts') + .mockResolvedValueOnce(['0x1']) + .mockResolvedValueOnce(['0x2']) + .mockResolvedValueOnce(['0x3']); + jest + .spyOn(metamaskController.preferencesController, 'setAddresses') + .mockReturnValue(); + jest + .spyOn(metamaskController.preferencesController, 'setSelectedAddress') + .mockReturnValue(); + jest + .spyOn(metamaskController.preferencesController, 'setAccountLabel') + .mockReturnValue(); - getAccountsStub = sinon.stub( - metamaskController.keyringController, - 'getAccounts', - ); - // Need to return different address to mock the behavior of - // adding a new account from the keyring - getAccountsStub.onCall(0).returns(Promise.resolve(['0x1'])); - getAccountsStub.onCall(1).returns(Promise.resolve(['0x2'])); - getAccountsStub.onCall(2).returns(Promise.resolve(['0x3'])); - getAccountsStub.onCall(3).returns(Promise.resolve(['0x4'])); - sinon.spy(metamaskController.preferencesController, 'setAddresses'); - sinon.spy( - metamaskController.preferencesController, - 'setSelectedAddress', - ); - sinon.spy(metamaskController.preferencesController, 'setAccountLabel'); await metamaskController .connectHardware(HardwareDeviceNames.trezor, 0, `m/44'/1'/0'/0`) .catch(() => null); @@ -808,97 +759,77 @@ describe('MetaMaskController', function () { ); }); - afterEach(function () { - window.open.restore(); - metamaskController.keyringController.addNewAccount.restore(); - metamaskController.keyringController.getAccounts.restore(); - metamaskController.preferencesController.setAddresses.restore(); - metamaskController.preferencesController.setSelectedAddress.restore(); - metamaskController.preferencesController.setAccountLabel.restore(); - }); - - it('should set unlockedAccount in the keyring', async function () { + it('should set unlockedAccount in the keyring', async () => { const keyrings = await metamaskController.coreKeyringController.getKeyringsByType( KeyringType.trezor, ); - assert.equal(keyrings[0].unlockedAccount, accountToUnlock); + expect(keyrings[0].unlockedAccount).toStrictEqual(accountToUnlock); }); - it('should call keyringController.addNewAccount', async function () { - assert(metamaskController.keyringController.addNewAccount.calledOnce); + it('should call keyringController.addNewAccount', async () => { + expect( + metamaskController.keyringController.addNewAccount, + ).toHaveBeenCalledTimes(1); }); - it('should call keyringController.getAccounts ', async function () { - assert(metamaskController.keyringController.getAccounts.called); + it('should call keyringController.getAccounts', async () => { + expect( + metamaskController.keyringController.getAccounts, + ).toHaveBeenCalledTimes(3); }); - it('should call preferencesController.setAddresses', async function () { - assert( - metamaskController.preferencesController.setAddresses.calledOnce, - ); + it('should call preferencesController.setAddresses', async () => { + expect( + metamaskController.preferencesController.setAddresses, + ).toHaveBeenCalledTimes(1); }); - it('should call preferencesController.setSelectedAddress', async function () { - assert( - metamaskController.preferencesController.setSelectedAddress - .calledOnce, - ); + it('should call preferencesController.setSelectedAddress', async () => { + expect( + metamaskController.preferencesController.setSelectedAddress, + ).toHaveBeenCalledTimes(1); }); - it('should call preferencesController.setAccountLabel', async function () { - assert( - metamaskController.preferencesController.setAccountLabel.calledOnce, - ); + it('should call preferencesController.setAccountLabel', async () => { + expect( + metamaskController.preferencesController.setAccountLabel, + ).toHaveBeenCalledTimes(1); }); }); - describe('#addNewAccount', function () { - it('errors when an primary keyring is does not exist', async function () { + describe('#addNewAccount', () => { + it('errors when an primary keyring is does not exist', async () => { const addNewAccount = metamaskController.addNewAccount(); - try { - await addNewAccount; - assert.fail('should throw'); - } catch (e) { - assert.equal(e.message, 'No HD keyring found'); - } + await expect(addNewAccount).rejects.toThrow('No HD keyring found'); }); }); - describe('#verifyseedPhrase', function () { - it('errors when no keying is provided', async function () { - try { - await metamaskController.verifySeedPhrase(); - } catch (error) { - assert.equal(error.message, 'No HD keyring found.'); - } + describe('#verifyseedPhrase', () => { + it('errors when no keying is provided', async () => { + await expect(metamaskController.verifySeedPhrase()).rejects.toThrow( + 'No HD keyring found', + ); }); - it('#addNewAccount', async function () { + it('#addNewAccount', async () => { await metamaskController.createNewVaultAndKeychain('password'); await metamaskController.addNewAccount(1); const getAccounts = await metamaskController.keyringController.getAccounts(); - assert.equal(getAccounts.length, 2); + expect(getAccounts).toHaveLength(2); }); }); - describe('#resetAccount', function () { - it('wipes transactions from only the correct network id and with the selected address', async function () { - const selectedAddressStub = sinon.stub( - metamaskController.preferencesController, - 'getSelectedAddress', - ); - const getNetworkIdStub = sinon.stub( - metamaskController.txController.txStateManager, - 'getNetworkId', - ); - - selectedAddressStub.returns( - '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', - ); - getNetworkIdStub.returns(42); + describe('#resetAccount', () => { + it('wipes transactions from only the correct network id and with the selected address', async () => { + jest + .spyOn(metamaskController.preferencesController, 'getSelectedAddress') + .mockReturnValue('0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'); + jest + .spyOn(metamaskController.txController.txStateManager, 'getNetworkId') + .mockReturnValue(42); metamaskController.txController.txStateManager._addTransactionsToState([ createTxMeta({ @@ -927,84 +858,75 @@ describe('MetaMaskController', function () { ]); await metamaskController.resetAccount(); - assert.equal( + + expect( metamaskController.txController.txStateManager.getTransaction(1), - undefined, - ); + ).toBeUndefined(); }); }); - describe('#removeAccount', function () { + describe('#removeAccount', () => { let ret; const addressToRemove = '0x1'; let mockKeyring; - beforeEach(async function () { + beforeEach(async () => { mockKeyring = { - getAccounts: sinon.stub().returns(Promise.resolve([])), - destroy: sinon.stub(), + getAccounts: jest.fn().mockResolvedValue([]), + destroy: jest.fn(), }; - sinon.stub(metamaskController.keyringController, 'removeAccount'); - sinon.stub(metamaskController, 'removeAllAccountPermissions'); - sinon - .stub( + jest + .spyOn(metamaskController.keyringController, 'removeAccount') + .mockReturnValue(); + jest + .spyOn(metamaskController, 'removeAllAccountPermissions') + .mockReturnValue(); + + jest + .spyOn( metamaskController.coreKeyringController, 'getKeyringForAccount', ) - .returns(Promise.resolve(mockKeyring)); + .mockResolvedValue(mockKeyring); ret = await metamaskController.removeAccount(addressToRemove); }); - afterEach(function () { - metamaskController.keyringController.removeAccount.restore(); - metamaskController.removeAllAccountPermissions.restore(); - - mockKeyring.getAccounts.resetHistory(); - mockKeyring.destroy.resetHistory(); - }); - - it('should call keyringController.removeAccount', async function () { - assert( - metamaskController.keyringController.removeAccount.calledWith( - addressToRemove, - ), - ); + it('should call keyringController.removeAccount', async () => { + expect( + metamaskController.keyringController.removeAccount, + ).toHaveBeenCalledWith(addressToRemove); }); - it('should call metamaskController.removeAllAccountPermissions', async function () { - assert( - metamaskController.removeAllAccountPermissions.calledWith( - addressToRemove, - ), - ); + it('should call metamaskController.removeAllAccountPermissions', async () => { + expect( + metamaskController.removeAllAccountPermissions, + ).toHaveBeenCalledWith(addressToRemove); }); - it('should return address', async function () { - assert.equal(ret, '0x1'); + it('should return address', async () => { + expect(ret).toStrictEqual('0x1'); }); - it('should call coreKeyringController.getKeyringForAccount', async function () { - assert( - metamaskController.coreKeyringController.getKeyringForAccount.calledWith( - addressToRemove, - ), - ); + it('should call coreKeyringController.getKeyringForAccount', async () => { + expect( + metamaskController.coreKeyringController.getKeyringForAccount, + ).toHaveBeenCalledWith(addressToRemove); }); - it('should call keyring.destroy', async function () { - assert(mockKeyring.destroy.calledOnce); + it('should call keyring.destroy', async () => { + expect(mockKeyring.destroy).toHaveBeenCalledTimes(1); }); }); - describe('#setupUntrustedCommunication', function () { + describe('#setupUntrustedCommunication', () => { const mockTxParams = { from: TEST_ADDRESS }; - beforeEach(function () { + beforeEach(() => { initializeMockMiddlewareLog(); }); - after(function () { + afterAll(() => { tearDownMockMiddlewareLog(); }); - it('sets up phishing stream for untrusted communication', async function () { + it('sets up phishing stream for untrusted communication', async () => { const phishingMessageSender = { url: 'http://test.metamask-phishing.io', tab: {}, @@ -1016,8 +938,7 @@ describe('MetaMaskController', function () { cb(); return; } - assert.equal( - chunk.data.hostname, + expect(chunk.data.hostname).toStrictEqual( new URL(phishingMessageSender.url).hostname, ); resolve(); @@ -1032,7 +953,7 @@ describe('MetaMaskController', function () { streamTest.end(); }); - it('adds a tabId and origin to requests', function (done) { + it('adds a tabId, origin and networkClient to requests', async () => { const messageSender = { url: 'http://mycrypto.com', tab: { id: 456 }, @@ -1056,26 +977,35 @@ describe('MetaMaskController', function () { params: [{ ...mockTxParams }], method: 'eth_sendTransaction', }; - streamTest.write( - { - name: 'metamask-provider', - data: message, - }, - null, - () => { - setTimeout(() => { - assert.deepStrictEqual(loggerMiddlewareMock.requests[0], { - ...message, - origin: 'http://mycrypto.com', - tabId: 456, + await new Promise((resolve) => { + streamTest.write( + { + name: 'metamask-provider', + data: message, + }, + null, + () => { + setTimeout(() => { + expect(loggerMiddlewareMock.requests[0]).toHaveProperty( + 'origin', + 'http://mycrypto.com', + ); + expect(loggerMiddlewareMock.requests[0]).toHaveProperty( + 'tabId', + 456, + ); + expect(loggerMiddlewareMock.requests[0]).toHaveProperty( + 'networkClientId', + 'networkConfigurationId1', + ); + resolve(); }); - done(); - }); - }, - ); + }, + ); + }); }); - it('should add only origin to request if tabId not provided', function (done) { + it('should add only origin to request if tabId not provided', async () => { const messageSender = { url: 'http://mycrypto.com', }; @@ -1098,34 +1028,39 @@ describe('MetaMaskController', function () { params: [{ ...mockTxParams }], method: 'eth_sendTransaction', }; - streamTest.write( - { - name: 'metamask-provider', - data: message, - }, - null, - () => { - setTimeout(() => { - assert.deepStrictEqual(loggerMiddlewareMock.requests[0], { - ...message, - origin: 'http://mycrypto.com', + await new Promise((resolve) => { + streamTest.write( + { + name: 'metamask-provider', + data: message, + }, + null, + () => { + setTimeout(() => { + expect(loggerMiddlewareMock.requests[0]).not.toHaveProperty( + 'tabId', + ); + expect(loggerMiddlewareMock.requests[0]).toHaveProperty( + 'origin', + 'http://mycrypto.com', + ); + resolve(); }); - done(); - }); - }, - ); + }, + ); + }); }); }); - describe('#setupTrustedCommunication', function () { - it('sets up controller JSON-RPC api for trusted communication', async function () { + describe('#setupTrustedCommunication', () => { + it('sets up controller JSON-RPC api for trusted communication', async () => { const messageSender = { url: 'http://mycrypto.com', tab: {}, }; const { promise, resolve } = deferredPromise(); const streamTest = createThoughStream((chunk, _, cb) => { - assert.equal(chunk.name, 'controller'); + expect(chunk.name).toStrictEqual('controller'); resolve(); cb(); }); @@ -1136,50 +1071,50 @@ describe('MetaMaskController', function () { }); }); - describe('#markPasswordForgotten', function () { - it('adds and sets forgottenPassword to config data to true', function () { + describe('#markPasswordForgotten', () => { + it('adds and sets forgottenPassword to config data to true', () => { metamaskController.markPasswordForgotten(noop); const state = metamaskController.getState(); - assert.equal(state.forgottenPassword, true); + expect(state.forgottenPassword).toStrictEqual(true); }); }); - describe('#unMarkPasswordForgotten', function () { - it('adds and sets forgottenPassword to config data to false', function () { + describe('#unMarkPasswordForgotten', () => { + it('adds and sets forgottenPassword to config data to false', () => { metamaskController.unMarkPasswordForgotten(noop); const state = metamaskController.getState(); - assert.equal(state.forgottenPassword, false); + expect(state.forgottenPassword).toStrictEqual(false); }); }); - describe('#_onKeyringControllerUpdate', function () { - it('should do nothing if there are no keyrings in state', async function () { - const syncAddresses = sinon.fake(); - const syncWithAddresses = sinon.fake(); - sandbox.replace(metamaskController, 'preferencesController', { - syncAddresses, - }); - sandbox.replace(metamaskController, 'accountTracker', { - syncWithAddresses, - }); + describe('#_onKeyringControllerUpdate', () => { + it('should do nothing if there are no keyrings in state', async () => { + jest + .spyOn(metamaskController.preferencesController, 'syncAddresses') + .mockReturnValue(); + jest + .spyOn(metamaskController.accountTracker, 'syncWithAddresses') + .mockReturnValue(); const oldState = metamaskController.getState(); await metamaskController._onKeyringControllerUpdate({ keyrings: [] }); - assert.ok(syncAddresses.notCalled); - assert.ok(syncWithAddresses.notCalled); - assert.deepEqual(metamaskController.getState(), oldState); + expect( + metamaskController.preferencesController.syncAddresses, + ).not.toHaveBeenCalled(); + expect( + metamaskController.accountTracker.syncWithAddresses, + ).not.toHaveBeenCalled(); + expect(metamaskController.getState()).toStrictEqual(oldState); }); - it('should sync addresses if there are keyrings in state', async function () { - const syncAddresses = sinon.fake(); - const syncWithAddresses = sinon.fake(); - sandbox.replace(metamaskController, 'preferencesController', { - syncAddresses, - }); - sandbox.replace(metamaskController, 'accountTracker', { - syncWithAddresses, - }); + it('should sync addresses if there are keyrings in state', async () => { + jest + .spyOn(metamaskController.preferencesController, 'syncAddresses') + .mockReturnValue(); + jest + .spyOn(metamaskController.accountTracker, 'syncWithAddresses') + .mockReturnValue(); const oldState = metamaskController.getState(); await metamaskController._onKeyringControllerUpdate({ @@ -1190,20 +1125,22 @@ describe('MetaMaskController', function () { ], }); - assert.deepEqual(syncAddresses.args, [[['0x1', '0x2']]]); - assert.deepEqual(syncWithAddresses.args, [[['0x1', '0x2']]]); - assert.deepEqual(metamaskController.getState(), oldState); + expect( + metamaskController.preferencesController.syncAddresses, + ).toHaveBeenCalledWith(['0x1', '0x2']); + expect( + metamaskController.accountTracker.syncWithAddresses, + ).toHaveBeenCalledWith(['0x1', '0x2']); + expect(metamaskController.getState()).toStrictEqual(oldState); }); - it('should NOT update selected address if already unlocked', async function () { - const syncAddresses = sinon.fake(); - const syncWithAddresses = sinon.fake(); - sandbox.replace(metamaskController, 'preferencesController', { - syncAddresses, - }); - sandbox.replace(metamaskController, 'accountTracker', { - syncWithAddresses, - }); + it('should NOT update selected address if already unlocked', async () => { + jest + .spyOn(metamaskController.preferencesController, 'syncAddresses') + .mockReturnValue(); + jest + .spyOn(metamaskController.accountTracker, 'syncWithAddresses') + .mockReturnValue(); const oldState = metamaskController.getState(); await metamaskController._onKeyringControllerUpdate({ @@ -1215,34 +1152,35 @@ describe('MetaMaskController', function () { ], }); - assert.deepEqual(syncAddresses.args, [[['0x1', '0x2']]]); - assert.deepEqual(syncWithAddresses.args, [[['0x1', '0x2']]]); - assert.deepEqual(metamaskController.getState(), oldState); + expect( + metamaskController.preferencesController.syncAddresses, + ).toHaveBeenCalledWith(['0x1', '0x2']); + expect( + metamaskController.accountTracker.syncWithAddresses, + ).toHaveBeenCalledWith(['0x1', '0x2']); + expect(metamaskController.getState()).toStrictEqual(oldState); }); }); - describe('markNotificationsAsRead', function () { - it('marks the notification as read', function () { + describe('markNotificationsAsRead', () => { + it('marks the notification as read', () => { metamaskController.markNotificationsAsRead([NOTIFICATION_ID]); const readNotification = metamaskController.getState().notifications[NOTIFICATION_ID]; - assert.notEqual(readNotification.readDate, null); + expect(readNotification.readDate).not.toBeNull(); }); }); - describe('dismissNotifications', function () { - it('deletes the notification from state', function () { + describe('dismissNotifications', () => { + it('deletes the notification from state', () => { metamaskController.dismissNotifications([NOTIFICATION_ID]); const state = metamaskController.getState().notifications; - assert.ok( - !Object.values(state).includes(NOTIFICATION_ID), - 'Object should not include the deleted notification', - ); + expect(Object.values(state)).not.toContain(NOTIFICATION_ID); }); }); - describe('getTokenStandardAndDetails', function () { - it('gets token data from the token list if available, and with a balance retrieved by fetchTokenBalance', async function () { + describe('getTokenStandardAndDetails', () => { + it('gets token data from the token list if available, and with a balance retrieved by fetchTokenBalance', async () => { const providerResultStub = { eth_getCode: '0x123', eth_call: @@ -1274,25 +1212,13 @@ describe('MetaMaskController', function () { '0xf0d172594caedee459b89ad44c94098e474571b6', ); - assert.ok( - tokenDetails.standard === 'ERC20', - 'tokenDetails should include token standard in upper case', - ); - assert.ok( - tokenDetails.decimals === String(tokenData.decimals), - 'tokenDetails should include token decimals as a string', - ); - assert.ok( - tokenDetails.symbol === tokenData.symbol, - 'tokenDetails should include token symbol', - ); - assert.ok( - tokenDetails.balance === '3000000000000000000', - 'tokenDetails should include a balance', - ); + expect(tokenDetails.standard).toStrictEqual('ERC20'); + expect(tokenDetails.decimals).toStrictEqual(String(tokenData.decimals)); + expect(tokenDetails.symbol).toStrictEqual(tokenData.symbol); + expect(tokenDetails.balance).toStrictEqual('3000000000000000000'); }); - it('gets token data from tokens if available, and with a balance retrieved by fetchTokenBalance', async function () { + it('gets token data from tokens if available, and with a balance retrieved by fetchTokenBalance', async () => { const providerResultStub = { eth_getCode: '0x123', eth_call: @@ -1325,25 +1251,13 @@ describe('MetaMaskController', function () { '0xf0d172594caedee459b89ad44c94098e474571b6', ); - assert.ok( - tokenDetails.standard === 'ERC20', - 'tokenDetails should include token standard in upper case', - ); - assert.ok( - tokenDetails.decimals === String(tokenData.decimals), - 'tokenDetails should include token decimals as a string', - ); - assert.ok( - tokenDetails.symbol === tokenData.symbol, - 'tokenDetails should include token symbol', - ); - assert.ok( - tokenDetails.balance === '3000000000000000000', - 'tokenDetails should include a balance', - ); + expect(tokenDetails.standard).toStrictEqual('ERC20'); + expect(tokenDetails.decimals).toStrictEqual(String(tokenData.decimals)); + expect(tokenDetails.symbol).toStrictEqual(tokenData.symbol); + expect(tokenDetails.balance).toStrictEqual('3000000000000000000'); }); - it('gets token data from contract-metadata if available, and with a balance retrieved by fetchTokenBalance', async function () { + it('gets token data from contract-metadata if available, and with a balance retrieved by fetchTokenBalance', async () => { const providerResultStub = { eth_getCode: '0x123', eth_call: @@ -1362,25 +1276,13 @@ describe('MetaMaskController', function () { '0xf0d172594caedee459b89ad44c94098e474571b6', ); - assert.ok( - tokenDetails.standard === 'ERC20', - 'tokenDetails should include token standard in upper case', - ); - assert.ok( - tokenDetails.decimals === '18', - 'tokenDetails should include token decimals as a string', - ); - assert.ok( - tokenDetails.symbol === 'DAI', - 'tokenDetails should include token symbol', - ); - assert.ok( - tokenDetails.balance === '3000000000000000000', - 'tokenDetails should include a balance', - ); + expect(tokenDetails.standard).toStrictEqual('ERC20'); + expect(tokenDetails.decimals).toStrictEqual('18'); + expect(tokenDetails.symbol).toStrictEqual('DAI'); + expect(tokenDetails.balance).toStrictEqual('3000000000000000000'); }); - it('gets token data from the blockchain, via the assetsContractController, if not available through other sources', async function () { + it('gets token data from the blockchain, via the assetsContractController, if not available through other sources', async () => { const providerResultStub = { eth_getCode: '0x123', eth_call: @@ -1409,39 +1311,28 @@ describe('MetaMaskController', function () { metamaskController.provider = provider; - sandbox - .stub( + jest + .spyOn( metamaskController.assetsContractController, 'getTokenStandardAndDetails', ) - .callsFake(() => { - return tokenData; - }); + .mockReturnValue(tokenData); const tokenDetails = await metamaskController.getTokenStandardAndDetails( '0xNotInTokenList', '0xf0d172594caedee459b89ad44c94098e474571b6', ); - assert.ok( - tokenDetails.standard === tokenData.standard.toUpperCase(), - 'tokenDetails should include token standard in upper case', - ); - assert.ok( - tokenDetails.decimals === String(tokenData.decimals), - 'tokenDetails should include token decimals as a string', - ); - assert.ok( - tokenDetails.symbol === tokenData.symbol, - 'tokenDetails should include token symbol', - ); - assert.ok( - tokenDetails.balance === tokenData.balance, - 'tokenDetails should include a balance', + + expect(tokenDetails.standard).toStrictEqual( + tokenData.standard.toUpperCase(), ); + expect(tokenDetails.decimals).toStrictEqual(String(tokenData.decimals)); + expect(tokenDetails.symbol).toStrictEqual(tokenData.symbol); + expect(tokenDetails.balance).toStrictEqual(tokenData.balance); }); - it('gets token data from the blockchain, via the assetsContractController, if it is in the token list but is an ERC721', async function () { + it('gets token data from the blockchain, via the assetsContractController, if it is in the token list but is an ERC721', async () => { const providerResultStub = { eth_getCode: '0x123', eth_call: @@ -1470,39 +1361,28 @@ describe('MetaMaskController', function () { metamaskController.provider = provider; - sandbox - .stub( + jest + .spyOn( metamaskController.assetsContractController, 'getTokenStandardAndDetails', ) - .callsFake(() => { - return tokenData; - }); + .mockReturnValue(tokenData); const tokenDetails = await metamaskController.getTokenStandardAndDetails( '0xAAA75474e89094c44da98b954eedeac495271d0f', '0xf0d172594caedee459b89ad44c94098e474571b6', ); - assert.ok( - tokenDetails.standard === tokenData.standard.toUpperCase(), - 'tokenDetails should include token standard in upper case', - ); - assert.ok( - tokenDetails.decimals === String(tokenData.decimals), - 'tokenDetails should include token decimals as a string', - ); - assert.ok( - tokenDetails.symbol === tokenData.symbol, - 'tokenDetails should include token symbol', - ); - assert.ok( - tokenDetails.balance === tokenData.balance, - 'tokenDetails should include a balance', + + expect(tokenDetails.standard).toStrictEqual( + tokenData.standard.toUpperCase(), ); + expect(tokenDetails.decimals).toStrictEqual(String(tokenData.decimals)); + expect(tokenDetails.symbol).toStrictEqual(tokenData.symbol); + expect(tokenDetails.balance).toStrictEqual(tokenData.balance); }); - it('gets token data from the blockchain, via the assetsContractController, if it is in the token list but is an ERC1155', async function () { + it('gets token data from the blockchain, via the assetsContractController, if it is in the token list but is an ERC1155', async () => { const providerResultStub = { eth_getCode: '0x123', eth_call: @@ -1531,199 +1411,195 @@ describe('MetaMaskController', function () { metamaskController.provider = provider; - sandbox - .stub( + jest + .spyOn( metamaskController.assetsContractController, 'getTokenStandardAndDetails', ) - .callsFake(() => { - return tokenData; - }); + .mockReturnValue(tokenData); const tokenDetails = await metamaskController.getTokenStandardAndDetails( '0xAAA75474e89094c44da98b954eedeac495271d0f', '0xf0d172594caedee459b89ad44c94098e474571b6', ); - assert.ok( - tokenDetails.standard === tokenData.standard.toUpperCase(), - 'tokenDetails should include token standard in upper case', - ); - assert.ok( - tokenDetails.decimals === String(tokenData.decimals), - 'tokenDetails should include token decimals as a string', - ); - assert.ok( - tokenDetails.symbol === tokenData.symbol, - 'tokenDetails should include token symbol', - ); - assert.ok( - tokenDetails.balance === tokenData.balance, - 'tokenDetails should include a balance', + expect(tokenDetails.standard).toStrictEqual( + tokenData.standard.toUpperCase(), ); + expect(tokenDetails.decimals).toStrictEqual(String(tokenData.decimals)); + expect(tokenDetails.symbol).toStrictEqual(tokenData.symbol); + expect(tokenDetails.balance).toStrictEqual(tokenData.balance); }); - describe('findNetworkConfigurationBy', function () { - it('returns null if passed an object containing a valid networkConfiguration key but no matching value is found', function () { - assert.strictEqual( + describe('findNetworkConfigurationBy', () => { + it('returns null if passed an object containing a valid networkConfiguration key but no matching value is found', () => { + expect( metamaskController.findNetworkConfigurationBy({ chainId: '0xnone', }), - null, - ); + ).toStrictEqual(null); }); - it('returns null if passed an object containing an invalid networkConfiguration key', function () { - assert.strictEqual( + it('returns null if passed an object containing an invalid networkConfiguration key', () => { + expect( metamaskController.findNetworkConfigurationBy({ invalidKey: '0xnone', }), - null, - ); + ).toStrictEqual(null); }); - it('returns matching networkConfiguration when passed a chainId that matches an existing configuration', function () { - assert.deepStrictEqual( + it('returns matching networkConfiguration when passed a chainId that matches an existing configuration', () => { + expect( metamaskController.findNetworkConfigurationBy({ chainId: MAINNET_CHAIN_ID, }), - { - chainId: MAINNET_CHAIN_ID, - nickname: 'Alt Mainnet', - id: NETWORK_CONFIGURATION_ID_1, - rpcUrl: ALT_MAINNET_RPC_URL, - ticker: ETH, - type: NETWORK_TYPES.RPC, - }, - ); + ).toStrictEqual({ + chainId: MAINNET_CHAIN_ID, + nickname: 'Alt Mainnet', + id: NETWORK_CONFIGURATION_ID_1, + rpcUrl: ALT_MAINNET_RPC_URL, + ticker: ETH, + type: NETWORK_TYPES.RPC, + }); }); - it('returns matching networkConfiguration when passed a ticker that matches an existing configuration', function () { - assert.deepStrictEqual( + it('returns matching networkConfiguration when passed a ticker that matches an existing configuration', () => { + expect( metamaskController.findNetworkConfigurationBy({ ticker: MATIC, }), - { - rpcUrl: POLYGON_RPC_URL, - type: NETWORK_TYPES.RPC, - chainId: POLYGON_CHAIN_ID, - ticker: MATIC, - nickname: 'Polygon', - id: NETWORK_CONFIGURATION_ID_2, - }, - ); + ).toStrictEqual({ + rpcUrl: POLYGON_RPC_URL, + type: NETWORK_TYPES.RPC, + chainId: POLYGON_CHAIN_ID, + ticker: MATIC, + nickname: 'Polygon', + id: NETWORK_CONFIGURATION_ID_2, + }); }); - it('returns matching networkConfiguration when passed a nickname that matches an existing configuration', function () { - assert.deepStrictEqual( + it('returns matching networkConfiguration when passed a nickname that matches an existing configuration', () => { + expect( metamaskController.findNetworkConfigurationBy({ nickname: 'Alt Mainnet', }), - { - chainId: MAINNET_CHAIN_ID, - nickname: 'Alt Mainnet', - id: NETWORK_CONFIGURATION_ID_1, - rpcUrl: ALT_MAINNET_RPC_URL, - ticker: ETH, - type: NETWORK_TYPES.RPC, - }, - ); + ).toStrictEqual({ + chainId: MAINNET_CHAIN_ID, + nickname: 'Alt Mainnet', + id: NETWORK_CONFIGURATION_ID_1, + rpcUrl: ALT_MAINNET_RPC_URL, + ticker: ETH, + type: NETWORK_TYPES.RPC, + }); }); - it('returns null if passed an object containing mismatched networkConfiguration key/value combination', function () { - assert.deepStrictEqual( + it('returns null if passed an object containing mismatched networkConfiguration key/value combination', () => { + expect( metamaskController.findNetworkConfigurationBy({ nickname: MAINNET_CHAIN_ID, }), - null, - ); + ).toStrictEqual(null); }); - it('returns the first networkConfiguration added if passed an key/value combination for which there are multiple matching configurations', function () { - assert.deepStrictEqual( + it('returns the first networkConfiguration added if passed an key/value combination for which there are multiple matching configurations', () => { + expect( metamaskController.findNetworkConfigurationBy({ chainId: POLYGON_CHAIN_ID, }), - { - rpcUrl: POLYGON_RPC_URL, - type: NETWORK_TYPES.RPC, - chainId: POLYGON_CHAIN_ID, - ticker: MATIC, - nickname: 'Polygon', - id: NETWORK_CONFIGURATION_ID_2, - }, - ); + ).toStrictEqual({ + rpcUrl: POLYGON_RPC_URL, + type: NETWORK_TYPES.RPC, + chainId: POLYGON_CHAIN_ID, + ticker: MATIC, + nickname: 'Polygon', + id: NETWORK_CONFIGURATION_ID_2, + }); }); }); }); - describe('incoming transactions', function () { - let txControllerStub, preferencesControllerSpy, controllerMessengerSpy; - - beforeEach(function () { - txControllerStub = TransactionController.prototype; - preferencesControllerSpy = metamaskController.preferencesController; - controllerMessengerSpy = ControllerMessenger.prototype; - }); - - it('starts incoming transaction polling if incomingTransactionsPreferences is enabled for that chainId', async function () { - assert(txControllerStub.startIncomingTransactionPolling.notCalled); + describe('incoming transactions', () => { + it('starts incoming transaction polling if incomingTransactionsPreferences is enabled for that chainId', async () => { + expect( + TransactionController.prototype.startIncomingTransactionPolling, + ).not.toHaveBeenCalled(); - await preferencesControllerSpy.store.subscribe.lastCall.args[0]({ - incomingTransactionsPreferences: { - [MAINNET_CHAIN_ID]: true, + await metamaskController.preferencesController.store.subscribe.mock.lastCall[0]( + { + incomingTransactionsPreferences: { + [MAINNET_CHAIN_ID]: true, + }, }, - }); + ); - assert(txControllerStub.startIncomingTransactionPolling.calledOnce); + expect( + TransactionController.prototype.startIncomingTransactionPolling, + ).toHaveBeenCalledTimes(1); }); - it('stops incoming transaction polling if incomingTransactionsPreferences is disabled for that chainIdd', async function () { - assert(txControllerStub.stopIncomingTransactionPolling.notCalled); + it('stops incoming transaction polling if incomingTransactionsPreferences is disabled for that chainId', async () => { + expect( + TransactionController.prototype.stopIncomingTransactionPolling, + ).not.toHaveBeenCalled(); - await preferencesControllerSpy.store.subscribe.lastCall.args[0]({ - incomingTransactionsPreferences: { - [MAINNET_CHAIN_ID]: false, + await metamaskController.preferencesController.store.subscribe.mock.lastCall[0]( + { + incomingTransactionsPreferences: { + [MAINNET_CHAIN_ID]: false, + }, }, - }); + ); - assert(txControllerStub.stopIncomingTransactionPolling.calledOnce); + expect( + TransactionController.prototype.stopIncomingTransactionPolling, + ).toHaveBeenCalledTimes(1); }); - it('updates incoming transactions when changing account', async function () { - assert(txControllerStub.updateIncomingTransactions.notCalled); + it('updates incoming transactions when changing account', async () => { + expect( + TransactionController.prototype.updateIncomingTransactions, + ).not.toHaveBeenCalled(); - await preferencesControllerSpy.store.subscribe.lastCall.args[0]({ - selectedAddress: 'foo', - }); + await metamaskController.preferencesController.store.subscribe.mock.lastCall[0]( + { + selectedAddress: 'foo', + }, + ); - assert(txControllerStub.updateIncomingTransactions.calledOnce); + expect( + TransactionController.prototype.updateIncomingTransactions, + ).toHaveBeenCalledTimes(1); }); - it('updates incoming transactions when changing network', async function () { - assert(txControllerStub.updateIncomingTransactions.notCalled); + it('updates incoming transactions when changing network', async () => { + expect( + TransactionController.prototype.updateIncomingTransactions, + ).not.toHaveBeenCalled(); - await controllerMessengerSpy.subscribe.args + await ControllerMessenger.prototype.subscribe.mock.calls .filter((args) => args[0] === 'NetworkController:networkDidChange') .slice(-1)[0][1](); - assert(txControllerStub.updateIncomingTransactions.calledOnce); + expect( + TransactionController.prototype.updateIncomingTransactions, + ).toHaveBeenCalledTimes(1); }); }); }); - describe('MV3 Specific behaviour', function () { - before(async function () { + describe('MV3 Specific behaviour', () => { + beforeAll(async () => { + mockIsManifestV3.mockReturnValue(true); globalThis.isFirstTimeProfileLoaded = true; }); - beforeEach(async function () { - sandbox.spy(MetaMaskControllerMV3.prototype, 'resetStates'); + beforeEach(async () => { + jest.spyOn(MetaMaskController.prototype, 'resetStates'); }); - it('it should reset state', function () { - browserPolyfillMock.storage.session.set.resetHistory(); + it('should reset state', () => { + browserPolyfillMock.storage.session.set.mockReset(); - const metamaskControllerMV3 = new MetaMaskControllerMV3({ + const metamaskController = new MetaMaskController({ showUserConfirmation: noop, encryptor: { encrypt(_, object) { @@ -1744,20 +1620,18 @@ describe('MetaMaskController', function () { infuraProjectId: 'foo', isFirstMetaMaskControllerSetup: true, }); - assert.equal(metamaskControllerMV3.resetStates.callCount, 1); - assert.equal(browserPolyfillMock.storage.session.set.callCount, 1); - assert.deepEqual( - browserPolyfillMock.storage.session.set.getCall(0).args[0], - { - isFirstMetaMaskControllerSetup: false, - }, - ); + + expect(metamaskController.resetStates).toHaveBeenCalledTimes(1); + expect(browserPolyfillMock.storage.session.set).toHaveBeenCalledTimes(1); + expect(browserPolyfillMock.storage.session.set).toHaveBeenCalledWith({ + isFirstMetaMaskControllerSetup: false, + }); }); - it('in mv3, it should not reset states if isFirstMetaMaskControllerSetup is false', function () { - browserPolyfillMock.storage.session.set.resetHistory(); + it('in mv3, it should not reset states if isFirstMetaMaskControllerSetup is false', () => { + browserPolyfillMock.storage.session.set.mockReset(); - const metamaskControllerMV3 = new MetaMaskControllerMV3({ + const metamaskController = new MetaMaskController({ showUserConfirmation: noop, encryptor: { encrypt(_, object) { @@ -1778,8 +1652,9 @@ describe('MetaMaskController', function () { infuraProjectId: 'foo', isFirstMetaMaskControllerSetup: false, }); - assert.equal(metamaskControllerMV3.resetStates.callCount, 0); - assert.equal(browserPolyfillMock.storage.session.set.callCount, 0); + + expect(metamaskController.resetStates).not.toHaveBeenCalled(); + expect(browserPolyfillMock.storage.session.set).not.toHaveBeenCalled(); }); }); }); diff --git a/app/scripts/migrations/097.test.ts b/app/scripts/migrations/097.test.ts new file mode 100644 index 000000000000..99201a0929dd --- /dev/null +++ b/app/scripts/migrations/097.test.ts @@ -0,0 +1,128 @@ +import { migrate, version } from './097'; + +const oldVersion = 96; +describe('migration #97', () => { + it('updates the version metadata', async () => { + const oldStorage = { + meta: { version: oldVersion }, + data: {}, + }; + + const newStorage = await migrate(oldStorage); + + expect(newStorage.meta).toStrictEqual({ version }); + }); + + it('handles missing TransactionController', async () => { + const oldState = { + OtherController: {}, + }; + + const transformedState = await migrate({ + meta: { version: oldVersion }, + data: oldState, + }); + + expect(transformedState.data).toEqual(oldState); + }); + + it('handles empty transactions', async () => { + const oldState = { + TransactionController: { + transactions: {}, + }, + }; + + const transformedState = await migrate({ + meta: { version: oldVersion }, + data: oldState, + }); + + expect(transformedState.data).toEqual(oldState); + }); + + it('handles missing state', async () => { + const transformedState = await migrate({ + meta: { version: oldVersion }, + data: {}, + }); + + expect(transformedState.data).toEqual({}); + }); + + it('removes nonceDetail from transactions', async () => { + const oldState = { + TransactionController: { + transactions: { + tx1: { + nonceDetails: { + local: { + details: { + highest: 347, + startPoint: 347, + }, + name: 'local', + nonce: 347, + }, + network: { + details: { + baseCount: 347, + blockNumber: '0x9c2682', + }, + name: 'network', + nonce: 347, + }, + params: { + highestLocallyConfirmed: 327, + highestSuggested: 347, + nextNetworkNonce: 347, + }, + }, + otherProp: 'value', + }, + tx2: { + nonceDetails: { + local: { + details: { + highest: 347, + startPoint: 347, + }, + name: 'local', + nonce: 347, + }, + network: { + details: { + baseCount: 347, + blockNumber: '0x9c2682', + }, + name: 'network', + nonce: 347, + }, + params: { + highestLocallyConfirmed: 327, + highestSuggested: 347, + nextNetworkNonce: 347, + }, + }, + otherProp: 'value', + }, + }, + }, + }; + const oldStorage = { + meta: { version: oldVersion }, + data: oldState, + }; + + const newStorage = await migrate(oldStorage); + + expect(newStorage.data).toEqual({ + TransactionController: { + transactions: { + tx1: { otherProp: 'value' }, + tx2: { otherProp: 'value' }, + }, + }, + }); + }); +}); diff --git a/app/scripts/migrations/097.ts b/app/scripts/migrations/097.ts new file mode 100644 index 000000000000..9e99cf61b40a --- /dev/null +++ b/app/scripts/migrations/097.ts @@ -0,0 +1,47 @@ +import { cloneDeep, isEmpty } from 'lodash'; + +type VersionedData = { + meta: { version: number }; + data: Record; +}; + +export const version = 97; + +/** + * Remove `nonceDetail` from transactions + * + * @param originalVersionedData + */ +export async function migrate( + originalVersionedData: VersionedData, +): Promise { + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + transformState(versionedData.data); + return versionedData; +} + +function transformState(state: Record) { + const transactionControllerState = state?.TransactionController || {}; + const transactions = transactionControllerState?.transactions || {}; + + if (isEmpty(transactions)) { + return; + } + + const newTxs = Object.keys(transactions).reduce((txs, txId) => { + const transaction = transactions[txId]; + if (transaction?.nonceDetails) { + delete transaction.nonceDetails; + } + return { + ...txs, + [txId]: transaction, + }; + }, {}); + + state.TransactionController = { + ...transactionControllerState, + transactions: newTxs, + }; +} diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index e59062f876a2..c8b27ac352b0 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -103,6 +103,7 @@ import * as m093 from './093'; import * as m094 from './094'; import * as m095 from './095'; import * as m096 from './096'; +import * as m097 from './097'; const migrations = [ m002, @@ -203,5 +204,6 @@ const migrations = [ m094, m095, m096, + m097, ]; export default migrations; diff --git a/builds.yml b/builds.yml index 90689f102daf..8be1a0d482a4 100644 --- a/builds.yml +++ b/builds.yml @@ -57,7 +57,7 @@ buildTypes: - SEGMENT_FLASK_WRITE_KEY - ALLOW_LOCAL_SNAPS: true - REQUIRE_SNAPS_ALLOWLIST: false - - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.consensys.io/0.38.1-flask.1/index.html + - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.consensys.io/0.38.3-flask.1/index.html - SUPPORT_LINK: https://metamask-flask.zendesk.com/hc - SUPPORT_REQUEST_LINK: https://metamask-flask.zendesk.com/hc/en-us/requests/new - INFURA_ENV_KEY_REF: INFURA_FLASK_PROJECT_ID @@ -76,7 +76,7 @@ buildTypes: - SEGMENT_FLASK_WRITE_KEY - ALLOW_LOCAL_SNAPS: true - REQUIRE_SNAPS_ALLOWLIST: false - - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.consensys.io/0.38.1-flask.1/index.html + - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.consensys.io/0.38.3-flask.1/index.html - SUPPORT_LINK: https://metamask-flask.zendesk.com/hc - SUPPORT_REQUEST_LINK: https://metamask-flask.zendesk.com/hc/en-us/requests/new - INFURA_ENV_KEY_REF: INFURA_FLASK_PROJECT_ID @@ -87,12 +87,16 @@ buildTypes: mmi: features: - build-mmi + - snaps env: - INFURA_MMI_PROJECT_ID - SEGMENT_MMI_WRITE_KEY - INFURA_ENV_KEY_REF: INFURA_MMI_PROJECT_ID - SEGMENT_WRITE_KEY_REF: SEGMENT_MMI_WRITE_KEY - - MMI_CONFIGURATION_SERVICE_URL: https://configuration.metamask-institutional.io/v1/configuration/default + - ALLOW_LOCAL_SNAPS: false + - REQUIRE_SNAPS_ALLOWLIST: true + - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.consensys.io/1.0.2/index.html + - MMI_CONFIGURATION_SERVICE_URL: https://configuration.metamask-institutional.io/v2/configuration/default - SUPPORT_LINK: https://mmi-support.zendesk.com/hc/en-us - SUPPORT_REQUEST_LINK: https://mmi-support.zendesk.com/hc/en-us/requests/new # For some reason, MMI uses this type of versioning diff --git a/docs/tests/jest.md b/docs/tests/jest.md index c4dc613aa46a..4e0d80863eb6 100644 --- a/docs/tests/jest.md +++ b/docs/tests/jest.md @@ -6,9 +6,9 @@ > yarn jest ``` -## Debugging +**note:** Breakpoints will not work in this mode. To debug, run the Jest test using a node server. -### Debugging Jest in VS Code +## Running a Jest test on a node server and inspecting in VS Code 1. Open **VS Code** 2. Open the “Run and Debug” panel (⇧⌘D) @@ -21,44 +21,58 @@ Additional methods and information to debug in VS Code can be found [here](https://jestjs.io/docs/troubleshooting#debugging-in-vs-code) -### Debugging Jest on Chrome DevTools +## Running a Jest test on a node server and inspecting in Chrome DevTools 1. Run Jest using Node with the V8 Inspector ```bash - > node --inspect ./node_modules/.bin/jest --watch -i + > yarn test:unit:jest:watch + ``` or - > node --inspect ./node_modules/.bin/jest + ```bash + > node --inspect ./node_modules/.bin/jest --watch ``` - **Options:** + **Useful options:** - ```jsx + ```bash node: - --inspect=[host:]port - Activate inspector on host:port. Default is 127.0.0.1:9229. + --inspect=[host:]port + Activate inspector on host:port. Default is 127.0.0.1:9229. - V8 Inspector integration allows attaching Chrome DevTools and IDEs - to Node.js instances for debugging and profiling. It uses the - Chrome DevTools Protocol. + V8 Inspector integration allows attaching Chrome DevTools and IDEs + to Node.js instances for debugging and profiling. It uses the + Chrome DevTools Protocol. jest: - --watch Watch files for changes and rerun tests - related to changed files. If you want to - re-run all tests when a file has changed, - use the `--watchAll` option. [boolean] - - -i, --runInBand Run all tests serially in the current - process (rather than creating a worker pool - of child processes that run tests). This is - sometimes useful for debugging, but such use - cases are pretty rare. [boolean] + -i, --runInBand + Run all tests serially in the current + process (rather than creating a worker pool + of child processes that run tests). This is + sometimes useful for debugging, but such use + cases are pretty rare. [boolean] + + -u, --updateSnapshot + Use this flag to re-record snapshots. Can be + used together with a test suite pattern or + with `--testNamePattern` to re-record + snapshot for test matching the pattern + + --watch + Watch files for changes and rerun tests + related to changed files. If you want to + re-run all tests when a file has changed, + use the `--watchAll` option. [boolean] ``` + **To view more options:** + ```bash + > ./node_modules/.bin/jest help + ``` 1. Open Chrome DevTools for Node 1. Open a **Chromium** browser diff --git a/jest.config.js b/jest.config.js index 72649eaf6118..f346219b0185 100644 --- a/jest.config.js +++ b/jest.config.js @@ -11,6 +11,7 @@ module.exports = { '/app/scripts/flask/**/*.js', '/app/scripts/lib/**/*.(js|ts)', '/app/scripts/lib/createRPCMethodTrackingMiddleware.js', + '/app/scripts/metamask-controller.js', '/app/scripts/migrations/*.js', '/app/scripts/migrations/*.ts', '!/app/scripts/migrations/*.test.(js|ts)', @@ -52,6 +53,7 @@ module.exports = { '/app/scripts/flask/**/*.test.js', '/app/scripts/lib/**/*.test.(js|ts)', '/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js', + '/app/scripts/metamask-controller.test.js', '/app/scripts/migrations/*.test.(js|ts)', '/app/scripts/platforms/*.test.js', '/app/scripts/translate.test.ts', diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index 18c7c3523c4d..0530d84fa850 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -1791,14 +1791,27 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, + "@metamask/permission-controller>@metamask/utils": true, "@metamask/permission-controller>nanoid": true, - "@metamask/utils": true, "deep-freeze-strict": true, "eth-rpc-errors": true, "immer": true, "json-rpc-engine": true } }, + "@metamask/permission-controller>@metamask/utils": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "@metamask/key-tree>@noble/hashes": true, + "browserify>buffer": true, + "nock>debug": true, + "semver": true, + "superstruct": true + } + }, "@metamask/permission-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -1917,6 +1930,11 @@ "crypto": true } }, + "@metamask/selected-network-controller": { + "packages": { + "@metamask/base-controller": true + } + }, "@metamask/signature-controller": { "globals": { "console.info": true diff --git a/lavamoat/browserify/desktop/policy.json b/lavamoat/browserify/desktop/policy.json index d5a883bb8a41..bdd2ba925bb9 100644 --- a/lavamoat/browserify/desktop/policy.json +++ b/lavamoat/browserify/desktop/policy.json @@ -1949,14 +1949,27 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, + "@metamask/permission-controller>@metamask/utils": true, "@metamask/permission-controller>nanoid": true, - "@metamask/utils": true, "deep-freeze-strict": true, "eth-rpc-errors": true, "immer": true, "json-rpc-engine": true } }, + "@metamask/permission-controller>@metamask/utils": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "@metamask/key-tree>@noble/hashes": true, + "browserify>buffer": true, + "nock>debug": true, + "semver": true, + "superstruct": true + } + }, "@metamask/permission-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -1978,52 +1991,6 @@ "eslint>optionator>fast-levenshtein": true } }, - "@metamask/post-message-stream": { - "globals": { - "MessageEvent.prototype": true, - "WorkerGlobalScope": true, - "addEventListener": true, - "browser": true, - "chrome": true, - "location.origin": true, - "postMessage": true, - "removeEventListener": true - }, - "packages": { - "@metamask/post-message-stream>readable-stream": true, - "@metamask/utils": true - } - }, - "@metamask/post-message-stream>readable-stream": { - "packages": { - "@metamask/post-message-stream>readable-stream>process-nextick-args": true, - "@metamask/post-message-stream>readable-stream>safe-buffer": true, - "@metamask/post-message-stream>readable-stream>string_decoder": true, - "browserify>browser-resolve": true, - "browserify>events": true, - "browserify>process": true, - "browserify>timers-browserify": true, - "pumpify>inherits": true, - "readable-stream>core-util-is": true, - "readable-stream>isarray": true, - "readable-stream>util-deprecate": true - } - }, - "@metamask/post-message-stream>readable-stream>process-nextick-args": { - "packages": { - "browserify>process": true - } - }, - "@metamask/post-message-stream>readable-stream>safe-buffer": { - "packages": { - "browserify>buffer": true - } - }, - "@metamask/post-message-stream>readable-stream>string_decoder": { - "packages": { - "@metamask/post-message-stream>readable-stream>safe-buffer": true - } - }, "@metamask/ppom-validator>elliptic": { "packages": { "@metamask/ppom-validator>elliptic>brorand": true, @@ -2084,7 +2051,20 @@ }, "@metamask/rpc-methods-flask>@metamask/snaps-ui": { "packages": { - "@metamask/rpc-methods-flask>@metamask/utils": true, + "@metamask/rpc-methods-flask>@metamask/snaps-ui>@metamask/utils": true, + "superstruct": true + } + }, + "@metamask/rpc-methods-flask>@metamask/snaps-ui>@metamask/utils": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "@metamask/key-tree>@noble/hashes": true, + "browserify>buffer": true, + "nock>debug": true, + "semver": true, "superstruct": true } }, @@ -2162,6 +2142,11 @@ "crypto": true } }, + "@metamask/selected-network-controller": { + "packages": { + "@metamask/base-controller": true + } + }, "@metamask/signature-controller": { "globals": { "console.info": true @@ -2221,8 +2206,8 @@ "packages": { "@metamask/base-controller": true, "@metamask/permission-controller": true, - "@metamask/post-message-stream": true, "@metamask/providers>@metamask/object-multiplex": true, + "@metamask/snaps-controllers-flask>@metamask/post-message-stream": true, "@metamask/snaps-controllers-flask>@metamask/rpc-methods": true, "@metamask/snaps-controllers-flask>@metamask/snaps-utils": true, "@metamask/snaps-controllers-flask>@metamask/utils": true, @@ -2239,13 +2224,41 @@ "pump": true } }, + "@metamask/snaps-controllers-flask>@metamask/post-message-stream": { + "globals": { + "MessageEvent.prototype": true, + "WorkerGlobalScope": true, + "addEventListener": true, + "browser": true, + "chrome": true, + "location.origin": true, + "postMessage": true, + "removeEventListener": true + }, + "packages": { + "@metamask/snaps-controllers-flask>@metamask/post-message-stream>@metamask/utils": true, + "@metamask/snaps-controllers-flask>concat-stream>readable-stream": true + } + }, + "@metamask/snaps-controllers-flask>@metamask/post-message-stream>@metamask/utils": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "browserify>buffer": true, + "nock>debug": true, + "semver": true, + "superstruct": true + } + }, "@metamask/snaps-controllers-flask>@metamask/rpc-methods": { "packages": { "@metamask/key-tree": true, "@metamask/key-tree>@noble/hashes": true, "@metamask/permission-controller": true, "@metamask/snaps-controllers-flask>@metamask/rpc-methods>@metamask/snaps-ui": true, - "@metamask/snaps-controllers-flask>@metamask/rpc-methods>@metamask/snaps-utils": true, + "@metamask/snaps-controllers-flask>@metamask/snaps-utils": true, "@metamask/snaps-controllers-flask>@metamask/utils": true, "eth-rpc-errors": true, "superstruct": true @@ -2253,34 +2266,19 @@ }, "@metamask/snaps-controllers-flask>@metamask/rpc-methods>@metamask/snaps-ui": { "packages": { - "@metamask/snaps-controllers-flask>@metamask/utils": true, + "@metamask/snaps-controllers-flask>@metamask/rpc-methods>@metamask/snaps-ui>@metamask/utils": true, "superstruct": true } }, - "@metamask/snaps-controllers-flask>@metamask/rpc-methods>@metamask/snaps-utils": { + "@metamask/snaps-controllers-flask>@metamask/rpc-methods>@metamask/snaps-ui>@metamask/utils": { "globals": { "TextDecoder": true, - "URL": true, - "console.error": true, - "console.log": true, - "console.warn": true, - "document.body.appendChild": true, - "document.createElement": true + "TextEncoder": true }, "packages": { - "@metamask/key-tree": true, "@metamask/key-tree>@noble/hashes": true, - "@metamask/key-tree>@scure/base": true, - "@metamask/snaps-controllers-flask>@metamask/utils": true, - "@metamask/snaps-utils-flask>is-svg": true, - "@metamask/snaps-utils>cron-parser": true, - "@metamask/snaps-utils>fast-json-stable-stringify": true, - "@metamask/snaps-utils>rfdc": true, - "@metamask/snaps-utils>validate-npm-package-name": true, "browserify>buffer": true, - "browserify>path-browserify": true, - "browserify>process": true, - "chalk": true, + "nock>debug": true, "semver": true, "superstruct": true } diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index 6af147aab6c4..2f97fd964747 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -1949,14 +1949,27 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, + "@metamask/permission-controller>@metamask/utils": true, "@metamask/permission-controller>nanoid": true, - "@metamask/utils": true, "deep-freeze-strict": true, "eth-rpc-errors": true, "immer": true, "json-rpc-engine": true } }, + "@metamask/permission-controller>@metamask/utils": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "@metamask/key-tree>@noble/hashes": true, + "browserify>buffer": true, + "nock>debug": true, + "semver": true, + "superstruct": true + } + }, "@metamask/permission-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -1978,52 +1991,6 @@ "eslint>optionator>fast-levenshtein": true } }, - "@metamask/post-message-stream": { - "globals": { - "MessageEvent.prototype": true, - "WorkerGlobalScope": true, - "addEventListener": true, - "browser": true, - "chrome": true, - "location.origin": true, - "postMessage": true, - "removeEventListener": true - }, - "packages": { - "@metamask/post-message-stream>readable-stream": true, - "@metamask/utils": true - } - }, - "@metamask/post-message-stream>readable-stream": { - "packages": { - "@metamask/post-message-stream>readable-stream>process-nextick-args": true, - "@metamask/post-message-stream>readable-stream>safe-buffer": true, - "@metamask/post-message-stream>readable-stream>string_decoder": true, - "browserify>browser-resolve": true, - "browserify>events": true, - "browserify>process": true, - "browserify>timers-browserify": true, - "pumpify>inherits": true, - "readable-stream>core-util-is": true, - "readable-stream>isarray": true, - "readable-stream>util-deprecate": true - } - }, - "@metamask/post-message-stream>readable-stream>process-nextick-args": { - "packages": { - "browserify>process": true - } - }, - "@metamask/post-message-stream>readable-stream>safe-buffer": { - "packages": { - "browserify>buffer": true - } - }, - "@metamask/post-message-stream>readable-stream>string_decoder": { - "packages": { - "@metamask/post-message-stream>readable-stream>safe-buffer": true - } - }, "@metamask/ppom-validator": { "globals": { "URL": true, @@ -2100,7 +2067,20 @@ }, "@metamask/rpc-methods-flask>@metamask/snaps-ui": { "packages": { - "@metamask/rpc-methods-flask>@metamask/utils": true, + "@metamask/rpc-methods-flask>@metamask/snaps-ui>@metamask/utils": true, + "superstruct": true + } + }, + "@metamask/rpc-methods-flask>@metamask/snaps-ui>@metamask/utils": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "@metamask/key-tree>@noble/hashes": true, + "browserify>buffer": true, + "nock>debug": true, + "semver": true, "superstruct": true } }, @@ -2178,6 +2158,11 @@ "crypto": true } }, + "@metamask/selected-network-controller": { + "packages": { + "@metamask/base-controller": true + } + }, "@metamask/signature-controller": { "globals": { "console.info": true @@ -2237,8 +2222,8 @@ "packages": { "@metamask/base-controller": true, "@metamask/permission-controller": true, - "@metamask/post-message-stream": true, "@metamask/providers>@metamask/object-multiplex": true, + "@metamask/snaps-controllers-flask>@metamask/post-message-stream": true, "@metamask/snaps-controllers-flask>@metamask/rpc-methods": true, "@metamask/snaps-controllers-flask>@metamask/snaps-utils": true, "@metamask/snaps-controllers-flask>@metamask/utils": true, @@ -2255,13 +2240,41 @@ "pump": true } }, + "@metamask/snaps-controllers-flask>@metamask/post-message-stream": { + "globals": { + "MessageEvent.prototype": true, + "WorkerGlobalScope": true, + "addEventListener": true, + "browser": true, + "chrome": true, + "location.origin": true, + "postMessage": true, + "removeEventListener": true + }, + "packages": { + "@metamask/snaps-controllers-flask>@metamask/post-message-stream>@metamask/utils": true, + "@metamask/snaps-controllers-flask>concat-stream>readable-stream": true + } + }, + "@metamask/snaps-controllers-flask>@metamask/post-message-stream>@metamask/utils": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "browserify>buffer": true, + "nock>debug": true, + "semver": true, + "superstruct": true + } + }, "@metamask/snaps-controllers-flask>@metamask/rpc-methods": { "packages": { "@metamask/key-tree": true, "@metamask/key-tree>@noble/hashes": true, "@metamask/permission-controller": true, "@metamask/snaps-controllers-flask>@metamask/rpc-methods>@metamask/snaps-ui": true, - "@metamask/snaps-controllers-flask>@metamask/rpc-methods>@metamask/snaps-utils": true, + "@metamask/snaps-controllers-flask>@metamask/snaps-utils": true, "@metamask/snaps-controllers-flask>@metamask/utils": true, "eth-rpc-errors": true, "superstruct": true @@ -2269,34 +2282,19 @@ }, "@metamask/snaps-controllers-flask>@metamask/rpc-methods>@metamask/snaps-ui": { "packages": { - "@metamask/snaps-controllers-flask>@metamask/utils": true, + "@metamask/snaps-controllers-flask>@metamask/rpc-methods>@metamask/snaps-ui>@metamask/utils": true, "superstruct": true } }, - "@metamask/snaps-controllers-flask>@metamask/rpc-methods>@metamask/snaps-utils": { + "@metamask/snaps-controllers-flask>@metamask/rpc-methods>@metamask/snaps-ui>@metamask/utils": { "globals": { "TextDecoder": true, - "URL": true, - "console.error": true, - "console.log": true, - "console.warn": true, - "document.body.appendChild": true, - "document.createElement": true + "TextEncoder": true }, "packages": { - "@metamask/key-tree": true, "@metamask/key-tree>@noble/hashes": true, - "@metamask/key-tree>@scure/base": true, - "@metamask/snaps-controllers-flask>@metamask/utils": true, - "@metamask/snaps-utils-flask>is-svg": true, - "@metamask/snaps-utils>cron-parser": true, - "@metamask/snaps-utils>fast-json-stable-stringify": true, - "@metamask/snaps-utils>rfdc": true, - "@metamask/snaps-utils>validate-npm-package-name": true, "browserify>buffer": true, - "browserify>path-browserify": true, - "browserify>process": true, - "chalk": true, + "nock>debug": true, "semver": true, "superstruct": true } diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index 47a5939bf129..8f1f171aa469 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -1798,14 +1798,27 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, + "@metamask/permission-controller>@metamask/utils": true, "@metamask/permission-controller>nanoid": true, - "@metamask/utils": true, "deep-freeze-strict": true, "eth-rpc-errors": true, "immer": true, "json-rpc-engine": true } }, + "@metamask/permission-controller>@metamask/utils": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "@metamask/key-tree>@noble/hashes": true, + "browserify>buffer": true, + "nock>debug": true, + "semver": true, + "superstruct": true + } + }, "@metamask/permission-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -1989,6 +2002,11 @@ "crypto": true } }, + "@metamask/selected-network-controller": { + "packages": { + "@metamask/base-controller": true + } + }, "@metamask/signature-controller": { "globals": { "console.info": true diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index ea4541e50fad..62a2de0bf326 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -765,68 +765,17 @@ }, "packages": { "@ethereumjs/tx>@ethereumjs/util": true, - "@metamask-institutional/extension>@metamask-institutional/custody-controller": true, + "@metamask-institutional/custody-controller": true, "@metamask-institutional/sdk": true, "@metamask-institutional/sdk>@metamask-institutional/types": true } }, - "@metamask-institutional/extension>@metamask-institutional/custody-controller": { - "packages": { - "@ethereumjs/tx>@ethereumjs/util": true, - "@metamask-institutional/extension>@metamask-institutional/custody-keyring": true, - "@metamask/obs-store": true - } - }, - "@metamask-institutional/extension>@metamask-institutional/custody-keyring": { - "globals": { - "console.log": true, - "console.warn": true - }, - "packages": { - "@ethereumjs/tx>@ethereumjs/util": true, - "@metamask-institutional/extension>@metamask-institutional/custody-keyring>@metamask-institutional/configuration-client": true, - "@metamask-institutional/sdk": true, - "@metamask-institutional/sdk>@metamask-institutional/types": true, - "@metamask/obs-store": true, - "browserify>crypto-browserify": true, - "browserify>events": true, - "gulp-sass>lodash.clonedeep": true - } - }, - "@metamask-institutional/extension>@metamask-institutional/custody-keyring>@metamask-institutional/configuration-client": { - "globals": { - "console.log": true, - "fetch": true - } - }, "@metamask-institutional/institutional-features": { "packages": { - "@metamask-institutional/institutional-features>@metamask-institutional/custody-keyring": true, + "@metamask-institutional/custody-keyring": true, "@metamask/obs-store": true } }, - "@metamask-institutional/institutional-features>@metamask-institutional/custody-keyring": { - "globals": { - "console.log": true, - "console.warn": true - }, - "packages": { - "@ethereumjs/tx>@ethereumjs/util": true, - "@metamask-institutional/institutional-features>@metamask-institutional/custody-keyring>@metamask-institutional/configuration-client": true, - "@metamask-institutional/sdk": true, - "@metamask-institutional/sdk>@metamask-institutional/types": true, - "@metamask/obs-store": true, - "browserify>crypto-browserify": true, - "browserify>events": true, - "gulp-sass>lodash.clonedeep": true - } - }, - "@metamask-institutional/institutional-features>@metamask-institutional/custody-keyring>@metamask-institutional/configuration-client": { - "globals": { - "console.log": true, - "fetch": true - } - }, "@metamask-institutional/portfolio-dashboard": { "globals": { "console.log": true, @@ -1955,6 +1904,13 @@ "browserify>events": true } }, + "@metamask/notification-controller": { + "packages": { + "@metamask/base-controller": true, + "@metamask/notification-controller>nanoid": true, + "@metamask/utils": true + } + }, "@metamask/notification-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -1982,14 +1938,27 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, + "@metamask/permission-controller>@metamask/utils": true, "@metamask/permission-controller>nanoid": true, - "@metamask/utils": true, "deep-freeze-strict": true, "eth-rpc-errors": true, "immer": true, "json-rpc-engine": true } }, + "@metamask/permission-controller>@metamask/utils": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "@metamask/key-tree>@noble/hashes": true, + "browserify>buffer": true, + "nock>debug": true, + "semver": true, + "superstruct": true + } + }, "@metamask/permission-controller>nanoid": { "globals": { "crypto.getRandomValues": true @@ -2011,6 +1980,52 @@ "eslint>optionator>fast-levenshtein": true } }, + "@metamask/post-message-stream": { + "globals": { + "MessageEvent.prototype": true, + "WorkerGlobalScope": true, + "addEventListener": true, + "browser": true, + "chrome": true, + "location.origin": true, + "postMessage": true, + "removeEventListener": true + }, + "packages": { + "@metamask/post-message-stream>readable-stream": true, + "@metamask/utils": true + } + }, + "@metamask/post-message-stream>readable-stream": { + "packages": { + "@metamask/post-message-stream>readable-stream>process-nextick-args": true, + "@metamask/post-message-stream>readable-stream>safe-buffer": true, + "@metamask/post-message-stream>readable-stream>string_decoder": true, + "browserify>browser-resolve": true, + "browserify>events": true, + "browserify>process": true, + "browserify>timers-browserify": true, + "pumpify>inherits": true, + "readable-stream>core-util-is": true, + "readable-stream>isarray": true, + "readable-stream>util-deprecate": true + } + }, + "@metamask/post-message-stream>readable-stream>process-nextick-args": { + "packages": { + "browserify>process": true + } + }, + "@metamask/post-message-stream>readable-stream>safe-buffer": { + "packages": { + "browserify>buffer": true + } + }, + "@metamask/post-message-stream>readable-stream>string_decoder": { + "packages": { + "@metamask/post-message-stream>readable-stream>safe-buffer": true + } + }, "@metamask/ppom-validator>elliptic": { "packages": { "@metamask/ppom-validator>elliptic>brorand": true, @@ -2038,6 +2053,25 @@ "ethereumjs-util>ethereum-cryptography>hash.js": true } }, + "@metamask/providers>@metamask/object-multiplex": { + "globals": { + "console.warn": true + }, + "packages": { + "end-of-stream": true, + "pump>once": true, + "readable-stream": true + } + }, + "@metamask/rate-limit-controller": { + "globals": { + "setTimeout": true + }, + "packages": { + "@metamask/base-controller": true, + "eth-rpc-errors": true + } + }, "@metamask/rpc-methods": { "packages": { "@metamask/browser-passworder": true, @@ -2108,6 +2142,11 @@ "crypto": true } }, + "@metamask/selected-network-controller": { + "packages": { + "@metamask/base-controller": true + } + }, "@metamask/signature-controller": { "globals": { "console.info": true @@ -2154,16 +2193,203 @@ "define": true } }, + "@metamask/snaps-controllers": { + "globals": { + "URL": true, + "chrome.offscreen.createDocument": true, + "chrome.offscreen.hasDocument": true, + "clearTimeout": true, + "document.getElementById": true, + "fetch.bind": true, + "setTimeout": true + }, + "packages": { + "@metamask/base-controller": true, + "@metamask/permission-controller": true, + "@metamask/post-message-stream": true, + "@metamask/providers>@metamask/object-multiplex": true, + "@metamask/rpc-methods": true, + "@metamask/snaps-controllers>@metamask/utils": true, + "@metamask/snaps-controllers>@xstate/fsm": true, + "@metamask/snaps-controllers>concat-stream": true, + "@metamask/snaps-controllers>gunzip-maybe": true, + "@metamask/snaps-controllers>nanoid": true, + "@metamask/snaps-controllers>readable-web-to-node-stream": true, + "@metamask/snaps-controllers>tar-stream": true, + "@metamask/snaps-utils": true, + "@metamask/snaps-utils>@metamask/snaps-registry": true, + "eth-rpc-errors": true, + "json-rpc-engine": true, + "json-rpc-middleware-stream": true, + "pump": true + } + }, "@metamask/snaps-controllers-flask>nanoid": { "globals": { "crypto.getRandomValues": true } }, + "@metamask/snaps-controllers>@metamask/utils": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "@metamask/key-tree>@noble/hashes": true, + "browserify>buffer": true, + "nock>debug": true, + "semver": true, + "superstruct": true + } + }, + "@metamask/snaps-controllers>concat-stream": { + "packages": { + "@metamask/snaps-controllers>concat-stream>readable-stream": true, + "browserify>buffer": true, + "browserify>concat-stream>typedarray": true, + "pumpify>inherits": true, + "terser>source-map-support>buffer-from": true + } + }, + "@metamask/snaps-controllers>concat-stream>readable-stream": { + "packages": { + "browserify>browser-resolve": true, + "browserify>buffer": true, + "browserify>events": true, + "browserify>process": true, + "browserify>string_decoder": true, + "pumpify>inherits": true, + "readable-stream>util-deprecate": true + } + }, + "@metamask/snaps-controllers>gunzip-maybe": { + "packages": { + "@metamask/snaps-controllers>gunzip-maybe>browserify-zlib": true, + "@metamask/snaps-controllers>gunzip-maybe>is-deflate": true, + "@metamask/snaps-controllers>gunzip-maybe>is-gzip": true, + "@metamask/snaps-controllers>gunzip-maybe>peek-stream": true, + "@metamask/snaps-controllers>gunzip-maybe>pumpify": true, + "@metamask/snaps-controllers>gunzip-maybe>through2": true + } + }, + "@metamask/snaps-controllers>gunzip-maybe>browserify-zlib": { + "packages": { + "@metamask/snaps-controllers>gunzip-maybe>browserify-zlib>pako": true, + "browserify>assert": true, + "browserify>buffer": true, + "browserify>process": true, + "browserify>util": true, + "readable-stream": true + } + }, + "@metamask/snaps-controllers>gunzip-maybe>peek-stream": { + "packages": { + "@metamask/snaps-controllers>gunzip-maybe>peek-stream>duplexify": true, + "@metamask/snaps-controllers>gunzip-maybe>peek-stream>through2": true, + "browserify>buffer": true, + "terser>source-map-support>buffer-from": true + } + }, + "@metamask/snaps-controllers>gunzip-maybe>peek-stream>duplexify": { + "packages": { + "browserify>buffer": true, + "browserify>process": true, + "duplexify>stream-shift": true, + "end-of-stream": true, + "pumpify>inherits": true, + "readable-stream": true + } + }, + "@metamask/snaps-controllers>gunzip-maybe>peek-stream>through2": { + "packages": { + "browserify>process": true, + "browserify>util": true, + "readable-stream": true, + "watchify>xtend": true + } + }, + "@metamask/snaps-controllers>gunzip-maybe>pumpify": { + "packages": { + "@metamask/snaps-controllers>gunzip-maybe>pumpify>duplexify": true, + "@metamask/snaps-controllers>gunzip-maybe>pumpify>pump": true, + "pumpify>inherits": true + } + }, + "@metamask/snaps-controllers>gunzip-maybe>pumpify>duplexify": { + "packages": { + "browserify>buffer": true, + "browserify>process": true, + "duplexify>stream-shift": true, + "end-of-stream": true, + "pumpify>inherits": true, + "readable-stream": true + } + }, + "@metamask/snaps-controllers>gunzip-maybe>pumpify>pump": { + "packages": { + "browserify>browser-resolve": true, + "end-of-stream": true, + "pump>once": true + } + }, + "@metamask/snaps-controllers>gunzip-maybe>through2": { + "packages": { + "browserify>process": true, + "browserify>util": true, + "readable-stream": true, + "watchify>xtend": true + } + }, "@metamask/snaps-controllers>nanoid": { "globals": { "crypto.getRandomValues": true } }, + "@metamask/snaps-controllers>readable-web-to-node-stream": { + "packages": { + "@metamask/snaps-controllers>readable-web-to-node-stream>readable-stream": true + } + }, + "@metamask/snaps-controllers>readable-web-to-node-stream>readable-stream": { + "packages": { + "browserify>browser-resolve": true, + "browserify>buffer": true, + "browserify>events": true, + "browserify>process": true, + "browserify>string_decoder": true, + "pumpify>inherits": true, + "readable-stream>util-deprecate": true + } + }, + "@metamask/snaps-controllers>tar-stream": { + "packages": { + "@metamask/snaps-controllers>tar-stream>fs-constants": true, + "@metamask/snaps-controllers>tar-stream>readable-stream": true, + "browserify>buffer": true, + "browserify>process": true, + "browserify>string_decoder": true, + "browserify>util": true, + "end-of-stream": true, + "madge>ora>bl": true, + "pumpify>inherits": true + } + }, + "@metamask/snaps-controllers>tar-stream>fs-constants": { + "packages": { + "browserify>constants-browserify": true + } + }, + "@metamask/snaps-controllers>tar-stream>readable-stream": { + "packages": { + "browserify>browser-resolve": true, + "browserify>buffer": true, + "browserify>events": true, + "browserify>process": true, + "browserify>string_decoder": true, + "pumpify>inherits": true, + "readable-stream>util-deprecate": true + } + }, "@metamask/snaps-ui": { "packages": { "@metamask/snaps-ui>@metamask/utils": true, @@ -2216,6 +2442,26 @@ "@metamask/snaps-utils>@metamask/utils": true } }, + "@metamask/snaps-utils>@metamask/snaps-registry": { + "packages": { + "@metamask/key-tree>@noble/secp256k1": true, + "@metamask/snaps-utils>@metamask/snaps-registry>@metamask/utils": true, + "superstruct": true + } + }, + "@metamask/snaps-utils>@metamask/snaps-registry>@metamask/utils": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "@metamask/key-tree>@noble/hashes": true, + "browserify>buffer": true, + "nock>debug": true, + "semver": true, + "superstruct": true + } + }, "@metamask/snaps-utils>@metamask/utils": { "globals": { "TextDecoder": true, @@ -4193,6 +4439,24 @@ "Intl": true } }, + "madge>ora>bl": { + "packages": { + "browserify>buffer": true, + "madge>ora>bl>readable-stream": true, + "pumpify>inherits": true + } + }, + "madge>ora>bl>readable-stream": { + "packages": { + "browserify>browser-resolve": true, + "browserify>buffer": true, + "browserify>events": true, + "browserify>process": true, + "browserify>string_decoder": true, + "pumpify>inherits": true, + "readable-stream>util-deprecate": true + } + }, "mocha>serialize-javascript>randombytes": { "globals": { "crypto": true, @@ -4457,6 +4721,115 @@ "react": true } }, + "react-markdown": { + "globals": { + "console.warn": true + }, + "packages": { + "prop-types": true, + "react": true, + "react-markdown>comma-separated-tokens": true, + "react-markdown>property-information": true, + "react-markdown>react-is": true, + "react-markdown>remark-parse": true, + "react-markdown>remark-rehype": true, + "react-markdown>space-separated-tokens": true, + "react-markdown>style-to-object": true, + "react-markdown>unified": true, + "react-markdown>unist-util-visit": true, + "react-markdown>vfile": true + } + }, + "react-markdown>property-information": { + "packages": { + "watchify>xtend": true + } + }, + "react-markdown>react-is": { + "globals": { + "console": true + } + }, + "react-markdown>remark-parse": { + "packages": { + "react-markdown>remark-parse>mdast-util-from-markdown": true + } + }, + "react-markdown>remark-parse>mdast-util-from-markdown": { + "packages": { + "react-markdown>remark-parse>mdast-util-from-markdown>mdast-util-to-string": true, + "react-markdown>remark-parse>mdast-util-from-markdown>micromark": true, + "react-markdown>remark-parse>mdast-util-from-markdown>unist-util-stringify-position": true, + "react-syntax-highlighter>refractor>parse-entities": true + } + }, + "react-markdown>remark-parse>mdast-util-from-markdown>micromark": { + "packages": { + "react-syntax-highlighter>refractor>parse-entities": true + } + }, + "react-markdown>remark-rehype": { + "packages": { + "react-markdown>remark-rehype>mdast-util-to-hast": true + } + }, + "react-markdown>remark-rehype>mdast-util-to-hast": { + "globals": { + "console.warn": true + }, + "packages": { + "react-markdown>remark-rehype>mdast-util-to-hast>mdast-util-definitions": true, + "react-markdown>remark-rehype>mdast-util-to-hast>mdurl": true, + "react-markdown>remark-rehype>mdast-util-to-hast>unist-builder": true, + "react-markdown>remark-rehype>mdast-util-to-hast>unist-util-generated": true, + "react-markdown>remark-rehype>mdast-util-to-hast>unist-util-position": true, + "react-markdown>unist-util-visit": true + } + }, + "react-markdown>remark-rehype>mdast-util-to-hast>mdast-util-definitions": { + "packages": { + "react-markdown>unist-util-visit": true + } + }, + "react-markdown>style-to-object": { + "packages": { + "react-markdown>style-to-object>inline-style-parser": true + } + }, + "react-markdown>unified": { + "packages": { + "mocha>yargs-unparser>is-plain-obj": true, + "react-markdown>unified>bail": true, + "react-markdown>unified>extend": true, + "react-markdown>unified>is-buffer": true, + "react-markdown>unified>trough": true, + "react-markdown>vfile": true + } + }, + "react-markdown>unist-util-visit": { + "packages": { + "react-markdown>unist-util-visit>unist-util-visit-parents": true + } + }, + "react-markdown>unist-util-visit>unist-util-visit-parents": { + "packages": { + "react-markdown>unist-util-visit>unist-util-is": true + } + }, + "react-markdown>vfile": { + "packages": { + "browserify>path-browserify": true, + "browserify>process": true, + "react-markdown>vfile>is-buffer": true, + "react-markdown>vfile>vfile-message": true, + "vinyl>replace-ext": true + } + }, + "react-markdown>vfile>vfile-message": { + "packages": { + "react-markdown>vfile>unist-util-stringify-position": true + } + }, "react-popper": { "globals": { "document": true @@ -4611,6 +4984,11 @@ "react": true } }, + "react-syntax-highlighter>refractor>parse-entities": { + "globals": { + "document.createElement": true + } + }, "react-tippy": { "globals": { "Element": true, @@ -4774,12 +5152,22 @@ "define": true } }, + "terser>source-map-support>buffer-from": { + "packages": { + "browserify>buffer": true + } + }, "uuid": { "globals": { "crypto": true, "msCrypto": true } }, + "vinyl>replace-ext": { + "packages": { + "browserify>path-browserify": true + } + }, "web3": { "globals": { "XMLHttpRequest": true diff --git a/package.json b/package.json index 8958f268505a..99a52e23d433 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "metamask-crx", - "version": "11.1.2", + "version": "11.2.0", "private": true, "repository": { "type": "git", @@ -32,6 +32,7 @@ "dapp-forwarder": "concurrently -k -n forwarder,dapp -p '[{time}][{name}]' 'yarn forwarder' 'yarn dapp'", "test:unit": "node ./test/run-unit-tests.js --mocha --jestGlobal --jestDev", "test:unit:jest": "node ./test/run-unit-tests.js --jestGlobal --jestDev", + "test:unit:jest:watch": "node --inspect ./node_modules/.bin/jest --watch", "test:unit:global": "mocha test/unit-global/*.test.js", "test:unit:mocha": "node ./test/run-unit-tests.js --mocha", "test:e2e:chrome": "SELENIUM_BROWSER=chrome node test/e2e/run-all.js", @@ -223,8 +224,8 @@ "@keystonehq/metamask-airgapped-keyring": "^0.13.1", "@lavamoat/snow": "^1.5.0", "@material-ui/core": "^4.11.0", - "@metamask-institutional/custody-controller": "0.2.10", - "@metamask-institutional/custody-keyring": "0.0.27", + "@metamask-institutional/custody-controller": "^0.2.12", + "@metamask-institutional/custody-keyring": "^1.0.2", "@metamask-institutional/extension": "^0.3.7", "@metamask-institutional/institutional-features": "^1.2.6", "@metamask-institutional/portfolio-dashboard": "^1.4.0", @@ -244,7 +245,7 @@ "@metamask/eth-json-rpc-middleware": "^11.0.0", "@metamask/eth-keyring-controller": "^10.0.1", "@metamask/eth-ledger-bridge-keyring": "^0.15.0", - "@metamask/eth-snap-keyring": "^0.1.3", + "@metamask/eth-snap-keyring": "^0.1.4", "@metamask/eth-token-tracker": "^4.0.0", "@metamask/eth-trezor-keyring": "^1.1.0", "@metamask/etherscan-link": "^2.2.0", @@ -255,7 +256,7 @@ "@metamask/logo": "^3.1.1", "@metamask/message-manager": "^7.3.0", "@metamask/metamask-eth-abis": "^3.0.0", - "@metamask/network-controller": "^12.0.0", + "@metamask/network-controller": "^12.1.1", "@metamask/notification-controller": "^3.0.0", "@metamask/obs-store": "^8.1.0", "@metamask/permission-controller": "^4.0.0", @@ -265,18 +266,19 @@ "@metamask/providers": "^11.1.0", "@metamask/rate-limit-controller": "^3.0.0", "@metamask/rpc-methods": "^1.0.2", - "@metamask/rpc-methods-flask": "npm:@metamask/rpc-methods@0.37.2-flask.1", + "@metamask/rpc-methods-flask": "npm:@metamask/rpc-methods@0.38.2-flask.1", "@metamask/safe-event-emitter": "^2.0.0", "@metamask/scure-bip39": "^2.0.3", + "@metamask/selected-network-controller": "^1.0.0", "@metamask/signature-controller": "^5.3.0", "@metamask/slip44": "^3.0.0", "@metamask/smart-transactions-controller": "^4.0.0", "@metamask/snaps-controllers": "^1.0.2", - "@metamask/snaps-controllers-flask": "npm:@metamask/snaps-controllers@0.38.0-flask.1", + "@metamask/snaps-controllers-flask": "npm:@metamask/snaps-controllers@0.38.3-flask.1", "@metamask/snaps-ui": "^1.0.2", - "@metamask/snaps-ui-flask": "npm:@metamask/snaps-ui@0.37.3-flask.1", + "@metamask/snaps-ui-flask": "npm:@metamask/snaps-ui@0.37.4-flask.1", "@metamask/snaps-utils": "^1.0.2", - "@metamask/snaps-utils-flask": "npm:@metamask/snaps-utils@0.38.0-flask.1", + "@metamask/snaps-utils-flask": "npm:@metamask/snaps-utils@0.38.3-flask.1", "@metamask/subject-metadata-controller": "^2.0.0", "@metamask/utils": "^5.0.0", "@ngraveio/bc-ur": "^1.1.6", @@ -447,7 +449,7 @@ "browserify": "^16.5.1", "chalk": "^4.1.2", "chokidar": "^3.5.3", - "chromedriver": "^114.0.0", + "chromedriver": "^116.0.0", "concurrently": "^7.6.0", "copy-webpack-plugin": "^6.0.3", "cross-spawn": "^7.0.3", @@ -457,6 +459,7 @@ "del": "^6.1.1", "depcheck": "^1.4.3", "dependency-tree": "^10.0.9", + "detect-port": "^1.5.1", "duplexify": "^4.1.1", "eslint": "^8.36.0", "eslint-config-prettier": "^8.5.0", diff --git a/shared/constants/network.ts b/shared/constants/network.ts index 52e0eb5b4346..db5ca5477740 100644 --- a/shared/constants/network.ts +++ b/shared/constants/network.ts @@ -161,6 +161,7 @@ export const CHAIN_IDS = { MOONRIVER: '0x505', CRONOS: '0x19', GNOSIS: '0x64', + ZKSYNC_ERA: '0x144', } as const; /** @@ -641,6 +642,10 @@ export const BUYABLE_CHAINS_MAP: { nativeCurrency: CURRENCY_SYMBOLS.ETH, network: 'linea', }, + [CHAIN_IDS.ZKSYNC_ERA]: { + nativeCurrency: CURRENCY_SYMBOLS.ETH, + network: 'zksync', + }, }; export const FEATURED_RPCS: RPCDefinition[] = [ diff --git a/shared/constants/permissions.test.js b/shared/constants/permissions.test.js index f1ef4a5563a2..0bc4e9cc37db 100644 --- a/shared/constants/permissions.test.js +++ b/shared/constants/permissions.test.js @@ -24,12 +24,14 @@ describe('EndowmentPermissions', () => { }); }); +const FlaskOnlyPermissions = ['snap_manageAccounts', 'snap_getLocale']; + describe('RestrictedMethods', () => { it('has the expected permission keys', () => { // this is done because we there is a difference between flask and stable permissions // the code fence in `shared/constants/snaps/permissions.ts` is not supported in jest const mainBuildRestrictedMethodPermissions = Object.keys(RestrictedMethods) - .filter((key) => key !== 'snap_manageAccounts') + .filter((key) => !FlaskOnlyPermissions.includes(key)) .sort(); expect(mainBuildRestrictedMethodPermissions).toStrictEqual( @@ -54,7 +56,7 @@ describe('Flask Restricted Methods', () => { it('has the expected flask permission keys', () => { const flaskExcludedSnapPermissions = Object.keys( ExcludedSnapPermissions, - ).filter((key) => key !== 'snap_manageAccounts'); + ).filter((key) => !FlaskOnlyPermissions.includes(key)); expect(Object.keys(RestrictedMethods).sort()).toStrictEqual( [ diff --git a/shared/constants/permissions.ts b/shared/constants/permissions.ts index 1d0c60ac19b8..32f91eb50ac6 100644 --- a/shared/constants/permissions.ts +++ b/shared/constants/permissions.ts @@ -12,6 +12,7 @@ export const RestrictedMethods = Object.freeze({ snap_getBip32Entropy: 'snap_getBip32Entropy', snap_getBip44Entropy: 'snap_getBip44Entropy', snap_getEntropy: 'snap_getEntropy', + snap_getLocale: 'snap_getLocale', wallet_snap: 'wallet_snap', ///: END:ONLY_INCLUDE_IN ///: BEGIN:ONLY_INCLUDE_IN(keyring-snaps) diff --git a/shared/constants/snaps.ts b/shared/constants/snaps.ts index 6ba3d9ab8d33..7c15f6d71d3b 100644 --- a/shared/constants/snaps.ts +++ b/shared/constants/snaps.ts @@ -87,7 +87,12 @@ export const SNAPS_DERIVATION_PATHS: SnapsDerivationPath[] = [ }, { path: ['m', `44'`, `501'`], - curve: 'secp256k1', + curve: 'ed25519', + name: 'Solana', + }, + { + path: ['m', `44'`, `501'`, "0'", "0'"], + curve: 'ed25519', name: 'Solana', }, { diff --git a/shared/constants/snaps/permissions.ts b/shared/constants/snaps/permissions.ts index 3642e2187166..d5e1b16c6d4f 100644 --- a/shared/constants/snaps/permissions.ts +++ b/shared/constants/snaps/permissions.ts @@ -15,6 +15,8 @@ export const EndowmentPermissions = Object.freeze({ export const ExcludedSnapPermissions = Object.freeze({ // TODO: Enable in Flask ///: BEGIN:ONLY_INCLUDE_IN(build-main) + snap_getLocale: + 'This permission is still in development and therefore not available.', snap_manageAccounts: 'This permission is still in development and therefore not available.', ///: END:ONLY_INCLUDE_IN diff --git a/shared/constants/swaps.ts b/shared/constants/swaps.ts index a253e8e78147..1b60dc8f95fc 100644 --- a/shared/constants/swaps.ts +++ b/shared/constants/swaps.ts @@ -105,6 +105,10 @@ export const OPTIMISM_SWAPS_TOKEN_OBJECT: SwapsTokenObject = { ...ETH_SWAPS_TOKEN_OBJECT, } as const; +export const ZKSYNC_ERA_SWAPS_TOKEN_OBJECT: SwapsTokenObject = { + ...ETH_SWAPS_TOKEN_OBJECT, +} as const; + // A gas value for ERC20 approve calls that should be sufficient for all ERC20 approve implementations export const DEFAULT_ERC20_APPROVE_GAS = '0x1d4c0'; @@ -116,6 +120,8 @@ const POLYGON_CONTRACT_ADDRESS = '0x1a1ec25dc08e98e5e93f1104b5e5cdd298707d31'; const AVALANCHE_CONTRACT_ADDRESS = '0x1a1ec25dc08e98e5e93f1104b5e5cdd298707d31'; const OPTIMISM_CONTRACT_ADDRESS = '0x9dda6ef3d919c9bc8885d5560999a3640431e8e6'; const ARBITRUM_CONTRACT_ADDRESS = '0x9dda6ef3d919c9bc8885d5560999a3640431e8e6'; +const ZKSYNC_ERA_CONTRACT_ADDRESS = + '0xf504c1fe13d14df615e66dcd0abf39e60c697f34'; export const WETH_CONTRACT_ADDRESS = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'; @@ -127,20 +133,19 @@ export const WMATIC_CONTRACT_ADDRESS = '0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270'; export const WAVAX_CONTRACT_ADDRESS = '0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7'; - export const WETH_OPTIMISM_CONTRACT_ADDRESS = '0x4200000000000000000000000000000000000006'; export const WETH_ARBITRUM_CONTRACT_ADDRESS = '0x82af49447d8a07e3bd95bd0d56f35241523fbab1'; +export const WETH_ZKSYNC_ERA_CONTRACT_ADDRESS = + '0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91'; const SWAPS_TESTNET_CHAIN_ID = '0x539'; -export const MMI_SWAPS_URL = 'https://metamask-institutional.io/swap'; - export const SWAPS_API_V2_BASE_URL = 'https://swap.metaswap.codefi.network'; export const SWAPS_DEV_API_V2_BASE_URL = 'https://swap.dev-api.cx.metamask.io'; export const GAS_API_BASE_URL = 'https://gas-api.metaswap.codefi.network'; -export const GAS_DEV_API_BASE_URL = 'https://gas.dev-api.cx.metamask.io'; +export const GAS_DEV_API_BASE_URL = 'https://gas.uat-api.cx.metamask.io'; const BSC_DEFAULT_BLOCK_EXPLORER_URL = 'https://bscscan.com/'; const MAINNET_DEFAULT_BLOCK_EXPLORER_URL = 'https://etherscan.io/'; @@ -149,6 +154,7 @@ const POLYGON_DEFAULT_BLOCK_EXPLORER_URL = 'https://polygonscan.com/'; const AVALANCHE_DEFAULT_BLOCK_EXPLORER_URL = 'https://snowtrace.io/'; const OPTIMISM_DEFAULT_BLOCK_EXPLORER_URL = 'https://optimistic.etherscan.io/'; const ARBITRUM_DEFAULT_BLOCK_EXPLORER_URL = 'https://arbiscan.io/'; +const ZKSYNC_DEFAULT_BLOCK_EXPLORER_URL = 'https://explorer.zksync.io/'; export const ALLOWED_PROD_SWAPS_CHAIN_IDS = [ CHAIN_IDS.MAINNET, @@ -158,6 +164,7 @@ export const ALLOWED_PROD_SWAPS_CHAIN_IDS = [ CHAIN_IDS.AVALANCHE, CHAIN_IDS.OPTIMISM, CHAIN_IDS.ARBITRUM, + CHAIN_IDS.ZKSYNC_ERA, ] as const; export const ALLOWED_DEV_SWAPS_CHAIN_IDS = [ @@ -179,6 +186,7 @@ export const SWAPS_CHAINID_CONTRACT_ADDRESS_MAP = { [CHAIN_IDS.AVALANCHE]: AVALANCHE_CONTRACT_ADDRESS, [CHAIN_IDS.OPTIMISM]: OPTIMISM_CONTRACT_ADDRESS, [CHAIN_IDS.ARBITRUM]: ARBITRUM_CONTRACT_ADDRESS, + [CHAIN_IDS.ZKSYNC_ERA]: ZKSYNC_ERA_CONTRACT_ADDRESS, } as const; export const SWAPS_WRAPPED_TOKENS_ADDRESSES = { @@ -190,6 +198,7 @@ export const SWAPS_WRAPPED_TOKENS_ADDRESSES = { [CHAIN_IDS.AVALANCHE]: WAVAX_CONTRACT_ADDRESS, [CHAIN_IDS.OPTIMISM]: WETH_OPTIMISM_CONTRACT_ADDRESS, [CHAIN_IDS.ARBITRUM]: WETH_ARBITRUM_CONTRACT_ADDRESS, + [CHAIN_IDS.ZKSYNC_ERA]: WETH_ZKSYNC_ERA_CONTRACT_ADDRESS, } as const; export const ALLOWED_CONTRACT_ADDRESSES = { @@ -225,6 +234,10 @@ export const ALLOWED_CONTRACT_ADDRESSES = { SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[CHAIN_IDS.ARBITRUM], SWAPS_WRAPPED_TOKENS_ADDRESSES[CHAIN_IDS.ARBITRUM], ], + [CHAIN_IDS.ZKSYNC_ERA]: [ + SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[CHAIN_IDS.ZKSYNC_ERA], + SWAPS_WRAPPED_TOKENS_ADDRESSES[CHAIN_IDS.ZKSYNC_ERA], + ], } as const; export const SWAPS_CHAINID_DEFAULT_TOKEN_MAP = { @@ -236,6 +249,7 @@ export const SWAPS_CHAINID_DEFAULT_TOKEN_MAP = { [CHAIN_IDS.AVALANCHE]: AVAX_SWAPS_TOKEN_OBJECT, [CHAIN_IDS.OPTIMISM]: OPTIMISM_SWAPS_TOKEN_OBJECT, [CHAIN_IDS.ARBITRUM]: ARBITRUM_SWAPS_TOKEN_OBJECT, + [CHAIN_IDS.ZKSYNC_ERA]: ZKSYNC_ERA_SWAPS_TOKEN_OBJECT, } as const; export const SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP = { @@ -246,6 +260,7 @@ export const SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP = { [CHAIN_IDS.AVALANCHE]: AVALANCHE_DEFAULT_BLOCK_EXPLORER_URL, [CHAIN_IDS.OPTIMISM]: OPTIMISM_DEFAULT_BLOCK_EXPLORER_URL, [CHAIN_IDS.ARBITRUM]: ARBITRUM_DEFAULT_BLOCK_EXPLORER_URL, + [CHAIN_IDS.ZKSYNC_ERA]: ZKSYNC_DEFAULT_BLOCK_EXPLORER_URL, } as const; export const ETHEREUM = 'ethereum'; @@ -255,6 +270,7 @@ export const GOERLI = 'goerli'; export const AVALANCHE = 'avalanche'; export const OPTIMISM = 'optimism'; export const ARBITRUM = 'arbitrum'; +export const ZKSYNC_ERA = 'zksync'; export const SWAPS_CLIENT_ID = 'extension'; diff --git a/shared/constants/transaction.ts b/shared/constants/transaction.ts index d14e9400e797..8a5ac8f98eb6 100644 --- a/shared/constants/transaction.ts +++ b/shared/constants/transaction.ts @@ -380,11 +380,6 @@ export interface TransactionMeta { originalGasEstimate: string; /** A boolean representing when the user manually edited the gas limit. */ userEditedGasLimit: boolean; - /** - * A metadata object containing information used to derive the suggested - * nonce, useful for debugging nonce issues. - */ - nonceDetails: Record; /** * A hex string of the final signed transaction, ready to submit to the * network. diff --git a/shared/lib/fetch-with-cache.test.js b/shared/lib/fetch-with-cache.test.js index 0b6f3f933d01..17285aaa12bf 100644 --- a/shared/lib/fetch-with-cache.test.js +++ b/shared/lib/fetch-with-cache.test.js @@ -21,9 +21,11 @@ describe('Fetch with cache', () => { .get('/price') .reply(200, '{"average": 1}'); - const response = await fetchWithCache( - 'https://fetchwithcache.metamask.io/price', - ); + const response = await fetchWithCache({ + url: 'https://fetchwithcache.metamask.io/price', + functionName: 'fetchPrice', + }); + expect(response).toStrictEqual({ average: 1, }); @@ -39,9 +41,10 @@ describe('Fetch with cache', () => { cachedTime: Date.now(), }); - const response = await fetchWithCache( - 'https://fetchwithcache.metamask.io/price', - ); + const response = await fetchWithCache({ + url: 'https://fetchwithcache.metamask.io/price', + functionName: 'fetchPrice', + }); expect(response).toStrictEqual({ average: 1, }); @@ -57,11 +60,11 @@ describe('Fetch with cache', () => { cachedTime: Date.now() - 1000, }); - const response = await fetchWithCache( - 'https://fetchwithcache.metamask.io/price', - {}, - { cacheRefreshTime: 123 }, - ); + const response = await fetchWithCache({ + url: 'https://fetchwithcache.metamask.io/price', + cacheOptions: { cacheRefreshTime: 123 }, + functionName: 'fetchPrice', + }); expect(response).toStrictEqual({ average: 3, }); @@ -74,11 +77,11 @@ describe('Fetch with cache', () => { .reply(200, '{"average": 4}'); await expect(() => - fetchWithCache( - 'https://fetchwithcache.metamask.io/price', - {}, - { timeout: 20 }, - ), + fetchWithCache({ + url: 'https://fetchwithcache.metamask.io/price', + cacheOptions: { timeout: 20 }, + functionName: 'fetchPrice', + }), ).rejects.toThrow({ name: 'AbortError', message: 'The user aborted a request.', @@ -91,7 +94,10 @@ describe('Fetch with cache', () => { .reply(500, '{"average": 6}'); await expect(() => - fetchWithCache('https://fetchwithcache.metamask.io/price'), + fetchWithCache({ + url: 'https://fetchwithcache.metamask.io/price', + functionName: 'fetchPrice', + }), ).rejects.toThrow(''); }); @@ -101,8 +107,10 @@ describe('Fetch with cache', () => { .reply(200, '{"average": 7}'); await expect(() => - fetchWithCache('https://fetchwithcache.metamask.io/price', { - method: 'POST', + fetchWithCache({ + url: 'https://fetchwithcache.metamask.io/price', + fetchOptions: { method: 'POST' }, + functionName: 'fetchPrice', }), ).rejects.toThrow(''); }); @@ -113,7 +121,11 @@ describe('Fetch with cache', () => { .reply(200, '{"average": 8}'); await expect(() => - fetchWithCache('https://fetchwithcache.metamask.io/price', { body: 1 }), + fetchWithCache({ + url: 'https://fetchwithcache.metamask.io/price', + fetchOptions: { body: 1 }, + functionName: 'fetchPrice', + }), ).rejects.toThrow(''); }); @@ -123,8 +135,10 @@ describe('Fetch with cache', () => { .reply(200, '{"average": 9}'); await expect(() => - fetchWithCache('https://fetchwithcache.metamask.io/price', { - headers: { 'Content-Type': 'text/plain' }, + fetchWithCache({ + url: 'https://fetchwithcache.metamask.io/price', + fetchOptions: { headers: { 'Content-Type': 'text/plain' } }, + functionName: 'fetchPrice', }), ).rejects.toThrow({ message: 'fetchWithCache only supports JSON responses', @@ -147,16 +161,16 @@ describe('Fetch with cache', () => { }); await Promise.all([ - fetchWithCache( - 'https://fetchwithcache.metamask.io/foo', - {}, - { cacheRefreshTime: 123 }, - ), - fetchWithCache( - 'https://fetchwithcache.metamask.io/bar', - {}, - { cacheRefreshTime: 123 }, - ), + fetchWithCache({ + url: 'https://fetchwithcache.metamask.io/foo', + cacheOptions: { cacheRefreshTime: 123 }, + functionName: 'fetchFoo', + }), + fetchWithCache({ + url: 'https://fetchwithcache.metamask.io/bar', + cacheOptions: { cacheRefreshTime: 123 }, + functionName: 'fetchFoo', + }), ]); expect( diff --git a/shared/lib/fetch-with-cache.js b/shared/lib/fetch-with-cache.ts similarity index 80% rename from shared/lib/fetch-with-cache.js rename to shared/lib/fetch-with-cache.ts index a92f4fb2e8b2..8a84ad76f8c4 100644 --- a/shared/lib/fetch-with-cache.js +++ b/shared/lib/fetch-with-cache.ts @@ -2,11 +2,17 @@ import { MINUTE, SECOND } from '../constants/time'; import getFetchWithTimeout from '../modules/fetch-with-timeout'; import { getStorageItem, setStorageItem } from './storage-helpers'; -const fetchWithCache = async ( +const fetchWithCache = async ({ url, fetchOptions = {}, - { cacheRefreshTime = MINUTE * 6, timeout = SECOND * 30 } = {}, -) => { + cacheOptions: { cacheRefreshTime = MINUTE * 6, timeout = SECOND * 30 } = {}, + functionName = '', +}: { + url: string; + fetchOptions?: Record; + cacheOptions?: Record; + functionName: string; +}) => { if ( fetchOptions.body || (fetchOptions.method && fetchOptions.method !== 'GET') @@ -40,7 +46,7 @@ const fetchWithCache = async ( }); if (!response.ok) { throw new Error( - `Fetch failed with status '${response.status}': '${response.statusText}'`, + `Fetch with cache failed within function ${functionName} with status'${response.status}': '${response.statusText}'`, ); } const responseJson = await response.json(); diff --git a/shared/lib/swaps-utils.js b/shared/lib/swaps-utils.js index c58557bca748..1d48bf5d479e 100644 --- a/shared/lib/swaps-utils.js +++ b/shared/lib/swaps-utils.js @@ -274,11 +274,12 @@ export async function fetchTradesInfo( const queryString = new URLSearchParams(urlParams).toString(); const tradeURL = `${getBaseApi('trade', chainId)}${queryString}`; - const tradesResponse = await fetchWithCache( - tradeURL, - { method: 'GET', headers: clientIdHeader }, - { cacheRefreshTime: 0, timeout: SECOND * 15 }, - ); + const tradesResponse = await fetchWithCache({ + url: tradeURL, + fetchOptions: { method: 'GET', headers: clientIdHeader }, + cacheOptions: { cacheRefreshTime: 0, timeout: SECOND * 15 }, + functionName: 'fetchTradesInfo', + }); const newQuotes = tradesResponse.reduce((aggIdTradeMap, quote) => { if ( quote.trade && diff --git a/test/data/mock-send-state.json b/test/data/mock-send-state.json index 969f7fdcc75c..8b4cbf16a709 100644 --- a/test/data/mock-send-state.json +++ b/test/data/mock-send-state.json @@ -408,32 +408,6 @@ "value": "0xb5", "note": "transactions#approveTransaction", "timestamp": 1528133131806 - }, - { - "op": "add", - "path": "/nonceDetails", - "value": { - "params": { - "highestLocallyConfirmed": 0, - "highestSuggested": 181, - "nextNetworkNonce": 181 - }, - "local": { - "name": "local", - "nonce": 181, - "details": { - "startPoint": 181, - "highest": 181 - } - }, - "network": { - "name": "network", - "nonce": 181, - "details": { - "baseCount": 181 - } - } - } } ], [ @@ -498,28 +472,6 @@ ] ], "origin": "MetaMask", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 0, - "highestSuggested": 181, - "nextNetworkNonce": 181 - }, - "local": { - "name": "local", - "nonce": 181, - "details": { - "startPoint": 181, - "highest": 181 - } - }, - "network": { - "name": "network", - "nonce": 181, - "details": { - "baseCount": 181 - } - } - }, "rawTx": "0xf86c81b5843b9aca0082cf089492e659448c48fc926ec942d0da1459260d36bb33881bc16d674ec80000802ba03f879cd33a31180da38545d0f809822e00ddf35954d8b0ece83bacf22347ce54a06ad050487978e425ca6a014ed55ea8e9a190069863ed96a0eefa88d729ea1eda", "hash": "0x516b77569173a04c76fdb6545cf279ebd0c75f5d25d6e4ce019925205f0e3709", "submittedTime": 1528133131951, @@ -588,32 +540,6 @@ "value": "0xb6", "note": "transactions#approveTransaction", "timestamp": 1528133151189 - }, - { - "op": "add", - "path": "/nonceDetails", - "value": { - "params": { - "highestLocallyConfirmed": 0, - "highestSuggested": 181, - "nextNetworkNonce": 181 - }, - "local": { - "name": "local", - "nonce": 182, - "details": { - "startPoint": 181, - "highest": 182 - } - }, - "network": { - "name": "network", - "nonce": 181, - "details": { - "baseCount": 181 - } - } - } } ], [ @@ -678,28 +604,6 @@ ] ], "origin": "MetaMask", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 0, - "highestSuggested": 181, - "nextNetworkNonce": 181 - }, - "local": { - "name": "local", - "nonce": 182, - "details": { - "startPoint": 181, - "highest": 182 - } - }, - "network": { - "name": "network", - "nonce": 181, - "details": { - "baseCount": 181 - } - } - }, "rawTx": "0xf86c81b6843b9aca0082cf089492e659448c48fc926ec942d0da1459260d36bb33881bc16d674ec80000802ba0692deaabf0d79544d41e7c475ad43760679a4f25d0fee908b1da308db1a291a7a0384db85fc6c843ea25986a0760f3c50ab6504fc559fc71fc7f23f60950eb316d", "hash": "0x9271b266d05022cfa841362fae43763ebafcee540d84278b0157ef4a68d4e26f", "submittedTime": 1528133151347, @@ -768,32 +672,6 @@ "value": "0xb7", "note": "transactions#approveTransaction", "timestamp": 1528133181726 - }, - { - "op": "add", - "path": "/nonceDetails", - "value": { - "params": { - "highestLocallyConfirmed": 182, - "highestSuggested": 182, - "nextNetworkNonce": 182 - }, - "local": { - "name": "local", - "nonce": 183, - "details": { - "startPoint": 182, - "highest": 183 - } - }, - "network": { - "name": "network", - "nonce": 182, - "details": { - "baseCount": 182 - } - } - } } ], [ @@ -858,28 +736,6 @@ ] ], "origin": "MetaMask", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 182, - "highestSuggested": 182, - "nextNetworkNonce": 182 - }, - "local": { - "name": "local", - "nonce": 183, - "details": { - "startPoint": 182, - "highest": 183 - } - }, - "network": { - "name": "network", - "nonce": 182, - "details": { - "baseCount": 182 - } - } - }, "rawTx": "0xf86d81b785012a05f20082cf089492e659448c48fc926ec942d0da1459260d36bb33881bc16d674ec80000802ba086f9846798be6988c39a5cf85f0dbe267e59ca0b96a6a7077e92cba33e10a258a064ffa52ac90c238ce21e6f085283216191b185a1eccd7daae6e2ab66ba26ada0", "hash": "0x4e061e977c099735bc9e5203e717f7d9dccb3fcb2f82031a12a3ed326f95d43b", "submittedTime": 1528133181885, @@ -953,32 +809,6 @@ "value": "0xb8", "note": "transactions#approveTransaction", "timestamp": 1528133227374 - }, - { - "op": "add", - "path": "/nonceDetails", - "value": { - "params": { - "highestLocallyConfirmed": 184, - "highestSuggested": 184, - "nextNetworkNonce": 184 - }, - "local": { - "name": "local", - "nonce": 184, - "details": { - "startPoint": 184, - "highest": 184 - } - }, - "network": { - "name": "network", - "nonce": 184, - "details": { - "baseCount": 184 - } - } - } } ], [ @@ -1043,28 +873,6 @@ ] ], "origin": "crypko.ai", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 184, - "highestSuggested": 184, - "nextNetworkNonce": 184 - }, - "local": { - "name": "local", - "nonce": 184, - "details": { - "startPoint": 184, - "highest": 184 - } - }, - "network": { - "name": "network", - "nonce": 184, - "details": { - "baseCount": 184 - } - } - }, "rawTx": "0xf8b181b8843b9aca008306169e94fe2149773b3513703e79ad23d05a778a185016ee870aa87bee538000b844ea94496b000000000000000000000000000000000000000000000000000000000001e1eb000000000000000000000000000000000000000000000000000000000001de332ca07bb2efbb8529d67606f9f89e7934c594a31d50c7d24a3286c20a2944a3b8c2a9a07b55ebd8aa28728ce0e38dd3b3503b78fccedae80053626d8649c68346c7c49c", "hash": "0x466ae7d4b7c270121f0a8d68fbc6c9091ffc4aa976a553a5bfa56a79cf9f63dd", "submittedTime": 1528133227538, @@ -1135,32 +943,6 @@ "value": "0xb9", "note": "transactions#approveTransaction", "timestamp": 1528133293706 - }, - { - "op": "add", - "path": "/nonceDetails", - "value": { - "params": { - "highestLocallyConfirmed": 185, - "highestSuggested": 185, - "nextNetworkNonce": 185 - }, - "local": { - "name": "local", - "nonce": 185, - "details": { - "startPoint": 185, - "highest": 185 - } - }, - "network": { - "name": "network", - "nonce": 185, - "details": { - "baseCount": 185 - } - } - } } ], [ @@ -1225,28 +1007,6 @@ ] ], "origin": "MetaMask", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 185, - "highestSuggested": 185, - "nextNetworkNonce": 185 - }, - "local": { - "name": "local", - "nonce": 185, - "details": { - "startPoint": 185, - "highest": 185 - } - }, - "network": { - "name": "network", - "nonce": 185, - "details": { - "baseCount": 185 - } - } - }, "rawTx": "0xf8a981b9843b9aca0082d50894108cf70c7d384c552f42c07c41c0e1e46d77ea0d80b844a9059cbb00000000000000000000000092e659448c48fc926ec942d0da1459260d36bb3300000000000000000000000000000000000000000000000000000000000000022ca04f05310490d3e3a9a159ae25f52cec9afb0a69527d30be832aaae12e64ff056ea075f81a5220bed481e764bab8830c57169c59fe528ca9cf3442f47f7618a9b4a9", "hash": "0x3680dc9815cd05b620b6dd0017d949604ca7d92f051d5542fc8a5ecaa876af09", "submittedTime": 1528133293859, diff --git a/test/data/mock-state.json b/test/data/mock-state.json index 32730d99e35f..33a4db866132 100644 --- a/test/data/mock-state.json +++ b/test/data/mock-state.json @@ -704,32 +704,6 @@ "value": "0xb5", "note": "transactions#approveTransaction", "timestamp": 1528133131806 - }, - { - "op": "add", - "path": "/nonceDetails", - "value": { - "params": { - "highestLocallyConfirmed": 0, - "highestSuggested": 181, - "nextNetworkNonce": 181 - }, - "local": { - "name": "local", - "nonce": 181, - "details": { - "startPoint": 181, - "highest": 181 - } - }, - "network": { - "name": "network", - "nonce": 181, - "details": { - "baseCount": 181 - } - } - } } ], [ @@ -794,28 +768,6 @@ ] ], "origin": "MetaMask", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 0, - "highestSuggested": 181, - "nextNetworkNonce": 181 - }, - "local": { - "name": "local", - "nonce": 181, - "details": { - "startPoint": 181, - "highest": 181 - } - }, - "network": { - "name": "network", - "nonce": 181, - "details": { - "baseCount": 181 - } - } - }, "rawTx": "0xf86c81b5843b9aca0082cf089492e659448c48fc926ec942d0da1459260d36bb33881bc16d674ec80000802ba03f879cd33a31180da38545d0f809822e00ddf35954d8b0ece83bacf22347ce54a06ad050487978e425ca6a014ed55ea8e9a190069863ed96a0eefa88d729ea1eda", "hash": "0x516b77569173a04c76fdb6545cf279ebd0c75f5d25d6e4ce019925205f0e3709", "submittedTime": 1528133131951, @@ -884,32 +836,6 @@ "value": "0xb6", "note": "transactions#approveTransaction", "timestamp": 1528133151189 - }, - { - "op": "add", - "path": "/nonceDetails", - "value": { - "params": { - "highestLocallyConfirmed": 0, - "highestSuggested": 181, - "nextNetworkNonce": 181 - }, - "local": { - "name": "local", - "nonce": 182, - "details": { - "startPoint": 181, - "highest": 182 - } - }, - "network": { - "name": "network", - "nonce": 181, - "details": { - "baseCount": 181 - } - } - } } ], [ @@ -974,28 +900,6 @@ ] ], "origin": "MetaMask", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 0, - "highestSuggested": 181, - "nextNetworkNonce": 181 - }, - "local": { - "name": "local", - "nonce": 182, - "details": { - "startPoint": 181, - "highest": 182 - } - }, - "network": { - "name": "network", - "nonce": 181, - "details": { - "baseCount": 181 - } - } - }, "rawTx": "0xf86c81b6843b9aca0082cf089492e659448c48fc926ec942d0da1459260d36bb33881bc16d674ec80000802ba0692deaabf0d79544d41e7c475ad43760679a4f25d0fee908b1da308db1a291a7a0384db85fc6c843ea25986a0760f3c50ab6504fc559fc71fc7f23f60950eb316d", "hash": "0x9271b266d05022cfa841362fae43763ebafcee540d84278b0157ef4a68d4e26f", "submittedTime": 1528133151347, @@ -1064,32 +968,6 @@ "value": "0xb7", "note": "transactions#approveTransaction", "timestamp": 1528133181726 - }, - { - "op": "add", - "path": "/nonceDetails", - "value": { - "params": { - "highestLocallyConfirmed": 182, - "highestSuggested": 182, - "nextNetworkNonce": 182 - }, - "local": { - "name": "local", - "nonce": 183, - "details": { - "startPoint": 182, - "highest": 183 - } - }, - "network": { - "name": "network", - "nonce": 182, - "details": { - "baseCount": 182 - } - } - } } ], [ @@ -1154,28 +1032,6 @@ ] ], "origin": "MetaMask", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 182, - "highestSuggested": 182, - "nextNetworkNonce": 182 - }, - "local": { - "name": "local", - "nonce": 183, - "details": { - "startPoint": 182, - "highest": 183 - } - }, - "network": { - "name": "network", - "nonce": 182, - "details": { - "baseCount": 182 - } - } - }, "rawTx": "0xf86d81b785012a05f20082cf089492e659448c48fc926ec942d0da1459260d36bb33881bc16d674ec80000802ba086f9846798be6988c39a5cf85f0dbe267e59ca0b96a6a7077e92cba33e10a258a064ffa52ac90c238ce21e6f085283216191b185a1eccd7daae6e2ab66ba26ada0", "hash": "0x4e061e977c099735bc9e5203e717f7d9dccb3fcb2f82031a12a3ed326f95d43b", "submittedTime": 1528133181885, @@ -1249,32 +1105,6 @@ "value": "0xb8", "note": "transactions#approveTransaction", "timestamp": 1528133227374 - }, - { - "op": "add", - "path": "/nonceDetails", - "value": { - "params": { - "highestLocallyConfirmed": 184, - "highestSuggested": 184, - "nextNetworkNonce": 184 - }, - "local": { - "name": "local", - "nonce": 184, - "details": { - "startPoint": 184, - "highest": 184 - } - }, - "network": { - "name": "network", - "nonce": 184, - "details": { - "baseCount": 184 - } - } - } } ], [ @@ -1339,28 +1169,6 @@ ] ], "origin": "crypko.ai", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 184, - "highestSuggested": 184, - "nextNetworkNonce": 184 - }, - "local": { - "name": "local", - "nonce": 184, - "details": { - "startPoint": 184, - "highest": 184 - } - }, - "network": { - "name": "network", - "nonce": 184, - "details": { - "baseCount": 184 - } - } - }, "rawTx": "0xf8b181b8843b9aca008306169e94fe2149773b3513703e79ad23d05a778a185016ee870aa87bee538000b844ea94496b000000000000000000000000000000000000000000000000000000000001e1eb000000000000000000000000000000000000000000000000000000000001de332ca07bb2efbb8529d67606f9f89e7934c594a31d50c7d24a3286c20a2944a3b8c2a9a07b55ebd8aa28728ce0e38dd3b3503b78fccedae80053626d8649c68346c7c49c", "hash": "0x466ae7d4b7c270121f0a8d68fbc6c9091ffc4aa976a553a5bfa56a79cf9f63dd", "submittedTime": 1528133227538, @@ -1431,32 +1239,6 @@ "value": "0xb9", "note": "transactions#approveTransaction", "timestamp": 1528133293706 - }, - { - "op": "add", - "path": "/nonceDetails", - "value": { - "params": { - "highestLocallyConfirmed": 185, - "highestSuggested": 185, - "nextNetworkNonce": 185 - }, - "local": { - "name": "local", - "nonce": 185, - "details": { - "startPoint": 185, - "highest": 185 - } - }, - "network": { - "name": "network", - "nonce": 185, - "details": { - "baseCount": 185 - } - } - } } ], [ @@ -1521,28 +1303,6 @@ ] ], "origin": "MetaMask", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 185, - "highestSuggested": 185, - "nextNetworkNonce": 185 - }, - "local": { - "name": "local", - "nonce": 185, - "details": { - "startPoint": 185, - "highest": 185 - } - }, - "network": { - "name": "network", - "nonce": 185, - "details": { - "baseCount": 185 - } - } - }, "rawTx": "0xf8a981b9843b9aca0082d50894108cf70c7d384c552f42c07c41c0e1e46d77ea0d80b844a9059cbb00000000000000000000000092e659448c48fc926ec942d0da1459260d36bb3300000000000000000000000000000000000000000000000000000000000000022ca04f05310490d3e3a9a159ae25f52cec9afb0a69527d30be832aaae12e64ff056ea075f81a5220bed481e764bab8830c57169c59fe528ca9cf3442f47f7618a9b4a9", "hash": "0x3680dc9815cd05b620b6dd0017d949604ca7d92f051d5542fc8a5ecaa876af09", "submittedTime": 1528133293859, diff --git a/test/data/mock-tx-history.json b/test/data/mock-tx-history.json index 790dd44fae5d..1291e9fb5b69 100644 --- a/test/data/mock-tx-history.json +++ b/test/data/mock-tx-history.json @@ -79,12 +79,6 @@ "gasPrice": "3b9aca00", "gas": "0x7b0d", "nonce": 0 - }, - "nonceDetails": { - "blockNumber": "0x16643c", - "baseCount": 0, - "baseCountHex": "0x0", - "pendingCount": 0 } }, { @@ -99,12 +93,6 @@ "gasPrice": "3b9aca00", "gas": "0x7b0d", "nonce": 0 - }, - "nonceDetails": { - "blockNumber": "0x16643c", - "baseCount": 0, - "baseCountHex": "0x0", - "pendingCount": 0 } }, { @@ -119,12 +107,6 @@ "gasPrice": "0x3b9aca00", "gas": "0x7b0d", "chainId": 5 - }, - "nonceDetails": { - "blockNumber": "0x16643c", - "baseCount": 0, - "baseCountHex": "0x0", - "pendingCount": 0 } }, { @@ -139,12 +121,6 @@ "gasPrice": "0x3b9aca00", "gas": "0x7b0d", "chainId": 5 - }, - "nonceDetails": { - "blockNumber": "0x16643c", - "baseCount": 0, - "baseCountHex": "0x0", - "pendingCount": 0 } }, { @@ -160,12 +136,6 @@ "gas": "0x7b0d", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16643c", - "baseCount": 0, - "baseCountHex": "0x0", - "pendingCount": 0 - }, "rawTx": "0xf86380843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a02e45f61129f0c97634e37a1823b858df7b0dfc867a44949aae7dd9bcea1c1b5aa03b1f002cda0872d40517d5b26caefa3e407ec8fd03bc7dc2d995b84726961264" }, { @@ -181,12 +151,6 @@ "gas": "0x7b0d", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16643c", - "baseCount": 0, - "baseCountHex": "0x0", - "pendingCount": 0 - }, "rawTx": "0xf86380843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a02e45f61129f0c97634e37a1823b858df7b0dfc867a44949aae7dd9bcea1c1b5aa03b1f002cda0872d40517d5b26caefa3e407ec8fd03bc7dc2d995b84726961264" }, { @@ -202,12 +166,6 @@ "gas": "0x7b0d", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16643c", - "baseCount": 0, - "baseCountHex": "0x0", - "pendingCount": 0 - }, "rawTx": "0xf86380843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a02e45f61129f0c97634e37a1823b858df7b0dfc867a44949aae7dd9bcea1c1b5aa03b1f002cda0872d40517d5b26caefa3e407ec8fd03bc7dc2d995b84726961264", "hash": "0x38c254639139c94303a3141aee041b15301509e743f08569ffac6aca17518012" }, @@ -224,12 +182,6 @@ "gas": "0x7b0d", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16643c", - "baseCount": 0, - "baseCountHex": "0x0", - "pendingCount": 0 - }, "rawTx": "0xf86380843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a02e45f61129f0c97634e37a1823b858df7b0dfc867a44949aae7dd9bcea1c1b5aa03b1f002cda0872d40517d5b26caefa3e407ec8fd03bc7dc2d995b84726961264", "hash": "0x38c254639139c94303a3141aee041b15301509e743f08569ffac6aca17518012" }, @@ -246,12 +198,6 @@ "gas": "0x7b0d", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16643c", - "baseCount": 0, - "baseCountHex": "0x0", - "pendingCount": 0 - }, "rawTx": "0xf86380843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a02e45f61129f0c97634e37a1823b858df7b0dfc867a44949aae7dd9bcea1c1b5aa03b1f002cda0872d40517d5b26caefa3e407ec8fd03bc7dc2d995b84726961264", "hash": "0x38c254639139c94303a3141aee041b15301509e743f08569ffac6aca17518012" }, @@ -268,12 +214,6 @@ "gas": "0x7b0d", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16643c", - "baseCount": 0, - "baseCountHex": "0x0", - "pendingCount": 0 - }, "rawTx": "0xf86380843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a02e45f61129f0c97634e37a1823b858df7b0dfc867a44949aae7dd9bcea1c1b5aa03b1f002cda0872d40517d5b26caefa3e407ec8fd03bc7dc2d995b84726961264", "hash": "0x38c254639139c94303a3141aee041b15301509e743f08569ffac6aca17518012" }, @@ -290,12 +230,6 @@ "gas": "0x7b0d", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16643c", - "baseCount": 0, - "baseCountHex": "0x0", - "pendingCount": 0 - }, "rawTx": "0xf86380843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a02e45f61129f0c97634e37a1823b858df7b0dfc867a44949aae7dd9bcea1c1b5aa03b1f002cda0872d40517d5b26caefa3e407ec8fd03bc7dc2d995b84726961264", "hash": "0x38c254639139c94303a3141aee041b15301509e743f08569ffac6aca17518012", "retryCount": 1 @@ -313,23 +247,11 @@ "gas": "0x7b0d", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16643c", - "baseCount": 0, - "baseCountHex": "0x0", - "pendingCount": 0 - }, "rawTx": "0xf86380843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a02e45f61129f0c97634e37a1823b858df7b0dfc867a44949aae7dd9bcea1c1b5aa03b1f002cda0872d40517d5b26caefa3e407ec8fd03bc7dc2d995b84726961264", "hash": "0x38c254639139c94303a3141aee041b15301509e743f08569ffac6aca17518012", "retryCount": 1 } ], - "nonceDetails": { - "blockNumber": "0x16643c", - "baseCount": 0, - "baseCountHex": "0x0", - "pendingCount": 0 - }, "rawTx": "0xf86380843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a02e45f61129f0c97634e37a1823b858df7b0dfc867a44949aae7dd9bcea1c1b5aa03b1f002cda0872d40517d5b26caefa3e407ec8fd03bc7dc2d995b84726961264", "hash": "0x38c254639139c94303a3141aee041b15301509e743f08569ffac6aca17518012", "retryCount": 1 @@ -454,12 +376,6 @@ "gasPrice": "28fa6ae00", "gas": "0x7b0d", "nonce": 1 - }, - "nonceDetails": { - "blockNumber": "0x168739", - "baseCount": 1, - "baseCountHex": "0x1", - "pendingCount": 0 } }, { @@ -474,12 +390,6 @@ "gasPrice": "28fa6ae00", "gas": "0x7b0d", "nonce": 1 - }, - "nonceDetails": { - "blockNumber": "0x168739", - "baseCount": 1, - "baseCountHex": "0x1", - "pendingCount": 0 } }, { @@ -495,12 +405,6 @@ "gas": "0x7b0d", "nonce": "0x01", "chainId": 5 - }, - "nonceDetails": { - "blockNumber": "0x168739", - "baseCount": 1, - "baseCountHex": "0x1", - "pendingCount": 0 } }, { @@ -516,12 +420,6 @@ "gas": "0x7b0d", "nonce": "0x01", "chainId": 5 - }, - "nonceDetails": { - "blockNumber": "0x168739", - "baseCount": 1, - "baseCountHex": "0x1", - "pendingCount": 0 } }, { @@ -538,12 +436,6 @@ "nonce": "0x01", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x168739", - "baseCount": 1, - "baseCountHex": "0x1", - "pendingCount": 0 - }, "rawTx": "0xf8640185028fa6ae00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a06261831b3d599a90dc24fac67bc648fd58cab2036e4e8dfbbb5c00c3fd9cf66ba00e2ea6ebc63ba715a94dc94e24120639c4ad60832d3285dd558929a61cc18cc0" }, { @@ -560,12 +452,6 @@ "nonce": "0x01", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x168739", - "baseCount": 1, - "baseCountHex": "0x1", - "pendingCount": 0 - }, "rawTx": "0xf8640185028fa6ae00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a06261831b3d599a90dc24fac67bc648fd58cab2036e4e8dfbbb5c00c3fd9cf66ba00e2ea6ebc63ba715a94dc94e24120639c4ad60832d3285dd558929a61cc18cc0" }, { @@ -582,12 +468,6 @@ "nonce": "0x01", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x168739", - "baseCount": 1, - "baseCountHex": "0x1", - "pendingCount": 0 - }, "rawTx": "0xf8640185028fa6ae00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a06261831b3d599a90dc24fac67bc648fd58cab2036e4e8dfbbb5c00c3fd9cf66ba00e2ea6ebc63ba715a94dc94e24120639c4ad60832d3285dd558929a61cc18cc0", "hash": "0xeb1c57dec9df8410bcc65374c7f684fc8ebfcda6865a149e38bb000fa706a150" }, @@ -605,12 +485,6 @@ "nonce": "0x01", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x168739", - "baseCount": 1, - "baseCountHex": "0x1", - "pendingCount": 0 - }, "rawTx": "0xf8640185028fa6ae00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a06261831b3d599a90dc24fac67bc648fd58cab2036e4e8dfbbb5c00c3fd9cf66ba00e2ea6ebc63ba715a94dc94e24120639c4ad60832d3285dd558929a61cc18cc0", "hash": "0xeb1c57dec9df8410bcc65374c7f684fc8ebfcda6865a149e38bb000fa706a150" }, @@ -628,12 +502,6 @@ "nonce": "0x01", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x168739", - "baseCount": 1, - "baseCountHex": "0x1", - "pendingCount": 0 - }, "rawTx": "0xf8640185028fa6ae00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a06261831b3d599a90dc24fac67bc648fd58cab2036e4e8dfbbb5c00c3fd9cf66ba00e2ea6ebc63ba715a94dc94e24120639c4ad60832d3285dd558929a61cc18cc0", "hash": "0xeb1c57dec9df8410bcc65374c7f684fc8ebfcda6865a149e38bb000fa706a150" }, @@ -651,12 +519,6 @@ "nonce": "0x01", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x168739", - "baseCount": 1, - "baseCountHex": "0x1", - "pendingCount": 0 - }, "rawTx": "0xf8640185028fa6ae00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a06261831b3d599a90dc24fac67bc648fd58cab2036e4e8dfbbb5c00c3fd9cf66ba00e2ea6ebc63ba715a94dc94e24120639c4ad60832d3285dd558929a61cc18cc0", "hash": "0xeb1c57dec9df8410bcc65374c7f684fc8ebfcda6865a149e38bb000fa706a150" }, @@ -674,12 +536,6 @@ "nonce": "0x01", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x168739", - "baseCount": 1, - "baseCountHex": "0x1", - "pendingCount": 0 - }, "rawTx": "0xf8640185028fa6ae00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a06261831b3d599a90dc24fac67bc648fd58cab2036e4e8dfbbb5c00c3fd9cf66ba00e2ea6ebc63ba715a94dc94e24120639c4ad60832d3285dd558929a61cc18cc0", "hash": "0xeb1c57dec9df8410bcc65374c7f684fc8ebfcda6865a149e38bb000fa706a150", "retryCount": 1 @@ -698,23 +554,11 @@ "nonce": "0x01", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x168739", - "baseCount": 1, - "baseCountHex": "0x1", - "pendingCount": 0 - }, "rawTx": "0xf8640185028fa6ae00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a06261831b3d599a90dc24fac67bc648fd58cab2036e4e8dfbbb5c00c3fd9cf66ba00e2ea6ebc63ba715a94dc94e24120639c4ad60832d3285dd558929a61cc18cc0", "hash": "0xeb1c57dec9df8410bcc65374c7f684fc8ebfcda6865a149e38bb000fa706a150", "retryCount": 1 } ], - "nonceDetails": { - "blockNumber": "0x168739", - "baseCount": 1, - "baseCountHex": "0x1", - "pendingCount": 0 - }, "rawTx": "0xf8640185028fa6ae00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a06261831b3d599a90dc24fac67bc648fd58cab2036e4e8dfbbb5c00c3fd9cf66ba00e2ea6ebc63ba715a94dc94e24120639c4ad60832d3285dd558929a61cc18cc0", "hash": "0xeb1c57dec9df8410bcc65374c7f684fc8ebfcda6865a149e38bb000fa706a150", "retryCount": 1 @@ -798,12 +642,6 @@ "gasPrice": "4a817c800", "gas": "0x7b0d", "nonce": 2 - }, - "nonceDetails": { - "blockNumber": "0x16b066", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 0 } }, { @@ -818,12 +656,6 @@ "gasPrice": "4a817c800", "gas": "0x7b0d", "nonce": 2 - }, - "nonceDetails": { - "blockNumber": "0x16b066", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 0 } }, { @@ -839,12 +671,6 @@ "gas": "0x7b0d", "nonce": "0x02", "chainId": 5 - }, - "nonceDetails": { - "blockNumber": "0x16b066", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 0 } }, { @@ -860,12 +686,6 @@ "gas": "0x7b0d", "nonce": "0x02", "chainId": 5 - }, - "nonceDetails": { - "blockNumber": "0x16b066", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 0 } }, { @@ -882,12 +702,6 @@ "nonce": "0x02", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b066", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 0 - }, "rawTx": "0xf864028504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa057380f9007a48d4bce31792859b1a25cb2b45ba615e7951d8e8a925360a0b301a042393e72d1a96a2605c0da95705c5f3f7c744f0affcac01e0a64721037f04adc" }, { @@ -904,12 +718,6 @@ "nonce": "0x02", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b066", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 0 - }, "rawTx": "0xf864028504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa057380f9007a48d4bce31792859b1a25cb2b45ba615e7951d8e8a925360a0b301a042393e72d1a96a2605c0da95705c5f3f7c744f0affcac01e0a64721037f04adc" }, { @@ -926,12 +734,6 @@ "nonce": "0x02", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b066", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 0 - }, "rawTx": "0xf864028504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa057380f9007a48d4bce31792859b1a25cb2b45ba615e7951d8e8a925360a0b301a042393e72d1a96a2605c0da95705c5f3f7c744f0affcac01e0a64721037f04adc", "hash": "0xc28ceb1e2c4e5c61b805b181e3cc99dd7bade58935233fab76c63cedfd494270" }, @@ -949,12 +751,6 @@ "nonce": "0x02", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b066", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 0 - }, "rawTx": "0xf864028504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa057380f9007a48d4bce31792859b1a25cb2b45ba615e7951d8e8a925360a0b301a042393e72d1a96a2605c0da95705c5f3f7c744f0affcac01e0a64721037f04adc", "hash": "0xc28ceb1e2c4e5c61b805b181e3cc99dd7bade58935233fab76c63cedfd494270" }, @@ -972,12 +768,6 @@ "nonce": "0x02", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b066", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 0 - }, "rawTx": "0xf864028504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa057380f9007a48d4bce31792859b1a25cb2b45ba615e7951d8e8a925360a0b301a042393e72d1a96a2605c0da95705c5f3f7c744f0affcac01e0a64721037f04adc", "hash": "0xc28ceb1e2c4e5c61b805b181e3cc99dd7bade58935233fab76c63cedfd494270" }, @@ -995,12 +785,6 @@ "nonce": "0x02", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b066", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 0 - }, "rawTx": "0xf864028504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa057380f9007a48d4bce31792859b1a25cb2b45ba615e7951d8e8a925360a0b301a042393e72d1a96a2605c0da95705c5f3f7c744f0affcac01e0a64721037f04adc", "hash": "0xc28ceb1e2c4e5c61b805b181e3cc99dd7bade58935233fab76c63cedfd494270" }, @@ -1018,12 +802,6 @@ "nonce": "0x02", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b066", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 0 - }, "rawTx": "0xf864028504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa057380f9007a48d4bce31792859b1a25cb2b45ba615e7951d8e8a925360a0b301a042393e72d1a96a2605c0da95705c5f3f7c744f0affcac01e0a64721037f04adc", "hash": "0xc28ceb1e2c4e5c61b805b181e3cc99dd7bade58935233fab76c63cedfd494270", "retryCount": 1 @@ -1042,23 +820,11 @@ "nonce": "0x02", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b066", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 0 - }, "rawTx": "0xf864028504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa057380f9007a48d4bce31792859b1a25cb2b45ba615e7951d8e8a925360a0b301a042393e72d1a96a2605c0da95705c5f3f7c744f0affcac01e0a64721037f04adc", "hash": "0xc28ceb1e2c4e5c61b805b181e3cc99dd7bade58935233fab76c63cedfd494270", "retryCount": 1 } ], - "nonceDetails": { - "blockNumber": "0x16b066", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 0 - }, "rawTx": "0xf864028504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa057380f9007a48d4bce31792859b1a25cb2b45ba615e7951d8e8a925360a0b301a042393e72d1a96a2605c0da95705c5f3f7c744f0affcac01e0a64721037f04adc", "hash": "0xc28ceb1e2c4e5c61b805b181e3cc99dd7bade58935233fab76c63cedfd494270", "retryCount": 1 @@ -1142,12 +908,6 @@ "gasPrice": "0x3b9aca00", "gas": "0x7b0d", "nonce": 3 - }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 1 } }, { @@ -1162,12 +922,6 @@ "gasPrice": "0x3b9aca00", "gas": "0x7b0d", "nonce": 3 - }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 1 } }, { @@ -1183,12 +937,6 @@ "gas": "0x7b0d", "nonce": "0x03", "chainId": 5 - }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 1 } }, { @@ -1204,12 +952,6 @@ "gas": "0x7b0d", "nonce": "0x03", "chainId": 5 - }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 1 } }, { @@ -1226,12 +968,6 @@ "nonce": "0x03", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 1 - }, "rawTx": "0xf86303843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa0e442afe9386066936f556d852a296d22b8392652aa2ddb26969d83d661759ee1a06dc55b164f666a37107e86d575d2701602fc100f0ef4875736d45995150d4897" }, { @@ -1248,12 +984,6 @@ "nonce": "0x03", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 1 - }, "rawTx": "0xf86303843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa0e442afe9386066936f556d852a296d22b8392652aa2ddb26969d83d661759ee1a06dc55b164f666a37107e86d575d2701602fc100f0ef4875736d45995150d4897" }, { @@ -1270,12 +1000,6 @@ "nonce": "0x03", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 1 - }, "rawTx": "0xf86303843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa0e442afe9386066936f556d852a296d22b8392652aa2ddb26969d83d661759ee1a06dc55b164f666a37107e86d575d2701602fc100f0ef4875736d45995150d4897", "hash": "0xfcc66b8002c64a5aaa076adea7f7e48d194de10e40eb64924c8de344805c8cb7" }, @@ -1293,12 +1017,6 @@ "nonce": "0x03", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 1 - }, "rawTx": "0xf86303843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa0e442afe9386066936f556d852a296d22b8392652aa2ddb26969d83d661759ee1a06dc55b164f666a37107e86d575d2701602fc100f0ef4875736d45995150d4897", "hash": "0xfcc66b8002c64a5aaa076adea7f7e48d194de10e40eb64924c8de344805c8cb7" }, @@ -1316,12 +1034,6 @@ "nonce": "0x03", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 1 - }, "rawTx": "0xf86303843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa0e442afe9386066936f556d852a296d22b8392652aa2ddb26969d83d661759ee1a06dc55b164f666a37107e86d575d2701602fc100f0ef4875736d45995150d4897", "hash": "0xfcc66b8002c64a5aaa076adea7f7e48d194de10e40eb64924c8de344805c8cb7" }, @@ -1339,12 +1051,6 @@ "nonce": "0x03", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 1 - }, "rawTx": "0xf86303843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa0e442afe9386066936f556d852a296d22b8392652aa2ddb26969d83d661759ee1a06dc55b164f666a37107e86d575d2701602fc100f0ef4875736d45995150d4897", "hash": "0xfcc66b8002c64a5aaa076adea7f7e48d194de10e40eb64924c8de344805c8cb7" }, @@ -1362,12 +1068,6 @@ "nonce": "0x03", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 1 - }, "rawTx": "0xf86303843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa0e442afe9386066936f556d852a296d22b8392652aa2ddb26969d83d661759ee1a06dc55b164f666a37107e86d575d2701602fc100f0ef4875736d45995150d4897", "hash": "0xfcc66b8002c64a5aaa076adea7f7e48d194de10e40eb64924c8de344805c8cb7", "retryCount": 2 @@ -1386,23 +1086,11 @@ "nonce": "0x03", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 1 - }, "rawTx": "0xf86303843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa0e442afe9386066936f556d852a296d22b8392652aa2ddb26969d83d661759ee1a06dc55b164f666a37107e86d575d2701602fc100f0ef4875736d45995150d4897", "hash": "0xfcc66b8002c64a5aaa076adea7f7e48d194de10e40eb64924c8de344805c8cb7", "retryCount": 2 } ], - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 1 - }, "rawTx": "0xf86303843b9aca00827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c80802aa0e442afe9386066936f556d852a296d22b8392652aa2ddb26969d83d661759ee1a06dc55b164f666a37107e86d575d2701602fc100f0ef4875736d45995150d4897", "hash": "0xfcc66b8002c64a5aaa076adea7f7e48d194de10e40eb64924c8de344805c8cb7", "retryCount": 2 @@ -1486,12 +1174,6 @@ "gasPrice": "4a817c800", "gas": "0x7b0d", "nonce": 4 - }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 2 } }, { @@ -1506,12 +1188,6 @@ "gasPrice": "4a817c800", "gas": "0x7b0d", "nonce": 4 - }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 2 } }, { @@ -1527,12 +1203,6 @@ "gas": "0x7b0d", "nonce": "0x04", "chainId": 5 - }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 2 } }, { @@ -1548,12 +1218,6 @@ "gas": "0x7b0d", "nonce": "0x04", "chainId": 5 - }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 2 } }, { @@ -1570,12 +1234,6 @@ "nonce": "0x04", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 2 - }, "rawTx": "0xf864048504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a04be1c01535745fa7ec7aeb6e0b64d009981713808ca443b181fad802ce941352a03887e90375d9225b8dfd0d42324eed8eb4982fd14ea7b4069290237b29d1dcd3" }, { @@ -1592,12 +1250,6 @@ "nonce": "0x04", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 2 - }, "rawTx": "0xf864048504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a04be1c01535745fa7ec7aeb6e0b64d009981713808ca443b181fad802ce941352a03887e90375d9225b8dfd0d42324eed8eb4982fd14ea7b4069290237b29d1dcd3" }, { @@ -1614,12 +1266,6 @@ "nonce": "0x04", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 2 - }, "rawTx": "0xf864048504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a04be1c01535745fa7ec7aeb6e0b64d009981713808ca443b181fad802ce941352a03887e90375d9225b8dfd0d42324eed8eb4982fd14ea7b4069290237b29d1dcd3", "hash": "0x9258ed7e451402612f572cbef52b63cd63cc2c59f443a207b7b4f8d317958635" }, @@ -1637,12 +1283,6 @@ "nonce": "0x04", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 2 - }, "rawTx": "0xf864048504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a04be1c01535745fa7ec7aeb6e0b64d009981713808ca443b181fad802ce941352a03887e90375d9225b8dfd0d42324eed8eb4982fd14ea7b4069290237b29d1dcd3", "hash": "0x9258ed7e451402612f572cbef52b63cd63cc2c59f443a207b7b4f8d317958635" }, @@ -1660,12 +1300,6 @@ "nonce": "0x04", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 2 - }, "rawTx": "0xf864048504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a04be1c01535745fa7ec7aeb6e0b64d009981713808ca443b181fad802ce941352a03887e90375d9225b8dfd0d42324eed8eb4982fd14ea7b4069290237b29d1dcd3", "hash": "0x9258ed7e451402612f572cbef52b63cd63cc2c59f443a207b7b4f8d317958635" }, @@ -1683,12 +1317,6 @@ "nonce": "0x04", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 2 - }, "rawTx": "0xf864048504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a04be1c01535745fa7ec7aeb6e0b64d009981713808ca443b181fad802ce941352a03887e90375d9225b8dfd0d42324eed8eb4982fd14ea7b4069290237b29d1dcd3", "hash": "0x9258ed7e451402612f572cbef52b63cd63cc2c59f443a207b7b4f8d317958635" }, @@ -1706,12 +1334,6 @@ "nonce": "0x04", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 2 - }, "rawTx": "0xf864048504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a04be1c01535745fa7ec7aeb6e0b64d009981713808ca443b181fad802ce941352a03887e90375d9225b8dfd0d42324eed8eb4982fd14ea7b4069290237b29d1dcd3", "hash": "0x9258ed7e451402612f572cbef52b63cd63cc2c59f443a207b7b4f8d317958635", "retryCount": 4 @@ -1730,23 +1352,11 @@ "nonce": "0x04", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 2 - }, "rawTx": "0xf864048504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a04be1c01535745fa7ec7aeb6e0b64d009981713808ca443b181fad802ce941352a03887e90375d9225b8dfd0d42324eed8eb4982fd14ea7b4069290237b29d1dcd3", "hash": "0x9258ed7e451402612f572cbef52b63cd63cc2c59f443a207b7b4f8d317958635", "retryCount": 4 } ], - "nonceDetails": { - "blockNumber": "0x16b067", - "baseCount": 2, - "baseCountHex": "0x2", - "pendingCount": 2 - }, "rawTx": "0xf864048504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a04be1c01535745fa7ec7aeb6e0b64d009981713808ca443b181fad802ce941352a03887e90375d9225b8dfd0d42324eed8eb4982fd14ea7b4069290237b29d1dcd3", "hash": "0x9258ed7e451402612f572cbef52b63cd63cc2c59f443a207b7b4f8d317958635", "retryCount": 4 @@ -1830,12 +1440,6 @@ "gasPrice": "4a817c800", "gas": "0x7b0d", "nonce": 5 - }, - "nonceDetails": { - "blockNumber": "0x16b068", - "baseCount": 3, - "baseCountHex": "0x3", - "pendingCount": 2 } }, { @@ -1850,12 +1454,6 @@ "gasPrice": "4a817c800", "gas": "0x7b0d", "nonce": 5 - }, - "nonceDetails": { - "blockNumber": "0x16b068", - "baseCount": 3, - "baseCountHex": "0x3", - "pendingCount": 2 } }, { @@ -1871,12 +1469,6 @@ "gas": "0x7b0d", "nonce": "0x05", "chainId": 5 - }, - "nonceDetails": { - "blockNumber": "0x16b068", - "baseCount": 3, - "baseCountHex": "0x3", - "pendingCount": 2 } }, { @@ -1892,12 +1484,6 @@ "gas": "0x7b0d", "nonce": "0x05", "chainId": 5 - }, - "nonceDetails": { - "blockNumber": "0x16b068", - "baseCount": 3, - "baseCountHex": "0x3", - "pendingCount": 2 } }, { @@ -1914,12 +1500,6 @@ "nonce": "0x05", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b068", - "baseCount": 3, - "baseCountHex": "0x3", - "pendingCount": 2 - }, "rawTx": "0xf864058504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a0dac4756e84c008714b3b8b43807157ed63737450780bc57590e930c8a360750ca00b43ac8ec5235f57ccca7e68ce8fbf77f43d6ffa5fbff296cba66cef47889cf5" }, { @@ -1936,12 +1516,6 @@ "nonce": "0x05", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b068", - "baseCount": 3, - "baseCountHex": "0x3", - "pendingCount": 2 - }, "rawTx": "0xf864058504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a0dac4756e84c008714b3b8b43807157ed63737450780bc57590e930c8a360750ca00b43ac8ec5235f57ccca7e68ce8fbf77f43d6ffa5fbff296cba66cef47889cf5" }, { @@ -1958,12 +1532,6 @@ "nonce": "0x05", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b068", - "baseCount": 3, - "baseCountHex": "0x3", - "pendingCount": 2 - }, "rawTx": "0xf864058504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a0dac4756e84c008714b3b8b43807157ed63737450780bc57590e930c8a360750ca00b43ac8ec5235f57ccca7e68ce8fbf77f43d6ffa5fbff296cba66cef47889cf5", "hash": "0x67cdff49c1f8ed506c759fc8fd7ffe93d59fcb3bfd926b964cad47e2e504dc9e" }, @@ -1981,12 +1549,6 @@ "nonce": "0x05", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b068", - "baseCount": 3, - "baseCountHex": "0x3", - "pendingCount": 2 - }, "rawTx": "0xf864058504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a0dac4756e84c008714b3b8b43807157ed63737450780bc57590e930c8a360750ca00b43ac8ec5235f57ccca7e68ce8fbf77f43d6ffa5fbff296cba66cef47889cf5", "hash": "0x67cdff49c1f8ed506c759fc8fd7ffe93d59fcb3bfd926b964cad47e2e504dc9e" }, @@ -2004,12 +1566,6 @@ "nonce": "0x05", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b068", - "baseCount": 3, - "baseCountHex": "0x3", - "pendingCount": 2 - }, "rawTx": "0xf864058504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a0dac4756e84c008714b3b8b43807157ed63737450780bc57590e930c8a360750ca00b43ac8ec5235f57ccca7e68ce8fbf77f43d6ffa5fbff296cba66cef47889cf5", "hash": "0x67cdff49c1f8ed506c759fc8fd7ffe93d59fcb3bfd926b964cad47e2e504dc9e" }, @@ -2027,12 +1583,6 @@ "nonce": "0x05", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b068", - "baseCount": 3, - "baseCountHex": "0x3", - "pendingCount": 2 - }, "rawTx": "0xf864058504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a0dac4756e84c008714b3b8b43807157ed63737450780bc57590e930c8a360750ca00b43ac8ec5235f57ccca7e68ce8fbf77f43d6ffa5fbff296cba66cef47889cf5", "hash": "0x67cdff49c1f8ed506c759fc8fd7ffe93d59fcb3bfd926b964cad47e2e504dc9e" }, @@ -2050,12 +1600,6 @@ "nonce": "0x05", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b068", - "baseCount": 3, - "baseCountHex": "0x3", - "pendingCount": 2 - }, "rawTx": "0xf864058504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a0dac4756e84c008714b3b8b43807157ed63737450780bc57590e930c8a360750ca00b43ac8ec5235f57ccca7e68ce8fbf77f43d6ffa5fbff296cba66cef47889cf5", "hash": "0x67cdff49c1f8ed506c759fc8fd7ffe93d59fcb3bfd926b964cad47e2e504dc9e", "retryCount": 3 @@ -2074,23 +1618,11 @@ "nonce": "0x05", "chainId": 5 }, - "nonceDetails": { - "blockNumber": "0x16b068", - "baseCount": 3, - "baseCountHex": "0x3", - "pendingCount": 2 - }, "rawTx": "0xf864058504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a0dac4756e84c008714b3b8b43807157ed63737450780bc57590e930c8a360750ca00b43ac8ec5235f57ccca7e68ce8fbf77f43d6ffa5fbff296cba66cef47889cf5", "hash": "0x67cdff49c1f8ed506c759fc8fd7ffe93d59fcb3bfd926b964cad47e2e504dc9e", "retryCount": 3 } ], - "nonceDetails": { - "blockNumber": "0x16b068", - "baseCount": 3, - "baseCountHex": "0x3", - "pendingCount": 2 - }, "rawTx": "0xf864058504a817c800827b0d943ae39e89dc7e736cce53091057a45bf44b1a566c808029a0dac4756e84c008714b3b8b43807157ed63737450780bc57590e930c8a360750ca00b43ac8ec5235f57ccca7e68ce8fbf77f43d6ffa5fbff296cba66cef47889cf5", "hash": "0x67cdff49c1f8ed506c759fc8fd7ffe93d59fcb3bfd926b964cad47e2e504dc9e", "retryCount": 3 diff --git a/test/data/transaction-data.json b/test/data/transaction-data.json index c9f367aa3878..e9189cf15f6b 100644 --- a/test/data/transaction-data.json +++ b/test/data/transaction-data.json @@ -17,29 +17,6 @@ }, "origin": "metamask", "type": "simpleSend", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 12, - "highestSuggested": 12, - "nextNetworkNonce": 12 - }, - "local": { - "name": "local", - "nonce": 12, - "details": { - "startPoint": 12, - "highest": 12 - } - }, - "network": { - "name": "network", - "nonce": 12, - "details": { - "blockNumber": "0x62d5dc", - "baseCount": 12 - } - } - }, "r": "0xe0b79a8e33b15460ea79b05a5fb16bc067a796592eeb4edc5007c88615c12595", "s": "0x1c834a25f1df07af5122996a40e99e554a40dc971a25041bc6e31638846c4f58", "v": "0x2c", @@ -78,29 +55,6 @@ }, "origin": "metamask", "type": "sentEther", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 12, - "highestSuggested": 12, - "nextNetworkNonce": 12 - }, - "local": { - "name": "local", - "nonce": 12, - "details": { - "startPoint": 12, - "highest": 12 - } - }, - "network": { - "name": "network", - "nonce": 12, - "details": { - "blockNumber": "0x62d5dc", - "baseCount": 12 - } - } - }, "r": "0xe0b79a8e33b15460ea79b05a5fb16bc067a796592eeb4edc5007c88615c12595", "s": "0x1c834a25f1df07af5122996a40e99e554a40dc971a25041bc6e31638846c4f58", "v": "0x2c", @@ -139,29 +93,6 @@ }, "origin": "metamask", "type": "simpleSend", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 12, - "highestSuggested": 12, - "nextNetworkNonce": 12 - }, - "local": { - "name": "local", - "nonce": 12, - "details": { - "startPoint": 12, - "highest": 12 - } - }, - "network": { - "name": "network", - "nonce": 12, - "details": { - "blockNumber": "0x62d5dc", - "baseCount": 12 - } - } - }, "r": "0xe0b79a8e33b15460ea79b05a5fb16bc067a796592eeb4edc5007c88615c12595", "s": "0x1c834a25f1df07af5122996a40e99e554a40dc971a25041bc6e31638846c4f58", "v": "0x2c", @@ -204,29 +135,6 @@ }, "origin": "metamask", "type": "simpleSend", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 0, - "highestSuggested": 10, - "nextNetworkNonce": 10 - }, - "local": { - "name": "local", - "nonce": 11, - "details": { - "startPoint": 10, - "highest": 11 - } - }, - "network": { - "name": "network", - "nonce": 10, - "details": { - "blockNumber": "0x62d5cc", - "baseCount": 10 - } - } - }, "r": "0xe6828baea0a93a52779ffa5ea55e927781fb7d4be58107a29c75d314d433d055", "s": "0x10613f984c57b8928d8ed9fce16ddda5746767e5f68f4c8fc29542e86a61f458", "v": "0x2b", @@ -265,29 +173,6 @@ }, "origin": "metamask", "type": "sentEther", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 0, - "highestSuggested": 10, - "nextNetworkNonce": 10 - }, - "local": { - "name": "local", - "nonce": 11, - "details": { - "startPoint": 10, - "highest": 11 - } - }, - "network": { - "name": "network", - "nonce": 10, - "details": { - "blockNumber": "0x62d5cc", - "baseCount": 10 - } - } - }, "r": "0xe6828baea0a93a52779ffa5ea55e927781fb7d4be58107a29c75d314d433d055", "s": "0x10613f984c57b8928d8ed9fce16ddda5746767e5f68f4c8fc29542e86a61f458", "v": "0x2b", @@ -326,29 +211,6 @@ }, "origin": "metamask", "type": "simpleSend", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 0, - "highestSuggested": 10, - "nextNetworkNonce": 10 - }, - "local": { - "name": "local", - "nonce": 11, - "details": { - "startPoint": 10, - "highest": 11 - } - }, - "network": { - "name": "network", - "nonce": 10, - "details": { - "blockNumber": "0x62d5cc", - "baseCount": 10 - } - } - }, "r": "0xe6828baea0a93a52779ffa5ea55e927781fb7d4be58107a29c75d314d433d055", "s": "0x10613f984c57b8928d8ed9fce16ddda5746767e5f68f4c8fc29542e86a61f458", "v": "0x2b", @@ -391,29 +253,6 @@ }, "origin": "metamask", "type": "simpleSend", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 0, - "highestSuggested": 10, - "nextNetworkNonce": 10 - }, - "local": { - "name": "local", - "nonce": 10, - "details": { - "startPoint": 10, - "highest": 10 - } - }, - "network": { - "name": "network", - "nonce": 10, - "details": { - "blockNumber": "0x62d5cb", - "baseCount": 10 - } - } - }, "r": "0x94b120a1df80be3dfad057b7ccac866b6b7583b63d61e5b021811c8b7ffc9a3b", "s": "0x1778de08e29a4c8dfc3aa3e2c2338e98494ebd2c380c901d0dfba95126dde65f", "v": "0x2c", @@ -453,29 +292,6 @@ }, "origin": "metamask", "type": "sentEther", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 0, - "highestSuggested": 10, - "nextNetworkNonce": 10 - }, - "local": { - "name": "local", - "nonce": 10, - "details": { - "startPoint": 10, - "highest": 10 - } - }, - "network": { - "name": "network", - "nonce": 10, - "details": { - "blockNumber": "0x62d5cb", - "baseCount": 10 - } - } - }, "r": "0x94b120a1df80be3dfad057b7ccac866b6b7583b63d61e5b021811c8b7ffc9a3b", "s": "0x1778de08e29a4c8dfc3aa3e2c2338e98494ebd2c380c901d0dfba95126dde65f", "v": "0x2c", @@ -515,29 +331,6 @@ }, "origin": "metamask", "type": "simpleSend", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 0, - "highestSuggested": 10, - "nextNetworkNonce": 10 - }, - "local": { - "name": "local", - "nonce": 10, - "details": { - "startPoint": 10, - "highest": 10 - } - }, - "network": { - "name": "network", - "nonce": 10, - "details": { - "blockNumber": "0x62d5cb", - "baseCount": 10 - } - } - }, "r": "0x94b120a1df80be3dfad057b7ccac866b6b7583b63d61e5b021811c8b7ffc9a3b", "s": "0x1778de08e29a4c8dfc3aa3e2c2338e98494ebd2c380c901d0dfba95126dde65f", "v": "0x2c", @@ -894,29 +687,6 @@ "maxPriorityFeePerGas": "0x3B9ACA00" }, "estimatedBaseFee": "3ba182755", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 87, - "highestSuggested": 87, - "nextNetworkNonce": 87 - }, - "local": { - "name": "local", - "nonce": 87, - "details": { - "startPoint": 87, - "highest": 87 - } - }, - "network": { - "name": "network", - "nonce": 87, - "details": { - "blockNumber": "0xa28e38", - "baseCount": 87 - } - } - }, "r": "0xd13310569a8d5876e37788183034bfe4bc3b49c0663c5fd9b2bf13adf9b4791c", "s": "0x7a83d8840e7edcdf4fdedfd2bc1ce19775e54fd17f29ede5165591a1cf3febea", "v": "0x00", @@ -1010,29 +780,6 @@ "maxPriorityFeePerGas": "0x3B9ACA00" }, "estimatedBaseFee": "3ba182755", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 87, - "highestSuggested": 87, - "nextNetworkNonce": 87 - }, - "local": { - "name": "local", - "nonce": 87, - "details": { - "startPoint": 87, - "highest": 87 - } - }, - "network": { - "name": "network", - "nonce": 87, - "details": { - "blockNumber": "0xa28e38", - "baseCount": 87 - } - } - }, "r": "0xd13310569a8d5876e37788183034bfe4bc3b49c0663c5fd9b2bf13adf9b4791c", "s": "0x7a83d8840e7edcdf4fdedfd2bc1ce19775e54fd17f29ede5165591a1cf3febea", "v": "0x00", @@ -1125,29 +872,6 @@ "maxPriorityFeePerGas": "0x3B9ACA00" }, "estimatedBaseFee": "3ba182755", - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 87, - "highestSuggested": 87, - "nextNetworkNonce": 87 - }, - "local": { - "name": "local", - "nonce": 87, - "details": { - "startPoint": 87, - "highest": 87 - } - }, - "network": { - "name": "network", - "nonce": 87, - "details": { - "blockNumber": "0xa28e38", - "baseCount": 87 - } - } - }, "r": "0xd13310569a8d5876e37788183034bfe4bc3b49c0663c5fd9b2bf13adf9b4791c", "s": "0x7a83d8840e7edcdf4fdedfd2bc1ce19775e54fd17f29ede5165591a1cf3febea", "v": "0x00", diff --git a/test/e2e/fixture-builder.js b/test/e2e/fixture-builder.js index 24dc9bf9730a..61db5bfc3e2e 100644 --- a/test/e2e/fixture-builder.js +++ b/test/e2e/fixture-builder.js @@ -1171,33 +1171,6 @@ class FixtureBuilder { note: 'transactions#approveTransaction', timestamp: 1617228031069, }, - { - op: 'add', - path: '/nonceDetails', - value: { - params: { - highestLocallyConfirmed: 0, - highestSuggested: 0, - nextNetworkNonce: 0, - }, - local: { - name: 'local', - nonce: 0, - details: { - startPoint: 0, - highest: 0, - }, - }, - network: { - name: 'network', - nonce: 0, - details: { - blockNumber: '0x0', - baseCount: 0, - }, - }, - }, - }, ], ], id: 4046084157914634, @@ -1300,33 +1273,6 @@ class FixtureBuilder { timestamp: 1671635510592, value: '0x2', }, - { - op: 'add', - path: '/nonceDetails', - value: { - local: { - details: { - highest: 2, - startPoint: 2, - }, - name: 'local', - nonce: 2, - }, - network: { - details: { - baseCount: 2, - blockNumber: '0x7cbf93', - }, - name: 'network', - nonce: 2, - }, - params: { - highestLocallyConfirmed: 0, - highestSuggested: 2, - nextNetworkNonce: 2, - }, - }, - }, ], [ { @@ -1390,29 +1336,6 @@ class FixtureBuilder { id: 5748272735958801, loadingDefaults: false, metamaskNetworkId: '5', - nonceDetails: { - local: { - details: { - highest: 2, - startPoint: 2, - }, - name: 'local', - nonce: 2, - }, - network: { - details: { - baseCount: 2, - blockNumber: '0x7cbf93', - }, - name: 'network', - nonce: 2, - }, - params: { - highestLocallyConfirmed: 0, - highestSuggested: 2, - nextNetworkNonce: 2, - }, - }, origin: 'metamask', status: 'confirmed', submittedTime: 1671635510753, diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index eb9c0efb4b4b..194bdaaf4971 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -3,6 +3,7 @@ const path = require('path'); const { promises: fs } = require('fs'); const BigNumber = require('bignumber.js'); const mockttp = require('mockttp'); +const detectPort = require('detect-port'); const createStaticServer = require('../../development/create-static-server'); const { tEn } = require('../lib/i18n-helpers'); const { setupMocking } = require('./mock-e2e'); @@ -108,6 +109,11 @@ async function withFixtures(options, testSuite) { const mockedEndpoint = await setupMocking(mockServer, testSpecificMock, { chainId: ganacheOptions?.chainId || 1337, }); + if ((await detectPort(8000)) !== 8000) { + throw new Error( + 'Failed to set up mock server, something else may be running on port 8000.', + ); + } await mockServer.start(8000); driver = (await buildWebDriver(driverOptions)).driver; diff --git a/test/e2e/tests/ipfs-toggle.spec.js b/test/e2e/tests/ipfs-toggle.spec.js index 149442b4ce91..74cfa4fb6122 100644 --- a/test/e2e/tests/ipfs-toggle.spec.js +++ b/test/e2e/tests/ipfs-toggle.spec.js @@ -57,7 +57,9 @@ describe('Settings', function () { tag: 'button', }); // should render image now - const nftImage = await driver.findElement('[data-testid="nft-image"]'); + const nftImage = await driver.findVisibleElement( + '[data-testid="nft-image"]', + ); assert.equal(await nftImage.isDisplayed(), true); }, ); diff --git a/test/e2e/tests/state-snapshots/errors-after-init-opt-in-background-state.json b/test/e2e/tests/state-snapshots/errors-after-init-opt-in-background-state.json index a522a1b11f93..f5a380e7413c 100644 --- a/test/e2e/tests/state-snapshots/errors-after-init-opt-in-background-state.json +++ b/test/e2e/tests/state-snapshots/errors-after-init-opt-in-background-state.json @@ -153,6 +153,10 @@ "isLineaMainnetReleased": true, "selectedAddress": "string" }, + "SelectedNetworkController": { + "domains": {}, + "perDomainNetwork": "boolean" + }, "SignatureController": { "unapprovedMsgs": "object", "unapprovedPersonalMsgs": "object", diff --git a/test/e2e/tests/state-snapshots/errors-after-init-opt-in-ui-state.json b/test/e2e/tests/state-snapshots/errors-after-init-opt-in-ui-state.json index aad4be321658..28486f27ec15 100644 --- a/test/e2e/tests/state-snapshots/errors-after-init-opt-in-ui-state.json +++ b/test/e2e/tests/state-snapshots/errors-after-init-opt-in-ui-state.json @@ -144,6 +144,8 @@ "allNftContracts": "object", "allNfts": "object", "ignoredNfts": "object", + "domains": {}, + "perDomainNetwork": "boolean", "snapErrors": "object", "snaps": "object", "snapStates": "object", diff --git a/test/stub/tx-meta-stub.js b/test/stub/tx-meta-stub.js index dd03619ce1a8..88b8bf99e72f 100644 --- a/test/stub/tx-meta-stub.js +++ b/test/stub/tx-meta-stub.js @@ -58,33 +58,6 @@ export const txMetaStub = { timestamp: 1572395158261, value: '0x5', }, - { - op: 'add', - path: '/nonceDetails', - value: { - local: { - details: { - highest: 4, - startPoint: 4, - }, - name: 'local', - nonce: 4, - }, - network: { - details: { - baseCount: 4, - blockNumber: '0x51a401', - }, - name: 'network', - nonce: 4, - }, - params: { - highestLocallyConfirmed: 0, - highestSuggested: 4, - nextNetworkNonce: 4, - }, - }, - }, ], [ { @@ -164,29 +137,6 @@ export const txMetaStub = { id: 405984854664302, loadingDefaults: false, metamaskNetworkId: '5', - nonceDetails: { - local: { - details: { - highest: 4, - startPoint: 4, - }, - name: 'local', - nonce: 4, - }, - network: { - details: { - baseCount: 4, - blockNumber: '0x51a401', - }, - name: 'network', - nonce: 4, - }, - params: { - highestLocallyConfirmed: 0, - highestSuggested: 4, - nextNetworkNonce: 4, - }, - }, origin: 'MetaMask', r: '0x5f973e540f2d3c2f06d3725a626b75247593cb36477187ae07ecfe0a4db3cf57', rawTx: diff --git a/ui/components/app/custom-spending-cap/custom-spending-cap.js b/ui/components/app/custom-spending-cap/custom-spending-cap.js index bcca9ec7efca..b2e1ec12566f 100644 --- a/ui/components/app/custom-spending-cap/custom-spending-cap.js +++ b/ui/components/app/custom-spending-cap/custom-spending-cap.js @@ -141,6 +141,7 @@ export default function CustomSpendingCap({ setError(spendingCapError); } } + setCustomSpendingCap(String(valueInput)); dispatch(setCustomTokenAmount(String(valueInput))); diff --git a/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.js b/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.js index 70fb157e1bf4..7987ae770605 100644 --- a/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.js +++ b/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.js @@ -7,7 +7,9 @@ import { TextColor, TextVariant, } from '../../../helpers/constants/design-system'; +///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask) import { PRIORITY_LEVEL_ICON_MAP } from '../../../helpers/constants/gas'; +///: END:ONLY_INCLUDE_IN import { useGasFeeContext } from '../../../contexts/gasFee'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { useTransactionEventFragment } from '../../../hooks/useTransactionEventFragment'; @@ -35,17 +37,22 @@ export default function EditGasFeeButton({ userAcknowledgedGasMissing }) { if (!supportsEIP1559 || !estimateUsed || !editEnabled) { return null; } - + ///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask) let icon = estimateUsed; + ///: END:ONLY_INCLUDE_IN let title = estimateUsed; if ( estimateUsed === PriorityLevels.high && editGasMode === EditGasModes.swaps ) { + ///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask) icon = 'swapSuggested'; + ///: END:ONLY_INCLUDE_IN title = 'swapSuggested'; } else if (estimateUsed === PriorityLevels.tenPercentIncreased) { + ///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask) icon = undefined; + ///: END:ONLY_INCLUDE_IN title = 'tenPercentIncreased'; } @@ -66,11 +73,15 @@ export default function EditGasFeeButton({ userAcknowledgedGasMissing }) { return (
+ ); }; diff --git a/ui/components/multichain/activity-list-item/activity-list-item.stories.js b/ui/components/multichain/activity-list-item/activity-list-item.stories.js index 09ea2d49caf6..dd3ca5718e05 100644 --- a/ui/components/multichain/activity-list-item/activity-list-item.stories.js +++ b/ui/components/multichain/activity-list-item/activity-list-item.stories.js @@ -30,9 +30,7 @@ const Template = (args) => ; export const DefaultStory = Template.bind({}); DefaultStory.args = { 'data-testid': 'activity-list-item', - onClick: () => { - console.log('clicked list item'); - }, + onClick: () => undefined, className: 'custom-class', title: 'Activity Title', icon: ( diff --git a/ui/components/multichain/app-footer/app-footer.js b/ui/components/multichain/app-footer/app-footer.js index b4862ced74c9..fe536945d5de 100644 --- a/ui/components/multichain/app-footer/app-footer.js +++ b/ui/components/multichain/app-footer/app-footer.js @@ -1,11 +1,15 @@ import React from 'react'; import { useLocation } from 'react-router-dom'; -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { CONNECTED_ROUTE, DEFAULT_ROUTE, } from '../../../helpers/constants/routes'; import { + AvatarFavicon, + AvatarNetwork, + AvatarNetworkSize, + BadgeWrapper, Box, ButtonIcon, ButtonIconSize, @@ -19,14 +23,23 @@ import { AlignItems, BackgroundColor, BlockSize, + BorderColor, BorderRadius, Display, FlexDirection, IconColor, JustifyContent, + Size, TextColor, TextVariant, } from '../../../helpers/constants/design-system'; +import { + getConnectedSubjectsForAllAddresses, + getCurrentNetwork, + getOriginOfCurrentTab, + getSelectedAddress, + getTestNetworkBackgroundColor, +} from '../../../selectors'; import { showSelectActionModal } from './app-footer-actions'; export const AppFooter = () => { @@ -39,6 +52,20 @@ export const AppFooter = () => { const activeWallet = location.pathname === DEFAULT_ROUTE; const activeConnections = location.pathname === CONNECTED_ROUTE; + const selectedAddress = useSelector(getSelectedAddress); + + const currentTabOrigin = useSelector(getOriginOfCurrentTab); + const connectedSites = useSelector(getConnectedSubjectsForAllAddresses); + const connectedSite = connectedSites[selectedAddress]?.find( + ({ origin }) => origin === currentTabOrigin, + ); + const connectedAvatar = connectedSite?.iconUrl; + const connectedAvatarName = connectedSite?.name; + + const testNetworkBackgroundColor = useSelector(getTestNetworkBackgroundColor); + + const currentChain = useSelector(getCurrentNetwork); + return ( { alignItems={AlignItems.center} tabIndex={0} > - + {connectedSite ? ( + + + } + > + + + + ) : ( + + )} ; - DefaultStory.storyName = 'Default'; + +export const ConnectedStory = () => ; +ConnectedStory.storyName = 'Connected'; +ConnectedStory.decorators = [ + (Story) => ( + + + + ), +]; diff --git a/ui/components/multichain/app-header/__snapshots__/app-header.test.js.snap b/ui/components/multichain/app-header/__snapshots__/app-header.test.js.snap index 27d8a85e77eb..67d265f76e1e 100644 --- a/ui/components/multichain/app-header/__snapshots__/app-header.test.js.snap +++ b/ui/components/multichain/app-header/__snapshots__/app-header.test.js.snap @@ -228,11 +228,11 @@ exports[`App Header should match snapshot 1`] = `
)} diff --git a/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.test.js b/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.test.js index 8fafcdd864eb..cc0c0b1cc5c4 100644 --- a/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.test.js +++ b/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.test.js @@ -50,23 +50,6 @@ describe('Confirm Add Custodian Token', () => { const store = configureMockStore()(mockStore); - it('opens confirm add custodian token with correct token', () => { - renderWithProvider(, store); - - const tokenContainer = screen.getByText('...testToken'); - expect(tokenContainer).toBeInTheDocument(); - }); - - it('shows the custodian on cancel click', () => { - renderWithProvider(, store); - - const cancelButton = screen.getByTestId('cancel-btn'); - - fireEvent.click(cancelButton); - - expect(screen.getByText('Custodian')).toBeInTheDocument(); - }); - it('tries to connect to custodian with empty token', async () => { const customMockedStore = { metamask: { @@ -119,7 +102,7 @@ describe('Confirm Add Custodian Token', () => { const confirmButton = screen.getByTestId('confirm-btn'); fireEvent.click(confirmButton); - expect(screen.getByText('test')).toBeInTheDocument(); + expect(screen.getByText('Confirm connection to test')).toBeInTheDocument(); }); it('shows the error area', () => { diff --git a/ui/pages/institutional/confirm-connect-custodian-modal/confirm-connect-custodian-modal.js b/ui/pages/institutional/confirm-connect-custodian-modal/confirm-connect-custodian-modal.js new file mode 100644 index 000000000000..d08e07d7fe1a --- /dev/null +++ b/ui/pages/institutional/confirm-connect-custodian-modal/confirm-connect-custodian-modal.js @@ -0,0 +1,99 @@ +import PropTypes from 'prop-types'; +import React, { useContext } from 'react'; +import { + AlignItems, + Display, + TextColor, + FlexDirection, + TextAlign, +} from '../../../helpers/constants/design-system'; +import { I18nContext } from '../../../contexts/i18n'; +import { + Button, + ButtonVariant, + Box, + Text, + Modal, + ModalOverlay, + ModalContent, + ModalHeader, +} from '../../../components/component-library'; + +const ConfirmConnectCustodianModal = ({ + onModalClose, + custodianName, + custodianURL, +}) => { + const t = useContext(I18nContext); + + return ( + + + + + {t('connectCustodianAccounts', [custodianName])} + + + + {t('confirmConnectCustodianText', [custodianName])} + + + + {t('confirmConnectCustodianRedirect', [custodianURL])} + + + + + + + + + + ); +}; + +export default ConfirmConnectCustodianModal; + +ConfirmConnectCustodianModal.propTypes = { + onModalClose: PropTypes.func.isRequired, + custodianName: PropTypes.string.isRequired, + custodianURL: PropTypes.string, +}; diff --git a/ui/pages/institutional/confirm-connect-custodian-modal/confirm-connect-custodian-modal.stories.js b/ui/pages/institutional/confirm-connect-custodian-modal/confirm-connect-custodian-modal.stories.js new file mode 100644 index 000000000000..66585a421bfc --- /dev/null +++ b/ui/pages/institutional/confirm-connect-custodian-modal/confirm-connect-custodian-modal.stories.js @@ -0,0 +1,23 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import configureStore from '../../../store/store'; +import testData from '../../../../.storybook/test-data'; +import ConfirmConnectCustodianModal from '.'; + +const store = configureStore(testData); + +export default { + title: 'Components/Institutional/ConfirmConnectCustodianModal', + decorators: [(story) => {story()}], + component: ConfirmConnectCustodianModal, +}; + +export const DefaultStory = () => ( + +); + +DefaultStory.storyName = 'ConfirmConnectCustodianModal'; diff --git a/ui/pages/institutional/confirm-connect-custodian-modal/confirm-connect-custodian-modal.test.js b/ui/pages/institutional/confirm-connect-custodian-modal/confirm-connect-custodian-modal.test.js new file mode 100644 index 000000000000..83f2d631a5dd --- /dev/null +++ b/ui/pages/institutional/confirm-connect-custodian-modal/confirm-connect-custodian-modal.test.js @@ -0,0 +1,42 @@ +import React from 'react'; +import { screen } from '@testing-library/react'; +import configureMockStore from 'redux-mock-store'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import ConfirmAddCustodianToken from '.'; + +describe('Confirm Add Custodian Token', () => { + global.platform = { openTab: jest.fn() }; + + const mockStore = { + metamask: { + providerConfig: { + type: 'test', + }, + preferences: { + useNativeCurrencyAsPrimaryCurrency: true, + }, + }, + history: { + push: '/', + mostRecentOverviewPage: '/', + }, + }; + + const store = configureMockStore()(mockStore); + + it('shows the modal with its text', () => { + renderWithProvider( + console.log('Close')} + custodianName="Qredo" + custodianURL="https://qredo.com" + />, + store, + ); + + const tokenContainer = screen.getByText( + "To connect your accounts log into your Qredo account and click on the 'connect to MMI' button.", + ); + expect(tokenContainer).toBeInTheDocument(); + }); +}); diff --git a/ui/pages/institutional/confirm-connect-custodian-modal/index.js b/ui/pages/institutional/confirm-connect-custodian-modal/index.js new file mode 100644 index 000000000000..99ed12dcdad1 --- /dev/null +++ b/ui/pages/institutional/confirm-connect-custodian-modal/index.js @@ -0,0 +1 @@ +export { default } from './confirm-connect-custodian-modal'; diff --git a/ui/pages/institutional/custody/__snapshots__/custody.test.js.snap b/ui/pages/institutional/custody/__snapshots__/custody.test.js.snap index 525078513a3f..f5edc5bb2ec0 100644 --- a/ui/pages/institutional/custody/__snapshots__/custody.test.js.snap +++ b/ui/pages/institutional/custody/__snapshots__/custody.test.js.snap @@ -1,98 +1,77 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`CustodyPage renders CustodyPage 1`] = ` -
+exports[`CustodyPage renders jwt token list when first custodian is selected, showing the jwt form and testing the sorting function 1`] = ` +
    -
    -
    + class="mm-box mm-box--display-flex mm-box--align-items-center" + > + Saturn Custody A +

    + Saturn Custody A +

    +
    +
    -
    -`; - -exports[`CustodyPage renders CustodyPage 2`] = ` -
    - -
    -
    - -

    - Back -

    -
    -

    - Custodial Accounts -

    -
    +

    - Please choose the custodian you want to connect in order to add or refresh a token. -

    -
    +
    + +
    +
    +
    +

    -

      -
      -
      - Saturn Custody -

      - Saturn Custody -

      -
      - -
      -
    -
    + Saturn Custody C +

    - +
    -
    +
`; - -exports[`CustodyPage renders CustodyPage 3`] = `
`; diff --git a/ui/pages/institutional/custody/custody.js b/ui/pages/institutional/custody/custody.js index 7cfc76bbc1e5..8343b41ffcdf 100644 --- a/ui/pages/institutional/custody/custody.js +++ b/ui/pages/institutional/custody/custody.js @@ -7,7 +7,6 @@ import React, { } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { useHistory } from 'react-router-dom'; -import { v4 as uuidv4 } from 'uuid'; import { isEqual } from 'lodash'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { mmiActionsFactory } from '../../../store/institutional/institution-background'; @@ -18,8 +17,8 @@ import { Label, IconName, IconSize, - BUTTON_SIZES, - BUTTON_VARIANT, + ButtonSize, + ButtonVariant, Box, Text, } from '../../../components/component-library'; @@ -39,6 +38,7 @@ import { } from '../../../helpers/constants/design-system'; import { CUSTODY_ACCOUNT_DONE_ROUTE, + CUSTODY_ACCOUNT_ROUTE, DEFAULT_ROUTE, } from '../../../helpers/constants/routes'; import { getCurrentChainId, getSelectedAddress } from '../../../selectors'; @@ -51,6 +51,10 @@ import { MetaMetricsEventName, } from '../../../../shared/constants/metametrics'; import PulseLoader from '../../../components/ui/pulse-loader/pulse-loader'; +import ConfirmConnectCustodianModal from '../confirm-connect-custodian-modal'; +import { findCustodianByDisplayName } from '../../../helpers/utils/institutional/find-by-custodian-name'; + +const GK8_DISPLAY_NAME = 'gk8'; const CustodyPage = () => { const t = useI18nContext(); @@ -63,11 +67,16 @@ const CustodyPage = () => { const { custodians } = useSelector(getMMIConfiguration); const [loading, setLoading] = useState(true); + const [ + isConfirmConnectCustodianModalVisible, + setIsConfirmConnectCustodianModalVisible, + ] = useState(false); const [selectedAccounts, setSelectedAccounts] = useState({}); const [selectedCustodianName, setSelectedCustodianName] = useState(''); const [selectedCustodianImage, setSelectedCustodianImage] = useState(null); const [selectedCustodianDisplayName, setSelectedCustodianDisplayName] = useState(''); + const [matchedCustodian, setMatchedCustodian] = useState(null); const [selectedCustodianType, setSelectedCustodianType] = useState(''); const [connectError, setConnectError] = useState(''); const [currentJwt, setCurrentJwt] = useState(''); @@ -80,26 +89,20 @@ const CustodyPage = () => { const [accounts, setAccounts] = useState(); const address = useSelector(getSelectedAddress); const connectRequest = connectRequests ? connectRequests[0] : undefined; + const isCheckBoxSelected = + accounts && Object.keys(selectedAccounts).length === accounts.length; const custodianButtons = useMemo(() => { const custodianItems = []; - const sortedCustodians = [...custodians].sort(function (a, b) { - const nameA = a.name.toLowerCase(); - const nameB = b.name.toLowerCase(); - - if (nameA < nameB) { - return -1; - } - if (nameA > nameB) { - return 1; - } - return 0; - }); + const sortedCustodians = [...custodians] + .filter((item) => item.type !== 'Jupiter') + .sort((a, b) => + a.envName.toLowerCase().localeCompare(b.envName.toLowerCase()), + ); function shouldShowInProduction(custodian) { return ( - custodian && 'production' in custodian && !custodian.production && process.env.METAMASK_ENVIRONMENT === 'production' @@ -107,19 +110,59 @@ const CustodyPage = () => { } function isHidden(custodian) { - return custodian && 'hidden' in custodian && custodian.hidden; + return 'hidden' in custodian && custodian.hidden; } function isNotSelectedCustodian(custodian) { return ( - custodian && - 'name' in custodian && + 'envName' in custodian && connectRequest && Object.keys(connectRequest).length && - custodian.name !== selectedCustodianName + custodian.envName !== selectedCustodianName ); } + async function handleButtonClick(custodian) { + try { + const custodianByDisplayName = findCustodianByDisplayName( + custodian.displayName, + custodians, + ); + + const jwtListValue = await dispatch( + mmiActions.getCustodianJWTList(custodian.envName), + ); + + setSelectedCustodianName(custodian.envName); + setSelectedCustodianDisplayName(custodian.displayName); + setSelectedCustodianImage(custodian.iconUrl); + setApiUrl(custodian.apiUrl); + setCurrentJwt(jwtListValue[0] || ''); + setJwtList(jwtListValue); + + // open confirm Connect Custodian modal except for gk8 + if ( + custodianByDisplayName?.displayName?.toLocaleLowerCase() === + GK8_DISPLAY_NAME + ) { + setSelectedCustodianType(custodian.type); + } else { + setMatchedCustodian(custodianByDisplayName); + setIsConfirmConnectCustodianModalVisible(true); + } + + trackEvent({ + category: MetaMetricsEventCategory.MMI, + event: MetaMetricsEventName.CustodianSelected, + properties: { + custodian: custodian.envName, + }, + }); + } catch (error) { + console.error('Error:', error); + } + } + sortedCustodians.forEach((custodian) => { if ( shouldShowInProduction(custodian) || @@ -131,7 +174,7 @@ const CustodyPage = () => { custodianItems.push( { @@ -199,25 +220,27 @@ const CustodyPage = () => { const handleConnectError = useCallback( (e) => { - let errorMessage; - const detailedError = e.message.split(':'); - - if (detailedError.length > 1 && !isNaN(parseInt(detailedError[0], 10))) { - if (parseInt(detailedError[0], 10) === 401) { - // Authentication Error - errorMessage = - 'Authentication error. Please ensure you have entered the correct token'; + const getErrorMessage = (error) => { + const detailedError = error.message.split(':'); + const errorCode = parseInt(detailedError[0], 10); + + if (detailedError.length > 1 && !isNaN(errorCode)) { + switch (errorCode) { + case 401: + return 'Authentication error. Please ensure you have entered the correct token'; + default: + return null; + } } - } - if (/Network Error/u.test(e.message)) { - errorMessage = - 'Network error. Please ensure you have entered the correct API URL'; - } + if (/Network Error/u.test(error.message)) { + return 'Network error. Please ensure you have entered the correct API URL'; + } - if (!errorMessage) { - errorMessage = e.message; - } + return error.message; + }; + + const errorMessage = getErrorMessage(e); setConnectError( `Something went wrong connecting your custodian account. Error details: ${errorMessage}`, @@ -326,6 +349,8 @@ const CustodyPage = () => { setCurrentJwt(''); setConnectError(''); setSelectError(''); + + history.push(CUSTODY_ACCOUNT_ROUTE); }; const setSelectAllAccounts = (e) => { @@ -357,7 +382,12 @@ const CustodyPage = () => { return ( {connectError && ( - + {connectError} )} @@ -366,8 +396,10 @@ const CustodyPage = () => { {selectError} )} + {!accounts && !selectedCustodianType && ( { marginTop={4} > { ) : ( + {shouldInjectMetametricsIframe ? ( +