diff --git a/.circleci/scripts/test-run-e2e-timeout-minutes.ts b/.circleci/scripts/test-run-e2e-timeout-minutes.ts new file mode 100644 index 000000000000..1fc06696712a --- /dev/null +++ b/.circleci/scripts/test-run-e2e-timeout-minutes.ts @@ -0,0 +1,8 @@ +import { filterE2eChangedFiles } from '../../test/e2e/changedFilesUtil'; + +const changedOrNewTests = filterE2eChangedFiles(); + +//15 minutes, plus 3 minutes for every changed file, up to a maximum of 30 minutes +const extraTime = Math.min(15 + changedOrNewTests.length * 3, 30); + +console.log(extraTime); diff --git a/.circleci/scripts/test-run-e2e.sh b/.circleci/scripts/test-run-e2e.sh index 5d71a6f561b0..59d46f3a4bfc 100755 --- a/.circleci/scripts/test-run-e2e.sh +++ b/.circleci/scripts/test-run-e2e.sh @@ -19,8 +19,11 @@ then exit 1 fi +TIMEOUT_MINUTES=$(yarn tsx .circleci/scripts/test-run-e2e-timeout-minutes.ts) +echo "TIMEOUT_MINUTES: $TIMEOUT_MINUTES" + # Run the actual test command from the parameters -timeout 20m "$@" --retries 1 +timeout "${TIMEOUT_MINUTES}"m "$@" --retries 1 # Error code 124 means the command timed out if [ $? -eq 124 ] diff --git a/.circleci/scripts/validate-locales-only.ts b/.circleci/scripts/validate-locales-only.ts index d34be572c0bb..4d552bcf218b 100644 --- a/.circleci/scripts/validate-locales-only.ts +++ b/.circleci/scripts/validate-locales-only.ts @@ -5,8 +5,8 @@ const { readChangedFiles } = require('../../test/e2e/changedFilesUtil.js'); * Fails the build if any changed files are outside of the /_locales/ directory. * Fails if no changed files are detected. */ -async function validateLocalesOnlyChangedFiles() { - const changedFiles = await readChangedFiles(); +function validateLocalesOnlyChangedFiles() { + const changedFiles = readChangedFiles(); if (!changedFiles || changedFiles.length === 0) { console.error('Failure: No changed files detected.'); process.exit(1); diff --git a/.depcheckrc.yml b/.depcheckrc.yml index 7ce26732fcf7..bafacc56c918 100644 --- a/.depcheckrc.yml +++ b/.depcheckrc.yml @@ -28,6 +28,7 @@ ignores: - '@sentry/cli' # invoked as `sentry-cli` - 'chromedriver' - 'depcheck' # ooo meta + - 'ethers' # ethers @5.7.0 expected by @account-abstraction/contracts, but conflicts with transitive ethers@6.x - 'ganache-cli' - 'geckodriver' - 'jest' diff --git a/.github/workflows/run-integration-tests.yml b/.github/workflows/run-integration-tests.yml deleted file mode 100644 index 8de1899e0dfa..000000000000 --- a/.github/workflows/run-integration-tests.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Run integration tests - -on: - push: - branches: [develop, master] - pull_request: - types: [opened,reopened,synchronize] - -jobs: - test-integration: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup environment - uses: metamask/github-tools/.github/actions/setup-environment@main - - - name: test:integration:coverage - run: yarn test:integration:coverage diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml new file mode 100644 index 000000000000..a0240346af64 --- /dev/null +++ b/.github/workflows/run-tests.yml @@ -0,0 +1,142 @@ +name: Run tests + +on: + push: + branches: + - develop + - master + pull_request: + types: + - opened + - reopened + - synchronize + +jobs: + test-unit: + name: Unit tests + runs-on: ubuntu-latest + strategy: + matrix: + shard: [1, 2, 3, 4, 5, 6] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup environment + uses: metamask/github-tools/.github/actions/setup-environment@main + + - name: test:unit:coverage + run: yarn test:unit:coverage --shard=${{ matrix.shard }}/${{ strategy.job-total }} + + - name: Rename coverage + run: mv coverage/unit/coverage-final.json coverage/unit/coverage-unit-${{matrix.shard}}.json + + - uses: actions/upload-artifact@v4 + with: + name: coverage-unit-${{matrix.shard}} + path: coverage/unit/coverage-unit-${{matrix.shard}}.json + + test-webpack: + name: Webpack tests + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup environment + uses: metamask/github-tools/.github/actions/setup-environment@main + + - name: test:unit:webpack:coverage + run: yarn test:unit:webpack:coverage + + - name: Rename coverage + run: mv coverage/webpack/coverage-final.json coverage/webpack/coverage-webpack.json + + - uses: actions/upload-artifact@v4 + with: + name: coverage-webpack + path: coverage/webpack/coverage-webpack.json + + test-integration: + name: Integration tests + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup environment + uses: metamask/github-tools/.github/actions/setup-environment@main + + - name: test:integration:coverage + run: yarn test:integration:coverage + + - name: Rename coverage + run: mv coverage/integration/coverage-final.json coverage/integration/coverage-integration.json + + - uses: actions/upload-artifact@v4 + with: + name: coverage-integration + path: coverage/integration/coverage-integration.json + + sonarcloud: + name: SonarCloud + runs-on: ubuntu-latest + needs: + - test-unit + - test-webpack + - test-integration + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for better relevancy of analysis + + - name: Setup environment + uses: metamask/github-tools/.github/actions/setup-environment@main + + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + path: coverage + merge-multiple: true + + - name: Merge coverage reports + run: yarn nyc merge coverage .nyc_output/coverage-final.json && yarn nyc report --reporter lcov + + - uses: actions/upload-artifact@v4 + with: + name: lcov.info + path: coverage/lcov.info + + - name: Get Sonar coverage + id: get-sonar-coverage + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: | + projectKey=$(grep 'sonar.projectKey=' sonar-project.properties | cut -d'=' -f2) + sonar_coverage=$(curl --silent --header "Authorization: Bearer $SONAR_TOKEN" "https://sonarcloud.io/api/measures/component?component=$projectKey&metricKeys=coverage" | jq -r '.component.measures[0].value // 0') + echo "The Sonar coverage of $projectKey is $sonar_coverage%." + echo 'SONAR_COVERAGE='"$sonar_coverage" >> "$GITHUB_OUTPUT" + + - name: Validate test coverage + env: + SONAR_COVERAGE: ${{ steps.get-sonar-coverage.outputs.SONAR_COVERAGE }} + run: | + coverage=$(yarn nyc report --reporter=text-summary | grep 'Lines' | awk '{gsub(/%/, ""); print $3}') + if [ -z "$coverage" ]; then + echo "::error::Could not retrieve test coverage." + exit 1 + fi + if (( $(echo "$coverage < $SONAR_COVERAGE" | bc -l) )); then + echo "::error::Quality gate failed for test coverage. Current test coverage is $coverage%, please increase coverage to at least $SONAR_COVERAGE%." + exit 1 + else + echo "Test coverage is $coverage%. Quality gate passed." + fi + + - name: SonarCloud Scan + # This is SonarSource/sonarcloud-github-action@v2.0.0 + uses: SonarSource/sonarcloud-github-action@4b4d7634dab97dcee0b75763a54a6dc92a9e6bc1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.github/workflows/run-unit-tests.yml b/.github/workflows/run-unit-tests.yml deleted file mode 100644 index 6765352f5d7d..000000000000 --- a/.github/workflows/run-unit-tests.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: Run unit tests - -on: - push: - branches: [develop, master] - pull_request: - types: [opened,reopened,synchronize] - -jobs: - test-unit: - runs-on: ubuntu-latest - strategy: - matrix: - shard: [1, 2, 3, 4, 5, 6] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup environment - uses: metamask/github-tools/.github/actions/setup-environment@main - - - name: test:unit:coverage - run: yarn test:unit:coverage --shard=${{ matrix.shard }}/${{ strategy.job-total }} - - - name: Rename coverage to shard coverage - run: mv coverage/coverage-final.json coverage/coverage-${{matrix.shard}}.json - - - uses: actions/upload-artifact@v4 - with: - name: coverage-${{matrix.shard}} - path: coverage/coverage-${{matrix.shard}}.json - - test-webpack: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup environment - uses: metamask/github-tools/.github/actions/setup-environment@main - - - name: test:unit:webpack:coverage - run: yarn test:unit:webpack:coverage - - - name: Rename coverage - run: mv coverage/coverage-final.json coverage/coverage-webpack.json - - - uses: actions/upload-artifact@v4 - with: - name: coverage-webpack - path: coverage/coverage-webpack.json - - report-coverage: - runs-on: ubuntu-latest - needs: - - test-unit - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Download coverage from shards - uses: actions/download-artifact@v4 - with: - path: coverage - pattern: coverage-* - merge-multiple: true - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 - with: - token: ${{ secrets.CODECOV_TOKEN }} - fail_ci_if_error: true diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml deleted file mode 100644 index f5e1a0552dd1..000000000000 --- a/.github/workflows/sonar.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Sonar -on: - push: - branches: - - develop - pull_request: - branches: - - develop - -jobs: - sonarcloud: - name: SonarCloud - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 # Shallow clones should be disabled for better relevancy of analysis - - name: SonarCloud Scan - # This is SonarSource/sonarcloud-github-action@v2.0.0 - uses: SonarSource/sonarcloud-github-action@4b4d7634dab97dcee0b75763a54a6dc92a9e6bc1 - env: - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.gitignore b/.gitignore index eb8b930adf69..1671e69527e0 100644 --- a/.gitignore +++ b/.gitignore @@ -79,4 +79,4 @@ licenseInfos.json html-report/ /app/images/branding - +/changed-files diff --git a/.storybook/main.js b/.storybook/main.js index 554f6d955ee0..d63d924aa2e2 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -48,6 +48,10 @@ module.exports = { config.resolve.alias['../../../../../../store/actions'] = require.resolve( '../ui/__mocks__/actions.js', ); + // Import within controller-utils crashes storybook. + config.resolve.alias['@ethereumjs/util'] = require.resolve( + '../ui/__mocks__/ethereumjs-util.js', + ); config.resolve.fallback = { child_process: false, constants: false, diff --git a/.storybook/metamask-storybook-theme.js b/.storybook/metamask-storybook-theme.js index ac58fe319ca4..685702767484 100644 --- a/.storybook/metamask-storybook-theme.js +++ b/.storybook/metamask-storybook-theme.js @@ -2,5 +2,5 @@ export const metamaskStorybookTheme = { brandTitle: 'MetaMask Storybook', // Typography - fontBase: 'Euclid Circular B, Roboto, Helvetica, Arial, sans-serif', + fontBase: 'Euclid Circular B, Helvetica, Arial, sans-serif', }; diff --git a/.yarn/patches/@metamask-keyring-controller-npm-17.1.1-098cb41930.patch b/.yarn/patches/@metamask-keyring-controller-npm-17.1.1-098cb41930.patch deleted file mode 100644 index 439c1ddf49ae..000000000000 --- a/.yarn/patches/@metamask-keyring-controller-npm-17.1.1-098cb41930.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/package.json b/package.json -index 5a6217eaed16fdfe7f1ad693871f85320bd6b421..69bdf1a9155497e37fc58db7bbc74597fd543535 100644 ---- a/package.json -+++ b/package.json -@@ -18,7 +18,7 @@ - "sideEffects": false, - "exports": { - ".": { -- "import": "./dist/index.mjs", -+ "import": "./dist/index.js", - "require": "./dist/index.js", - "types": "./dist/types/index.d.ts" - }, diff --git a/.yarn/patches/@metamask-snaps-controllers-npm-9.5.0-8b21e3c072.patch b/.yarn/patches/@metamask-snaps-controllers-npm-9.5.0-8b21e3c072.patch deleted file mode 100644 index 314a33b9f881..000000000000 --- a/.yarn/patches/@metamask-snaps-controllers-npm-9.5.0-8b21e3c072.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/package.json b/package.json -index e738c058c38f8bc5c14bab9644ecced32eefa075..9aba0d03fc642572fcbdc2c791e335df72d70f35 100644 ---- a/package.json -+++ b/package.json -@@ -9,7 +9,7 @@ - "sideEffects": false, - "exports": { - ".": { -- "import": "./dist/index.mjs", -+ "import": "./dist/index.js", - "require": "./dist/index.js", - "types": "./dist/types/index.d.ts" - }, diff --git a/.yarn/patches/jest-environment-jsdom-npm-29.7.0-0b72dd0e0b.patch b/.yarn/patches/jest-environment-jsdom-npm-29.7.0-0b72dd0e0b.patch new file mode 100644 index 000000000000..94e712adf366 --- /dev/null +++ b/.yarn/patches/jest-environment-jsdom-npm-29.7.0-0b72dd0e0b.patch @@ -0,0 +1,16 @@ +diff --git a/build/index.js b/build/index.js +index 2e6c16c33c2f588cf8d6a5717ac776bb8908bd0d..5534a739c6bc7cda9e0f8439656a6215dfacc26a 100644 +--- a/build/index.js ++++ b/build/index.js +@@ -95,6 +95,11 @@ class JSDOMEnvironment { + + // TODO: remove this ASAP, but it currently causes tests to run really slow + global.Buffer = Buffer; ++ // Needed to support toChecksumAddress from the ethereumjs-util@7.1.5. ++ // It converts a hex string to a buffer and then expects it to be an instanceof Uint8Array. ++ // And although on Node env that buffer is an instance of Uint8Array, on JSDOM it is not. ++ // So we need to override the jsdom Uint8Array with Node Uint8Array. ++ global.Uint8Array = Uint8Array; + + // Report uncaught errors. + this.errorEventListener = event => { diff --git a/README.md b/README.md index 531a1e4fc3b6..d70eb03a32b2 100644 --- a/README.md +++ b/README.md @@ -83,8 +83,13 @@ If you are using VS Code and are unable to make commits from the source control To start a development build (e.g. with logging and file watching) run `yarn start`. -Alternatively, one can skip wallet onboarding and preload the vault state with a specific SRP by adding `TEST_SRP=''` and `PASSWORD=''` to the `.metamaskrc` file and running `yarn start:skip-onboarding`. +#### Development build with wallet state +You can start a development build with a preloaded wallet state, by adding `TEST_SRP=''` and `PASSWORD=''` to the `.metamaskrc` file. Then you have the following options: +1. Start the wallet with the default fixture flags, by running `yarn start:with-state`. +2. Check the list of available fixture flags, by running `yarn start:with-state --help`. +3. Start the wallet with custom fixture flags, by running `yarn start:with-state --FIXTURE_NAME=VALUE` for example `yarn start:with-state --withAccounts=100`. You can pass as many flags as you want. The rest of the fixtures will take the default values. +#### Development build with Webpack You can also start a development build using the `yarn webpack` command, or `yarn webpack --watch`. This uses an alternative build system that is much faster, but not yet production ready. See the [Webpack README](./development/webpack/README.md) for more information. #### React and Redux DevTools diff --git a/app/_locales/am/messages.json b/app/_locales/am/messages.json index cb193bc11c36..f2efb2511d06 100644 --- a/app/_locales/am/messages.json +++ b/app/_locales/am/messages.json @@ -220,9 +220,6 @@ "editContact": { "message": "ዕውቂያን አርትዕ" }, - "ensRegistrationError": { - "message": "በ ENS የስም ምዝገባ ላይ የተፈጠረ ስህተት" - }, "enterPasswordContinue": { "message": "ለመቀጠል የይለፍ ቃል ያስገቡ" }, @@ -345,9 +342,6 @@ "invalidAddressRecipient": { "message": "የተቀባይ አድራሻ ትክክል አይደለም" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "ETH አውታረ መረብ አይደለም፣ ወደ ትናንሽ ፊደላት ቀይር" - }, "invalidBlockExplorerURL": { "message": "ልክ ያልሆነ Block Explorer ዩአርኤል" }, @@ -444,9 +438,6 @@ "next": { "message": "ቀጣይ" }, - "noAddressForName": { - "message": "በዚህ ስም የተሞላ አድራሻ የለም።" - }, "noConversionRateAvailable": { "message": "ምንም የልወጣ ተመን አይገኝም" }, @@ -530,9 +521,6 @@ "readdToken": { "message": "በመለያ አማራጮችዎ ምናሌ ውስጥ ወደ “ተለዋጭ ስም አክል” በመግባት ለወደፊቱ ይህን ተለዋጭ ስም መልሰው ማከል ይችላሉ።" }, - "recipientAddressPlaceholder": { - "message": "ፍለጋ፣ ለሕዝብ ክፍት የሆነ አድራሻ (0x), ወይም ENS" - }, "reject": { "message": "አይቀበሉ" }, diff --git a/app/_locales/ar/messages.json b/app/_locales/ar/messages.json index e262cebf3537..e9a099be976c 100644 --- a/app/_locales/ar/messages.json +++ b/app/_locales/ar/messages.json @@ -233,9 +233,6 @@ "editContact": { "message": "تعديل جهة الاتصال" }, - "ensRegistrationError": { - "message": "خطأ في تسجيل اسم ENS" - }, "enterPasswordContinue": { "message": "أدخل كلمة المرور للمتابعة" }, @@ -354,9 +351,6 @@ "invalidAddressRecipient": { "message": "عنوان المستلم غير صحيح" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "لا تجعلها شبكة ETH، قم بتعيين الأحرف صغيرة" - }, "invalidBlockExplorerURL": { "message": "غير صحيح Block Explorer رابط" }, @@ -456,9 +450,6 @@ "next": { "message": "التالي" }, - "noAddressForName": { - "message": "لم يتم تعيين عنوان لهذا الاسم." - }, "noConversionRateAvailable": { "message": "لا يوجد معدل تحويل متاح" }, @@ -542,9 +533,6 @@ "readdToken": { "message": "يمكنك إضافة هذه العملة الرمزية مرة أخرى في المستقبل من خلال الانتقال إلى \"إضافة عملة رمزية\" في قائمة خيارات الحسابات الخاصة بك." }, - "recipientAddressPlaceholder": { - "message": "البحث، العنوان العام (0x)، أو ENS" - }, "reject": { "message": "رفض" }, diff --git a/app/_locales/bg/messages.json b/app/_locales/bg/messages.json index 2169f13ecf9d..8a21fc86c7f4 100644 --- a/app/_locales/bg/messages.json +++ b/app/_locales/bg/messages.json @@ -229,9 +229,6 @@ "editContact": { "message": "Редактиране на контакт" }, - "ensRegistrationError": { - "message": "Грешка при регистрацията на име на ENS" - }, "enterPasswordContinue": { "message": "Въведете парола, за да продължите" }, @@ -350,9 +347,6 @@ "invalidAddressRecipient": { "message": "Адресът на получателя е невалиден" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Не е ETH мрежа, задаване на малки букви" - }, "invalidBlockExplorerURL": { "message": "Невалиден Block Explorer URL адрес" }, @@ -455,9 +449,6 @@ "next": { "message": "Напред" }, - "noAddressForName": { - "message": "За това име не е зададен адрес." - }, "noConversionRateAvailable": { "message": "Няма наличен процент на преобръщане" }, @@ -541,9 +532,6 @@ "readdToken": { "message": "Можете да добавите този жетон в бъдеще, като отидете на „Добавяне на жетон“ в менюто с опции на акаунти." }, - "recipientAddressPlaceholder": { - "message": "Търсене, публичен адрес (0x) или ENS" - }, "reject": { "message": "Отхвърляне" }, diff --git a/app/_locales/bn/messages.json b/app/_locales/bn/messages.json index 29e06173be17..593ab8dd158b 100644 --- a/app/_locales/bn/messages.json +++ b/app/_locales/bn/messages.json @@ -226,9 +226,6 @@ "editContact": { "message": "পরিচিতি সম্পাদনা করুন" }, - "ensRegistrationError": { - "message": "ENS নাম নিবন্ধীকরণে ত্রুটি হয়েছে" - }, "enterPasswordContinue": { "message": "অবিরত রাখতে পাসওয়ার্ড লিখুন" }, @@ -351,9 +348,6 @@ "invalidAddressRecipient": { "message": "প্রাপকের ঠিকানা অবৈধ" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "ETH নেটওয়ার্ক নয়, ছোটো হরফে সেট করা হয়েছে" - }, "invalidBlockExplorerURL": { "message": "অবৈধ Block Explorer URL" }, @@ -453,9 +447,6 @@ "next": { "message": "পরবর্তী" }, - "noAddressForName": { - "message": "এই নামের জন্য কোনো ঠিকানা সেট করা হয় নি।" - }, "noConversionRateAvailable": { "message": "কোনো বিনিময় হার উপলভ্য নয়" }, @@ -539,9 +530,6 @@ "readdToken": { "message": "আপনি আপনার অ্যাকাউন্টস বিকল্পের মেনুতে \"টোকেনগুলি যোগ করুন\" এ গিয়ে ভবিষ্যতে আবার এই টোকেনটি যোগ করতে পারবেন। " }, - "recipientAddressPlaceholder": { - "message": "অনুসন্ধান, সার্বজনীন ঠিকানা (0x), বা ENS" - }, "reject": { "message": "প্রত্যাখ্যান" }, diff --git a/app/_locales/ca/messages.json b/app/_locales/ca/messages.json index 4393ea21f108..61f2c5e32481 100644 --- a/app/_locales/ca/messages.json +++ b/app/_locales/ca/messages.json @@ -226,9 +226,6 @@ "editContact": { "message": "Editar Contacte" }, - "ensRegistrationError": { - "message": "Error al registre de nom ENS" - }, "enterPasswordContinue": { "message": "Introdueix la contrasenya per continuar" }, @@ -341,9 +338,6 @@ "invalidAddressRecipient": { "message": "L'adreça del recipient no és vàlida" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "No hi ha xarxa ETH, posar en minúscules" - }, "invalidBlockExplorerURL": { "message": "URL de Block Explorer" }, @@ -443,9 +437,6 @@ "next": { "message": "Següent" }, - "noAddressForName": { - "message": "No existeix cap adreça amb aquest nom." - }, "noConversionRateAvailable": { "message": "No hi ha cap tarifa de conversió disponible" }, @@ -526,9 +517,6 @@ "readdToken": { "message": "Pots tornar a afegir aquesta fitxa en el futur anant a \"Afegir fitxa\" al menu d'opcions dels teus comptes." }, - "recipientAddressPlaceholder": { - "message": "Cerca, adreça pública (0x), o ENS" - }, "reject": { "message": "Rebutja" }, diff --git a/app/_locales/cs/messages.json b/app/_locales/cs/messages.json index f67d21b5cb52..96b9a3291ea3 100644 --- a/app/_locales/cs/messages.json +++ b/app/_locales/cs/messages.json @@ -220,9 +220,6 @@ "next": { "message": "Další" }, - "noAddressForName": { - "message": "Pro toto jméno nebyla nastavena žádná adresa." - }, "noTransactions": { "message": "Žádné transakce" }, diff --git a/app/_locales/da/messages.json b/app/_locales/da/messages.json index f5d7c9c89c3e..26aa63a60257 100644 --- a/app/_locales/da/messages.json +++ b/app/_locales/da/messages.json @@ -229,9 +229,6 @@ "editContact": { "message": "Redigér Kontakt" }, - "ensRegistrationError": { - "message": "Fejl i ENS-navneregistrering" - }, "enterPasswordContinue": { "message": "Indtast adgangskode for at fortsætte" }, @@ -347,9 +344,6 @@ "invalidAddressRecipient": { "message": "Modtageradressen er ugyldig" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Ikke ETH-netværk, sat til små bogstaver" - }, "invalidBlockExplorerURL": { "message": "Ugyldig Block Explorer-webadresse" }, @@ -443,9 +437,6 @@ "next": { "message": "Næste" }, - "noAddressForName": { - "message": "Ingen adresse indstillet for dette navn." - }, "noConversionRateAvailable": { "message": "Ingen tilgængelig omregningskurs" }, @@ -526,9 +517,6 @@ "readdToken": { "message": "Du kan tilføje denne token i fremtiden, ved at gå til \"Tilføj token\" under dine valgmenuen for dine konti." }, - "recipientAddressPlaceholder": { - "message": "Søg, offentlig adresse (0x) eller ENS" - }, "reject": { "message": "Afvis" }, diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index 5178ae6630a8..ff0773178691 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -1597,9 +1597,6 @@ "domain": { "message": "Domain" }, - "domainNotSupportedOnNetwork": { - "message": "Netzwerk unterstützt kein Domain-Lookup" - }, "done": { "message": "Fertig" }, @@ -1773,12 +1770,6 @@ "ensDomainsSettingTitle": { "message": "ENS-Domains in der Adresszeile anzeigen" }, - "ensIllegalCharacter": { - "message": "Unzulässiges Zeichen für ENS." - }, - "ensRegistrationError": { - "message": "Fehler bei der ENS-Namensregistrierung" - }, "ensUnknownError": { "message": "ENS-Lookup fehlgeschlagen." }, @@ -2422,9 +2413,6 @@ "invalidAddressRecipient": { "message": "Empfängeradresse ist unzulässig" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Kein ETH-Netzwerk, auf Kleinschreibung gesetzt" - }, "invalidAssetType": { "message": "Dieses Asset ist ein NFT und muss auf der Seite „NFTs importieren“ unter dem Tab NFTs erneut hinzugefügt werden." }, @@ -3152,9 +3140,6 @@ "noAccountsFound": { "message": "Keine Konten für die angegebene Suchanfrage gefunden" }, - "noAddressForName": { - "message": "Für den angegebene Namen wurde keine Adresse eingegeben." - }, "noConnectedAccountDescription": { "message": "Wählen Sie ein Konto, das Sie auf dieser Website verwenden möchten, um fortzufahren." }, @@ -4166,12 +4151,6 @@ "receive": { "message": "Empfangen" }, - "recipientAddressPlaceholder": { - "message": "Öffentliche Adresse (0x) oder ENS-Name eingeben" - }, - "recipientAddressPlaceholderFlask": { - "message": "Öffentliche Adresse (0x) oder Domainname eingeben" - }, "recommendedGasLabel": { "message": "Empfohlen" }, diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json index 897763ec56b3..3a191b6e9579 100644 --- a/app/_locales/el/messages.json +++ b/app/_locales/el/messages.json @@ -1597,9 +1597,6 @@ "domain": { "message": "Τομέας" }, - "domainNotSupportedOnNetwork": { - "message": "Το δίκτυο δεν υποστηρίζει αναζήτηση τομέα" - }, "done": { "message": "Τέλος" }, @@ -1773,12 +1770,6 @@ "ensDomainsSettingTitle": { "message": "Εμφάνιση τομέων ENS στη γραμμή διευθύνσεων" }, - "ensIllegalCharacter": { - "message": "Μη έγκυρος χαρακτήρας για το ENS." - }, - "ensRegistrationError": { - "message": "Σφάλμα στην καταχώριση ονόματος ENS" - }, "ensUnknownError": { "message": "Η αναζήτηση ENS απέτυχε." }, @@ -2422,9 +2413,6 @@ "invalidAddressRecipient": { "message": "Η διεύθυνση παραλήπτη δεν είναι έγκυρη" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Δεν είναι δίκτυο ETH, ορίστε με πεζά γράμματα" - }, "invalidAssetType": { "message": "Αυτό το περιουσιακό στοιχείο είναι NFT και πρέπει να προστεθεί ξανά στη σελίδα «Εισαγωγή NFT» που βρίσκεται στην καρτέλα των NFT" }, @@ -3152,9 +3140,6 @@ "noAccountsFound": { "message": "Δεν βρέθηκαν λογαριασμοί για το συγκεκριμένο αίτημα αναζήτησης" }, - "noAddressForName": { - "message": "Δεν έχει οριστεί διεύθυνση για αυτό το όνομα." - }, "noConnectedAccountDescription": { "message": "Επιλέξτε έναν λογαριασμό που θέλετε να χρησιμοποιήσετε σε αυτόν τον ιστότοπο για να συνεχίσετε." }, @@ -4166,12 +4151,6 @@ "receive": { "message": "Λήψη" }, - "recipientAddressPlaceholder": { - "message": "Εισάγετε τη δημόσια διεύθυνση (0x) ή το όνομα ENS" - }, - "recipientAddressPlaceholderFlask": { - "message": "Εισαγάγετε τη δημόσια διεύθυνση (0x) ή το όνομα τομέα" - }, "recommendedGasLabel": { "message": "Προτεινόμενο" }, diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index b512383c874e..5aee8cd393aa 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1657,9 +1657,6 @@ "domain": { "message": "Domain" }, - "domainNotSupportedOnNetwork": { - "message": "Network does not support domain lookup" - }, "done": { "message": "Done" }, @@ -1848,12 +1845,6 @@ "ensDomainsSettingTitle": { "message": "Show ENS domains in address bar" }, - "ensIllegalCharacter": { - "message": "Illegal character for ENS." - }, - "ensRegistrationError": { - "message": "Error in ENS name registration" - }, "ensUnknownError": { "message": "ENS lookup failed." }, @@ -2518,9 +2509,6 @@ "invalidAddressRecipient": { "message": "Recipient address is invalid" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Not ETH network, set to lowercase" - }, "invalidAssetType": { "message": "This asset is an NFT and needs to be re-added on the Import NFTs page found under the NFTs tab" }, @@ -3265,9 +3253,6 @@ "noAccountsFound": { "message": "No accounts found for the given search query" }, - "noAddressForName": { - "message": "No address has been set for this name." - }, "noConnectedAccountDescription": { "message": "Select an account you want to use on this site to continue." }, @@ -4290,10 +4275,7 @@ "receiveCrypto": { "message": "Receive crypto" }, - "recipientAddressPlaceholder": { - "message": "Enter public address (0x) or ENS name" - }, - "recipientAddressPlaceholderFlask": { + "recipientAddressPlaceholderNew": { "message": "Enter public address (0x) or domain name" }, "recommendedGasLabel": { diff --git a/app/_locales/en_GB/messages.json b/app/_locales/en_GB/messages.json index 78474d81a9f8..e67b9f0e4fcb 100644 --- a/app/_locales/en_GB/messages.json +++ b/app/_locales/en_GB/messages.json @@ -1612,9 +1612,6 @@ "domain": { "message": "Domain" }, - "domainNotSupportedOnNetwork": { - "message": "Network does not support domain lookup" - }, "done": { "message": "Done" }, @@ -1800,12 +1797,6 @@ "ensDomainsSettingTitle": { "message": "Show ENS domains in address bar" }, - "ensIllegalCharacter": { - "message": "Illegal character for ENS." - }, - "ensRegistrationError": { - "message": "Error in ENS name registration" - }, "ensUnknownError": { "message": "ENS lookup failed." }, @@ -2455,9 +2446,6 @@ "invalidAddressRecipient": { "message": "Recipient address is invalid" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Not ETH network, set to lowercase" - }, "invalidAssetType": { "message": "This asset is an NFT and needs to be re-added on the Import NFTs page found under the NFTs tab" }, @@ -3181,9 +3169,6 @@ "noAccountsFound": { "message": "No accounts found for the given search query" }, - "noAddressForName": { - "message": "No address has been set for this name." - }, "noConnectedAccountDescription": { "message": "Select an account you want to use on this site to continue." }, @@ -4199,9 +4184,6 @@ "message": "Receive" }, "recipientAddressPlaceholder": { - "message": "Enter public address (0x) or ENS name" - }, - "recipientAddressPlaceholderFlask": { "message": "Enter public address (0x) or domain name" }, "recommendedGasLabel": { diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index e9ec77cb3de6..88524f86f3cc 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -1594,9 +1594,6 @@ "domain": { "message": "Dominio" }, - "domainNotSupportedOnNetwork": { - "message": "La red no admite la búsqueda de dominios" - }, "done": { "message": "Hecho" }, @@ -1770,12 +1767,6 @@ "ensDomainsSettingTitle": { "message": "Mostrar dominios ENS en la barra de direcciones" }, - "ensIllegalCharacter": { - "message": "Caracter ilegal para ENS." - }, - "ensRegistrationError": { - "message": "Error en el registro del nombre de ENS" - }, "ensUnknownError": { "message": "Error al buscar ENS." }, @@ -2419,9 +2410,6 @@ "invalidAddressRecipient": { "message": "La dirección del destinatario no es válida" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "No es una red ETH; configurar en minúsculas" - }, "invalidAssetType": { "message": "Este activo es un NFT y debe volver a añadirse en la página de Importar NFTs que se encuentra en la pestaña de NFTs" }, @@ -3149,9 +3137,6 @@ "noAccountsFound": { "message": "No se encuentran cuentas para la consulta de búsqueda determinada" }, - "noAddressForName": { - "message": "No se estableció ninguna dirección para este nombre." - }, "noConnectedAccountDescription": { "message": "Seleccione una cuenta que desee utilizar en este sitio para continuar." }, @@ -4163,12 +4148,6 @@ "receive": { "message": "Recibir" }, - "recipientAddressPlaceholder": { - "message": "Ingrese la dirección pública (0x) o el nombre de ENS" - }, - "recipientAddressPlaceholderFlask": { - "message": "Ingrese la dirección pública (0x) o el nombre de dominio" - }, "recommendedGasLabel": { "message": "Recomendado" }, diff --git a/app/_locales/es_419/messages.json b/app/_locales/es_419/messages.json index c406955c36c9..1dd375450a81 100644 --- a/app/_locales/es_419/messages.json +++ b/app/_locales/es_419/messages.json @@ -705,12 +705,6 @@ "message": "El punto de conexión devolvió un id. de cadena diferente: $1", "description": "$1 is the return value of eth_chainId from an RPC endpoint" }, - "ensIllegalCharacter": { - "message": "Caracter ilegal para ENS." - }, - "ensRegistrationError": { - "message": "Error en el registro del nombre de ENS" - }, "ensUnknownError": { "message": "Error al buscar ENS." }, @@ -1020,9 +1014,6 @@ "invalidAddressRecipient": { "message": "La dirección del destinatario no es válida" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "No es una red ETH; configurar en minúsculas" - }, "invalidBlockExplorerURL": { "message": "Dirección URL del explorador de bloques no válida" }, @@ -1339,9 +1330,6 @@ "noAccountsFound": { "message": "No se encuentran cuentas para la consulta de búsqueda determinada" }, - "noAddressForName": { - "message": "No se estableció ninguna dirección para este nombre." - }, "noConversionDateAvailable": { "message": "No hay fecha de conversión de moneda disponible" }, @@ -1562,9 +1550,6 @@ "receive": { "message": "Recibir" }, - "recipientAddressPlaceholder": { - "message": "Búsqueda, dirección pública (0x) o ENS" - }, "recommendedGasLabel": { "message": "Recomendado" }, diff --git a/app/_locales/et/messages.json b/app/_locales/et/messages.json index dbfe1f88fb55..1e9bdffeb20e 100644 --- a/app/_locales/et/messages.json +++ b/app/_locales/et/messages.json @@ -229,9 +229,6 @@ "editContact": { "message": "Muuda kontakti" }, - "ensRegistrationError": { - "message": "Tõrge ENS-i nime registreerimisel" - }, "enterPasswordContinue": { "message": "Jätkamiseks sisestage parool" }, @@ -350,9 +347,6 @@ "invalidAddressRecipient": { "message": "Saaja aadress on vale" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Kehtetu ETH-võrk, kasutage väiketähti" - }, "invalidBlockExplorerURL": { "message": "Vale Block Explorer URL" }, @@ -449,9 +443,6 @@ "next": { "message": "Edasi" }, - "noAddressForName": { - "message": "Sellele nimele pole registreeritud ühtegi aadressi." - }, "noConversionRateAvailable": { "message": "Ühtegi vahetuskurssi pole saadaval" }, @@ -535,9 +526,6 @@ "readdToken": { "message": "Saate selle loa tulevikus tagasi lisada, kui lähete oma kontovalikute menüüs vahelehele „Lisa luba“." }, - "recipientAddressPlaceholder": { - "message": "Otsing, avalik aadress (0x) või ENS" - }, "reject": { "message": "Lükka tagasi" }, diff --git a/app/_locales/fa/messages.json b/app/_locales/fa/messages.json index 9f1d89793c1b..8fe574e7a81a 100644 --- a/app/_locales/fa/messages.json +++ b/app/_locales/fa/messages.json @@ -229,9 +229,6 @@ "editContact": { "message": "ویرایش تماس" }, - "ensRegistrationError": { - "message": "خطا در ثبت نام ENS" - }, "enterPasswordContinue": { "message": "برای ادامه رمز عبور را وارد کنید" }, @@ -354,9 +351,6 @@ "invalidAddressRecipient": { "message": "آدرس دریافت کننده نامعتبر است" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "شبکه ETH نه، به حروف کوچک تنظیم کنید" - }, "invalidBlockExplorerURL": { "message": "Block Explorer URL نا معتبر" }, @@ -459,9 +453,6 @@ "next": { "message": "بعدی" }, - "noAddressForName": { - "message": "هیچ آدرسی برای این نام تنظیم نشده است." - }, "noConversionRateAvailable": { "message": "هیچ نرخ تغییر موجود نمیباشد" }, @@ -545,9 +536,6 @@ "readdToken": { "message": "شما میتوانید این رمزیاب را دوباره برای آینده با رفتن به گزینه \"Add token\" در مینوی تنظیمات حساب ها، اضافه نمایید." }, - "recipientAddressPlaceholder": { - "message": "جستجو، آدرس عمومی (0x)، یا ENS" - }, "reject": { "message": "عدم پذیرش" }, diff --git a/app/_locales/fi/messages.json b/app/_locales/fi/messages.json index 4f193797912c..b69440707992 100644 --- a/app/_locales/fi/messages.json +++ b/app/_locales/fi/messages.json @@ -229,9 +229,6 @@ "editContact": { "message": "Muokkaa yhteystietoa" }, - "ensRegistrationError": { - "message": "Virhe ENS-nimen rekisteröinnissä" - }, "enterPasswordContinue": { "message": "Syötä salasana voidaksesi jatkaa" }, @@ -354,9 +351,6 @@ "invalidAddressRecipient": { "message": "Vastaanottajan osoite on virheellinen" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Ei ole ETH-verkosto; vaihda pieniin kirjaimiin" - }, "invalidBlockExplorerURL": { "message": "Virheellinen Block Explorer URL-osoite" }, @@ -459,9 +453,6 @@ "next": { "message": "Seuraava" }, - "noAddressForName": { - "message": "Tälle nimelle ei ole määritetty osoitetta." - }, "noConversionRateAvailable": { "message": "Vaihtokurssi ei saatavilla" }, @@ -542,9 +533,6 @@ "readdToken": { "message": "Voit lisätä tämän tietueen myöhemmin takaisin siirtymällä tilisi vaihtoehtovalikon kohtaan ”Lisää tietue”." }, - "recipientAddressPlaceholder": { - "message": "Haku, julkinen osoite (0x) tai ENS" - }, "reject": { "message": "Hylkää" }, diff --git a/app/_locales/fil/messages.json b/app/_locales/fil/messages.json index ab098442e52e..a437fb1e7100 100644 --- a/app/_locales/fil/messages.json +++ b/app/_locales/fil/messages.json @@ -205,9 +205,6 @@ "editContact": { "message": "I-edit ang Contact" }, - "ensRegistrationError": { - "message": "May error sa pagrerehistro ng ENS name" - }, "enterPasswordContinue": { "message": "Ilagay ang password para magpatuloy" }, @@ -311,9 +308,6 @@ "invalidAddressRecipient": { "message": "Hindi valid ang address ng recipient" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Hindi ito isang ETH network, i-set sa lowercase" - }, "invalidBlockExplorerURL": { "message": "Hindi valid ang Block Explorer URL" }, @@ -393,9 +387,6 @@ "next": { "message": "Susunod" }, - "noAddressForName": { - "message": "Walang address na na-set para sa pangalang ito." - }, "noConversionRateAvailable": { "message": "Walang Presyo ng Palitan na Available" }, @@ -469,9 +460,6 @@ "readdToken": { "message": "Puwede mong idagdag ulit ang token na ito sa hinaharap sa pamamagitan ng pagpunta sa “Magdagdag ng token” sa menu ng mga opsyon ng iyong mga accounts." }, - "recipientAddressPlaceholder": { - "message": "Maghanap, pampublikong address (0x), o ENS" - }, "reject": { "message": "Tanggihan" }, diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index db411ae0996b..f376101c5b2d 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -1597,9 +1597,6 @@ "domain": { "message": "Domaine" }, - "domainNotSupportedOnNetwork": { - "message": "Le réseau ne prend pas en charge la recherche de noms de domaine" - }, "done": { "message": "Terminé" }, @@ -1773,12 +1770,6 @@ "ensDomainsSettingTitle": { "message": "Afficher les domaines ENS dans la barre d’adresse" }, - "ensIllegalCharacter": { - "message": "Caractère invalide pour l’ENS." - }, - "ensRegistrationError": { - "message": "Erreur dans l’enregistrement du nom ENS" - }, "ensUnknownError": { "message": "La recherche d’ENS a échoué." }, @@ -2422,9 +2413,6 @@ "invalidAddressRecipient": { "message": "L’adresse du destinataire n’est pas valide" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Pas de réseau ETH, régler en minuscules" - }, "invalidAssetType": { "message": "Cet actif est un NFT et doit être ajouté de nouveau à la page Importer des NFT qui se trouve sous l’onglet NFT" }, @@ -3152,9 +3140,6 @@ "noAccountsFound": { "message": "Aucun compte trouvé pour la demande de recherche effectuée" }, - "noAddressForName": { - "message": "Aucune adresse n’a été définie pour ce nom." - }, "noConnectedAccountDescription": { "message": "Sélectionnez un compte que vous souhaitez utiliser sur ce site pour continuer." }, @@ -4166,12 +4151,6 @@ "receive": { "message": "Recevoir" }, - "recipientAddressPlaceholder": { - "message": "Saisissez l’adresse publique (0x) ou le nom de domaine ENS" - }, - "recipientAddressPlaceholderFlask": { - "message": "Saisissez l’adresse publique (0x) ou le nom de domaine" - }, "recommendedGasLabel": { "message": "Recommandé" }, diff --git a/app/_locales/he/messages.json b/app/_locales/he/messages.json index e29f44c9f834..b255bd0310c4 100644 --- a/app/_locales/he/messages.json +++ b/app/_locales/he/messages.json @@ -229,9 +229,6 @@ "editContact": { "message": "ערוך איש קשר" }, - "ensRegistrationError": { - "message": "שגיאה ברישום שם ENS" - }, "enterPasswordContinue": { "message": "יש להזין ססמה כדי להמשיך" }, @@ -354,9 +351,6 @@ "invalidAddressRecipient": { "message": "כתובת הנמען אינה חוקית" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "לא רשת ETH, מוגדר במצב אותיות קטנות" - }, "invalidBlockExplorerURL": { "message": "כתובת URL לא חוקית של Block Explorer" }, @@ -456,9 +450,6 @@ "next": { "message": "הבא" }, - "noAddressForName": { - "message": "לא הוגדרה כתובת עבור שם זה." - }, "noConversionRateAvailable": { "message": "אין שער המרה זמין" }, @@ -542,9 +533,6 @@ "readdToken": { "message": "באפשרותך להוסיף טוקן זה בחזרה בעתיד על ידי מעבר אל \"הוסף טוקן\" בתפריט אפשרויות החשבונות שלך." }, - "recipientAddressPlaceholder": { - "message": "חיפוש, כתובת ציבורית (0x), או ENS" - }, "reject": { "message": "דחה" }, diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index 460f47a33735..cff9295abc33 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -1597,9 +1597,6 @@ "domain": { "message": "डोमेन" }, - "domainNotSupportedOnNetwork": { - "message": "नेटवर्क, डोमेन लुकअप का सपोर्ट नहीं करता" - }, "done": { "message": "हो गया" }, @@ -1773,12 +1770,6 @@ "ensDomainsSettingTitle": { "message": "एड्रेस बार में ENS डोमेन दिखाएँ" }, - "ensIllegalCharacter": { - "message": "ENS के लिए गैर-कानूनी कैरेक्टर।" - }, - "ensRegistrationError": { - "message": "ENS नाम रजिस्ट्रेशन में गड़बड़ी" - }, "ensUnknownError": { "message": "ENS लुकअप नहीं हो पाया।" }, @@ -2422,9 +2413,6 @@ "invalidAddressRecipient": { "message": "प्राप्तकर्ता का एड्रेस ग़लत है" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "ETH नेटवर्क नहीं, लोअरकेस में सेट करें" - }, "invalidAssetType": { "message": "ये एसेट एक NFT है और इसे इंपोर्ट NFTज़ पेज पर फिर से जोड़ना होगा जो NFTज़ टैब के नीचे मिलेगा" }, @@ -3152,9 +3140,6 @@ "noAccountsFound": { "message": "दी गई खोज क्वेरी के लिए कोई अकाउंट नहीं मिला" }, - "noAddressForName": { - "message": "इस नाम के लिए कोई एड्रेस नहीं सेट किया गया है।" - }, "noConnectedAccountDescription": { "message": "जारी रखने के लिए जिस अकाउंट को आप इस साइट पर उपयोग करना चाहते हैं वह अकाउंट चुनें।" }, @@ -4166,12 +4151,6 @@ "receive": { "message": "प्राप्त करें" }, - "recipientAddressPlaceholder": { - "message": "सार्वजनिक एड्रेस (0x) या ENS नाम डालें" - }, - "recipientAddressPlaceholderFlask": { - "message": "पब्लिक एड्रेस (0x) या डोमेन नाम एंटर करें" - }, "recommendedGasLabel": { "message": "अनुशंसित" }, diff --git a/app/_locales/hn/messages.json b/app/_locales/hn/messages.json index 03c87498c87f..246c9c88d5bc 100644 --- a/app/_locales/hn/messages.json +++ b/app/_locales/hn/messages.json @@ -203,9 +203,6 @@ "next": { "message": "अगला" }, - "noAddressForName": { - "message": "इस नाम के लिए कोई पता सेट नहीं किया गया है।" - }, "noTransactions": { "message": "कोई लेन-देन नहीं" }, diff --git a/app/_locales/hr/messages.json b/app/_locales/hr/messages.json index d7e62da80ba4..b8e1c9bf15c1 100644 --- a/app/_locales/hr/messages.json +++ b/app/_locales/hr/messages.json @@ -229,9 +229,6 @@ "editContact": { "message": "Uredi kontakt" }, - "ensRegistrationError": { - "message": "Greška u registraciji naziva ENS" - }, "enterPasswordContinue": { "message": "Upišite lozinku za nastavak" }, @@ -350,9 +347,6 @@ "invalidAddressRecipient": { "message": "Adresa primatelja nije valjana" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Ne mreža ETH, postavite na mala slova" - }, "invalidBlockExplorerURL": { "message": "Nevaljani URL Block Explorer-a" }, @@ -452,9 +446,6 @@ "next": { "message": "Sljedeće" }, - "noAddressForName": { - "message": "Nijedna adresa nije postavljena za ovaj naziv." - }, "noConversionRateAvailable": { "message": "Nijedan konverzijski tečaj nije dostupan" }, @@ -538,9 +529,6 @@ "readdToken": { "message": "Ovaj token možete dodati kasnije odlaskom pod stavku „Dodaj token” u izborniku mogućnosti računa. " }, - "recipientAddressPlaceholder": { - "message": "Pretraži, javne adrese (0x) ili ENS" - }, "reject": { "message": "Odbaci" }, diff --git a/app/_locales/ht/messages.json b/app/_locales/ht/messages.json index 02f06746a58a..879eeab1722d 100644 --- a/app/_locales/ht/messages.json +++ b/app/_locales/ht/messages.json @@ -317,9 +317,6 @@ "next": { "message": "Aprè sa" }, - "noAddressForName": { - "message": "Pa gen adrès ki etabli pou non sa a." - }, "noConversionRateAvailable": { "message": "Pa gen okenn Konvèsyon Disponib" }, diff --git a/app/_locales/hu/messages.json b/app/_locales/hu/messages.json index 456b63710dd6..eef301ef9273 100644 --- a/app/_locales/hu/messages.json +++ b/app/_locales/hu/messages.json @@ -229,9 +229,6 @@ "editContact": { "message": "Kapcsolatok szerkesztése" }, - "ensRegistrationError": { - "message": "Hiba történt az ENS név regisztrációjakor" - }, "enterPasswordContinue": { "message": "A folytatáshoz adja meg a jelszót" }, @@ -350,9 +347,6 @@ "invalidAddressRecipient": { "message": "A címzett címe érvénytelen " }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Nem ETH hálózat, állítsa kisbetűre" - }, "invalidBlockExplorerURL": { "message": "Helytelen Block Explorer URL" }, @@ -452,9 +446,6 @@ "next": { "message": "Következő" }, - "noAddressForName": { - "message": "Nem lett cím beállítva ehhez a névhez." - }, "noConversionRateAvailable": { "message": "Nincs elérhető átváltási díj" }, @@ -538,9 +529,6 @@ "readdToken": { "message": "Ezt a tokent a jövőben is hozzáadhatja, ha a fiókbeállítások menü „Token hozzáadása” elemére lép." }, - "recipientAddressPlaceholder": { - "message": "Keresés, nyilvános cím (0x) vagy ENS" - }, "reject": { "message": "Elutasítás" }, diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index 6e6bf520481b..8e2437d8c2bf 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -1597,9 +1597,6 @@ "domain": { "message": "Domain" }, - "domainNotSupportedOnNetwork": { - "message": "Jaringan tidak mendukung pencarian domain" - }, "done": { "message": "Selesai" }, @@ -1773,12 +1770,6 @@ "ensDomainsSettingTitle": { "message": "Tampilkan domain ENS di bilah alamat" }, - "ensIllegalCharacter": { - "message": "Karakter tidak sah untuk ENS." - }, - "ensRegistrationError": { - "message": "Terjadi kesalahan pada pendaftaran nama ENS" - }, "ensUnknownError": { "message": "Pencarian ENS gagal." }, @@ -2422,9 +2413,6 @@ "invalidAddressRecipient": { "message": "Alamat penerima tidak valid" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Bukan jaringan ETH, atur ke huruf kecil" - }, "invalidAssetType": { "message": "Aset ini merupakan NFT dan harus ditambahkan kembali di halaman Impor NFT yang ada di bawah tab NFT" }, @@ -3152,9 +3140,6 @@ "noAccountsFound": { "message": "Tidak ditemukan akun untuk kueri pencarian yang diberikan" }, - "noAddressForName": { - "message": "Alamat untuk nama ini belum diatur." - }, "noConnectedAccountDescription": { "message": "Pilih akun yang ingin Anda gunakan di situs ini untuk melanjutkan." }, @@ -4166,12 +4151,6 @@ "receive": { "message": "Terima" }, - "recipientAddressPlaceholder": { - "message": "Masukkan alamat publik (0x) atau nama ENS" - }, - "recipientAddressPlaceholderFlask": { - "message": "Masukkan alamat publik (0x) atau nama domain" - }, "recommendedGasLabel": { "message": "Direkomendasikan" }, diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index 9f9085f4ed81..2cd696e5b5ba 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -774,9 +774,6 @@ "message": "L'endpoint ha restituito un chain ID diverso: $1", "description": "$1 is the return value of eth_chainId from an RPC endpoint" }, - "ensRegistrationError": { - "message": "Errore nella registrazione del nome ENS" - }, "enterMaxSpendLimit": { "message": "Inserisici Limite Spesa" }, @@ -955,9 +952,6 @@ "invalidAddressRecipient": { "message": "Indirizzo destinatario invalido" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Rete non ETH, inserisci caratteri minuscoli" - }, "invalidBlockExplorerURL": { "message": "URI Block Explorer invalido" }, @@ -1120,9 +1114,6 @@ "noAccountsFound": { "message": "Nessun account trovato per la ricerca effettuata" }, - "noAddressForName": { - "message": "Nessun indirizzo è stato impostato per questo nome." - }, "noConversionRateAvailable": { "message": "Tasso di conversione non disponibile" }, @@ -1236,9 +1227,6 @@ "receive": { "message": "Ricevi" }, - "recipientAddressPlaceholder": { - "message": "Ricerca, indirizzo pubblico (0x) o ENS" - }, "reject": { "message": "Annulla" }, diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index 6fd157c2e8b2..e1ca82a04a42 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -1597,9 +1597,6 @@ "domain": { "message": "ドメイン" }, - "domainNotSupportedOnNetwork": { - "message": "ネットワークがドメイン検索をサポートしていません" - }, "done": { "message": "完了" }, @@ -1773,12 +1770,6 @@ "ensDomainsSettingTitle": { "message": "アドレスバーにENSドメインを表示する" }, - "ensIllegalCharacter": { - "message": "ENSにサポートされていない文字が使用されています。" - }, - "ensRegistrationError": { - "message": "ENS名の登録エラー" - }, "ensUnknownError": { "message": "ENSの検索に失敗しました。" }, @@ -2422,9 +2413,6 @@ "invalidAddressRecipient": { "message": "送金先アドレスが無効です" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "ETHネットワークではありません。小文字にしてください。" - }, "invalidAssetType": { "message": "このアセットはNFTであるため、「NFT」タブの「NFTのインポート」ページで追加しなおす必要があります" }, @@ -3152,9 +3140,6 @@ "noAccountsFound": { "message": "指定された検索クエリでアカウントが見つかりませんでした" }, - "noAddressForName": { - "message": "この名前にアドレスが設定されていません。" - }, "noConnectedAccountDescription": { "message": "続行するには、このサイトで使用するアカウントを選択してください。" }, @@ -4166,12 +4151,6 @@ "receive": { "message": "受取" }, - "recipientAddressPlaceholder": { - "message": "パブリックアドレス (0x) またはENS名を入力してください" - }, - "recipientAddressPlaceholderFlask": { - "message": "パブリックアドレス (0x) またはドメイン名を入力してください" - }, "recommendedGasLabel": { "message": "推奨" }, diff --git a/app/_locales/kn/messages.json b/app/_locales/kn/messages.json index 0b0479e3dddf..d5fe970b32e0 100644 --- a/app/_locales/kn/messages.json +++ b/app/_locales/kn/messages.json @@ -229,9 +229,6 @@ "editContact": { "message": "ಸಂಪರ್ಕವನ್ನು ಸಂಪಾದಿಸಿ" }, - "ensRegistrationError": { - "message": "ENS ಹೆಸರಿನ ನೋಂದಣಿಯಲ್ಲಿ ದೋಷ" - }, "enterPasswordContinue": { "message": "ಮುಂದುವರೆಯಲು ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ" }, @@ -354,9 +351,6 @@ "invalidAddressRecipient": { "message": "ಸ್ವೀಕೃತಿದಾರರ ವಿಳಾಸವು ಅಮಾನ್ಯವಾಗಿದೆ" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "ETH ನೆಟ್‌ವರ್ಕ್‌ಗಳಿಲ್ಲ, ಸಣ್ಣಕ್ಷರಕ್ಕೆ ಹೊಂದಿಸಲಾಗಿದೆ" - }, "invalidBlockExplorerURL": { "message": "ಅಮಾನ್ಯವಾದ Block Explorer URL" }, @@ -459,9 +453,6 @@ "next": { "message": "ಮುಂದೆ" }, - "noAddressForName": { - "message": "ಈ ಹೆಸರಿಗೆ ಯಾವುದೇ ವಿಳಾಸವನ್ನು ಹೊಂದಿಸಲಾಗಿಲ್ಲ." - }, "noConversionRateAvailable": { "message": "ಯಾವುದೇ ಪರಿವರ್ತನೆ ದರ ಲಭ್ಯವಿಲ್ಲ" }, @@ -545,9 +536,6 @@ "readdToken": { "message": "ನಿಮ್ಮ ಖಾತೆಗಳ ಆಯ್ಕೆಗಳ ಮೆನುವಿನಲ್ಲಿ \"ಟೋಕನ್ ಸೇರಿಸು\" ಗೆ ಹೋಗುವ ಮೂಲಕ ನೀವು ಈ ಟೋಕನ್ ಅನ್ನು ಭವಿಷ್ಯದಲ್ಲಿ ಮರಳಿ ಸೇರಿಸಬಹುದು." }, - "recipientAddressPlaceholder": { - "message": "ಸಾರ್ವಜನಿಕ ವಿಳಾಸ (0x) ಅಥವಾ ENS ಹುಡುಕಿ" - }, "reject": { "message": "ತಿರಸ್ಕರಿಸಿ" }, diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index a027815872d8..2c36d6ad2f58 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -1597,9 +1597,6 @@ "domain": { "message": "도메인" }, - "domainNotSupportedOnNetwork": { - "message": "네트워크에서 도메인 조회를 지원하지 않음" - }, "done": { "message": "완료" }, @@ -1773,12 +1770,6 @@ "ensDomainsSettingTitle": { "message": "주소창에 ENS 도메인 표시하기" }, - "ensIllegalCharacter": { - "message": "ENS에 맞지 않는 문자입니다." - }, - "ensRegistrationError": { - "message": "ENS 이름 등록 중 오류 발생" - }, "ensUnknownError": { "message": "ENS를 조회하지 못했습니다." }, @@ -2422,9 +2413,6 @@ "invalidAddressRecipient": { "message": "수신 주소가 올바르지 않음" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "ETH 네트워크가 아닙니다. 소문자로 설정하세요." - }, "invalidAssetType": { "message": "이 자산은 NFT이므로 NFT 탭에 있는 NFT 가져오기 페이지에서 다시 추가해야 합니다" }, @@ -3152,9 +3140,6 @@ "noAccountsFound": { "message": "검색어에 해당하는 계정이 없습니다." }, - "noAddressForName": { - "message": "이 이름에 설정된 주소가 없습니다." - }, "noConnectedAccountDescription": { "message": "이 사이트에서 계속 사용하고자 하는 계정을 선택하세요." }, @@ -4166,12 +4151,6 @@ "receive": { "message": "받기" }, - "recipientAddressPlaceholder": { - "message": "공개 주소(0x) 또는 ENS 제목 입력" - }, - "recipientAddressPlaceholderFlask": { - "message": "공개 주소(0x) 또는 도메인 이름 입력" - }, "recommendedGasLabel": { "message": "권장됨" }, diff --git a/app/_locales/lt/messages.json b/app/_locales/lt/messages.json index 0600ea96f32b..1c0c341f7726 100644 --- a/app/_locales/lt/messages.json +++ b/app/_locales/lt/messages.json @@ -229,9 +229,6 @@ "editContact": { "message": "Taisyti kontaktą" }, - "ensRegistrationError": { - "message": "ENS pavadinimo registracijos klaida" - }, "enterPasswordContinue": { "message": "Norėdami tęsti, įveskite slaptažodį" }, @@ -354,9 +351,6 @@ "invalidAddressRecipient": { "message": "Gavėjo adresas netinkamas" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Ne ETH tinklas, nustatykite į mažąsias raides" - }, "invalidBlockExplorerURL": { "message": "Netinkamas Block Explorer URL" }, @@ -459,9 +453,6 @@ "next": { "message": "Toliau" }, - "noAddressForName": { - "message": "Šiam pavadinimui nenurodytas adresas." - }, "noConversionRateAvailable": { "message": "Nėra keitimo kurso" }, @@ -545,9 +536,6 @@ "readdToken": { "message": "Šį žetoną galite bet kada galite įtraukti ir vėl, tiesiog savo paskyros parinkčių meniu nueikite į „Įtraukti žetoną“." }, - "recipientAddressPlaceholder": { - "message": "Ieška, viešieji adresai (0x) arba ENS" - }, "reject": { "message": "Atmesti" }, diff --git a/app/_locales/lv/messages.json b/app/_locales/lv/messages.json index c0dfc6d573b8..08b28f2c30ca 100644 --- a/app/_locales/lv/messages.json +++ b/app/_locales/lv/messages.json @@ -229,9 +229,6 @@ "editContact": { "message": "Rediģēt līgumu" }, - "ensRegistrationError": { - "message": "Kļūda ENS vārda reģistrācijā" - }, "enterPasswordContinue": { "message": "Ievadiet paroli, lai turpinātu" }, @@ -350,9 +347,6 @@ "invalidAddressRecipient": { "message": "Nederīga saņēmēja adrese" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Nav ETH tīkls, iestatīti mazie burti" - }, "invalidBlockExplorerURL": { "message": "Nederīgs Block Explorer URL" }, @@ -455,9 +449,6 @@ "next": { "message": "Nākamais" }, - "noAddressForName": { - "message": "Šim vārdam nav iestatīta adrese." - }, "noConversionRateAvailable": { "message": "Konversijas kurss nav pieejams" }, @@ -541,9 +532,6 @@ "readdToken": { "message": "Jūs varat šo marķieri iestatīt atpakaļ nākotnē, konta opciju izvēlnē atverot \"Pievienot marķieri\"." }, - "recipientAddressPlaceholder": { - "message": "Meklēšana, publiskā adrese (0x) vai ENS" - }, "reject": { "message": "Noraidīt" }, diff --git a/app/_locales/ms/messages.json b/app/_locales/ms/messages.json index b8a0cb2ac507..8bd9278ef2d3 100644 --- a/app/_locales/ms/messages.json +++ b/app/_locales/ms/messages.json @@ -226,9 +226,6 @@ "editContact": { "message": "Edit Kenalan" }, - "ensRegistrationError": { - "message": "Ralat dalam pendaftaran nama ENS" - }, "enterPasswordContinue": { "message": "Masukkan kata laluan untuk teruskan" }, @@ -343,9 +340,6 @@ "invalidAddressRecipient": { "message": "Alamat penerima tidak sah" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Bukan rangkaian ETH, tetapkan kepada huruf kecil" - }, "invalidBlockExplorerURL": { "message": "URL Block Explorer tidak sah" }, @@ -442,9 +436,6 @@ "next": { "message": "Seterusnya" }, - "noAddressForName": { - "message": "Tiada alamat yang ditetapkan untuk nama ini." - }, "noConversionRateAvailable": { "message": "Tiada Kadar Penukaran yang Tersedia" }, @@ -525,9 +516,6 @@ "readdToken": { "message": "Anda boleh tambah token ini kembali pada masa depan dengan pergi ke \"Tambah token\" di dalam menu pilihan akaun anda." }, - "recipientAddressPlaceholder": { - "message": "Cari, alamat awam (0x), atau ENS" - }, "reject": { "message": "Tolak" }, diff --git a/app/_locales/nl/messages.json b/app/_locales/nl/messages.json index f3ae82f80616..de0a2fd9f5e2 100644 --- a/app/_locales/nl/messages.json +++ b/app/_locales/nl/messages.json @@ -193,9 +193,6 @@ "next": { "message": "volgende" }, - "noAddressForName": { - "message": "Er is geen adres ingesteld voor deze naam." - }, "noTransactions": { "message": "Geen transacties" }, diff --git a/app/_locales/no/messages.json b/app/_locales/no/messages.json index 56c05ffd958c..7e50d555e852 100644 --- a/app/_locales/no/messages.json +++ b/app/_locales/no/messages.json @@ -226,9 +226,6 @@ "editContact": { "message": "Rediger kontakt" }, - "ensRegistrationError": { - "message": "Feil i ENS-navneregistrering" - }, "enterPasswordContinue": { "message": "Skriv inn passord for å fortsette" }, @@ -341,9 +338,6 @@ "invalidAddressRecipient": { "message": "Mottaksadresse er ugyldig " }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Ikke ETH-nettverk, bruk små bokstaver" - }, "invalidBlockExplorerURL": { "message": "Ugyldig Block Explorer URL" }, @@ -443,9 +437,6 @@ "next": { "message": "Neste" }, - "noAddressForName": { - "message": "Ingen adresse har blitt angitt for dette navnet. " - }, "noConversionRateAvailable": { "message": "Ingen konverteringsrate tilgjengelig " }, @@ -529,9 +520,6 @@ "readdToken": { "message": "Du kan legge til dette tokenet igjen i fremtiden ved å gå til \"Legg til token\" i menyen for kontoalternativer." }, - "recipientAddressPlaceholder": { - "message": "Søk, offentlig adresse (0x) eller ENS" - }, "reject": { "message": "Avslå" }, diff --git a/app/_locales/ph/messages.json b/app/_locales/ph/messages.json index debc2d35640a..ecbc7a99ab37 100644 --- a/app/_locales/ph/messages.json +++ b/app/_locales/ph/messages.json @@ -445,9 +445,6 @@ "message": "Nagbalik ang endpoint ng ibang chain ID: $1", "description": "$1 is the return value of eth_chainId from an RPC endpoint" }, - "ensRegistrationError": { - "message": "Nagka-error sa pag-register ng ENS name" - }, "enterMaxSpendLimit": { "message": "Ilagay ang Max na Limitasyon sa Paggastos" }, @@ -670,9 +667,6 @@ "invalidAddressRecipient": { "message": "Hindi valid ang address ng tatanggap" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Hindi ETH network, itakda sa maliliit na letra" - }, "invalidBlockExplorerURL": { "message": "Invalid na URL ng Block Explorer" }, @@ -879,9 +873,6 @@ "noAccountsFound": { "message": "Walang nakitang account para sa ibinigay na query sa paghahanap" }, - "noAddressForName": { - "message": "Walang naitakdang address para sa pangalang ito." - }, "noConversionRateAvailable": { "message": "Hindi Available ang Rate ng Conversion" }, @@ -1013,9 +1004,6 @@ "receive": { "message": "Tumanggap" }, - "recipientAddressPlaceholder": { - "message": "Maghanap, pampublikong address (0x), o ENS" - }, "recoveryPhraseReminderBackupStart": { "message": "Magsimula rito" }, diff --git a/app/_locales/pl/messages.json b/app/_locales/pl/messages.json index dbc986a194e4..46b178cdf985 100644 --- a/app/_locales/pl/messages.json +++ b/app/_locales/pl/messages.json @@ -229,9 +229,6 @@ "editContact": { "message": "Edytuj kontakt" }, - "ensRegistrationError": { - "message": "Błąd w rejestracji nazwy ENS" - }, "enterPasswordContinue": { "message": "Podaj hasło żeby kontynuować" }, @@ -354,9 +351,6 @@ "invalidAddressRecipient": { "message": "Nieprawidłowy adres odbiorcy" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "To nie jest sieć ETH, zmień na małe litery" - }, "invalidBlockExplorerURL": { "message": "Nieprawidłowe Block Explorer URI" }, @@ -456,9 +450,6 @@ "next": { "message": "Dalej" }, - "noAddressForName": { - "message": "Nie wybrano żadnego adresu dla tej nazwy." - }, "noConversionRateAvailable": { "message": "Brak kursu waluty" }, @@ -539,9 +530,6 @@ "readdToken": { "message": "Możesz później ponownie dodać ten token poprzez \"Dodaj token\" w opcjach menu swojego konta." }, - "recipientAddressPlaceholder": { - "message": "Szukaj, adres publiczny (0x) lub ENS" - }, "reject": { "message": "Odrzuć" }, diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json index 7ee487ac9bcf..27587daf31d0 100644 --- a/app/_locales/pt/messages.json +++ b/app/_locales/pt/messages.json @@ -1597,9 +1597,6 @@ "domain": { "message": "Domínio" }, - "domainNotSupportedOnNetwork": { - "message": "A rede não suporta a consulta de domínio" - }, "done": { "message": "Concluído" }, @@ -1773,12 +1770,6 @@ "ensDomainsSettingTitle": { "message": "Exibir domínios ENS na barra de endereço" }, - "ensIllegalCharacter": { - "message": "Caractere inválido para ENS." - }, - "ensRegistrationError": { - "message": "Erro no registro do nome ENS" - }, "ensUnknownError": { "message": "Falha na busca de ENS." }, @@ -2422,9 +2413,6 @@ "invalidAddressRecipient": { "message": "O endereço do destinatário é inválido " }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Não é uma rede de ETH; configurar em minúsculas" - }, "invalidAssetType": { "message": "Esse ativo é um NFT e precisa ser adicionado novamente à página Importar NFT, encontrada na aba NFTs." }, @@ -3152,9 +3140,6 @@ "noAccountsFound": { "message": "Nenhuma conta encontrada para a pesquisa efetuada" }, - "noAddressForName": { - "message": "Não foi configurado nenhum endereço para esse nome." - }, "noConnectedAccountDescription": { "message": "Selecione uma conta que você deseja usar neste site para continuar." }, @@ -4166,12 +4151,6 @@ "receive": { "message": "Receber" }, - "recipientAddressPlaceholder": { - "message": "Insira o endereço público (0x) ou o nome ENS" - }, - "recipientAddressPlaceholderFlask": { - "message": "Insira o endereço público (0x) ou nome do domínio" - }, "recommendedGasLabel": { "message": "Recomendado" }, diff --git a/app/_locales/pt_BR/messages.json b/app/_locales/pt_BR/messages.json index a4b211bb0529..eae48ba1dc7f 100644 --- a/app/_locales/pt_BR/messages.json +++ b/app/_locales/pt_BR/messages.json @@ -705,12 +705,6 @@ "message": "O endpoint retornou um ID diferente da chain: $1", "description": "$1 is the return value of eth_chainId from an RPC endpoint" }, - "ensIllegalCharacter": { - "message": "Caractere inválido para ENS." - }, - "ensRegistrationError": { - "message": "Erro no registro do nome ENS" - }, "ensUnknownError": { "message": "Falha na busca de ENS." }, @@ -1020,9 +1014,6 @@ "invalidAddressRecipient": { "message": "O endereço do destinatário é inválido" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Não é uma rede de ETH; configurar em minúsculas" - }, "invalidBlockExplorerURL": { "message": "URL inválido do Block Explorer" }, @@ -1339,9 +1330,6 @@ "noAccountsFound": { "message": "Nenhuma conta encontrada para a busca efetuada" }, - "noAddressForName": { - "message": "Não foi configurado nenhum endereço para esse nome." - }, "noConversionDateAvailable": { "message": "Não há uma data de conversão de moeda disponível" }, @@ -1566,9 +1554,6 @@ "receive": { "message": "Receber" }, - "recipientAddressPlaceholder": { - "message": "Busca, endereço público (0x) ou ENS" - }, "recommendedGasLabel": { "message": "Recomendado" }, diff --git a/app/_locales/ro/messages.json b/app/_locales/ro/messages.json index a7f916825e57..dde9be461087 100644 --- a/app/_locales/ro/messages.json +++ b/app/_locales/ro/messages.json @@ -229,9 +229,6 @@ "editContact": { "message": "Editați contact" }, - "ensRegistrationError": { - "message": "Eroare la înregistrarea numelui ENS" - }, "enterPasswordContinue": { "message": "Introduceți parola pentru a continua" }, @@ -344,9 +341,6 @@ "invalidAddressRecipient": { "message": "Adresa destinatarului nu este validă" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Nu este rețea ETH, setați pe minuscule" - }, "invalidBlockExplorerURL": { "message": "URL Block Explorer nevalid" }, @@ -446,9 +440,6 @@ "next": { "message": "Înainte" }, - "noAddressForName": { - "message": "Nu a fost configurată nicio adresă pentru acest nume." - }, "noConversionRateAvailable": { "message": "Nici o rată de conversie disponibilă" }, @@ -532,9 +523,6 @@ "readdToken": { "message": "Puteți adăuga din nou acest indicativ în viitor accesând „Adăugați indicativ” din meniul de opțiuni al contului dvs." }, - "recipientAddressPlaceholder": { - "message": "Căutare, adresa publică (0x) sau ENS" - }, "reject": { "message": "Respingeți" }, diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index a02ba7831f01..6b13eaf1a46f 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -1597,9 +1597,6 @@ "domain": { "message": "Домен" }, - "domainNotSupportedOnNetwork": { - "message": "Сеть не поддерживает поиск домена" - }, "done": { "message": "Выполнено" }, @@ -1773,12 +1770,6 @@ "ensDomainsSettingTitle": { "message": "Показать домены ENS в адресной строке" }, - "ensIllegalCharacter": { - "message": "Недопустимый символ для ENS." - }, - "ensRegistrationError": { - "message": "Ошибка при регистрации имени ENS" - }, "ensUnknownError": { "message": "Ошибка поиска ENS." }, @@ -2422,9 +2413,6 @@ "invalidAddressRecipient": { "message": "Неверный адрес получателя" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Не сеть ETH, задана в нижнем регистре" - }, "invalidAssetType": { "message": "Этот актив является NFT, и его необходимо повторно добавить на странице «Импорт NFT», которая находится на вкладке NFT." }, @@ -3152,9 +3140,6 @@ "noAccountsFound": { "message": "По данному поисковому запросу счетов не найдено" }, - "noAddressForName": { - "message": "Для этого имени не задан адрес." - }, "noConnectedAccountDescription": { "message": "Для продолжения выберите счет, который вы хотите использовать на этом сайте." }, @@ -4166,12 +4151,6 @@ "receive": { "message": "Получить" }, - "recipientAddressPlaceholder": { - "message": "Введите публичный адрес (0x) или имя ENS" - }, - "recipientAddressPlaceholderFlask": { - "message": "Введите публичный адрес (0x) или имя домена" - }, "recommendedGasLabel": { "message": "Рекомендовано" }, diff --git a/app/_locales/sk/messages.json b/app/_locales/sk/messages.json index 79a185cf896c..6e28cc44f574 100644 --- a/app/_locales/sk/messages.json +++ b/app/_locales/sk/messages.json @@ -223,9 +223,6 @@ "editContact": { "message": "Upraviť kontakt" }, - "ensRegistrationError": { - "message": "Chyba pri registrácii názvu ENS" - }, "enterPasswordContinue": { "message": "Pokračujte zadaním hesla" }, @@ -341,9 +338,6 @@ "invalidAddressRecipient": { "message": "Adresa příjemce je neplatná" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Nie sieť ETH, nastaviť malé písmená" - }, "invalidBlockExplorerURL": { "message": "Neplatné Block Explorer URI" }, @@ -434,9 +428,6 @@ "next": { "message": "Další" }, - "noAddressForName": { - "message": "Pro toto jméno nebyla nastavena žádná adresa." - }, "noConversionRateAvailable": { "message": "Nie je k dispozícii žiadna sadzba konverzie" }, @@ -517,9 +508,6 @@ "readdToken": { "message": "Tento token můžete v budoucnu přidat zpět s „Přidat token“ v nastavení účtu." }, - "recipientAddressPlaceholder": { - "message": "Vyhľadávať verejnú adresu (0x) alebo ENS" - }, "reject": { "message": "Odmítnout" }, diff --git a/app/_locales/sl/messages.json b/app/_locales/sl/messages.json index 64e7c5662c3c..60f18a004305 100644 --- a/app/_locales/sl/messages.json +++ b/app/_locales/sl/messages.json @@ -229,9 +229,6 @@ "editContact": { "message": "Uredi stik" }, - "ensRegistrationError": { - "message": "Napaka pri registraciji imena ENS" - }, "enterPasswordContinue": { "message": "Za nadaljevanje vnesite geslo" }, @@ -348,9 +345,6 @@ "invalidAddressRecipient": { "message": "Neveljaven nasklov prejemnika" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Ni omrežja ETH, nastavljene so male črke" - }, "invalidBlockExplorerURL": { "message": "Neveljaven Block Explorer URL" }, @@ -447,9 +441,6 @@ "next": { "message": "Naprej" }, - "noAddressForName": { - "message": "Za to ime ni naslovov." - }, "noConversionRateAvailable": { "message": "Menjalni tečaj ni na voljo" }, @@ -533,9 +524,6 @@ "readdToken": { "message": "Ta žeton lahko dodate tudi kasneje z uporabo gumba “Dodaj žeton” v možnostih vašega računa." }, - "recipientAddressPlaceholder": { - "message": "Iskanje, javni naslov (0x) ali ENS" - }, "reject": { "message": "Zavrni" }, diff --git a/app/_locales/sr/messages.json b/app/_locales/sr/messages.json index 1741b7567833..58bc09614d32 100644 --- a/app/_locales/sr/messages.json +++ b/app/_locales/sr/messages.json @@ -226,9 +226,6 @@ "editContact": { "message": "Izmeni kontakt" }, - "ensRegistrationError": { - "message": "Greška u registraciji ENS imena." - }, "enterPasswordContinue": { "message": "Unesite lozinku kako biste nastavili" }, @@ -351,9 +348,6 @@ "invalidAddressRecipient": { "message": "Adresa primaoca nije važeća" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Nije ETH mreža, podešeno na mala slova" - }, "invalidBlockExplorerURL": { "message": "Nevažeći Block Explorer URL" }, @@ -450,9 +444,6 @@ "next": { "message": "Даље" }, - "noAddressForName": { - "message": "Za ovo ime nije podešena adresa." - }, "noConversionRateAvailable": { "message": "Nije dostupan kurs za konverziju" }, @@ -536,9 +527,6 @@ "readdToken": { "message": "U budućnosti možete vratiti ovaj token tako što ćete otvoriti „Dodaj token“ u meniju opcija vašeg naloga." }, - "recipientAddressPlaceholder": { - "message": "Pretraga, javna adresa (0x) ili ENS" - }, "reject": { "message": "Одбиј" }, diff --git a/app/_locales/sv/messages.json b/app/_locales/sv/messages.json index df3766108437..204c84f63caa 100644 --- a/app/_locales/sv/messages.json +++ b/app/_locales/sv/messages.json @@ -223,9 +223,6 @@ "editContact": { "message": "Redigera kontakt" }, - "ensRegistrationError": { - "message": "Fel i ENS-namnregistrering" - }, "enterPasswordContinue": { "message": "Ange lösenord för att fortsätta" }, @@ -344,9 +341,6 @@ "invalidAddressRecipient": { "message": "Mottagarens adress är ogiltig" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Ej ETH-nätverk, ange med små bokstäver" - }, "invalidBlockExplorerURL": { "message": "Ogiltig Block Explorer URL" }, @@ -443,9 +437,6 @@ "next": { "message": "Nästa" }, - "noAddressForName": { - "message": "Inga adresser har angetts för detta namn." - }, "noConversionRateAvailable": { "message": "Ingen omräkningskurs tillgänglig" }, @@ -529,9 +520,6 @@ "readdToken": { "message": "Du kan lägga till denna token i framtiden genom att välja \"Lägg till token\" i kontots alternativmeny." }, - "recipientAddressPlaceholder": { - "message": "Sök, allmän adress (0x) eller ENS" - }, "reject": { "message": "Avvisa" }, diff --git a/app/_locales/sw/messages.json b/app/_locales/sw/messages.json index 7eb535bee573..1d9be8ad3f8d 100644 --- a/app/_locales/sw/messages.json +++ b/app/_locales/sw/messages.json @@ -223,9 +223,6 @@ "editContact": { "message": "Hariri Mawasiliano" }, - "ensRegistrationError": { - "message": "Hitilafu imetokea kwenye usajili wa jina la ENS" - }, "enterPasswordContinue": { "message": "Ingiza nenosiri ili uendelee" }, @@ -341,9 +338,6 @@ "invalidAddressRecipient": { "message": "Anwani ya mpokeaji si halali" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Kwa mtandao wa ETH, weka herufi ndogo" - }, "invalidBlockExplorerURL": { "message": "Block Explorer URL batili" }, @@ -437,9 +431,6 @@ "next": { "message": "Inayofuata" }, - "noAddressForName": { - "message": "Hakuna anwani iliyoundwa kwa jina hili." - }, "noConversionRateAvailable": { "message": "Hakuna Kiwango cha Ubadilishaji" }, @@ -523,9 +514,6 @@ "readdToken": { "message": "Unaweza kuongeza tena kianzio hiki hapo baadaye kwa kwenda kwenye \"Ongeza kianzio\" kwenye machaguo yako ya menyu ya akaunti." }, - "recipientAddressPlaceholder": { - "message": "Tafuta, anwani za umma (0x), au ENS" - }, "reject": { "message": "Kataa" }, diff --git a/app/_locales/ta/messages.json b/app/_locales/ta/messages.json index f9c7274ac55c..8a6f3351db0d 100644 --- a/app/_locales/ta/messages.json +++ b/app/_locales/ta/messages.json @@ -263,9 +263,6 @@ "next": { "message": "அடுத்தது" }, - "noAddressForName": { - "message": "இந்த பெயருக்கான முகவரி அமைக்கப்படவில்லை." - }, "noTransactions": { "message": "பரிவர்த்தனைகள் இல்லை" }, diff --git a/app/_locales/th/messages.json b/app/_locales/th/messages.json index 0b2dbb8664aa..19b005ef7cee 100644 --- a/app/_locales/th/messages.json +++ b/app/_locales/th/messages.json @@ -182,9 +182,6 @@ "invalidAddressRecipient": { "message": "แอดแดรสผู้รับไม่ถูกต้อง" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "ไม่ใช่เครือข่าย ETH ตั้งเป็นตัวพิมพ์เล็ก" - }, "invalidBlockExplorerURL": { "message": "Block Explorer URI ไม่ถูกต้อง" }, @@ -248,9 +245,6 @@ "next": { "message": "ถัดไป" }, - "noAddressForName": { - "message": "ยังไม่มีแอดแดรสไหนตั้งในชื่อนี้" - }, "noTransactions": { "message": "ยังไม่มีรายการธุรกรรม" }, diff --git a/app/_locales/tl/messages.json b/app/_locales/tl/messages.json index 5068cd8e5dcd..624e9059634a 100644 --- a/app/_locales/tl/messages.json +++ b/app/_locales/tl/messages.json @@ -1597,9 +1597,6 @@ "domain": { "message": "Domain" }, - "domainNotSupportedOnNetwork": { - "message": "Hindi sinusuportahan ng network ang domain lookup" - }, "done": { "message": "Tapos na" }, @@ -1773,12 +1770,6 @@ "ensDomainsSettingTitle": { "message": "Ipinapakita ang mga ENS domain sa address bar" }, - "ensIllegalCharacter": { - "message": "Mga ilegal na character para sa ENS." - }, - "ensRegistrationError": { - "message": "Nagka-error sa pag-register ng ENS name" - }, "ensUnknownError": { "message": "Nabigong makita ang ENS." }, @@ -2422,9 +2413,6 @@ "invalidAddressRecipient": { "message": "Ang address ng tatanggap ay hindi wasto" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Hindi ETH network, itakda sa maliliit na letra" - }, "invalidAssetType": { "message": "Ang asset na ito ay isang NFT at kailangang idagdag muli sa pahina ng Mag-import ng mga NFT na matatagpuan sa ilalim ng tab ng mga NFT" }, @@ -3152,9 +3140,6 @@ "noAccountsFound": { "message": "Walang nakitang account para sa ibinigay na query sa paghahanap" }, - "noAddressForName": { - "message": "Walang naitakdang address para sa pangalang ito." - }, "noConnectedAccountDescription": { "message": "Pumili ng account na gusto mong gamitin sa site na ito para magpatuloy." }, @@ -4166,12 +4151,6 @@ "receive": { "message": "Tumanggap" }, - "recipientAddressPlaceholder": { - "message": "Ilagay ang pampublikong address (0x) o ENS name" - }, - "recipientAddressPlaceholderFlask": { - "message": "Ilagay ang pampublikong address (0x) o pangalan ng domain" - }, "recommendedGasLabel": { "message": "Nirekomenda" }, diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json index 0c5ef35c5c88..09ee23ea8d92 100644 --- a/app/_locales/tr/messages.json +++ b/app/_locales/tr/messages.json @@ -1597,9 +1597,6 @@ "domain": { "message": "Alan" }, - "domainNotSupportedOnNetwork": { - "message": "Ağ alan aramasını desteklemiyor" - }, "done": { "message": "Bitti" }, @@ -1773,12 +1770,6 @@ "ensDomainsSettingTitle": { "message": "ENS alanlarını adres çubuğunda göster" }, - "ensIllegalCharacter": { - "message": "ENS için uygun olmayan karakter." - }, - "ensRegistrationError": { - "message": "ENS adı kaydında hata" - }, "ensUnknownError": { "message": "ENS arama başarısız oldu." }, @@ -2422,9 +2413,6 @@ "invalidAddressRecipient": { "message": "Alıcı adresi geçersiz" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "ETH ağı yok, küçük harfle başlayın" - }, "invalidAssetType": { "message": "Bu varlık bir NFT'dir ve NFT'ler sekmesi altında bulunan NFT'leri İçe Aktar sayfasına yeniden eklenmesi gerekir" }, @@ -3152,9 +3140,6 @@ "noAccountsFound": { "message": "Belirtilen arama sorgusu için hesap bulunamadı" }, - "noAddressForName": { - "message": "Bu isim için adres tanımlanmamış." - }, "noConnectedAccountDescription": { "message": "Devam etmek için bu sitede kullanmak istediğiniz bir hesap seçin." }, @@ -4166,12 +4151,6 @@ "receive": { "message": "Al" }, - "recipientAddressPlaceholder": { - "message": "Genel adres (0x) veya ENS adı girin" - }, - "recipientAddressPlaceholderFlask": { - "message": "Genel adres (0x) veya alan adı girin" - }, "recommendedGasLabel": { "message": "Önerilen" }, diff --git a/app/_locales/uk/messages.json b/app/_locales/uk/messages.json index 59bb0b477008..48d559bbdb40 100644 --- a/app/_locales/uk/messages.json +++ b/app/_locales/uk/messages.json @@ -229,9 +229,6 @@ "editContact": { "message": "Редагувати контракт" }, - "ensRegistrationError": { - "message": "Помилка у реєстрації ENS ім'я" - }, "enterPasswordContinue": { "message": "Введіть пароль, щоб продовжити" }, @@ -354,9 +351,6 @@ "invalidAddressRecipient": { "message": "Недійсна адреса отримувача" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Не є мережею ETH, налаштуйте нижній регістр" - }, "invalidBlockExplorerURL": { "message": "Недійсний Block Explorer URL" }, @@ -459,9 +453,6 @@ "next": { "message": "Далі" }, - "noAddressForName": { - "message": "На це ім'я не встановлено адреси." - }, "noConversionRateAvailable": { "message": "Немає доступного обмінного курсу" }, @@ -545,9 +536,6 @@ "readdToken": { "message": "Ви можете знову додати цей токен у меню облікового запису у розділі “Додати токен”. " }, - "recipientAddressPlaceholder": { - "message": "Пошук, публічна адреса (0x), або ENS" - }, "reject": { "message": "Відхилити" }, diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index 25159e58b605..b1fa5514980e 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -1597,9 +1597,6 @@ "domain": { "message": "Tên miền" }, - "domainNotSupportedOnNetwork": { - "message": "Mạng không hỗ trợ tra cứu tên miền" - }, "done": { "message": "Hoàn tất" }, @@ -1773,12 +1770,6 @@ "ensDomainsSettingTitle": { "message": "Hiển thị tên miền ENS trong thanh địa chỉ" }, - "ensIllegalCharacter": { - "message": "Ký tự không hợp lệ đối với ENS." - }, - "ensRegistrationError": { - "message": "Lỗi khi đăng ký tên ENS" - }, "ensUnknownError": { "message": "Tra cứu ENS thất bại." }, @@ -2422,9 +2413,6 @@ "invalidAddressRecipient": { "message": "Địa chỉ người nhận không hợp lệ" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "Không phải mạng ETH, hãy đặt thành chữ viết thường" - }, "invalidAssetType": { "message": "Tài sản này là một NFT và cần được thêm lại trên trang Nhập NFT bên dưới thẻ NFT" }, @@ -3152,9 +3140,6 @@ "noAccountsFound": { "message": "Không tìm thấy tài khoản nào cho cụm từ tìm kiếm đã đưa ra" }, - "noAddressForName": { - "message": "Chưa có địa chỉ nào được đặt cho tên này." - }, "noConnectedAccountDescription": { "message": "Chọn tài khoản mà bạn muốn sử dụng trên trang web này để tiếp tục." }, @@ -4166,12 +4151,6 @@ "receive": { "message": "Nhận" }, - "recipientAddressPlaceholder": { - "message": "Nhập địa chỉ công khai (0x) hoặc tên ENS" - }, - "recipientAddressPlaceholderFlask": { - "message": "Nhập địa chỉ công khai (0x) hoặc tên miền" - }, "recommendedGasLabel": { "message": "Được đề xuất" }, diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index e2853be601a0..8733daf9431c 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -1597,9 +1597,6 @@ "domain": { "message": "域" }, - "domainNotSupportedOnNetwork": { - "message": "网络不支持域查找" - }, "done": { "message": "完成" }, @@ -1773,12 +1770,6 @@ "ensDomainsSettingTitle": { "message": "在地址栏中显示ENS域" }, - "ensIllegalCharacter": { - "message": "ENS 的非法字符。" - }, - "ensRegistrationError": { - "message": "ENS 名称注册错误" - }, "ensUnknownError": { "message": "ENS 查找失败。" }, @@ -2422,9 +2413,6 @@ "invalidAddressRecipient": { "message": "接收方地址无效" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "非 ETH 网络,请使用小写" - }, "invalidAssetType": { "message": "该资产是NFT,需要在NFT选项卡下的“导入NFT”页面上重新添加" }, @@ -3152,9 +3140,6 @@ "noAccountsFound": { "message": "未找到符合给定查询条件的账户" }, - "noAddressForName": { - "message": "此名称尚未设置地址。" - }, "noConnectedAccountDescription": { "message": "选择要在此站点上使用的账户以继续。" }, @@ -4166,12 +4151,6 @@ "receive": { "message": "收款" }, - "recipientAddressPlaceholder": { - "message": "输入公钥 (0x) 或 ENS 名称" - }, - "recipientAddressPlaceholderFlask": { - "message": "输入公钥 (0x) 或域名" - }, "recommendedGasLabel": { "message": "建议" }, diff --git a/app/_locales/zh_TW/messages.json b/app/_locales/zh_TW/messages.json index 83c0fc09e565..04d3b772da22 100644 --- a/app/_locales/zh_TW/messages.json +++ b/app/_locales/zh_TW/messages.json @@ -444,12 +444,6 @@ "message": "這個 RPC 端點回傳了一個不同的鏈 ID:$1", "description": "$1 is the return value of eth_chainId from an RPC endpoint" }, - "ensIllegalCharacter": { - "message": "Illegal Character for ENS." - }, - "ensRegistrationError": { - "message": "ENS 名稱註冊錯誤" - }, "ensUnknownError": { "message": "ENS Lookup failed." }, @@ -675,9 +669,6 @@ "invalidAddressRecipient": { "message": "接收位址錯誤" }, - "invalidAddressRecipientNotEthNetwork": { - "message": "非 ETH 網路,請設定至小寫" - }, "invalidBlockExplorerURL": { "message": "無效的區塊鏈瀏覽器 URL" }, @@ -875,9 +866,6 @@ "noAccountsFound": { "message": "指定的搜尋條件找不到帳戶" }, - "noAddressForName": { - "message": "此 ENS 尚未指定位址。" - }, "noConversionRateAvailable": { "message": "尚未有匯率比較值" }, @@ -1005,9 +993,6 @@ "receive": { "message": "接收" }, - "recipientAddressPlaceholder": { - "message": "搜尋、公開位址 (0x)、或 ENS" - }, "reject": { "message": "拒絕" }, diff --git a/app/home.html b/app/home.html index 7308064505b0..9c4ec38b448a 100644 --- a/app/home.html +++ b/app/home.html @@ -8,6 +8,7 @@ <% } else { %> MetaMask <% } %> + diff --git a/app/images/icons/close.svg b/app/images/icons/close.svg index 7b75bbb61aad..a31907c8fd62 100644 --- a/app/images/icons/close.svg +++ b/app/images/icons/close.svg @@ -1 +1 @@ - + diff --git a/app/notification.html b/app/notification.html index 3a19128baa1f..c5bfd8358730 100644 --- a/app/notification.html +++ b/app/notification.html @@ -32,6 +32,7 @@ margin-top: 1rem; } + diff --git a/app/popup.html b/app/popup.html index 92806e42047a..760ec6683203 100644 --- a/app/popup.html +++ b/app/popup.html @@ -4,6 +4,7 @@ MetaMask + diff --git a/app/scripts/background.js b/app/scripts/background.js index 3c50f8760b71..3f513e142729 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -77,7 +77,7 @@ import { getPlatform, shouldEmitDappViewedEvent, } from './lib/util'; -import { generateSkipOnboardingState } from './skip-onboarding'; +import { generateWalletState } from './fixtures/generate-wallet-state'; import { createOffscreen } from './offscreen'; /* eslint-enable import/first */ @@ -559,15 +559,15 @@ export async function loadStateFromPersistence() { // migrations const migrator = new Migrator({ migrations, - defaultVersion: process.env.SKIP_ONBOARDING + defaultVersion: process.env.WITH_STATE ? FIXTURE_STATE_METADATA_VERSION : null, }); migrator.on('error', console.warn); - if (process.env.SKIP_ONBOARDING) { - const skipOnboardingStateOverrides = await generateSkipOnboardingState(); - firstTimeState = { ...firstTimeState, ...skipOnboardingStateOverrides }; + if (process.env.WITH_STATE) { + const stateOverrides = await generateWalletState(); + firstTimeState = { ...firstTimeState, ...stateOverrides }; } // read from disk @@ -1005,8 +1005,6 @@ export function setupController( updateBadge, ); - controller.txController.initApprovals(); - /** * Formats a count for display as a badge label. * diff --git a/app/scripts/constants/sentry-state.ts b/app/scripts/constants/sentry-state.ts index 10539fc7a5e4..33bf9bac0f22 100644 --- a/app/scripts/constants/sentry-state.ts +++ b/app/scripts/constants/sentry-state.ts @@ -279,8 +279,6 @@ export const SENTRY_BACKGROUND_STATE = { }, }, SnapController: { - unencryptedSnapStates: false, - snapStates: false, snaps: false, }, SnapInterfaceController: { diff --git a/app/scripts/controllers/metametrics.js b/app/scripts/controllers/metametrics.js index d815607d27e8..e7618decb3ba 100644 --- a/app/scripts/controllers/metametrics.js +++ b/app/scripts/controllers/metametrics.js @@ -333,7 +333,7 @@ export default class MetaMetricsController { * Updates an event fragment in state * * @param {string} id - The fragment id to update - * @param {MetaMetricsEventFragment} payload - Fragment settings and + * @param {Partial} payload - Fragment settings and * properties to initiate the fragment with. */ updateEventFragment(id, payload) { @@ -356,19 +356,23 @@ export default class MetaMetricsController { }); } + /** + * @typedef {object} MetaMetricsFinalizeEventFragmentOptions + * @property {boolean} [abandoned = false] - if true track the failure + * event instead of the success event + * @property {MetaMetricsContext.page} [page] - page the final event + * occurred on. This will override whatever is set on the fragment + * @property {MetaMetricsContext.referrer} [referrer] - Dapp that + * originated the fragment. This is for fallback only, the fragment referrer + * property will take precedence. + */ + /** * Finalizes a fragment, tracking either a success event or failure Event * and then removes the fragment from state. * * @param {string} id - UUID of the event fragment to be closed - * @param {object} options - * @param {boolean} [options.abandoned] - if true track the failure - * event instead of the success event - * @param {MetaMetricsContext.page} [options.page] - page the final event - * occurred on. This will override whatever is set on the fragment - * @param {MetaMetricsContext.referrer} [options.referrer] - Dapp that - * originated the fragment. This is for fallback only, the fragment referrer - * property will take precedence. + * @param {MetaMetricsFinalizeEventFragmentOptions} options */ finalizeEventFragment(id, { abandoned = false, page, referrer } = {}) { const fragment = this.store.getState().fragments[id]; @@ -837,6 +841,7 @@ export default class MetaMetricsController { metamaskState.useTokenDetection, [MetaMetricsUserTrait.UseNativeCurrencyAsPrimaryCurrency]: metamaskState.useNativeCurrencyAsPrimaryCurrency, + [MetaMetricsUserTrait.CurrentCurrency]: metamaskState.currentCurrency, ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) [MetaMetricsUserTrait.MmiExtensionId]: this.extension?.runtime?.id, [MetaMetricsUserTrait.MmiAccountAddress]: mmiAccountAddress, diff --git a/app/scripts/controllers/preferences-controller.ts b/app/scripts/controllers/preferences-controller.ts index 8a3451b8b163..b06f83739e8f 100644 --- a/app/scripts/controllers/preferences-controller.ts +++ b/app/scripts/controllers/preferences-controller.ts @@ -521,8 +521,11 @@ export default class PreferencesController { */ addKnownMethodData(fourBytePrefix: string, methodData: string): void { const { knownMethodData } = this.store.getState(); - knownMethodData[fourBytePrefix] = methodData; - this.store.updateState({ knownMethodData }); + + const updatedKnownMethodData = { ...knownMethodData }; + updatedKnownMethodData[fourBytePrefix] = methodData; + + this.store.updateState({ knownMethodData: updatedKnownMethodData }); } /** @@ -765,11 +768,16 @@ export default class PreferencesController { const addresses = Object.values(accounts).map((account) => account.address.toLowerCase(), ); - Object.keys(identities).forEach((identity) => { - if (addresses.includes(identity.toLowerCase())) { - lostIdentities[identity] = identities[identity]; - } - }); + + const updatedLostIdentities = Object.keys(identities).reduce( + (acc, identity) => { + if (addresses.includes(identity.toLowerCase())) { + acc[identity] = identities[identity]; + } + return acc; + }, + { ...(lostIdentities ?? {}) }, + ); const updatedIdentities = Object.values(accounts).reduce( (identitiesMap: Record, account) => { @@ -786,7 +794,7 @@ export default class PreferencesController { this.store.updateState({ identities: updatedIdentities, - lostIdentities, + lostIdentities: updatedLostIdentities, selectedAddress: selectedAccount?.address || '', // it will be an empty string during onboarding }); } diff --git a/app/scripts/fixtures/generate-wallet-state.js b/app/scripts/fixtures/generate-wallet-state.js new file mode 100644 index 000000000000..43d8010bcea8 --- /dev/null +++ b/app/scripts/fixtures/generate-wallet-state.js @@ -0,0 +1,318 @@ +import { ControllerMessenger } from '@metamask/base-controller'; +import { KeyringController } from '@metamask/keyring-controller'; +import { wordlist } from '@metamask/scure-bip39/dist/wordlists/english'; +import { UI_NOTIFICATIONS } from '../../../shared/notifications'; +import { E2E_SRP, defaultFixture } from '../../../test/e2e/default-fixture'; +import FixtureBuilder from '../../../test/e2e/fixture-builder'; +import { encryptorFactory } from '../lib/encryptor-factory'; +import { FIXTURES_APP_STATE } from './with-app-state'; +import { FIXTURES_NETWORKS } from './with-networks'; +import { FIXTURES_PREFERENCES } from './with-preferences'; +import { FIXTURES_ERC20_TOKENS } from './with-erc20-tokens'; +import { withAddressBook } from './with-address-book'; +import { withConfirmedTransactions } from './with-confirmed-transactions'; +import { withUnreadNotifications } from './with-unread-notifications'; + +const FIXTURES_CONFIG = process.env.WITH_STATE + ? JSON.parse(process.env.WITH_STATE) + : {}; + +/** + * Generates the wallet state based on the fixtures set in the environment variable. + * + * @returns {Promise} The generated wallet state. + */ +export async function generateWalletState() { + const fixtureBuilder = new FixtureBuilder({ inputChainId: '0xaa36a7' }); + + const { vault, accounts } = await generateVaultAndAccount( + process.env.TEST_SRP || E2E_SRP, + process.env.PASSWORD, + ); + + fixtureBuilder + .withAccountsController(generateAccountsControllerState(accounts)) + .withAddressBookController(generateAddressBookControllerState()) + .withAnnouncementController(generateAnnouncementControllerState()) + .withAppStateController(FIXTURES_APP_STATE) + .withKeyringController(generateKeyringControllerState(vault)) + .withNetworkController(generateNetworkControllerState()) + .withNotificationServicesController( + generateNotificationControllerState(accounts[0]), + ) + .withPreferencesController(generatePreferencesControllerState(accounts)) + .withTokensController(generateTokensControllerState(accounts[0])) + .withTransactionController(generateTransactionControllerState(accounts[0])); + + return fixtureBuilder.fixture.data; +} + +/** + * Generates a new vault and account based on the provided seed phrase and password. + * + * @param {string} encodedSeedPhrase - The encoded seed phrase. + * @param {string} password - The password for the vault. + * @returns {Promise<{vault: object, account: string}>} The generated vault and account. + */ +async function generateVaultAndAccount(encodedSeedPhrase, password) { + const controllerMessenger = new ControllerMessenger(); + const keyringControllerMessenger = controllerMessenger.getRestricted({ + name: 'KeyringController', + }); + const krCtrl = new KeyringController({ + encryptor: encryptorFactory(600_000), + messenger: keyringControllerMessenger, + }); + + const seedPhraseAsBuffer = Buffer.from(encodedSeedPhrase); + const _convertMnemonicToWordlistIndices = (mnemonic) => { + const indices = mnemonic + .toString() + .split(' ') + .map((word) => wordlist.indexOf(word)); + return new Uint8Array(new Uint16Array(indices).buffer); + }; + + await krCtrl.createNewVaultAndRestore( + password, + _convertMnemonicToWordlistIndices(seedPhraseAsBuffer), + ); + + const accounts = []; + const account = krCtrl.state.keyrings[0].accounts[0]; + accounts.push(account); + + for (let i = 1; i < FIXTURES_CONFIG.withAccounts; i++) { + const newAccount = await krCtrl.addNewAccount(i); + accounts.push(newAccount); + } + const { vault } = krCtrl.state; + + return { vault, accounts }; +} + +/** + * Generates the state for the KeyringController. + * + * @param {object} vault - The vault object. + * @returns {object} The generated KeyringController state. + */ +function generateKeyringControllerState(vault) { + console.log('Generating KeyringController state'); + + return { + ...defaultFixture().data.KeyringController, + vault, + }; +} + +/** + * Generates the state for the AccountsController. + * + * @param {string} accounts - The account addresses. + * @returns {object} The generated AccountsController state. + */ +function generateAccountsControllerState(accounts) { + console.log('Generating AccountsController state'); + const internalAccounts = { + selectedAccount: 'account-id', + accounts: {}, + }; + + accounts.forEach((account, index) => { + internalAccounts.accounts[`acount-id-${index}`] = { + selectedAccount: 'account-id', + id: 'account-id', + address: account, + metadata: { + name: `Account ${index + 1}`, + lastSelected: 1665507600000, + keyring: { + type: 'HD Key Tree', + }, + }, + options: {}, + methods: [ + 'personal_sign', + 'eth_signTransaction', + 'eth_signTypedData_v1', + 'eth_signTypedData_v3', + 'eth_signTypedData_v4', + ], + type: 'eip155:eoa', + }; + }); + return { + internalAccounts, + }; +} + +/** + * Generates the state for the AddressBookController. + * + * @returns {object} The generated AddressBookController state. + */ +function generateAddressBookControllerState() { + console.log('Generating AddressBookController state'); + + const numEntries = FIXTURES_CONFIG.withContacts; + if (numEntries > 0) { + return withAddressBook(numEntries); + } + + return {}; +} + +/** + * Generates the state for the AnnouncementController. + * All the what's new modals are dismissed for convenience. + * + * @returns {object} The generated AnnouncementController state. + */ +function generateAnnouncementControllerState() { + console.log('Generating AnnouncementController state'); + + const allAnnouncementsAlreadyShown = Object.keys(UI_NOTIFICATIONS).reduce( + (acc, val) => { + acc[val] = { + ...UI_NOTIFICATIONS[val], + isShown: true, + }; + return acc; + }, + {}, + ); + return allAnnouncementsAlreadyShown; +} + +/** + * Generates the state for the NotificationController. + * + * @param {string} account - The account address to add the notifications to. + * @returns {object} The generated NotificationController state. + */ +function generateNotificationControllerState(account) { + console.log('Generating NotificationController state'); + + let notifications = {}; + + if (FIXTURES_CONFIG.withUnreadNotifications > 0) { + notifications = withUnreadNotifications( + account, + FIXTURES_CONFIG.withUnreadNotifications, + ); + } + return notifications; +} + +/** + * Generates the state for the NetworkController. + * Sepolia is always pre-loaded and set as the active provider. + * + * @returns {object} The generated NetworkController state. + */ +function generateNetworkControllerState() { + console.log('Generating NetworkController state'); + + const defaultNetworkState = { + ...defaultFixture().data.NetworkController, + networkConfigurations: {}, + networksMetadata: { + sepolia: { + EIPS: { + 1559: true, + }, + status: 'available', + }, + }, + selectedNetworkClientId: 'sepolia', + }; + + if (FIXTURES_CONFIG.withNetworks) { + return { + ...defaultNetworkState, + ...FIXTURES_NETWORKS, + }; + } + return defaultNetworkState; +} + +/** + * Generates the state for the PreferencesController. + * + * @param {string} accounts - The account addresses. + * @returns {object} The generated PreferencesController state. + */ +function generatePreferencesControllerState(accounts) { + console.log('Generating PreferencesController state'); + let preferencesControllerState = {}; + + if (FIXTURES_CONFIG.withPreferences) { + preferencesControllerState = FIXTURES_PREFERENCES; + } + + // Add account identities + preferencesControllerState.identities = Object.assign( + ...accounts.map((address, index) => ({ + [address]: { + address, + lastSelected: 1725363500048, + name: `Account ${index + 1}`, + }, + })), + ); + + preferencesControllerState.lostIdentities = Object.assign( + ...accounts.map((address, index) => ({ + [address]: { + address, + lastSelected: 1725363500048, + name: `Account ${index + 1}`, + }, + })), + ); + + return preferencesControllerState; +} + +/** + * Generates the state for the TokensController. + * + * @param {string} account - The account address to add the transactions to. + * @returns {object} The generated TokensController state. + */ +function generateTokensControllerState(account) { + console.log('Generating TokensController state'); + + const tokens = FIXTURES_ERC20_TOKENS; + if (FIXTURES_CONFIG.withErc20Tokens) { + // Update `myAccount` key for the account address + for (const network of Object.values(tokens.allTokens)) { + network[account] = network.myAccount; + delete network.myAccount; + } + return tokens; + } + return {}; +} + +/** + * Generates the state for the TransactionController. + * + * @param {string} account - The account address to add the transactions to. + * @returns {object} The generated TransactionController state. + */ +function generateTransactionControllerState(account) { + console.log('Generating TransactionController state'); + + let transactions = {}; + + if (FIXTURES_CONFIG.withConfirmedTransactions > 0) { + transactions = withConfirmedTransactions( + account, + FIXTURES_CONFIG.withConfirmedTransactions, + ); + } + + return transactions; +} diff --git a/app/scripts/fixtures/with-address-book.js b/app/scripts/fixtures/with-address-book.js new file mode 100644 index 000000000000..f8b72ceae17a --- /dev/null +++ b/app/scripts/fixtures/with-address-book.js @@ -0,0 +1,45 @@ +import { CHAIN_IDS } from '../../../shared/constants/network'; + +/** + * Generates a random Ethereum address. + * + * @returns {string} A randomly generated Ethereum address. + */ +const generateRandomAddress = () => { + const hexChars = '0123456789abcdef'; + let address = '0x'; + for (let i = 0; i < 40; i++) { + address += hexChars[Math.floor(Math.random() * 16)]; + } + + return address; +}; + +/** + * Generates an address book with a specified number of entries, for the supported networks. + * + * @param {number} numEntries - The number of address book entries to generate for each network. + * @returns {object} The generated address book object. + */ +export const withAddressBook = (numEntries) => { + const networks = [CHAIN_IDS.MAINNET, CHAIN_IDS.SEPOLIA]; + + const addressBook = {}; + + networks.forEach((network) => { + addressBook[network] = {}; + + for (let i = 1; i <= numEntries; i++) { + const address = generateRandomAddress(); + addressBook[network][address] = { + address, + chainId: network, + isEns: false, + memo: '', + name: `Contact ${i}`, + }; + } + }); + + return { addressBook }; +}; diff --git a/app/scripts/fixtures/with-app-state.js b/app/scripts/fixtures/with-app-state.js new file mode 100644 index 000000000000..eff071079c81 --- /dev/null +++ b/app/scripts/fixtures/with-app-state.js @@ -0,0 +1,3 @@ +export const FIXTURES_APP_STATE = { + showProductTour: false, +}; diff --git a/app/scripts/fixtures/with-confirmed-transactions.js b/app/scripts/fixtures/with-confirmed-transactions.js new file mode 100644 index 000000000000..29a40b8185f7 --- /dev/null +++ b/app/scripts/fixtures/with-confirmed-transactions.js @@ -0,0 +1,99 @@ +import { v4 as uuidv4 } from 'uuid'; +import { CHAIN_IDS } from '../../../shared/constants/network'; + +/** + * Generates a specified number of confirmed transactions for each network. + * + * @param {string} from - The address from which the transactions are sent. + * @param {number} numEntries - The number of transactions to generate for each network. + * @returns {object} The generated transactions object. + */ +export const withConfirmedTransactions = (from, numEntries) => { + const networks = [CHAIN_IDS.MAINNET, CHAIN_IDS.SEPOLIA]; + const transactions = {}; + + networks.forEach((network) => { + for (let i = 0; i < numEntries; i++) { + const id = uuidv4(); + const transaction = { + chainId: network, + dappSuggestedGasFees: { + gas: '0x5208', + maxFeePerGas: '0x59682f0c', + maxPriorityFeePerGas: '0x59682f00', + }, + history: [ + { + chainId: network, + dappSuggestedGasFees: { + gas: '0x5208', + maxFeePerGas: '0x59682f0c', + maxPriorityFeePerGas: '0x59682f00', + }, + id, + loadingDefaults: true, + origin: 'https://metamask.github.io', + status: 'confirmed', + time: Date.now(), + txParams: { + from, + gas: '0x5208', + maxFeePerGas: '0x59682f0c', + maxPriorityFeePerGas: '0x59682f00', + to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', + value: '0x29a2241af62c0000', + }, + type: 'simpleSend', + }, + [ + { + note: 'Added new confirmed transaction.', + op: 'replace', + path: '/loadingDefaults', + timestamp: Date.now(), + value: false, + }, + { + op: 'add', + path: '/simulationData', + value: { + error: { + code: 'disabled', + message: 'Simulation disabled', + }, + tokenBalanceChanges: [], + }, + note: 'TransactionController#updateSimulationData - Update simulation data', + timestamp: Date.now(), + }, + ], + ], + simulationData: { + error: { + code: 'disabled', + message: 'Simulation disabled', + }, + tokenBalanceChanges: [], + }, + id, + loadingDefaults: false, + origin: 'https://metamask.github.io', + status: 'confirmed', + time: Date.now(), + txParams: { + from, + gas: '0x5208', + maxFeePerGas: '0x59682f0c', + maxPriorityFeePerGas: '0x59682f00', + to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', + value: '0x29a2241af62c0000', + }, + type: 'simpleSend', + }; + + transactions[id] = transaction; + } + }); + + return { transactions }; +}; diff --git a/app/scripts/fixtures/with-erc20-tokens.js b/app/scripts/fixtures/with-erc20-tokens.js new file mode 100644 index 000000000000..8088aef9e4c4 --- /dev/null +++ b/app/scripts/fixtures/with-erc20-tokens.js @@ -0,0 +1,87 @@ +const _TOKENS = [ + { + address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + symbol: 'DAI', + decimals: 18, + image: + 'https://static.metafi.codefi.network/api/v1/tokenIcons/1/0x6b175474e89094c44da98b954eedeac495271d0f.png', + isERC721: false, + aggregators: [], + }, + { + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + symbol: 'USDC', + decimals: 6, + image: + 'https://static.metafi.codefi.network/api/v1/tokenIcons/1/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48.png', + isERC721: false, + aggregators: [], + }, + { + address: '0xdAC17F958D2ee523a2206206994597C13D831ec7', + symbol: 'USDT', + decimals: 6, + image: + 'https://static.metafi.codefi.network/api/v1/tokenIcons/1/0xdAC17F958D2ee523a2206206994597C13D831ec7.png', + isERC721: false, + aggregators: [], + }, + { + address: '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F', + symbol: 'SNX', + decimals: 18, + image: + 'https://static.metafi.codefi.network/api/v1/tokenIcons/1/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F.png', + isERC721: false, + aggregators: [], + }, + { + address: '0x111111111117dC0aa78b770fA6A738034120C302', + symbol: '1INCH', + decimals: 18, + image: + 'https://static.metafi.codefi.network/api/v1/tokenIcons/1/0x111111111117dC0aa78b770fA6A738034120C302.png', + isERC721: false, + aggregators: [], + }, + { + address: '0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0', + symbol: 'MATIC', + decimals: 18, + image: + 'https://static.metafi.codefi.network/api/v1/tokenIcons/1/0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0.png', + isERC721: false, + aggregators: [], + }, + { + address: '0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE', + symbol: 'SHIB', + decimals: 18, + image: + 'https://static.metafi.codefi.network/api/v1/tokenIcons/1/0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE.png', + isERC721: false, + aggregators: [], + }, + { + address: '0xFd09911130e6930Bf87F2B0554c44F400bD80D3e', + symbol: 'ETHIX', + decimals: 18, + image: + 'https://static.metafi.codefi.network/api/v1/tokenIcons/1/0xFd09911130e6930Bf87F2B0554c44F400bD80D3e.png', + isERC721: false, + aggregators: [], + }, +]; + +export const FIXTURES_ERC20_TOKENS = { + tokens: _TOKENS, + ignoredTokens: [], + detectedTokens: [], + allTokens: { + '0x1': { + myAccount: _TOKENS, + }, + }, + allIgnoredTokens: {}, + allDetectedTokens: {}, +}; diff --git a/app/scripts/fixtures/with-networks.js b/app/scripts/fixtures/with-networks.js new file mode 100644 index 000000000000..1efb15e25f3c --- /dev/null +++ b/app/scripts/fixtures/with-networks.js @@ -0,0 +1,130 @@ +export const FIXTURES_NETWORKS = { + providerConfig: { + chainId: '0xaa36a7', + rpcPrefs: { + blockExplorerUrl: 'https://sepolia.etherscan.io', + }, + ticker: 'SepoliaETH', + type: 'sepolia', + }, + networkConfigurations: { + networkConfigurationId: { + chainId: '0xaa36a7', + nickname: 'Sepolia', + rpcPrefs: {}, + rpcUrl: 'https://sepolia.infura.io/v3/', + ticker: 'SepoliaETH', + networkConfigurationId: 'networkConfigurationId', + }, + optimism: { + chainId: '0xa', + id: 'optimism', + nickname: 'OP Mainnet', + rpcPrefs: { + blockExplorerUrl: 'https://optimistic.etherscan.io/', + imageUrl: './images/optimism.svg', + }, + rpcUrl: 'https://optimism-mainnet.infura.io/v3/', + ticker: 'ETH', + }, + base: { + chainId: '0x2105', + id: 'base', + nickname: 'Base Mainnet', + rpcPrefs: { + blockExplorerUrl: 'https://basescan.org', + imageUrl: './images/base.svg', + }, + rpcUrl: 'https://mainnet.base.org', + ticker: 'ETH', + }, + polygon: { + chainId: '0x89', + id: 'polygon', + nickname: 'Polygon Mainnet', + rpcPrefs: { + blockExplorerUrl: 'https://polygonscan.com/', + imageUrl: './images/matic-token.svg', + }, + rpcUrl: 'https://polygon-mainnet.infura.io/v3/', + ticker: 'MATIC', + }, + binance: { + chainId: '0x38', + id: 'binance', + nickname: 'BNB Chain', + rpcPrefs: { + blockExplorerUrl: 'https://bscscan.com/', + imageUrl: './images/bnb.svg', + }, + rpcUrl: 'https://bsc-dataseed.binance.org/', + ticker: 'BNB', + }, + gnosis: { + id: 'gnosis', + rpcUrl: 'https://rpc.gnosischain.com', + chainId: '0x64', + ticker: 'XDAI', + nickname: 'Gnosis', + rpcPrefs: { + blockExplorerUrl: 'https://gnosisscan.io', + imageUrl: './images/gnosis.svg', + }, + }, + arbitrum: { + id: 'arbitrum', + rpcUrl: 'https://arbitrum-mainnet.infura.io/v3/', + chainId: '0xa4b1', + ticker: 'ETH', + nickname: 'Arbitrum One', + rpcPrefs: { + blockExplorerUrl: 'https://explorer.arbitrum.io', + imageUrl: './images/arbitrum.svg', + }, + }, + avalanche: { + id: 'avalanche', + rpcUrl: 'https://avalanche-mainnet.infura.io/v3/', + chainId: '0xa86a', + ticker: 'AVAX', + nickname: 'Avalanche Network C-Chain', + rpcPrefs: { + blockExplorerUrl: 'https://snowtrace.io/', + imageUrl: './images/avax-token.svg', + }, + }, + celo: { + id: 'celo', + rpcUrl: 'https://celo-mainnet.infura.io/v3/', + chainId: '0xa4ec', + ticker: 'CELO', + nickname: 'Celo Mainnet', + rpcPrefs: { + blockExplorerUrl: 'https://celoscan.io', + imageUrl: './images/celo.svg', + }, + }, + zkSync: { + id: 'zkSync', + rpcUrl: 'https://mainnet.era.zksync.io', + chainId: '0x144', + ticker: 'ETH', + nickname: 'zkSync Era Mainnet', + rpcPrefs: { + blockExplorerUrl: 'https://explorer.zksync.io/', + imageUrl: './images/zk-sync.svg', + }, + }, + localhost: { + id: 'localhost', + rpcUrl: 'http://localhost:8545', + chainId: '0x539', + ticker: 'ETH', + nickname: 'Localhost 8545', + rpcPrefs: { + blockExplorerUrl: '', + imageUrl: '', + }, + }, + }, +}; diff --git a/app/scripts/fixtures/with-preferences.js b/app/scripts/fixtures/with-preferences.js new file mode 100644 index 000000000000..8d1e4293e8a4 --- /dev/null +++ b/app/scripts/fixtures/with-preferences.js @@ -0,0 +1,40 @@ +export const FIXTURES_PREFERENCES = { + preferences: { + hideZeroBalanceTokens: false, + showExtensionInFullSizeView: false, + showFiatInTestnets: true, + showTestNetworks: true, + smartTransactionsOptInStatus: true, + useNativeCurrencyAsPrimaryCurrency: true, + petnamesEnabled: true, + redesignedConfirmationsEnabled: true, + featureNotificationsEnabled: true, + showTokenAutodetectModal: false, + showNftAutodetectModal: false, + isRedesignedConfirmationsDeveloperEnabled: false, + showConfirmationAdvancedDetails: false, + }, + featureFlags: { + sendHexData: true, + }, + firstTimeFlowType: 'import', + completedOnboarding: true, + currentLocale: 'en', + knownMethodData: {}, + use4ByteResolution: true, + participateInMetaMetrics: true, + dataCollectionForMarketing: true, + useNftDetection: true, + useNonceField: true, + usePhishDetect: true, + useTokenDetection: true, + useCurrencyRateCheck: true, + useMultiAccountBalanceChecker: true, + useRequestQueue: true, + theme: 'light', + useExternalNameSources: true, + useTransactionSimulations: true, + enableMV3TimestampSave: true, + useExternalServices: true, + isProfileSyncingEnabled: true, +}; diff --git a/app/scripts/fixtures/with-unread-notifications.js b/app/scripts/fixtures/with-unread-notifications.js new file mode 100644 index 000000000000..e99cefe43778 --- /dev/null +++ b/app/scripts/fixtures/with-unread-notifications.js @@ -0,0 +1,57 @@ +import { v4 as uuidv4 } from 'uuid'; + +/** + * Generates a specified number of unread notifications for the given account. + * + * @param {string} account - The account address to use in the notifications. + * @param {number} numNotifications - The number of unread notifications to generate. + * @returns {object} The generated unread notifications object. + */ +export const withUnreadNotifications = (account, numNotifications) => { + const notifications = []; + + for (let i = 0; i < numNotifications; i++) { + const id = uuidv4(); + const triggerId = uuidv4(); + const txHash = `0x${uuidv4().replace(/-/gu, '').padEnd(64, '0')}`; + + const notification = { + address: account, + block_number: 59796924, + block_timestamp: '1721922504', + chain_id: 1, + created_at: new Date().toISOString(), + data: { + to: account, + from: account, + kind: 'eth_received', + amount: { + eth: '0.000100000000000000', + usd: '0.27', + }, + network_fee: { + gas_price: '30000000078', + native_token_price_in_usd: '0.497927', + }, + }, + id, + trigger_id: triggerId, + tx_hash: txHash, + unread: true, + type: 'eth_received', + createdAt: new Date().toISOString(), + isRead: false, + }; + + notifications.push(notification); + } + + const notificationServicesController = { + isFeatureAnnouncementsEnabled: true, + isMetamaskNotificationsFeatureSeen: true, + isNotificationServicesEnabled: true, + metamaskNotificationsReadList: [], + metamaskNotificationsList: notifications, + }; + return notificationServicesController; +}; diff --git a/app/scripts/lib/ComposableObservableStore.js b/app/scripts/lib/ComposableObservableStore.js index def67b51240f..e3ce671719d7 100644 --- a/app/scripts/lib/ComposableObservableStore.js +++ b/app/scripts/lib/ComposableObservableStore.js @@ -59,7 +59,7 @@ export default class ComposableObservableStore extends ObservableStore { const store = config[key]; if (store.subscribe) { config[key].subscribe((state) => { - this.updateState({ [key]: state }); + this.#onStateChange(key, state); }); } else { this.controllerMessenger.subscribe( @@ -69,7 +69,7 @@ export default class ComposableObservableStore extends ObservableStore { if (this.persist) { updatedState = getPersistentState(state, config[key].metadata); } - this.updateState({ [key]: updatedState }); + this.#onStateChange(key, updatedState); }, ); } @@ -104,4 +104,12 @@ export default class ComposableObservableStore extends ObservableStore { } return flatState; } + + #onStateChange(controllerKey, newState) { + const oldState = this.getState()[controllerKey]; + + this.updateState({ [controllerKey]: newState }); + + this.emit('stateChange', { oldState, newState, controllerKey }); + } } diff --git a/app/scripts/lib/PatchStore.test.ts b/app/scripts/lib/PatchStore.test.ts new file mode 100644 index 000000000000..2be1ec091a45 --- /dev/null +++ b/app/scripts/lib/PatchStore.test.ts @@ -0,0 +1,183 @@ +import ComposableObservableStore from './ComposableObservableStore'; +import { PatchStore } from './PatchStore'; +import { sanitizeUIState } from './state-utils'; + +jest.mock('./state-utils'); + +function createComposableStoreMock() { + return { + on: jest.fn(), + removeListener: jest.fn(), + } as unknown as jest.Mocked; +} + +function triggerStateChange( + composableStoreMock: jest.Mocked, + oldState: Record, + newState: Record, +) { + composableStoreMock.on.mock.calls[0][1]({ + controllerKey: 'test-controller', + oldState, + newState, + }); +} + +describe('PatchStore', () => { + const sanitizeUIStateMock = jest.mocked(sanitizeUIState); + + beforeEach(() => { + jest.resetAllMocks(); + sanitizeUIStateMock.mockImplementation((state) => state); + }); + + describe('flushPendingPatches', () => { + it('returns pending patches created by composable store events', () => { + const composableStoreMock = createComposableStoreMock(); + const patchStore = new PatchStore(composableStoreMock); + + triggerStateChange( + composableStoreMock, + { test1: 'value1' }, + { test1: 'value2' }, + ); + + triggerStateChange( + composableStoreMock, + { test2: true }, + { test2: false }, + ); + + const patches = patchStore.flushPendingPatches(); + + expect(patches).toEqual([ + { + op: 'replace', + path: ['test1'], + value: 'value2', + }, + { + op: 'replace', + path: ['test2'], + value: false, + }, + ]); + }); + + it('ignores state properties if old and new state is shallow equal', () => { + const objectMock = {}; + const composableStoreMock = createComposableStoreMock(); + const patchStore = new PatchStore(composableStoreMock); + + triggerStateChange( + composableStoreMock, + { test1: 'value1' }, + { test1: 'value1' }, + ); + + triggerStateChange( + composableStoreMock, + { test2: objectMock }, + { test2: objectMock }, + ); + + triggerStateChange( + composableStoreMock, + { test3: { test: 'value' } }, + { test3: { test: 'value' } }, + ); + + const patches = patchStore.flushPendingPatches(); + + expect(patches).toEqual([ + { + op: 'replace', + path: ['test3'], + value: { test: 'value' }, + }, + ]); + }); + + it('returns empty array if no composable store events', () => { + const composableStoreMock = createComposableStoreMock(); + const patchStore = new PatchStore(composableStoreMock); + + const patches = patchStore.flushPendingPatches(); + + expect(patches).toEqual([]); + }); + + it('clears pending patches', () => { + const composableStoreMock = createComposableStoreMock(); + const patchStore = new PatchStore(composableStoreMock); + + triggerStateChange( + composableStoreMock, + { test1: 'value1' }, + { test1: 'value2' }, + ); + + const patches1 = patchStore.flushPendingPatches(); + const patches2 = patchStore.flushPendingPatches(); + + expect(patches1).toHaveLength(1); + expect(patches2).toHaveLength(0); + }); + + it('sanitizes state in patches', () => { + const composableStoreMock = createComposableStoreMock(); + const patchStore = new PatchStore(composableStoreMock); + + sanitizeUIStateMock.mockReturnValueOnce({ test2: 'value' }); + + triggerStateChange( + composableStoreMock, + { test1: false }, + { test1: true }, + ); + + const patches = patchStore.flushPendingPatches(); + + expect(patches).toEqual([ + { + op: 'replace', + path: ['test2'], + value: 'value', + }, + ]); + }); + + it('adds isInitialized patch if vault in new state', () => { + const composableStoreMock = createComposableStoreMock(); + const patchStore = new PatchStore(composableStoreMock); + + triggerStateChange(composableStoreMock, { vault: 0 }, { vault: 123 }); + + const patches = patchStore.flushPendingPatches(); + + expect(patches).toEqual([ + { + op: 'replace', + path: ['vault'], + value: 123, + }, + { + op: 'replace', + path: ['isInitialized'], + value: true, + }, + ]); + }); + }); + + describe('destroy', () => { + it('removes listener from composable store', () => { + const composableStoreMock = createComposableStoreMock(); + const patchStore = new PatchStore(composableStoreMock); + + patchStore.destroy(); + + expect(composableStoreMock.removeListener).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/app/scripts/lib/PatchStore.ts b/app/scripts/lib/PatchStore.ts new file mode 100644 index 000000000000..3da2d0d24b3d --- /dev/null +++ b/app/scripts/lib/PatchStore.ts @@ -0,0 +1,103 @@ +import { createProjectLogger } from '@metamask/utils'; +import { Patch } from 'immer'; +import { v4 as uuid } from 'uuid'; +import ComposableObservableStore from './ComposableObservableStore'; +import { sanitizeUIState } from './state-utils'; + +const log = createProjectLogger('patch-store'); + +export class PatchStore { + private id: string; + + private observableStore: ComposableObservableStore; + + private pendingPatches: Map = new Map(); + + private listener: (request: { + controllerKey: string; + oldState: Record; + newState: Record; + }) => void; + + constructor(observableStore: ComposableObservableStore) { + this.id = uuid(); + this.observableStore = observableStore; + this.listener = this._onStateChange.bind(this); + + this.observableStore.on('stateChange', this.listener); + + log('Created', this.id); + } + + flushPendingPatches(): Patch[] { + const patches = [...this.pendingPatches.values()]; + + this.pendingPatches.clear(); + + for (const patch of patches) { + log('Flushed', patch.path.join('.'), this.id, patch); + } + + return patches; + } + + destroy() { + this.observableStore.removeListener('stateChange', this.listener); + log('Destroyed', this.id); + } + + private _onStateChange({ + oldState, + newState, + }: { + controllerKey: string; + oldState: Record; + newState: Record; + }) { + const sanitizedNewState = sanitizeUIState(newState); + const patches = this._generatePatches(oldState, sanitizedNewState); + const isInitialized = Boolean(newState.vault); + + if (isInitialized) { + patches.push({ + op: 'replace', + path: ['isInitialized'], + value: isInitialized, + }); + } + + if (!patches.length) { + return; + } + + for (const patch of patches) { + const path = patch.path.join('.'); + + this.pendingPatches.set(path, patch); + + log('Updated', path, this.id, patch); + } + } + + private _generatePatches( + oldState: Record, + newState: Record, + ): Patch[] { + return Object.keys(newState) + .map((key) => { + const oldData = oldState[key]; + const newData = newState[key]; + + if (oldData === newData) { + return null; + } + + return { + op: 'replace', + path: [key], + value: newData, + }; + }) + .filter(Boolean) as Patch[]; + } +} diff --git a/app/scripts/lib/createRPCMethodTrackingMiddleware.js b/app/scripts/lib/createRPCMethodTrackingMiddleware.js index 40b619f4f847..092b95943c2d 100644 --- a/app/scripts/lib/createRPCMethodTrackingMiddleware.js +++ b/app/scripts/lib/createRPCMethodTrackingMiddleware.js @@ -131,9 +131,9 @@ let globalRateLimitCount = 0; * * @param {MetaMetricsController} metaMetricsController * @param {OriginalRequest} req - * @param {object} properties + * @param {Partial} fragmentPayload */ -function createSignatureFragment(metaMetricsController, req, properties) { +function createSignatureFragment(metaMetricsController, req, fragmentPayload) { metaMetricsController.createEventFragment({ category: MetaMetricsEventCategory.InpageProvider, initialEvent: MetaMetricsEventName.SignatureRequested, @@ -144,7 +144,7 @@ function createSignatureFragment(metaMetricsController, req, properties) { referrer: { url: req.origin, }, - properties, + ...fragmentPayload, }); } @@ -153,23 +153,28 @@ function createSignatureFragment(metaMetricsController, req, properties) { * * @param {MetaMetricsController} metaMetricsController * @param {OriginalRequest} req - * @param {object} options - * @param {boolean} options.abandoned - * @param {object} options.properties + * @param {MetaMetricsFinalizeEventFragmentOptions} finalizeEventOptions + * @param {Partial} fragmentPayload */ function finalizeSignatureFragment( metaMetricsController, req, - { abandoned, properties }, + finalizeEventOptions, + fragmentPayload, ) { const signatureUniqueId = generateSignatureUniqueId(req.id); - metaMetricsController.updateEventFragment(signatureUniqueId, { - properties, - }); - metaMetricsController.finalizeEventFragment(signatureUniqueId, { - abandoned, - }); + if (fragmentPayload) { + metaMetricsController.updateEventFragment( + signatureUniqueId, + fragmentPayload, + ); + } + + metaMetricsController.finalizeEventFragment( + signatureUniqueId, + finalizeEventOptions, + ); } /** @@ -368,7 +373,9 @@ export default function createRPCMethodTrackingMiddleware({ } if (event === MetaMetricsEventName.SignatureRequested) { - createSignatureFragment(metaMetricsController, req, eventProperties); + createSignatureFragment(metaMetricsController, req, { + properties: eventProperties, + }); } else { metaMetricsController.trackEvent({ event, @@ -430,10 +437,19 @@ export default function createRPCMethodTrackingMiddleware({ }; if (signatureUniqueId) { - finalizeSignatureFragment(metaMetricsController, req, { + const finalizeOptions = { abandoned: event === eventType.REJECTED, + }; + const fragmentPayload = { properties, - }); + }; + + finalizeSignatureFragment( + metaMetricsController, + req, + finalizeOptions, + fragmentPayload, + ); } else { metaMetricsController.trackEvent({ event, diff --git a/app/scripts/lib/createTracingMiddleware.test.ts b/app/scripts/lib/createTracingMiddleware.test.ts index ceb87e0f3ac5..cafe97b71181 100644 --- a/app/scripts/lib/createTracingMiddleware.test.ts +++ b/app/scripts/lib/createTracingMiddleware.test.ts @@ -19,8 +19,8 @@ describe('createTracingMiddleware', () => { request = { ...REQUEST_MOCK }; - global.sentry = { - getMetaMetricsEnabled: () => Promise.resolve(true), + globalThis.sentry = { + withIsolationScope: jest.fn().mockReturnValue({}), }; }); diff --git a/app/scripts/lib/createTracingMiddleware.ts b/app/scripts/lib/createTracingMiddleware.ts index 99e0a73795b1..27e928a95199 100644 --- a/app/scripts/lib/createTracingMiddleware.ts +++ b/app/scripts/lib/createTracingMiddleware.ts @@ -1,4 +1,4 @@ -// Request and repsones are currently untyped. +// Request and responses are currently untyped. /* eslint-disable @typescript-eslint/no-explicit-any */ import { MESSAGE_TYPE } from '../../../shared/constants/app'; diff --git a/app/scripts/lib/ppom/ppom-middleware.test.ts b/app/scripts/lib/ppom/ppom-middleware.test.ts index 6b9c78a7ddc7..f82d029aac51 100644 --- a/app/scripts/lib/ppom/ppom-middleware.test.ts +++ b/app/scripts/lib/ppom/ppom-middleware.test.ts @@ -8,7 +8,6 @@ import { BlockaidResultType, } from '../../../../shared/constants/security-provider'; import { flushPromises } from '../../../../test/lib/timer-helpers'; -import { mockNetworkState } from '../../../../test/stub/networks'; import { createPPOMMiddleware, PPOMMiddlewareRequest } from './ppom-middleware'; import { generateSecurityAlertId, @@ -19,6 +18,7 @@ import { import { SecurityAlertResponse } from './types'; jest.mock('./ppom-util'); +jest.mock('@metamask/controller-utils'); const SECURITY_ALERT_ID_MOCK = '123'; const INTERNAL_ACCOUNT_ADDRESS = '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b'; @@ -33,6 +33,8 @@ const REQUEST_MOCK = { params: [], id: '', jsonrpc: '2.0' as const, + origin: 'test.com', + networkClientId: 'networkClientId', }; const createMiddleware = ( @@ -40,15 +42,9 @@ const createMiddleware = ( chainId?: Hex; error?: Error; securityAlertsEnabled?: boolean; - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - updateSecurityAlertResponse?: any; - } = { - updateSecurityAlertResponse: () => undefined, - }, + } = {}, ) => { - const { chainId, error, securityAlertsEnabled, updateSecurityAlertResponse } = - options; + const { chainId, error, securityAlertsEnabled } = options; const ppomController = {}; @@ -67,7 +63,9 @@ const createMiddleware = ( } const networkController = { - state: mockNetworkState({ chainId: chainId || CHAIN_IDS.MAINNET }), + getNetworkConfigurationByNetworkClientId: jest + .fn() + .mockReturnValue({ chainId: chainId || CHAIN_IDS.MAINNET }), }; const appStateController = { @@ -78,7 +76,9 @@ const createMiddleware = ( listAccounts: () => [{ address: INTERNAL_ACCOUNT_ADDRESS }], }; - return createPPOMMiddleware( + const updateSecurityAlertResponse = jest.fn(); + + const middleware = createPPOMMiddleware( // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any ppomController as any, @@ -95,6 +95,16 @@ const createMiddleware = ( accountsController as any, updateSecurityAlertResponse, ); + + return { + middleware, + ppomController, + preferenceController, + networkController, + appStateController, + accountsController, + updateSecurityAlertResponse, + }; }; describe('PPOMMiddleware', () => { @@ -110,14 +120,39 @@ describe('PPOMMiddleware', () => { generateSecurityAlertIdMock.mockReturnValue(SECURITY_ALERT_ID_MOCK); handlePPOMErrorMock.mockReturnValue(SECURITY_ALERT_RESPONSE_MOCK); isChainSupportedMock.mockResolvedValue(true); + + globalThis.sentry = { + withIsolationScope: jest + .fn() + .mockImplementation((fn) => fn({ setTags: jest.fn() })), + startSpan: jest.fn().mockImplementation((_, fn) => fn({})), + startSpanManual: jest.fn().mockImplementation((_, fn) => fn({})), + }; }); - it('updates alert response after validating request', async () => { - const updateSecurityAlertResponse = jest.fn(); + it('gets the network configuration for the request networkClientId', async () => { + const { middleware, networkController } = createMiddleware(); - const middlewareFunction = createMiddleware({ - updateSecurityAlertResponse, - }); + const req = { + ...REQUEST_MOCK, + method: 'eth_sendTransaction', + securityAlertResponse: undefined, + }; + + await middleware(req, { ...JsonRpcResponseStruct.TYPE }, () => undefined); + + await flushPromises(); + + expect( + networkController.getNetworkConfigurationByNetworkClientId, + ).toHaveBeenCalledTimes(1); + expect( + networkController.getNetworkConfigurationByNetworkClientId, + ).toHaveBeenCalledWith('networkClientId'); + }); + + it('updates alert response after validating request', async () => { + const { middleware, updateSecurityAlertResponse } = createMiddleware(); const req = { ...REQUEST_MOCK, @@ -125,11 +160,7 @@ describe('PPOMMiddleware', () => { securityAlertResponse: undefined, }; - await middlewareFunction( - req, - { ...JsonRpcResponseStruct.TYPE }, - () => undefined, - ); + await middleware(req, { ...JsonRpcResponseStruct.TYPE }, () => undefined); await flushPromises(); @@ -142,7 +173,7 @@ describe('PPOMMiddleware', () => { }); it('adds loading response to confirmation requests while validation is in progress', async () => { - const middlewareFunction = createMiddleware(); + const { middleware } = createMiddleware(); const req: PPOMMiddlewareRequest<(string | { to: string })[]> = { ...REQUEST_MOCK, @@ -150,11 +181,7 @@ describe('PPOMMiddleware', () => { securityAlertResponse: undefined, }; - await middlewareFunction( - req, - { ...JsonRpcResponseStruct.TYPE }, - () => undefined, - ); + await middleware(req, { ...JsonRpcResponseStruct.TYPE }, () => undefined); expect(req.securityAlertResponse?.reason).toBe(BlockaidReason.inProgress); expect(req.securityAlertResponse?.result_type).toBe( @@ -163,7 +190,7 @@ describe('PPOMMiddleware', () => { }); it('does not do validation if the user has not enabled the preference', async () => { - const middlewareFunction = createMiddleware({ + const { middleware } = createMiddleware({ securityAlertsEnabled: false, }); @@ -174,7 +201,7 @@ describe('PPOMMiddleware', () => { }; // @ts-expect-error Passing in invalid input for testing purposes - await middlewareFunction(req, undefined, () => undefined); + await middleware(req, undefined, () => undefined); expect(req.securityAlertResponse).toBeUndefined(); expect(validateRequestWithPPOM).not.toHaveBeenCalled(); @@ -182,7 +209,7 @@ describe('PPOMMiddleware', () => { it('does not do validation if user is not on a supported network', async () => { isChainSupportedMock.mockResolvedValue(false); - const middlewareFunction = createMiddleware({ + const { middleware } = createMiddleware({ chainId: '0x2', }); @@ -192,18 +219,14 @@ describe('PPOMMiddleware', () => { securityAlertResponse: undefined, }; - await middlewareFunction( - req, - { ...JsonRpcResponseStruct.TYPE }, - () => undefined, - ); + await middleware(req, { ...JsonRpcResponseStruct.TYPE }, () => undefined); expect(req.securityAlertResponse).toBeUndefined(); expect(validateRequestWithPPOM).not.toHaveBeenCalled(); }); it('does not do validation when request is not for confirmation method', async () => { - const middlewareFunction = createMiddleware(); + const { middleware } = createMiddleware(); const req = { ...REQUEST_MOCK, @@ -211,18 +234,14 @@ describe('PPOMMiddleware', () => { securityAlertResponse: undefined, }; - await middlewareFunction( - req, - { ...JsonRpcResponseStruct.TYPE }, - () => undefined, - ); + await middleware(req, { ...JsonRpcResponseStruct.TYPE }, () => undefined); expect(req.securityAlertResponse).toBeUndefined(); expect(validateRequestWithPPOM).not.toHaveBeenCalled(); }); it('does not do validation when request is send to users own account', async () => { - const middlewareFunction = createMiddleware(); + const { middleware } = createMiddleware(); const req = { ...REQUEST_MOCK, @@ -231,18 +250,14 @@ describe('PPOMMiddleware', () => { securityAlertResponse: undefined, }; - await middlewareFunction( - req, - { ...JsonRpcResponseStruct.TYPE }, - () => undefined, - ); + await middleware(req, { ...JsonRpcResponseStruct.TYPE }, () => undefined); expect(req.securityAlertResponse).toBeUndefined(); expect(validateRequestWithPPOM).not.toHaveBeenCalled(); }); it('does not do validation for SIWE signature', async () => { - const middlewareFunction = createMiddleware({ + const { middleware } = createMiddleware({ securityAlertsEnabled: true, }); @@ -281,17 +296,17 @@ describe('PPOMMiddleware', () => { }); // @ts-expect-error Passing invalid input for testing purposes - await middlewareFunction(req, undefined, () => undefined); + await middleware(req, undefined, () => undefined); expect(req.securityAlertResponse).toBeUndefined(); expect(validateRequestWithPPOM).not.toHaveBeenCalled(); }); it('calls next method', async () => { - const middlewareFunction = createMiddleware(); + const { middleware } = createMiddleware(); const nextMock = jest.fn(); - await middlewareFunction( + await middleware( { ...REQUEST_MOCK, method: 'eth_sendTransaction' }, { ...JsonRpcResponseStruct.TYPE }, nextMock, @@ -306,7 +321,7 @@ describe('PPOMMiddleware', () => { const nextMock = jest.fn(); - const middlewareFunction = createMiddleware({ error }); + const { middleware } = createMiddleware({ error }); const req = { ...REQUEST_MOCK, @@ -314,7 +329,7 @@ describe('PPOMMiddleware', () => { securityAlertResponse: undefined, }; - await middlewareFunction(req, { ...JsonRpcResponseStruct.TYPE }, nextMock); + await middleware(req, { ...JsonRpcResponseStruct.TYPE }, nextMock); expect(req.securityAlertResponse).toStrictEqual( SECURITY_ALERT_RESPONSE_MOCK, diff --git a/app/scripts/lib/ppom/ppom-middleware.ts b/app/scripts/lib/ppom/ppom-middleware.ts index d623d4868af5..5b9107337a05 100644 --- a/app/scripts/lib/ppom/ppom-middleware.ts +++ b/app/scripts/lib/ppom/ppom-middleware.ts @@ -1,6 +1,9 @@ import { AccountsController } from '@metamask/accounts-controller'; import { PPOMController } from '@metamask/ppom-validator'; -import { NetworkController } from '@metamask/network-controller'; +import { + NetworkClientId, + NetworkController, +} from '@metamask/network-controller'; import { Json, JsonRpcParams, @@ -14,7 +17,6 @@ import { SIGNING_METHODS } from '../../../../shared/constants/transaction'; import PreferencesController from '../../controllers/preferences-controller'; import { AppStateController } from '../../controllers/app-state'; import { LOADING_SECURITY_ALERT_RESPONSE } from '../../../../shared/constants/security-provider'; -import { getProviderConfig } from '../../../../ui/ducks/metamask/metamask'; import { trace, TraceContext, TraceName } from '../../../../shared/lib/trace'; import { generateSecurityAlertId, @@ -33,6 +35,7 @@ const CONFIRMATION_METHODS = Object.freeze([ export type PPOMMiddlewareRequest< Params extends JsonRpcParams = JsonRpcParams, > = Required> & { + networkClientId: NetworkClientId; securityAlertResponse?: SecurityAlertResponse | undefined; traceContext?: TraceContext; }; @@ -78,9 +81,13 @@ export function createPPOMMiddleware< const securityAlertsEnabled = preferencesController.store.getState()?.securityAlertsEnabled; - const { chainId } = getProviderConfig({ - metamask: networkController.state, - }); + // This will always exist as the SelectedNetworkMiddleware + // adds networkClientId to the request before this middleware runs + const { chainId } = + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + networkController.getNetworkConfigurationByNetworkClientId( + req.networkClientId, + )!; const isSupportedChain = await isChainSupported(chainId); if ( diff --git a/app/scripts/lib/state-utils.test.ts b/app/scripts/lib/state-utils.test.ts new file mode 100644 index 000000000000..bd296141aef7 --- /dev/null +++ b/app/scripts/lib/state-utils.test.ts @@ -0,0 +1,60 @@ +import { sanitizeUIState } from './state-utils'; + +describe('State Utils', () => { + describe('sanitizeUIState', () => { + it('removes unsafe properties', () => { + const state = { + test1: 'value1', + snapStates: true, + unencryptedSnapStates: true, + vault: true, + test2: false, + }; + + const sanitizedState = sanitizeUIState(state); + + expect(sanitizedState).toStrictEqual({ + test1: 'value1', + test2: false, + }); + }); + + it('strips large properties from snaps state', () => { + const state = { + test1: 'value1', + test2: true, + snaps: { + snap1: { + id: 'snap1', + test3: 123, + sourceCode: 'sourceCode1', + auxiliaryFiles: 'auxiliaryFiles1', + }, + snap2: { + id: 'snap2', + test4: 456, + sourceCode: 'sourceCode2', + auxiliaryFiles: 'auxiliaryFiles2', + }, + }, + }; + + const sanitizedState = sanitizeUIState(state); + + expect(sanitizedState).toStrictEqual({ + test1: 'value1', + test2: true, + snaps: { + snap1: { + id: 'snap1', + test3: 123, + }, + snap2: { + id: 'snap2', + test4: 456, + }, + }, + }); + }); + }); +}); diff --git a/app/scripts/lib/state-utils.ts b/app/scripts/lib/state-utils.ts new file mode 100644 index 000000000000..90275bbc7d33 --- /dev/null +++ b/app/scripts/lib/state-utils.ts @@ -0,0 +1,43 @@ +import { SnapControllerState } from '@metamask/snaps-controllers'; +import { Snap } from '@metamask/snaps-utils'; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type FlattenedUIState = Record; + +const REMOVE_KEYS = ['snapStates', 'unencryptedSnapStates', 'vault']; + +export function sanitizeUIState(state: FlattenedUIState): FlattenedUIState { + const newState = { ...state }; + + for (const key of REMOVE_KEYS) { + delete newState[key]; + } + + sanitizeSnapData(newState); + + return newState; +} + +function sanitizeSnapData(state: FlattenedUIState) { + const snapsData = state.snaps as SnapControllerState['snaps'] | undefined; + + if (!snapsData) { + return; + } + + state.snaps = Object.values(snapsData).reduce((acc, snap) => { + acc[snap.id] = stripLargeSnapData(snap) as Snap; + return acc; + }, {} as SnapControllerState['snaps']); +} + +function stripLargeSnapData(snapData: Snap): Partial { + const newData: Partial = { + ...snapData, + }; + + delete newData.sourceCode; + delete newData.auxiliaryFiles; + + return newData; +} diff --git a/app/scripts/lib/transaction/mmi-hooks.test.ts b/app/scripts/lib/transaction/mmi-hooks.test.ts index fee5dff83de5..45d0b83c2341 100644 --- a/app/scripts/lib/transaction/mmi-hooks.test.ts +++ b/app/scripts/lib/transaction/mmi-hooks.test.ts @@ -2,7 +2,6 @@ import { TransactionStatus } from '@metamask/transaction-controller'; import { afterTransactionSign, beforeCheckPendingTransaction, - beforeTransactionApproveOnInit, beforeTransactionPublish, getAdditionalSignArguments, } from './mmi-hooks'; @@ -85,24 +84,6 @@ describe('MMI hooks', () => { }); }); - describe('beforeTransactionApproveOnInit', () => { - it('returns true if txMeta has custodyStatus', () => { - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const txMeta = { custodyStatus: TransactionStatus.approved } as any; - const result = beforeTransactionApproveOnInit(txMeta); - expect(result).toBe(false); - }); - - it('returns false if txMeta has no custodyStatus', () => { - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const txMeta = { to: toMocked } as any; - const result = beforeTransactionApproveOnInit(txMeta); - expect(result).toBe(true); - }); - }); - describe('beforeCheckPendingTransaction', () => { it('returns true if txMeta has custodyStatus', () => { const txMeta = { diff --git a/app/scripts/lib/transaction/mmi-hooks.ts b/app/scripts/lib/transaction/mmi-hooks.ts index d4dc3cc4dcda..1716fe738c04 100644 --- a/app/scripts/lib/transaction/mmi-hooks.ts +++ b/app/scripts/lib/transaction/mmi-hooks.ts @@ -53,18 +53,6 @@ export function getAdditionalSignArguments( return [txMeta.custodyStatus ? txMeta : undefined]; } -/** - * Whether or not should run the logic before approve the transaction when transaction controller is rebooted. - * - * @param txMeta - The transaction meta. - */ - -export function beforeTransactionApproveOnInit( - txMeta: TransactionMeta, -): boolean { - return !txMeta?.custodyStatus; -} - /** * Whether or not should run the logic before checking the transaction when checking pending transactions. * diff --git a/app/scripts/metamask-controller.actions.test.js b/app/scripts/metamask-controller.actions.test.js index b5c4ef72dc63..f3dc22b46865 100644 --- a/app/scripts/metamask-controller.actions.test.js +++ b/app/scripts/metamask-controller.actions.test.js @@ -70,7 +70,7 @@ describe('MetaMaskController', function () { const noop = () => undefined; beforeAll(async function () { - await ganacheServer.start(); + await ganacheServer.start({ port: 32545 }); }); beforeEach(function () { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 0b9f0d20bf63..c5fd4b834aed 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -246,7 +246,6 @@ import { afterTransactionSign as afterTransactionSignMMI, beforeCheckPendingTransaction as beforeCheckPendingTransactionMMI, beforeTransactionPublish as beforeTransactionPublishMMI, - beforeTransactionApproveOnInit as beforeApproveOnInitMMI, getAdditionalSignArguments as getAdditionalSignArgumentsMMI, } from './lib/transaction/mmi-hooks'; ///: END:ONLY_INCLUDE_IF @@ -346,6 +345,8 @@ import { onPushNotificationReceived, } from './controllers/push-notifications'; import createTracingMiddleware from './lib/createTracingMiddleware'; +import { PatchStore } from './lib/PatchStore'; +import { sanitizeUIState } from './lib/state-utils'; export const METAMASK_CONTROLLER_EVENTS = { // Fired after state changes that impact the extension badge (unapproved msg count) @@ -592,28 +593,24 @@ export default class MetamaskController extends EventEmitter { state: initState.TokenListController, }); - this.assetsContractController = new AssetsContractController( - { - chainId: getCurrentChainId({ metamask: this.networkController.state }), - onPreferencesStateChange: (listener) => - this.preferencesController.store.subscribe(listener), - onNetworkDidChange: (cb) => - networkControllerMessenger.subscribe( - 'NetworkController:networkDidChange', - () => { - const networkState = this.networkController.state; - return cb(networkState); - }, - ), - getNetworkClientById: this.networkController.getNetworkClientById.bind( - this.networkController, - ), - }, - { - provider: this.provider, - }, - initState.AssetsContractController, - ); + const assetsContractControllerMessenger = + this.controllerMessenger.getRestricted({ + name: 'AssetsContractController', + allowedActions: [ + 'NetworkController:getNetworkClientById', + 'NetworkController:getNetworkConfigurationByNetworkClientId', + 'NetworkController:getSelectedNetworkClient', + 'NetworkController:getState', + ], + allowedEvents: [ + 'PreferencesController:stateChange', + 'NetworkController:networkDidChange', + ], + }); + this.assetsContractController = new AssetsContractController({ + messenger: assetsContractControllerMessenger, + chainId: getCurrentChainId({ metamask: this.networkController.state }), + }); const tokensControllerMessenger = this.controllerMessenger.getRestricted({ name: 'TokensController', @@ -649,32 +646,18 @@ export default class MetamaskController extends EventEmitter { `${this.networkController.name}:getNetworkClientById`, 'AccountsController:getSelectedAccount', 'AccountsController:getAccount', + 'AssetsContractController:getERC721AssetName', + 'AssetsContractController:getERC721AssetSymbol', + 'AssetsContractController:getERC721TokenURI', + 'AssetsContractController:getERC721OwnerOf', + 'AssetsContractController:getERC1155BalanceOf', + 'AssetsContractController:getERC1155TokenURI', ], }); this.nftController = new NftController({ state: initState.NftController, messenger: nftControllerMessenger, chainId: getCurrentChainId({ metamask: this.networkController.state }), - getERC721AssetName: this.assetsContractController.getERC721AssetName.bind( - this.assetsContractController, - ), - getERC721AssetSymbol: - this.assetsContractController.getERC721AssetSymbol.bind( - this.assetsContractController, - ), - getERC721TokenURI: this.assetsContractController.getERC721TokenURI.bind( - this.assetsContractController, - ), - getERC721OwnerOf: this.assetsContractController.getERC721OwnerOf.bind( - this.assetsContractController, - ), - getERC1155BalanceOf: - this.assetsContractController.getERC1155BalanceOf.bind( - this.assetsContractController, - ), - getERC1155TokenURI: this.assetsContractController.getERC1155TokenURI.bind( - this.assetsContractController, - ), onNftAdded: ({ address, symbol, tokenId, standard, source }) => this.metaMetricsController.trackEvent({ event: MetaMetricsEventName.NftAdded, @@ -1497,10 +1480,36 @@ export default class MetamaskController extends EventEmitter { getMetaMetricsState: () => this.metaMetricsController.state.participateInMetaMetrics ?? false, state: initState.UserStorageController, + config: { + accountSyncing: { + onAccountAdded: (profileId) => { + this.metaMetricsController.trackEvent({ + category: MetaMetricsEventCategory.ProfileSyncing, + event: MetaMetricsEventName.AccountsSyncAccountAdded, + properties: { + profile_id: profileId, + }, + }); + }, + onAccountNameUpdated: (profileId) => { + this.metaMetricsController.trackEvent({ + category: MetaMetricsEventCategory.ProfileSyncing, + event: MetaMetricsEventName.AccountsSyncAccountNameUpdated, + properties: { + profile_id: profileId, + }, + }); + }, + }, + }, + env: { + isAccountSyncingEnabled: true, + }, messenger: this.controllerMessenger.getRestricted({ name: 'UserStorageController', allowedActions: [ 'KeyringController:getState', + 'KeyringController:addNewAccount', 'SnapController:handleRequest', 'AuthenticationController:getBearerToken', 'AuthenticationController:getSessionProfile', @@ -1509,6 +1518,8 @@ export default class MetamaskController extends EventEmitter { 'AuthenticationController:performSignIn', 'NotificationServicesController:disableNotificationServices', 'NotificationServicesController:selectIsNotificationServicesEnabled', + 'AccountsController:listAccounts', + 'AccountsController:updateAccountMetadata', ], allowedEvents: [ 'KeyringController:lock', @@ -1847,7 +1858,6 @@ export default class MetamaskController extends EventEmitter { ), beforeCheckPendingTransaction: beforeCheckPendingTransactionMMI.bind(this), - beforeApproveOnInit: beforeApproveOnInitMMI.bind(this), beforePublish: beforeTransactionPublishMMI.bind(this), getAdditionalSignArguments: getAdditionalSignArgumentsMMI.bind(this), ///: END:ONLY_INCLUDE_IF @@ -3077,24 +3087,11 @@ export default class MetamaskController extends EventEmitter { getState() { const { vault } = this.keyringController.state; const isInitialized = Boolean(vault); - const flatState = this.memStore.getFlatState(); - // The vault should not be exposed to the UI - delete flatState.vault; - return { isInitialized, - ...flatState, - // Snap state, source code and other files are stripped out to prevent piping to the MetaMask UI. - snapStates: {}, - unencryptedSnapStates: {}, - snaps: Object.values(flatState.snaps ?? {}).reduce((acc, snap) => { - // eslint-disable-next-line no-unused-vars - const { sourceCode, auxiliaryFiles, ...rest } = snap; - acc[snap.id] = rest; - return acc; - }, {}), + ...sanitizeUIState(flatState), }; } @@ -3918,6 +3915,10 @@ export default class MetamaskController extends EventEmitter { userStorageController.setIsProfileSyncingEnabled.bind( userStorageController, ), + syncInternalAccountsWithUserStorage: + userStorageController.syncInternalAccountsWithUserStorage.bind( + userStorageController, + ), // NotificationServicesController checkAccountsPresence: @@ -4889,11 +4890,11 @@ export default class MetamaskController extends EventEmitter { * by creating a new transaction. * * @param {number} originalTxId - the id of the txMeta that you want to - * attempt to cancel + * attempt to cancel * @param {import( * './controllers/transactions' * ).CustomGasSettings} [customGasSettings] - overrides to use for gas params - * instead of allowing this method to generate them + * instead of allowing this method to generate them * @param options * @returns {object} MetaMask state */ @@ -4912,11 +4913,11 @@ export default class MetamaskController extends EventEmitter { * by creating a new transaction. * * @param {number} originalTxId - the id of the txMeta that you want to - * attempt to speed up + * attempt to speed up * @param {import( * './controllers/transactions' * ).CustomGasSettings} [customGasSettings] - overrides to use for gas params - * instead of allowing this method to generate them + * instead of allowing this method to generate them * @param options * @returns {object} MetaMask state */ @@ -5219,26 +5220,41 @@ export default class MetamaskController extends EventEmitter { * @param {*} outStream - The stream to provide our API over. */ setupControllerConnection(outStream) { - const api = this.getApi(); - - // report new active controller connection - this.activeControllerConnections += 1; - this.emit('controllerConnectionChanged', this.activeControllerConnections); + const patchStore = new PatchStore(this.memStore); + let uiReady = false; - // set up postStream transport - outStream.on('data', createMetaRPCHandler(api, outStream)); - const handleUpdate = (update) => { - if (!isStreamWritable(outStream)) { + const handleUpdate = () => { + if (!isStreamWritable(outStream) || !uiReady) { return; } - // send notification to client-side + + const patches = patchStore.flushPendingPatches(); + outStream.write({ jsonrpc: '2.0', method: 'sendUpdate', - params: [update], + params: [patches], }); }; + + const api = { + ...this.getApi(), + startPatches: () => { + uiReady = true; + handleUpdate(); + }, + getStatePatches: () => patchStore.flushPendingPatches(), + }; + this.on('update', handleUpdate); + + // report new active controller connection + this.activeControllerConnections += 1; + this.emit('controllerConnectionChanged', this.activeControllerConnections); + + // set up postStream transport + outStream.on('data', createMetaRPCHandler(api, outStream)); + const startUISync = () => { if (!isStreamWritable(outStream)) { return; @@ -5265,6 +5281,7 @@ export default class MetamaskController extends EventEmitter { ); outStream.mmFinished = true; this.removeListener('update', handleUpdate); + patchStore.destroy(); } }; @@ -5513,6 +5530,7 @@ export default class MetamaskController extends EventEmitter { engine.push(createTracingMiddleware()); + // PPOMMiddleware come after the SelectedNetworkMiddleware engine.push( createPPOMMiddleware( this.ppomController, diff --git a/app/scripts/metamask-controller.test.js b/app/scripts/metamask-controller.test.js index 8cd77b920d1e..401f95a21990 100644 --- a/app/scripts/metamask-controller.test.js +++ b/app/scripts/metamask-controller.test.js @@ -336,6 +336,10 @@ describe('MetaMaskController', () => { }, ]), ); + + globalThis.sentry = { + withIsolationScope: jest.fn(), + }; }); afterEach(() => { diff --git a/app/scripts/skip-onboarding.js b/app/scripts/skip-onboarding.js deleted file mode 100644 index 17ce107927ec..000000000000 --- a/app/scripts/skip-onboarding.js +++ /dev/null @@ -1,142 +0,0 @@ -import { ControllerMessenger } from '@metamask/base-controller'; -import { KeyringController } from '@metamask/keyring-controller'; -import { wordlist } from '@metamask/scure-bip39/dist/wordlists/english'; -import { UI_NOTIFICATIONS } from '../../shared/notifications'; -import { E2E_SRP, defaultFixture } from '../../test/e2e/default-fixture'; -import { encryptorFactory } from './lib/encryptor-factory'; - -export async function generateSkipOnboardingState() { - const state = defaultFixture('0xaa36a7').data; - - state.AppStateController = generateAppStateControllerState(); - state.AnnouncementController = generateAnnouncementControllerState(); - state.NetworkController = generateNetworkControllerState(); - - if (process.env.PASSWORD) { - const { vault, account } = await generateVaultAndAccount( - process.env.TEST_SRP || E2E_SRP, - process.env.PASSWORD, - ); - - state.KeyringController = generateKeyringControllerState(vault); - state.AccountsController = generateAccountsControllerState(account); - } - - return state; -} - -// dismiss product tour -function generateAppStateControllerState() { - return { - ...defaultFixture().data.AppStateController, - showProductTour: false, - }; -} - -// dismiss 'what's new' modals -function generateAnnouncementControllerState() { - const allAnnouncementsAlreadyShown = Object.keys(UI_NOTIFICATIONS).reduce( - (acc, val) => { - acc[val] = { - ...UI_NOTIFICATIONS[val], - isShown: true, - }; - return acc; - }, - {}, - ); - - return { - ...defaultFixture().data.AnnouncementController, - announcements: { - ...defaultFixture().data.AnnouncementController.announcements, - ...allAnnouncementsAlreadyShown, - }, - }; -} - -// configure 'Sepolia' network -// TODO: Support for local node -function generateNetworkControllerState() { - return { - ...defaultFixture().data.NetworkController, - networkConfigurations: { - networkConfigurationId: { - chainId: '0xaa36a7', - nickname: 'Sepolia', - rpcPrefs: {}, - rpcUrl: 'https://sepolia.infura.io/v3/6c21df2a8dcb4a77b9bbcc1b65ee9ded', - ticker: 'SepoliaETH', - networkConfigurationId: 'networkConfigurationId', - }, - }, - }; -} - -async function generateVaultAndAccount(encodedSeedPhrase, password) { - const controllerMessenger = new ControllerMessenger(); - const keyringControllerMessenger = controllerMessenger.getRestricted({ - name: 'KeyringController', - }); - const krCtrl = new KeyringController({ - encryptor: encryptorFactory(600_000), - messenger: keyringControllerMessenger, - }); - - const seedPhraseAsBuffer = Buffer.from(encodedSeedPhrase); - const _convertMnemonicToWordlistIndices = (mnemonic) => { - const indices = mnemonic - .toString() - .split(' ') - .map((word) => wordlist.indexOf(word)); - return new Uint8Array(new Uint16Array(indices).buffer); - }; - - await krCtrl.createNewVaultAndRestore( - password, - _convertMnemonicToWordlistIndices(seedPhraseAsBuffer), - ); - - const { vault } = krCtrl.state; - const account = krCtrl.state.keyrings[0].accounts[0]; - - return { vault, account }; -} - -function generateKeyringControllerState(vault) { - return { - ...defaultFixture().data.KeyringController, - vault, - }; -} - -function generateAccountsControllerState(account) { - return { - ...defaultFixture().data.AccountsController, - internalAccounts: { - selectedAccount: 'account-id', - accounts: { - 'account-id': { - id: 'account-id', - address: account, - metadata: { - name: 'Account 1', - lastSelected: 1665507600000, - keyring: { - type: 'HD Key Tree', - }, - }, - options: {}, - methods: [ - 'personal_sign', - 'eth_signTransaction', - 'eth_signTypedData_v1', - 'eth_signTypedData_v3', - 'eth_signTypedData_v4', - ], - type: 'eip155:eoa', - }, - }, - }, - }; -} diff --git a/app/scripts/snaps/preinstalled-snaps.ts b/app/scripts/snaps/preinstalled-snaps.ts index b30945e76477..d38d4f1fca4a 100644 --- a/app/scripts/snaps/preinstalled-snaps.ts +++ b/app/scripts/snaps/preinstalled-snaps.ts @@ -1,5 +1,6 @@ import type { PreinstalledSnap } from '@metamask/snaps-controllers'; import MessageSigningSnap from '@metamask/message-signing-snap/dist/preinstalled-snap.json'; +import EnsResolverSnap from '@metamask/ens-resolver-snap/dist/preinstalled-snap.json'; import AccountWatcherSnap from '@metamask/account-watcher/dist/preinstalled-snap.json'; ///: BEGIN:ONLY_INCLUDE_IF(build-flask) import BitcoinWalletSnap from '@metamask/bitcoin-wallet-snap/dist/preinstalled-snap.json'; @@ -8,6 +9,7 @@ import BitcoinWalletSnap from '@metamask/bitcoin-wallet-snap/dist/preinstalled-s // The casts here are less than ideal but we expect the SnapController to validate the inputs. const PREINSTALLED_SNAPS = Object.freeze([ MessageSigningSnap as PreinstalledSnap, + EnsResolverSnap as PreinstalledSnap, AccountWatcherSnap as PreinstalledSnap, ///: BEGIN:ONLY_INCLUDE_IF(build-flask) BitcoinWalletSnap as unknown as PreinstalledSnap, diff --git a/app/scripts/start-with-wallet-state.mjs b/app/scripts/start-with-wallet-state.mjs new file mode 100644 index 000000000000..2464b7b87097 --- /dev/null +++ b/app/scripts/start-with-wallet-state.mjs @@ -0,0 +1,122 @@ +import childProcess from 'child_process'; + +// Default fixtures and flags +const FIXTURES_FLAGS = { + '--withAccounts': { + type: 'number', + defaultValue: 30, + explanation: 'Specify the number of wallet accounts to generate.', + }, + '--withConfirmedTransactions': { + type: 'number', + defaultValue: 30, + explanation: 'Specify the number of confirmed transactions to generate.', + }, + '--withContacts': { + type: 'number', + defaultValue: 30, + explanation: + 'Specify the number of contacts to generate in the address book.', + }, + '--withErc20Tokens': { + type: 'boolean', + defaultValue: true, + explanation: 'Specify whether to import ERC20 tokens in Mainnet.', + }, + '--withNetworks': { + type: 'boolean', + defaultValue: true, + explanation: 'Specify whether to load suggested networks.', + }, + '--withPreferences': { + type: 'boolean', + defaultValue: true, + explanation: 'Specify whether to activate all preferences.', + }, + '--withUnreadNotifications': { + type: 'number', + defaultValue: 30, + explanation: 'Specify the number of unread notifications to load.', + }, + '--withStartCommand': { + type: 'string', + defaultValue: 'start', + explanation: + 'Specify the start command for the wallet (put double quotes around a multi-word command like --withStartCommand="webpack --watch").', + }, +}; + +function startWithWalletState() { + const args = process.argv.slice(2); + + if (args.includes('--help')) { + console.log('Available fixture flags:'); + Object.keys(FIXTURES_FLAGS).forEach((key) => { + console.log( + ` \x1b[36m${key}\x1b[0m ${FIXTURES_FLAGS[key].explanation} (default: \x1b[33m${FIXTURES_FLAGS[key].defaultValue}\x1b[0m)`, + ); + }); + return; + } + + const FIXTURES_CONFIG = {}; + + Object.keys(FIXTURES_FLAGS).forEach((key) => { + FIXTURES_CONFIG[key.replace(/^--/u, '')] = FIXTURES_FLAGS[key].defaultValue; + }); + + let invalidArguments = false; + + // Arguments parsing and validation + args.forEach((arg) => { + const [key, value] = arg.split('='); + if (Object.prototype.hasOwnProperty.call(FIXTURES_FLAGS, key)) { + let valueType; + switch (FIXTURES_FLAGS[key].type) { + case 'number': + valueType = !isNaN(parseFloat(value)) && isFinite(value); + break; + case 'boolean': + valueType = value === 'true' || value === 'false'; + break; + case 'string': + valueType = typeof value === 'string'; + break; + default: + throw new Error(`Unknown type for argument ${key}`); + } + if (valueType) { + const configKey = key.replace(/^--/u, ''); + if (FIXTURES_FLAGS[key].type === 'number') { + FIXTURES_CONFIG[configKey] = parseFloat(value); + } else if (FIXTURES_FLAGS[key].type === 'boolean') { + FIXTURES_CONFIG[configKey] = value === 'true'; + } else { + FIXTURES_CONFIG[configKey] = value; + } + } else { + console.error(`Invalid value for argument ${key}: ${value}`); + invalidArguments = true; + } + } else { + console.error(`Invalid argument: ${key}`); + invalidArguments = true; + } + }); + + console.log('Fixture flags:', FIXTURES_CONFIG); + if (invalidArguments) { + throw new Error('Invalid arguments'); + } + + const fixturesConfig = JSON.stringify(FIXTURES_CONFIG); + + // Start the wallet with state + process.env.WITH_STATE = fixturesConfig; + childProcess.spawn('yarn', [FIXTURES_CONFIG['withStartCommand']], { + stdio: 'inherit', + shell: true, + }); +} + +startWithWalletState(); diff --git a/builds.yml b/builds.yml index 573b0633b78c..89d41923540c 100644 --- a/builds.yml +++ b/builds.yml @@ -26,7 +26,7 @@ buildTypes: - SEGMENT_WRITE_KEY_REF: SEGMENT_PROD_WRITE_KEY - ALLOW_LOCAL_SNAPS: false - REQUIRE_SNAPS_ALLOWLIST: true - - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/iframe/6.6.2/index.html + - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/iframe/6.7.0/index.html - ACCOUNT_SNAPS_DIRECTORY_URL: https://snaps.metamask.io/account-management # Main build uses the default browser manifest manifestOverrides: false @@ -46,7 +46,7 @@ buildTypes: - SEGMENT_WRITE_KEY_REF: SEGMENT_BETA_WRITE_KEY - ALLOW_LOCAL_SNAPS: false - REQUIRE_SNAPS_ALLOWLIST: true - - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/iframe/6.6.2/index.html + - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/iframe/6.7.0/index.html - ACCOUNT_SNAPS_DIRECTORY_URL: https://snaps.metamask.io/account-management # Modifies how the version is displayed. # eg. instead of 10.25.0 -> 10.25.0-beta.2 @@ -67,7 +67,7 @@ buildTypes: - SEGMENT_FLASK_WRITE_KEY - ALLOW_LOCAL_SNAPS: true - REQUIRE_SNAPS_ALLOWLIST: false - - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/iframe/6.6.2/index.html + - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/iframe/6.7.0/index.html - SUPPORT_LINK: https://support.metamask.io/ - SUPPORT_REQUEST_LINK: https://support.metamask.io/ - INFURA_ENV_KEY_REF: INFURA_FLASK_PROJECT_ID @@ -90,7 +90,7 @@ buildTypes: - SEGMENT_WRITE_KEY_REF: SEGMENT_MMI_WRITE_KEY - ALLOW_LOCAL_SNAPS: false - REQUIRE_SNAPS_ALLOWLIST: true - - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/iframe/6.6.2/index.html + - IFRAME_EXECUTION_ENVIRONMENT_URL: https://execution.metamask.io/iframe/6.7.0/index.html - MMI_CONFIGURATION_SERVICE_URL: https://configuration.metamask-institutional.io/v2/configuration/default - SUPPORT_LINK: https://support.metamask-institutional.io - SUPPORT_REQUEST_LINK: https://support.metamask-institutional.io @@ -145,7 +145,7 @@ env: # The unlock password - PASSWORD: null - TEST_SRP: null - - SKIP_ONBOARDING: null + - WITH_STATE: null # Also see METAMASK_DEBUG and NODE_DEBUG - DEBUG: null - SUPPORT_LINK: https://support.metamask.io diff --git a/development/webpack/utils/loaders/swcLoader.ts b/development/webpack/utils/loaders/swcLoader.ts index b2511a809a27..524aca4e31ab 100644 --- a/development/webpack/utils/loaders/swcLoader.ts +++ b/development/webpack/utils/loaders/swcLoader.ts @@ -29,6 +29,16 @@ const schema = { type: 'boolean', default: false, }, + experimental: { + type: 'object', + properties: { + keepImportAttributes: { + type: 'boolean', + default: false, + }, + }, + additionalProperties: false, + }, transform: { type: 'object', properties: { diff --git a/jest.config.js b/jest.config.js index 605848626405..be304e027ace 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,14 +1,16 @@ module.exports = { collectCoverageFrom: [ - '/app/scripts/**/*.(js|ts|tsx)', + '/app/**/*.(js|ts|tsx)', + '/development/**/*.(js|ts|tsx)', + '/offscreen/**/*.(js|ts|tsx)', '/shared/**/*.(js|ts|tsx)', + '/test/**/*.(js|ts|tsx)', + '/types/**/*.(js|ts|tsx)', '/ui/**/*.(js|ts|tsx)', - '/development/build/transforms/**/*.js', - '/test/unit-global/**/*.test.(js|ts|tsx)', ], - coverageDirectory: './coverage', + coverageDirectory: './coverage/unit', coveragePathIgnorePatterns: ['.stories.*', '.snap'], - coverageReporters: process.env.CI ? ['json'] : ['html', 'json'], + coverageReporters: ['html', 'json'], reporters: [ 'default', [ diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index f2c265e4cb2c..58ce56a82eaa 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -76,7 +76,15 @@ "TextEncoder": true }, "packages": { - "@metamask/assets-controllers>multiformats": true + "@ensdomains/content-hash>multicodec>uint8arrays>multiformats": true + } + }, + "@ensdomains/content-hash>multicodec>uint8arrays>multiformats": { + "globals": { + "TextDecoder": true, + "TextEncoder": true, + "console.warn": true, + "crypto.subtle.digest": true } }, "@ensdomains/content-hash>multihashes": { @@ -191,64 +199,27 @@ "console.log": true }, "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, - "@ethersproject/hash": true - } - }, - "@ethersproject/abi>@ethersproject/address": { - "packages": { - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true, - "@ethersproject/providers>@ethersproject/rlp": true - } - }, - "@ethersproject/abi>@ethersproject/constants": { - "packages": { - "@ethersproject/bignumber": true - } - }, - "@ethersproject/abi>@ethersproject/keccak256": { - "packages": { - "@ethersproject/bytes": true, - "@metamask/ethjs>js-sha3": true - } - }, - "@ethersproject/abi>@ethersproject/logger": { - "globals": { - "console": true - } - }, - "@ethersproject/abi>@ethersproject/properties": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true - } - }, - "@ethersproject/abi>@ethersproject/strings": { - "packages": { - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bytes": true + "@ethersproject/hash": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true } }, "@ethersproject/bignumber": { "packages": { - "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/bytes": true, - "bn.js": true + "bn.js": true, + "ethers>@ethersproject/logger": true } }, "@ethersproject/bytes": { "packages": { - "@ethersproject/abi>@ethersproject/logger": true + "ethers>@ethersproject/logger": true } }, "@ethersproject/contracts": { @@ -257,116 +228,41 @@ }, "packages": { "@ethersproject/abi": true, - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, - "@ethersproject/hash>@ethersproject/abstract-signer": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/wallet>@ethersproject/abstract-provider": true + "ethers>@ethersproject/abstract-provider": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/transactions": true } }, "@ethersproject/hash": { "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, - "@ethersproject/hash>@ethersproject/base64": true - } - }, - "@ethersproject/hash>@ethersproject/abstract-signer": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true - } - }, - "@ethersproject/hash>@ethersproject/base64": { - "globals": { - "atob": true, - "btoa": true - }, - "packages": { - "@ethersproject/bytes": true + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true } }, "@ethersproject/hdnode": { "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/basex": true, - "@ethersproject/hdnode>@ethersproject/pbkdf2": true, - "@ethersproject/hdnode>@ethersproject/sha2": true, - "@ethersproject/hdnode>@ethersproject/signing-key": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/hdnode>@ethersproject/wordlists": true - } - }, - "@ethersproject/hdnode>@ethersproject/basex": { - "packages": { - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/bytes": true - } - }, - "@ethersproject/hdnode>@ethersproject/pbkdf2": { - "packages": { - "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/sha2": true - } - }, - "@ethersproject/hdnode>@ethersproject/sha2": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bytes": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true - } - }, - "@ethersproject/hdnode>@ethersproject/signing-key": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/signing-key>elliptic": true - } - }, - "@ethersproject/hdnode>@ethersproject/signing-key>elliptic": { - "packages": { - "@metamask/ppom-validator>elliptic>brorand": true, - "@metamask/ppom-validator>elliptic>hmac-drbg": true, - "@metamask/ppom-validator>elliptic>minimalistic-assert": true, - "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, - "bn.js": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, - "pumpify>inherits": true - } - }, - "@ethersproject/hdnode>@ethersproject/transactions": { - "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/signing-key": true, - "@ethersproject/providers>@ethersproject/rlp": true - } - }, - "@ethersproject/hdnode>@ethersproject/wordlists": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bytes": true, - "@ethersproject/hash": true + "ethers>@ethersproject/basex": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/pbkdf2": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/signing-key": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true, + "ethers>@ethersproject/wordlists": true } }, "@ethersproject/providers": { @@ -380,24 +276,24 @@ "setTimeout": true }, "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, "@ethersproject/hash": true, - "@ethersproject/hash>@ethersproject/abstract-signer": true, - "@ethersproject/hash>@ethersproject/base64": true, - "@ethersproject/hdnode>@ethersproject/basex": true, - "@ethersproject/hdnode>@ethersproject/sha2": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, "@ethersproject/providers>@ethersproject/web": true, "@ethersproject/providers>bech32": true, - "@ethersproject/wallet>@ethersproject/abstract-provider": true, - "@ethersproject/wallet>@ethersproject/random": true, - "@metamask/test-bundler>@ethersproject/networks": true + "@metamask/test-bundler>@ethersproject/networks": true, + "ethers>@ethersproject/abstract-provider": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/basex": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true } }, "@ethersproject/providers>@ethersproject/random": { @@ -405,12 +301,6 @@ "crypto.getRandomValues": true } }, - "@ethersproject/providers>@ethersproject/rlp": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bytes": true - } - }, "@ethersproject/providers>@ethersproject/web": { "globals": { "clearTimeout": true, @@ -418,63 +308,28 @@ "setTimeout": true }, "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bytes": true, - "@ethersproject/hash>@ethersproject/base64": true + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true } }, "@ethersproject/wallet": { "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/bytes": true, "@ethersproject/hash": true, - "@ethersproject/hash>@ethersproject/abstract-signer": true, "@ethersproject/hdnode": true, - "@ethersproject/hdnode>@ethersproject/signing-key": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/wallet>@ethersproject/abstract-provider": true, - "@ethersproject/wallet>@ethersproject/json-wallets": true, - "@ethersproject/wallet>@ethersproject/random": true - } - }, - "@ethersproject/wallet>@ethersproject/abstract-provider": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true - } - }, - "@ethersproject/wallet>@ethersproject/json-wallets": { - "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bytes": true, - "@ethersproject/hdnode": true, - "@ethersproject/hdnode>@ethersproject/pbkdf2": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/wallet>@ethersproject/json-wallets>aes-js": true, - "@ethersproject/wallet>@ethersproject/random": true, - "ethereumjs-util>ethereum-cryptography>scrypt-js": true - } - }, - "@ethersproject/wallet>@ethersproject/json-wallets>aes-js": { - "globals": { - "define": true - } - }, - "@ethersproject/wallet>@ethersproject/random": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bytes": true + "ethers>@ethersproject/abstract-provider": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/json-wallets": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/signing-key": true, + "ethers>@ethersproject/transactions": true } }, "@keystonehq/bc-ur-registry-eth": { @@ -846,14 +701,13 @@ "setTimeout": true }, "packages": { + "@ensdomains/content-hash>multicodec>uint8arrays>multiformats": true, "@ethereumjs/tx>@ethereumjs/util": true, - "@ethersproject/abi>@ethersproject/address": true, "@ethersproject/contracts": true, "@ethersproject/providers": true, "@metamask/abi-utils": true, "@metamask/assets-controllers>@metamask/base-controller": true, "@metamask/assets-controllers>@metamask/polling-controller": true, - "@metamask/assets-controllers>multiformats": true, "@metamask/contract-metadata": true, "@metamask/controller-utils": true, "@metamask/eth-query": true, @@ -863,6 +717,7 @@ "@metamask/utils": true, "bn.js": true, "cockatiel": true, + "ethers>@ethersproject/address": true, "lodash": true, "single-call-balance-checker-abi": true, "uuid": true @@ -888,14 +743,6 @@ "uuid": true } }, - "@metamask/assets-controllers>multiformats": { - "globals": { - "TextDecoder": true, - "TextEncoder": true, - "console.warn": true, - "crypto.subtle.digest": true - } - }, "@metamask/base-controller": { "globals": { "setTimeout": true @@ -1117,26 +964,11 @@ "packages": { "@ethereumjs/tx": true, "@metamask/eth-sig-util": true, - "@metamask/eth-snap-keyring>@metamask/utils": true, "@metamask/eth-snap-keyring>uuid": true, "@metamask/keyring-api": true, - "superstruct": true, - "webpack>events": true - } - }, - "@metamask/eth-snap-keyring>@metamask/utils": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - }, - "packages": { + "@metamask/utils": true, "@metamask/utils>@metamask/superstruct": true, - "@metamask/utils>@scure/base": true, - "@metamask/utils>pony-cause": true, - "@noble/hashes": true, - "browserify>buffer": true, - "nock>debug": true, - "semver": true + "webpack>events": true } }, "@metamask/eth-snap-keyring>uuid": { @@ -1509,9 +1341,9 @@ "@metamask/keyring-controller": { "packages": { "@ethereumjs/tx>@ethereumjs/util": true, + "@metamask/base-controller": true, "@metamask/browser-passworder": true, "@metamask/eth-sig-util": true, - "@metamask/keyring-controller>@metamask/base-controller": true, "@metamask/keyring-controller>@metamask/eth-hd-keyring": true, "@metamask/keyring-controller>@metamask/eth-simple-keyring": true, "@metamask/keyring-controller>ethereumjs-wallet": true, @@ -1519,14 +1351,6 @@ "@metamask/utils": true } }, - "@metamask/keyring-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/keyring-controller>@metamask/eth-hd-keyring": { "globals": { "TextEncoder": true @@ -1590,7 +1414,7 @@ "crypto-browserify>randombytes": true, "eth-lattice-keyring>gridplus-sdk>aes-js": true, "ethereumjs-util>ethereum-cryptography>bs58check": true, - "ethereumjs-util>ethereum-cryptography>scrypt-js": true, + "ethers>@ethersproject/json-wallets>scrypt-js": true, "uuid": true } }, @@ -1601,8 +1425,8 @@ "crypto-browserify>create-hmac": true, "crypto-browserify>randombytes": true, "ethereumjs-util>ethereum-cryptography>bs58check": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethers>@ethersproject/sha2>hash.js": true, "ganache>secp256k1": true, "koa>content-disposition>safe-buffer": true } @@ -2123,25 +1947,10 @@ "removeEventListener": true }, "packages": { - "@metamask/post-message-stream>@metamask/utils": true, + "@metamask/utils": true, "readable-stream": true } }, - "@metamask/post-message-stream>@metamask/utils": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - }, - "packages": { - "@metamask/utils>@metamask/superstruct": true, - "@metamask/utils>@scure/base": true, - "@metamask/utils>pony-cause": true, - "@noble/hashes": true, - "browserify>buffer": true, - "nock>debug": true, - "semver": true - } - }, "@metamask/ppom-validator": { "globals": { "URL": true, @@ -2217,7 +2026,7 @@ "@metamask/ppom-validator>elliptic>minimalistic-assert": true, "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, "bn.js": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, + "ethers>@ethersproject/sha2>hash.js": true, "pumpify>inherits": true } }, @@ -2234,7 +2043,7 @@ "packages": { "@metamask/ppom-validator>elliptic>minimalistic-assert": true, "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true + "ethers>@ethersproject/sha2>hash.js": true } }, "@metamask/profile-sync-controller": { @@ -2269,7 +2078,7 @@ "@metamask/controller-utils>@spruceid/siwe-parser>valid-url": true, "@metamask/profile-sync-controller>siwe>@spruceid/siwe-parser": true, "@metamask/profile-sync-controller>siwe>@stablelib/random": true, - "@metamask/test-bundler>ethers": true + "ethers": true } }, "@metamask/profile-sync-controller>siwe>@spruceid/siwe-parser": { @@ -2680,6 +2489,7 @@ "@metamask/utils": true, "browserify>browserify-zlib": true, "eslint>fast-deep-equal": true, + "immer": true, "readable-stream": true } }, @@ -2780,74 +2590,10 @@ }, "packages": { "@metamask/post-message-stream": true, - "@metamask/snaps-execution-environments>@metamask/snaps-utils": true, "@metamask/snaps-utils": true, "@metamask/utils": true } }, - "@metamask/snaps-execution-environments>@metamask/snaps-utils": { - "globals": { - "File": true, - "FileReader": true, - "TextDecoder": true, - "TextEncoder": true, - "URL": true, - "console.error": true, - "console.log": true, - "console.warn": true, - "crypto": true, - "document.body.appendChild": true, - "document.createElement": true, - "fetch": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/snaps-utils>@metamask/slip44": true, - "@metamask/rpc-errors": true, - "@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/permission-controller": true, - "@metamask/snaps-sdk": true, - "@metamask/snaps-sdk>@metamask/key-tree": true, - "@metamask/snaps-utils>cron-parser": true, - "@metamask/snaps-utils>fast-json-stable-stringify": true, - "@metamask/snaps-utils>fast-xml-parser": true, - "@metamask/snaps-utils>marked": true, - "@metamask/snaps-utils>rfdc": true, - "@metamask/snaps-utils>validate-npm-package-name": true, - "@metamask/utils": true, - "@metamask/utils>@metamask/superstruct": true, - "@metamask/utils>@scure/base": true, - "@noble/hashes": true, - "chalk": true, - "semver": true - } - }, - "@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, - "@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/permission-controller": { - "globals": { - "console.error": true - }, - "packages": { - "@metamask/controller-utils": true, - "@metamask/rpc-errors": true, - "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, - "@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/base-controller": true, - "@metamask/snaps-execution-environments>nanoid": true, - "@metamask/utils": true, - "deep-freeze-strict": true, - "immer": true - } - }, - "@metamask/snaps-execution-environments>nanoid": { - "globals": { - "crypto.getRandomValues": true - } - }, "@metamask/snaps-rpc-methods": { "packages": { "@metamask/rpc-errors": true, @@ -3018,54 +2764,7 @@ }, "@metamask/test-bundler>@ethersproject/networks": { "packages": { - "@ethersproject/abi>@ethersproject/logger": true - } - }, - "@metamask/test-bundler>ethers": { - "packages": { - "@ethersproject/abi": true, - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true, - "@ethersproject/contracts": true, - "@ethersproject/hash": true, - "@ethersproject/hash>@ethersproject/abstract-signer": true, - "@ethersproject/hash>@ethersproject/base64": true, - "@ethersproject/hdnode": true, - "@ethersproject/hdnode>@ethersproject/basex": true, - "@ethersproject/hdnode>@ethersproject/sha2": true, - "@ethersproject/hdnode>@ethersproject/signing-key": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/hdnode>@ethersproject/wordlists": true, - "@ethersproject/providers": true, - "@ethersproject/providers>@ethersproject/rlp": true, - "@ethersproject/providers>@ethersproject/web": true, - "@ethersproject/wallet": true, - "@ethersproject/wallet>@ethersproject/json-wallets": true, - "@ethersproject/wallet>@ethersproject/random": true, - "@metamask/test-bundler>ethers>@ethersproject/solidity": true, - "@metamask/test-bundler>ethers>@ethersproject/units": true - } - }, - "@metamask/test-bundler>ethers>@ethersproject/solidity": { - "packages": { - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/sha2": true - } - }, - "@metamask/test-bundler>ethers>@ethersproject/units": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bignumber": true + "ethers>@ethersproject/logger": true } }, "@metamask/transaction-controller": { @@ -3082,6 +2781,7 @@ "@ethersproject/abi": true, "@ethersproject/contracts": true, "@ethersproject/providers": true, + "@metamask/base-controller": true, "@metamask/controller-utils": true, "@metamask/eth-query": true, "@metamask/gas-fee-controller": true, @@ -3089,7 +2789,6 @@ "@metamask/name-controller>async-mutex": true, "@metamask/network-controller": true, "@metamask/rpc-errors": true, - "@metamask/transaction-controller>@metamask/base-controller": true, "@metamask/transaction-controller>@metamask/nonce-tracker": true, "@metamask/utils": true, "bn.js": true, @@ -3101,14 +2800,6 @@ "webpack>events": true } }, - "@metamask/transaction-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/transaction-controller>@metamask/nonce-tracker": { "packages": { "@ethersproject/providers": true, @@ -4252,7 +3943,7 @@ "eth-lattice-keyring>gridplus-sdk>secp256k1": true, "eth-lattice-keyring>gridplus-sdk>uuid": true, "ethereumjs-util>ethereum-cryptography>bs58check": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, + "ethers>@ethersproject/sha2>hash.js": true, "lodash": true } }, @@ -4346,7 +4037,7 @@ "@metamask/ppom-validator>elliptic>minimalistic-assert": true, "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, "bn.js": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, + "ethers>@ethersproject/sha2>hash.js": true, "pumpify>inherits": true } }, @@ -4377,7 +4068,7 @@ "@metamask/ppom-validator>elliptic>minimalistic-assert": true, "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, "bn.js": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, + "ethers>@ethersproject/sha2>hash.js": true, "pumpify>inherits": true } }, @@ -4486,19 +4177,119 @@ "@ensdomains/content-hash>multihashes>multibase>base-x": true } }, - "ethereumjs-util>ethereum-cryptography>hash.js": { - "packages": { - "@metamask/ppom-validator>elliptic>minimalistic-assert": true, - "pumpify>inherits": true - } - }, "ethereumjs-util>ethereum-cryptography>keccak": { "packages": { "browserify>buffer": true, "readable-stream": true } }, - "ethereumjs-util>ethereum-cryptography>scrypt-js": { + "ethereumjs-util>rlp": { + "packages": { + "bn.js": true, + "browserify>buffer": true + } + }, + "ethereumjs-wallet>randombytes": { + "globals": { + "crypto.getRandomValues": true + } + }, + "ethers": { + "packages": { + "@ethersproject/abi": true, + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/contracts": true, + "@ethersproject/hash": true, + "@ethersproject/hdnode": true, + "@ethersproject/wallet": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/basex": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/json-wallets": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/providers": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/rlp": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/signing-key": true, + "ethers>@ethersproject/solidity": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true, + "ethers>@ethersproject/units": true, + "ethers>@ethersproject/web": true, + "ethers>@ethersproject/wordlists": true + } + }, + "ethers>@ethersproject/abstract-provider": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true + } + }, + "ethers>@ethersproject/abstract-signer": { + "packages": { + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true + } + }, + "ethers>@ethersproject/address": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/rlp": true + } + }, + "ethers>@ethersproject/base64": { + "globals": { + "atob": true, + "btoa": true + }, + "packages": { + "@ethersproject/bytes": true + } + }, + "ethers>@ethersproject/basex": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/properties": true + } + }, + "ethers>@ethersproject/constants": { + "packages": { + "@ethersproject/bignumber": true + } + }, + "ethers>@ethersproject/json-wallets": { + "packages": { + "@ethersproject/bytes": true, + "@ethersproject/hdnode": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/json-wallets>aes-js": true, + "ethers>@ethersproject/json-wallets>scrypt-js": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/pbkdf2": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true + } + }, + "ethers>@ethersproject/json-wallets>aes-js": { + "globals": { + "define": true + } + }, + "ethers>@ethersproject/json-wallets>scrypt-js": { "globals": { "define": true, "setTimeout": true @@ -4507,15 +4298,179 @@ "browserify>timers-browserify": true } }, - "ethereumjs-util>rlp": { + "ethers>@ethersproject/keccak256": { "packages": { + "@ethersproject/bytes": true, + "@metamask/ethjs>js-sha3": true + } + }, + "ethers>@ethersproject/logger": { + "globals": { + "console": true + } + }, + "ethers>@ethersproject/pbkdf2": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/sha2": true + } + }, + "ethers>@ethersproject/properties": { + "packages": { + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/providers": { + "globals": { + "WebSocket": true, + "clearInterval": true, + "clearTimeout": true, + "console.log": true, + "console.warn": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/hash": true, + "ethers>@ethersproject/abstract-provider": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/basex": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/providers>@ethersproject/networks": true, + "ethers>@ethersproject/providers>@ethersproject/web": true, + "ethers>@ethersproject/providers>bech32": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true + } + }, + "ethers>@ethersproject/providers>@ethersproject/networks": { + "packages": { + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/providers>@ethersproject/web": { + "globals": { + "clearTimeout": true, + "fetch": true, + "setTimeout": true + }, + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true + } + }, + "ethers>@ethersproject/random": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/rlp": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/sha2": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/sha2>hash.js": true + } + }, + "ethers>@ethersproject/sha2>hash.js": { + "packages": { + "@metamask/ppom-validator>elliptic>minimalistic-assert": true, + "pumpify>inherits": true + } + }, + "ethers>@ethersproject/signing-key": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/signing-key>elliptic": true + } + }, + "ethers>@ethersproject/signing-key>elliptic": { + "packages": { + "@metamask/ppom-validator>elliptic>brorand": true, + "@metamask/ppom-validator>elliptic>hmac-drbg": true, + "@metamask/ppom-validator>elliptic>minimalistic-assert": true, + "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, "bn.js": true, - "browserify>buffer": true + "ethers>@ethersproject/sha2>hash.js": true, + "pumpify>inherits": true } }, - "ethereumjs-wallet>randombytes": { + "ethers>@ethersproject/solidity": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/strings": true + } + }, + "ethers>@ethersproject/strings": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/transactions": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/rlp": true, + "ethers>@ethersproject/signing-key": true + } + }, + "ethers>@ethersproject/units": { + "packages": { + "@ethersproject/bignumber": true, + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/web": { "globals": { - "crypto.getRandomValues": true + "clearTimeout": true, + "fetch": true, + "setTimeout": true + }, + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true + } + }, + "ethers>@ethersproject/wordlists": { + "packages": { + "@ethersproject/bytes": true, + "@ethersproject/hash": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true } }, "extension-port-stream": { diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index f2c265e4cb2c..58ce56a82eaa 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -76,7 +76,15 @@ "TextEncoder": true }, "packages": { - "@metamask/assets-controllers>multiformats": true + "@ensdomains/content-hash>multicodec>uint8arrays>multiformats": true + } + }, + "@ensdomains/content-hash>multicodec>uint8arrays>multiformats": { + "globals": { + "TextDecoder": true, + "TextEncoder": true, + "console.warn": true, + "crypto.subtle.digest": true } }, "@ensdomains/content-hash>multihashes": { @@ -191,64 +199,27 @@ "console.log": true }, "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, - "@ethersproject/hash": true - } - }, - "@ethersproject/abi>@ethersproject/address": { - "packages": { - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true, - "@ethersproject/providers>@ethersproject/rlp": true - } - }, - "@ethersproject/abi>@ethersproject/constants": { - "packages": { - "@ethersproject/bignumber": true - } - }, - "@ethersproject/abi>@ethersproject/keccak256": { - "packages": { - "@ethersproject/bytes": true, - "@metamask/ethjs>js-sha3": true - } - }, - "@ethersproject/abi>@ethersproject/logger": { - "globals": { - "console": true - } - }, - "@ethersproject/abi>@ethersproject/properties": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true - } - }, - "@ethersproject/abi>@ethersproject/strings": { - "packages": { - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bytes": true + "@ethersproject/hash": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true } }, "@ethersproject/bignumber": { "packages": { - "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/bytes": true, - "bn.js": true + "bn.js": true, + "ethers>@ethersproject/logger": true } }, "@ethersproject/bytes": { "packages": { - "@ethersproject/abi>@ethersproject/logger": true + "ethers>@ethersproject/logger": true } }, "@ethersproject/contracts": { @@ -257,116 +228,41 @@ }, "packages": { "@ethersproject/abi": true, - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, - "@ethersproject/hash>@ethersproject/abstract-signer": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/wallet>@ethersproject/abstract-provider": true + "ethers>@ethersproject/abstract-provider": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/transactions": true } }, "@ethersproject/hash": { "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, - "@ethersproject/hash>@ethersproject/base64": true - } - }, - "@ethersproject/hash>@ethersproject/abstract-signer": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true - } - }, - "@ethersproject/hash>@ethersproject/base64": { - "globals": { - "atob": true, - "btoa": true - }, - "packages": { - "@ethersproject/bytes": true + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true } }, "@ethersproject/hdnode": { "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/basex": true, - "@ethersproject/hdnode>@ethersproject/pbkdf2": true, - "@ethersproject/hdnode>@ethersproject/sha2": true, - "@ethersproject/hdnode>@ethersproject/signing-key": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/hdnode>@ethersproject/wordlists": true - } - }, - "@ethersproject/hdnode>@ethersproject/basex": { - "packages": { - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/bytes": true - } - }, - "@ethersproject/hdnode>@ethersproject/pbkdf2": { - "packages": { - "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/sha2": true - } - }, - "@ethersproject/hdnode>@ethersproject/sha2": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bytes": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true - } - }, - "@ethersproject/hdnode>@ethersproject/signing-key": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/signing-key>elliptic": true - } - }, - "@ethersproject/hdnode>@ethersproject/signing-key>elliptic": { - "packages": { - "@metamask/ppom-validator>elliptic>brorand": true, - "@metamask/ppom-validator>elliptic>hmac-drbg": true, - "@metamask/ppom-validator>elliptic>minimalistic-assert": true, - "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, - "bn.js": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, - "pumpify>inherits": true - } - }, - "@ethersproject/hdnode>@ethersproject/transactions": { - "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/signing-key": true, - "@ethersproject/providers>@ethersproject/rlp": true - } - }, - "@ethersproject/hdnode>@ethersproject/wordlists": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bytes": true, - "@ethersproject/hash": true + "ethers>@ethersproject/basex": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/pbkdf2": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/signing-key": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true, + "ethers>@ethersproject/wordlists": true } }, "@ethersproject/providers": { @@ -380,24 +276,24 @@ "setTimeout": true }, "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, "@ethersproject/hash": true, - "@ethersproject/hash>@ethersproject/abstract-signer": true, - "@ethersproject/hash>@ethersproject/base64": true, - "@ethersproject/hdnode>@ethersproject/basex": true, - "@ethersproject/hdnode>@ethersproject/sha2": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, "@ethersproject/providers>@ethersproject/web": true, "@ethersproject/providers>bech32": true, - "@ethersproject/wallet>@ethersproject/abstract-provider": true, - "@ethersproject/wallet>@ethersproject/random": true, - "@metamask/test-bundler>@ethersproject/networks": true + "@metamask/test-bundler>@ethersproject/networks": true, + "ethers>@ethersproject/abstract-provider": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/basex": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true } }, "@ethersproject/providers>@ethersproject/random": { @@ -405,12 +301,6 @@ "crypto.getRandomValues": true } }, - "@ethersproject/providers>@ethersproject/rlp": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bytes": true - } - }, "@ethersproject/providers>@ethersproject/web": { "globals": { "clearTimeout": true, @@ -418,63 +308,28 @@ "setTimeout": true }, "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bytes": true, - "@ethersproject/hash>@ethersproject/base64": true + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true } }, "@ethersproject/wallet": { "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/bytes": true, "@ethersproject/hash": true, - "@ethersproject/hash>@ethersproject/abstract-signer": true, "@ethersproject/hdnode": true, - "@ethersproject/hdnode>@ethersproject/signing-key": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/wallet>@ethersproject/abstract-provider": true, - "@ethersproject/wallet>@ethersproject/json-wallets": true, - "@ethersproject/wallet>@ethersproject/random": true - } - }, - "@ethersproject/wallet>@ethersproject/abstract-provider": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true - } - }, - "@ethersproject/wallet>@ethersproject/json-wallets": { - "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bytes": true, - "@ethersproject/hdnode": true, - "@ethersproject/hdnode>@ethersproject/pbkdf2": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/wallet>@ethersproject/json-wallets>aes-js": true, - "@ethersproject/wallet>@ethersproject/random": true, - "ethereumjs-util>ethereum-cryptography>scrypt-js": true - } - }, - "@ethersproject/wallet>@ethersproject/json-wallets>aes-js": { - "globals": { - "define": true - } - }, - "@ethersproject/wallet>@ethersproject/random": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bytes": true + "ethers>@ethersproject/abstract-provider": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/json-wallets": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/signing-key": true, + "ethers>@ethersproject/transactions": true } }, "@keystonehq/bc-ur-registry-eth": { @@ -846,14 +701,13 @@ "setTimeout": true }, "packages": { + "@ensdomains/content-hash>multicodec>uint8arrays>multiformats": true, "@ethereumjs/tx>@ethereumjs/util": true, - "@ethersproject/abi>@ethersproject/address": true, "@ethersproject/contracts": true, "@ethersproject/providers": true, "@metamask/abi-utils": true, "@metamask/assets-controllers>@metamask/base-controller": true, "@metamask/assets-controllers>@metamask/polling-controller": true, - "@metamask/assets-controllers>multiformats": true, "@metamask/contract-metadata": true, "@metamask/controller-utils": true, "@metamask/eth-query": true, @@ -863,6 +717,7 @@ "@metamask/utils": true, "bn.js": true, "cockatiel": true, + "ethers>@ethersproject/address": true, "lodash": true, "single-call-balance-checker-abi": true, "uuid": true @@ -888,14 +743,6 @@ "uuid": true } }, - "@metamask/assets-controllers>multiformats": { - "globals": { - "TextDecoder": true, - "TextEncoder": true, - "console.warn": true, - "crypto.subtle.digest": true - } - }, "@metamask/base-controller": { "globals": { "setTimeout": true @@ -1117,26 +964,11 @@ "packages": { "@ethereumjs/tx": true, "@metamask/eth-sig-util": true, - "@metamask/eth-snap-keyring>@metamask/utils": true, "@metamask/eth-snap-keyring>uuid": true, "@metamask/keyring-api": true, - "superstruct": true, - "webpack>events": true - } - }, - "@metamask/eth-snap-keyring>@metamask/utils": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - }, - "packages": { + "@metamask/utils": true, "@metamask/utils>@metamask/superstruct": true, - "@metamask/utils>@scure/base": true, - "@metamask/utils>pony-cause": true, - "@noble/hashes": true, - "browserify>buffer": true, - "nock>debug": true, - "semver": true + "webpack>events": true } }, "@metamask/eth-snap-keyring>uuid": { @@ -1509,9 +1341,9 @@ "@metamask/keyring-controller": { "packages": { "@ethereumjs/tx>@ethereumjs/util": true, + "@metamask/base-controller": true, "@metamask/browser-passworder": true, "@metamask/eth-sig-util": true, - "@metamask/keyring-controller>@metamask/base-controller": true, "@metamask/keyring-controller>@metamask/eth-hd-keyring": true, "@metamask/keyring-controller>@metamask/eth-simple-keyring": true, "@metamask/keyring-controller>ethereumjs-wallet": true, @@ -1519,14 +1351,6 @@ "@metamask/utils": true } }, - "@metamask/keyring-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/keyring-controller>@metamask/eth-hd-keyring": { "globals": { "TextEncoder": true @@ -1590,7 +1414,7 @@ "crypto-browserify>randombytes": true, "eth-lattice-keyring>gridplus-sdk>aes-js": true, "ethereumjs-util>ethereum-cryptography>bs58check": true, - "ethereumjs-util>ethereum-cryptography>scrypt-js": true, + "ethers>@ethersproject/json-wallets>scrypt-js": true, "uuid": true } }, @@ -1601,8 +1425,8 @@ "crypto-browserify>create-hmac": true, "crypto-browserify>randombytes": true, "ethereumjs-util>ethereum-cryptography>bs58check": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethers>@ethersproject/sha2>hash.js": true, "ganache>secp256k1": true, "koa>content-disposition>safe-buffer": true } @@ -2123,25 +1947,10 @@ "removeEventListener": true }, "packages": { - "@metamask/post-message-stream>@metamask/utils": true, + "@metamask/utils": true, "readable-stream": true } }, - "@metamask/post-message-stream>@metamask/utils": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - }, - "packages": { - "@metamask/utils>@metamask/superstruct": true, - "@metamask/utils>@scure/base": true, - "@metamask/utils>pony-cause": true, - "@noble/hashes": true, - "browserify>buffer": true, - "nock>debug": true, - "semver": true - } - }, "@metamask/ppom-validator": { "globals": { "URL": true, @@ -2217,7 +2026,7 @@ "@metamask/ppom-validator>elliptic>minimalistic-assert": true, "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, "bn.js": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, + "ethers>@ethersproject/sha2>hash.js": true, "pumpify>inherits": true } }, @@ -2234,7 +2043,7 @@ "packages": { "@metamask/ppom-validator>elliptic>minimalistic-assert": true, "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true + "ethers>@ethersproject/sha2>hash.js": true } }, "@metamask/profile-sync-controller": { @@ -2269,7 +2078,7 @@ "@metamask/controller-utils>@spruceid/siwe-parser>valid-url": true, "@metamask/profile-sync-controller>siwe>@spruceid/siwe-parser": true, "@metamask/profile-sync-controller>siwe>@stablelib/random": true, - "@metamask/test-bundler>ethers": true + "ethers": true } }, "@metamask/profile-sync-controller>siwe>@spruceid/siwe-parser": { @@ -2680,6 +2489,7 @@ "@metamask/utils": true, "browserify>browserify-zlib": true, "eslint>fast-deep-equal": true, + "immer": true, "readable-stream": true } }, @@ -2780,74 +2590,10 @@ }, "packages": { "@metamask/post-message-stream": true, - "@metamask/snaps-execution-environments>@metamask/snaps-utils": true, "@metamask/snaps-utils": true, "@metamask/utils": true } }, - "@metamask/snaps-execution-environments>@metamask/snaps-utils": { - "globals": { - "File": true, - "FileReader": true, - "TextDecoder": true, - "TextEncoder": true, - "URL": true, - "console.error": true, - "console.log": true, - "console.warn": true, - "crypto": true, - "document.body.appendChild": true, - "document.createElement": true, - "fetch": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/snaps-utils>@metamask/slip44": true, - "@metamask/rpc-errors": true, - "@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/permission-controller": true, - "@metamask/snaps-sdk": true, - "@metamask/snaps-sdk>@metamask/key-tree": true, - "@metamask/snaps-utils>cron-parser": true, - "@metamask/snaps-utils>fast-json-stable-stringify": true, - "@metamask/snaps-utils>fast-xml-parser": true, - "@metamask/snaps-utils>marked": true, - "@metamask/snaps-utils>rfdc": true, - "@metamask/snaps-utils>validate-npm-package-name": true, - "@metamask/utils": true, - "@metamask/utils>@metamask/superstruct": true, - "@metamask/utils>@scure/base": true, - "@noble/hashes": true, - "chalk": true, - "semver": true - } - }, - "@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, - "@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/permission-controller": { - "globals": { - "console.error": true - }, - "packages": { - "@metamask/controller-utils": true, - "@metamask/rpc-errors": true, - "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, - "@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/base-controller": true, - "@metamask/snaps-execution-environments>nanoid": true, - "@metamask/utils": true, - "deep-freeze-strict": true, - "immer": true - } - }, - "@metamask/snaps-execution-environments>nanoid": { - "globals": { - "crypto.getRandomValues": true - } - }, "@metamask/snaps-rpc-methods": { "packages": { "@metamask/rpc-errors": true, @@ -3018,54 +2764,7 @@ }, "@metamask/test-bundler>@ethersproject/networks": { "packages": { - "@ethersproject/abi>@ethersproject/logger": true - } - }, - "@metamask/test-bundler>ethers": { - "packages": { - "@ethersproject/abi": true, - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true, - "@ethersproject/contracts": true, - "@ethersproject/hash": true, - "@ethersproject/hash>@ethersproject/abstract-signer": true, - "@ethersproject/hash>@ethersproject/base64": true, - "@ethersproject/hdnode": true, - "@ethersproject/hdnode>@ethersproject/basex": true, - "@ethersproject/hdnode>@ethersproject/sha2": true, - "@ethersproject/hdnode>@ethersproject/signing-key": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/hdnode>@ethersproject/wordlists": true, - "@ethersproject/providers": true, - "@ethersproject/providers>@ethersproject/rlp": true, - "@ethersproject/providers>@ethersproject/web": true, - "@ethersproject/wallet": true, - "@ethersproject/wallet>@ethersproject/json-wallets": true, - "@ethersproject/wallet>@ethersproject/random": true, - "@metamask/test-bundler>ethers>@ethersproject/solidity": true, - "@metamask/test-bundler>ethers>@ethersproject/units": true - } - }, - "@metamask/test-bundler>ethers>@ethersproject/solidity": { - "packages": { - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/sha2": true - } - }, - "@metamask/test-bundler>ethers>@ethersproject/units": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bignumber": true + "ethers>@ethersproject/logger": true } }, "@metamask/transaction-controller": { @@ -3082,6 +2781,7 @@ "@ethersproject/abi": true, "@ethersproject/contracts": true, "@ethersproject/providers": true, + "@metamask/base-controller": true, "@metamask/controller-utils": true, "@metamask/eth-query": true, "@metamask/gas-fee-controller": true, @@ -3089,7 +2789,6 @@ "@metamask/name-controller>async-mutex": true, "@metamask/network-controller": true, "@metamask/rpc-errors": true, - "@metamask/transaction-controller>@metamask/base-controller": true, "@metamask/transaction-controller>@metamask/nonce-tracker": true, "@metamask/utils": true, "bn.js": true, @@ -3101,14 +2800,6 @@ "webpack>events": true } }, - "@metamask/transaction-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/transaction-controller>@metamask/nonce-tracker": { "packages": { "@ethersproject/providers": true, @@ -4252,7 +3943,7 @@ "eth-lattice-keyring>gridplus-sdk>secp256k1": true, "eth-lattice-keyring>gridplus-sdk>uuid": true, "ethereumjs-util>ethereum-cryptography>bs58check": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, + "ethers>@ethersproject/sha2>hash.js": true, "lodash": true } }, @@ -4346,7 +4037,7 @@ "@metamask/ppom-validator>elliptic>minimalistic-assert": true, "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, "bn.js": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, + "ethers>@ethersproject/sha2>hash.js": true, "pumpify>inherits": true } }, @@ -4377,7 +4068,7 @@ "@metamask/ppom-validator>elliptic>minimalistic-assert": true, "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, "bn.js": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, + "ethers>@ethersproject/sha2>hash.js": true, "pumpify>inherits": true } }, @@ -4486,19 +4177,119 @@ "@ensdomains/content-hash>multihashes>multibase>base-x": true } }, - "ethereumjs-util>ethereum-cryptography>hash.js": { - "packages": { - "@metamask/ppom-validator>elliptic>minimalistic-assert": true, - "pumpify>inherits": true - } - }, "ethereumjs-util>ethereum-cryptography>keccak": { "packages": { "browserify>buffer": true, "readable-stream": true } }, - "ethereumjs-util>ethereum-cryptography>scrypt-js": { + "ethereumjs-util>rlp": { + "packages": { + "bn.js": true, + "browserify>buffer": true + } + }, + "ethereumjs-wallet>randombytes": { + "globals": { + "crypto.getRandomValues": true + } + }, + "ethers": { + "packages": { + "@ethersproject/abi": true, + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/contracts": true, + "@ethersproject/hash": true, + "@ethersproject/hdnode": true, + "@ethersproject/wallet": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/basex": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/json-wallets": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/providers": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/rlp": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/signing-key": true, + "ethers>@ethersproject/solidity": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true, + "ethers>@ethersproject/units": true, + "ethers>@ethersproject/web": true, + "ethers>@ethersproject/wordlists": true + } + }, + "ethers>@ethersproject/abstract-provider": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true + } + }, + "ethers>@ethersproject/abstract-signer": { + "packages": { + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true + } + }, + "ethers>@ethersproject/address": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/rlp": true + } + }, + "ethers>@ethersproject/base64": { + "globals": { + "atob": true, + "btoa": true + }, + "packages": { + "@ethersproject/bytes": true + } + }, + "ethers>@ethersproject/basex": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/properties": true + } + }, + "ethers>@ethersproject/constants": { + "packages": { + "@ethersproject/bignumber": true + } + }, + "ethers>@ethersproject/json-wallets": { + "packages": { + "@ethersproject/bytes": true, + "@ethersproject/hdnode": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/json-wallets>aes-js": true, + "ethers>@ethersproject/json-wallets>scrypt-js": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/pbkdf2": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true + } + }, + "ethers>@ethersproject/json-wallets>aes-js": { + "globals": { + "define": true + } + }, + "ethers>@ethersproject/json-wallets>scrypt-js": { "globals": { "define": true, "setTimeout": true @@ -4507,15 +4298,179 @@ "browserify>timers-browserify": true } }, - "ethereumjs-util>rlp": { + "ethers>@ethersproject/keccak256": { "packages": { + "@ethersproject/bytes": true, + "@metamask/ethjs>js-sha3": true + } + }, + "ethers>@ethersproject/logger": { + "globals": { + "console": true + } + }, + "ethers>@ethersproject/pbkdf2": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/sha2": true + } + }, + "ethers>@ethersproject/properties": { + "packages": { + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/providers": { + "globals": { + "WebSocket": true, + "clearInterval": true, + "clearTimeout": true, + "console.log": true, + "console.warn": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/hash": true, + "ethers>@ethersproject/abstract-provider": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/basex": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/providers>@ethersproject/networks": true, + "ethers>@ethersproject/providers>@ethersproject/web": true, + "ethers>@ethersproject/providers>bech32": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true + } + }, + "ethers>@ethersproject/providers>@ethersproject/networks": { + "packages": { + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/providers>@ethersproject/web": { + "globals": { + "clearTimeout": true, + "fetch": true, + "setTimeout": true + }, + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true + } + }, + "ethers>@ethersproject/random": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/rlp": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/sha2": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/sha2>hash.js": true + } + }, + "ethers>@ethersproject/sha2>hash.js": { + "packages": { + "@metamask/ppom-validator>elliptic>minimalistic-assert": true, + "pumpify>inherits": true + } + }, + "ethers>@ethersproject/signing-key": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/signing-key>elliptic": true + } + }, + "ethers>@ethersproject/signing-key>elliptic": { + "packages": { + "@metamask/ppom-validator>elliptic>brorand": true, + "@metamask/ppom-validator>elliptic>hmac-drbg": true, + "@metamask/ppom-validator>elliptic>minimalistic-assert": true, + "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, "bn.js": true, - "browserify>buffer": true + "ethers>@ethersproject/sha2>hash.js": true, + "pumpify>inherits": true } }, - "ethereumjs-wallet>randombytes": { + "ethers>@ethersproject/solidity": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/strings": true + } + }, + "ethers>@ethersproject/strings": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/transactions": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/rlp": true, + "ethers>@ethersproject/signing-key": true + } + }, + "ethers>@ethersproject/units": { + "packages": { + "@ethersproject/bignumber": true, + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/web": { "globals": { - "crypto.getRandomValues": true + "clearTimeout": true, + "fetch": true, + "setTimeout": true + }, + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true + } + }, + "ethers>@ethersproject/wordlists": { + "packages": { + "@ethersproject/bytes": true, + "@ethersproject/hash": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true } }, "extension-port-stream": { diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index f2c265e4cb2c..58ce56a82eaa 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -76,7 +76,15 @@ "TextEncoder": true }, "packages": { - "@metamask/assets-controllers>multiformats": true + "@ensdomains/content-hash>multicodec>uint8arrays>multiformats": true + } + }, + "@ensdomains/content-hash>multicodec>uint8arrays>multiformats": { + "globals": { + "TextDecoder": true, + "TextEncoder": true, + "console.warn": true, + "crypto.subtle.digest": true } }, "@ensdomains/content-hash>multihashes": { @@ -191,64 +199,27 @@ "console.log": true }, "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, - "@ethersproject/hash": true - } - }, - "@ethersproject/abi>@ethersproject/address": { - "packages": { - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true, - "@ethersproject/providers>@ethersproject/rlp": true - } - }, - "@ethersproject/abi>@ethersproject/constants": { - "packages": { - "@ethersproject/bignumber": true - } - }, - "@ethersproject/abi>@ethersproject/keccak256": { - "packages": { - "@ethersproject/bytes": true, - "@metamask/ethjs>js-sha3": true - } - }, - "@ethersproject/abi>@ethersproject/logger": { - "globals": { - "console": true - } - }, - "@ethersproject/abi>@ethersproject/properties": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true - } - }, - "@ethersproject/abi>@ethersproject/strings": { - "packages": { - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bytes": true + "@ethersproject/hash": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true } }, "@ethersproject/bignumber": { "packages": { - "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/bytes": true, - "bn.js": true + "bn.js": true, + "ethers>@ethersproject/logger": true } }, "@ethersproject/bytes": { "packages": { - "@ethersproject/abi>@ethersproject/logger": true + "ethers>@ethersproject/logger": true } }, "@ethersproject/contracts": { @@ -257,116 +228,41 @@ }, "packages": { "@ethersproject/abi": true, - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, - "@ethersproject/hash>@ethersproject/abstract-signer": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/wallet>@ethersproject/abstract-provider": true + "ethers>@ethersproject/abstract-provider": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/transactions": true } }, "@ethersproject/hash": { "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, - "@ethersproject/hash>@ethersproject/base64": true - } - }, - "@ethersproject/hash>@ethersproject/abstract-signer": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true - } - }, - "@ethersproject/hash>@ethersproject/base64": { - "globals": { - "atob": true, - "btoa": true - }, - "packages": { - "@ethersproject/bytes": true + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true } }, "@ethersproject/hdnode": { "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/basex": true, - "@ethersproject/hdnode>@ethersproject/pbkdf2": true, - "@ethersproject/hdnode>@ethersproject/sha2": true, - "@ethersproject/hdnode>@ethersproject/signing-key": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/hdnode>@ethersproject/wordlists": true - } - }, - "@ethersproject/hdnode>@ethersproject/basex": { - "packages": { - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/bytes": true - } - }, - "@ethersproject/hdnode>@ethersproject/pbkdf2": { - "packages": { - "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/sha2": true - } - }, - "@ethersproject/hdnode>@ethersproject/sha2": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bytes": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true - } - }, - "@ethersproject/hdnode>@ethersproject/signing-key": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/signing-key>elliptic": true - } - }, - "@ethersproject/hdnode>@ethersproject/signing-key>elliptic": { - "packages": { - "@metamask/ppom-validator>elliptic>brorand": true, - "@metamask/ppom-validator>elliptic>hmac-drbg": true, - "@metamask/ppom-validator>elliptic>minimalistic-assert": true, - "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, - "bn.js": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, - "pumpify>inherits": true - } - }, - "@ethersproject/hdnode>@ethersproject/transactions": { - "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/signing-key": true, - "@ethersproject/providers>@ethersproject/rlp": true - } - }, - "@ethersproject/hdnode>@ethersproject/wordlists": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bytes": true, - "@ethersproject/hash": true + "ethers>@ethersproject/basex": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/pbkdf2": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/signing-key": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true, + "ethers>@ethersproject/wordlists": true } }, "@ethersproject/providers": { @@ -380,24 +276,24 @@ "setTimeout": true }, "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, "@ethersproject/hash": true, - "@ethersproject/hash>@ethersproject/abstract-signer": true, - "@ethersproject/hash>@ethersproject/base64": true, - "@ethersproject/hdnode>@ethersproject/basex": true, - "@ethersproject/hdnode>@ethersproject/sha2": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, "@ethersproject/providers>@ethersproject/web": true, "@ethersproject/providers>bech32": true, - "@ethersproject/wallet>@ethersproject/abstract-provider": true, - "@ethersproject/wallet>@ethersproject/random": true, - "@metamask/test-bundler>@ethersproject/networks": true + "@metamask/test-bundler>@ethersproject/networks": true, + "ethers>@ethersproject/abstract-provider": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/basex": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true } }, "@ethersproject/providers>@ethersproject/random": { @@ -405,12 +301,6 @@ "crypto.getRandomValues": true } }, - "@ethersproject/providers>@ethersproject/rlp": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bytes": true - } - }, "@ethersproject/providers>@ethersproject/web": { "globals": { "clearTimeout": true, @@ -418,63 +308,28 @@ "setTimeout": true }, "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bytes": true, - "@ethersproject/hash>@ethersproject/base64": true + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true } }, "@ethersproject/wallet": { "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/bytes": true, "@ethersproject/hash": true, - "@ethersproject/hash>@ethersproject/abstract-signer": true, "@ethersproject/hdnode": true, - "@ethersproject/hdnode>@ethersproject/signing-key": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/wallet>@ethersproject/abstract-provider": true, - "@ethersproject/wallet>@ethersproject/json-wallets": true, - "@ethersproject/wallet>@ethersproject/random": true - } - }, - "@ethersproject/wallet>@ethersproject/abstract-provider": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true - } - }, - "@ethersproject/wallet>@ethersproject/json-wallets": { - "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bytes": true, - "@ethersproject/hdnode": true, - "@ethersproject/hdnode>@ethersproject/pbkdf2": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/wallet>@ethersproject/json-wallets>aes-js": true, - "@ethersproject/wallet>@ethersproject/random": true, - "ethereumjs-util>ethereum-cryptography>scrypt-js": true - } - }, - "@ethersproject/wallet>@ethersproject/json-wallets>aes-js": { - "globals": { - "define": true - } - }, - "@ethersproject/wallet>@ethersproject/random": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bytes": true + "ethers>@ethersproject/abstract-provider": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/json-wallets": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/signing-key": true, + "ethers>@ethersproject/transactions": true } }, "@keystonehq/bc-ur-registry-eth": { @@ -846,14 +701,13 @@ "setTimeout": true }, "packages": { + "@ensdomains/content-hash>multicodec>uint8arrays>multiformats": true, "@ethereumjs/tx>@ethereumjs/util": true, - "@ethersproject/abi>@ethersproject/address": true, "@ethersproject/contracts": true, "@ethersproject/providers": true, "@metamask/abi-utils": true, "@metamask/assets-controllers>@metamask/base-controller": true, "@metamask/assets-controllers>@metamask/polling-controller": true, - "@metamask/assets-controllers>multiformats": true, "@metamask/contract-metadata": true, "@metamask/controller-utils": true, "@metamask/eth-query": true, @@ -863,6 +717,7 @@ "@metamask/utils": true, "bn.js": true, "cockatiel": true, + "ethers>@ethersproject/address": true, "lodash": true, "single-call-balance-checker-abi": true, "uuid": true @@ -888,14 +743,6 @@ "uuid": true } }, - "@metamask/assets-controllers>multiformats": { - "globals": { - "TextDecoder": true, - "TextEncoder": true, - "console.warn": true, - "crypto.subtle.digest": true - } - }, "@metamask/base-controller": { "globals": { "setTimeout": true @@ -1117,26 +964,11 @@ "packages": { "@ethereumjs/tx": true, "@metamask/eth-sig-util": true, - "@metamask/eth-snap-keyring>@metamask/utils": true, "@metamask/eth-snap-keyring>uuid": true, "@metamask/keyring-api": true, - "superstruct": true, - "webpack>events": true - } - }, - "@metamask/eth-snap-keyring>@metamask/utils": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - }, - "packages": { + "@metamask/utils": true, "@metamask/utils>@metamask/superstruct": true, - "@metamask/utils>@scure/base": true, - "@metamask/utils>pony-cause": true, - "@noble/hashes": true, - "browserify>buffer": true, - "nock>debug": true, - "semver": true + "webpack>events": true } }, "@metamask/eth-snap-keyring>uuid": { @@ -1509,9 +1341,9 @@ "@metamask/keyring-controller": { "packages": { "@ethereumjs/tx>@ethereumjs/util": true, + "@metamask/base-controller": true, "@metamask/browser-passworder": true, "@metamask/eth-sig-util": true, - "@metamask/keyring-controller>@metamask/base-controller": true, "@metamask/keyring-controller>@metamask/eth-hd-keyring": true, "@metamask/keyring-controller>@metamask/eth-simple-keyring": true, "@metamask/keyring-controller>ethereumjs-wallet": true, @@ -1519,14 +1351,6 @@ "@metamask/utils": true } }, - "@metamask/keyring-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/keyring-controller>@metamask/eth-hd-keyring": { "globals": { "TextEncoder": true @@ -1590,7 +1414,7 @@ "crypto-browserify>randombytes": true, "eth-lattice-keyring>gridplus-sdk>aes-js": true, "ethereumjs-util>ethereum-cryptography>bs58check": true, - "ethereumjs-util>ethereum-cryptography>scrypt-js": true, + "ethers>@ethersproject/json-wallets>scrypt-js": true, "uuid": true } }, @@ -1601,8 +1425,8 @@ "crypto-browserify>create-hmac": true, "crypto-browserify>randombytes": true, "ethereumjs-util>ethereum-cryptography>bs58check": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethers>@ethersproject/sha2>hash.js": true, "ganache>secp256k1": true, "koa>content-disposition>safe-buffer": true } @@ -2123,25 +1947,10 @@ "removeEventListener": true }, "packages": { - "@metamask/post-message-stream>@metamask/utils": true, + "@metamask/utils": true, "readable-stream": true } }, - "@metamask/post-message-stream>@metamask/utils": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - }, - "packages": { - "@metamask/utils>@metamask/superstruct": true, - "@metamask/utils>@scure/base": true, - "@metamask/utils>pony-cause": true, - "@noble/hashes": true, - "browserify>buffer": true, - "nock>debug": true, - "semver": true - } - }, "@metamask/ppom-validator": { "globals": { "URL": true, @@ -2217,7 +2026,7 @@ "@metamask/ppom-validator>elliptic>minimalistic-assert": true, "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, "bn.js": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, + "ethers>@ethersproject/sha2>hash.js": true, "pumpify>inherits": true } }, @@ -2234,7 +2043,7 @@ "packages": { "@metamask/ppom-validator>elliptic>minimalistic-assert": true, "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true + "ethers>@ethersproject/sha2>hash.js": true } }, "@metamask/profile-sync-controller": { @@ -2269,7 +2078,7 @@ "@metamask/controller-utils>@spruceid/siwe-parser>valid-url": true, "@metamask/profile-sync-controller>siwe>@spruceid/siwe-parser": true, "@metamask/profile-sync-controller>siwe>@stablelib/random": true, - "@metamask/test-bundler>ethers": true + "ethers": true } }, "@metamask/profile-sync-controller>siwe>@spruceid/siwe-parser": { @@ -2680,6 +2489,7 @@ "@metamask/utils": true, "browserify>browserify-zlib": true, "eslint>fast-deep-equal": true, + "immer": true, "readable-stream": true } }, @@ -2780,74 +2590,10 @@ }, "packages": { "@metamask/post-message-stream": true, - "@metamask/snaps-execution-environments>@metamask/snaps-utils": true, "@metamask/snaps-utils": true, "@metamask/utils": true } }, - "@metamask/snaps-execution-environments>@metamask/snaps-utils": { - "globals": { - "File": true, - "FileReader": true, - "TextDecoder": true, - "TextEncoder": true, - "URL": true, - "console.error": true, - "console.log": true, - "console.warn": true, - "crypto": true, - "document.body.appendChild": true, - "document.createElement": true, - "fetch": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/snaps-utils>@metamask/slip44": true, - "@metamask/rpc-errors": true, - "@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/permission-controller": true, - "@metamask/snaps-sdk": true, - "@metamask/snaps-sdk>@metamask/key-tree": true, - "@metamask/snaps-utils>cron-parser": true, - "@metamask/snaps-utils>fast-json-stable-stringify": true, - "@metamask/snaps-utils>fast-xml-parser": true, - "@metamask/snaps-utils>marked": true, - "@metamask/snaps-utils>rfdc": true, - "@metamask/snaps-utils>validate-npm-package-name": true, - "@metamask/utils": true, - "@metamask/utils>@metamask/superstruct": true, - "@metamask/utils>@scure/base": true, - "@noble/hashes": true, - "chalk": true, - "semver": true - } - }, - "@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, - "@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/permission-controller": { - "globals": { - "console.error": true - }, - "packages": { - "@metamask/controller-utils": true, - "@metamask/rpc-errors": true, - "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, - "@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/base-controller": true, - "@metamask/snaps-execution-environments>nanoid": true, - "@metamask/utils": true, - "deep-freeze-strict": true, - "immer": true - } - }, - "@metamask/snaps-execution-environments>nanoid": { - "globals": { - "crypto.getRandomValues": true - } - }, "@metamask/snaps-rpc-methods": { "packages": { "@metamask/rpc-errors": true, @@ -3018,54 +2764,7 @@ }, "@metamask/test-bundler>@ethersproject/networks": { "packages": { - "@ethersproject/abi>@ethersproject/logger": true - } - }, - "@metamask/test-bundler>ethers": { - "packages": { - "@ethersproject/abi": true, - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true, - "@ethersproject/contracts": true, - "@ethersproject/hash": true, - "@ethersproject/hash>@ethersproject/abstract-signer": true, - "@ethersproject/hash>@ethersproject/base64": true, - "@ethersproject/hdnode": true, - "@ethersproject/hdnode>@ethersproject/basex": true, - "@ethersproject/hdnode>@ethersproject/sha2": true, - "@ethersproject/hdnode>@ethersproject/signing-key": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/hdnode>@ethersproject/wordlists": true, - "@ethersproject/providers": true, - "@ethersproject/providers>@ethersproject/rlp": true, - "@ethersproject/providers>@ethersproject/web": true, - "@ethersproject/wallet": true, - "@ethersproject/wallet>@ethersproject/json-wallets": true, - "@ethersproject/wallet>@ethersproject/random": true, - "@metamask/test-bundler>ethers>@ethersproject/solidity": true, - "@metamask/test-bundler>ethers>@ethersproject/units": true - } - }, - "@metamask/test-bundler>ethers>@ethersproject/solidity": { - "packages": { - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/sha2": true - } - }, - "@metamask/test-bundler>ethers>@ethersproject/units": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bignumber": true + "ethers>@ethersproject/logger": true } }, "@metamask/transaction-controller": { @@ -3082,6 +2781,7 @@ "@ethersproject/abi": true, "@ethersproject/contracts": true, "@ethersproject/providers": true, + "@metamask/base-controller": true, "@metamask/controller-utils": true, "@metamask/eth-query": true, "@metamask/gas-fee-controller": true, @@ -3089,7 +2789,6 @@ "@metamask/name-controller>async-mutex": true, "@metamask/network-controller": true, "@metamask/rpc-errors": true, - "@metamask/transaction-controller>@metamask/base-controller": true, "@metamask/transaction-controller>@metamask/nonce-tracker": true, "@metamask/utils": true, "bn.js": true, @@ -3101,14 +2800,6 @@ "webpack>events": true } }, - "@metamask/transaction-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/transaction-controller>@metamask/nonce-tracker": { "packages": { "@ethersproject/providers": true, @@ -4252,7 +3943,7 @@ "eth-lattice-keyring>gridplus-sdk>secp256k1": true, "eth-lattice-keyring>gridplus-sdk>uuid": true, "ethereumjs-util>ethereum-cryptography>bs58check": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, + "ethers>@ethersproject/sha2>hash.js": true, "lodash": true } }, @@ -4346,7 +4037,7 @@ "@metamask/ppom-validator>elliptic>minimalistic-assert": true, "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, "bn.js": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, + "ethers>@ethersproject/sha2>hash.js": true, "pumpify>inherits": true } }, @@ -4377,7 +4068,7 @@ "@metamask/ppom-validator>elliptic>minimalistic-assert": true, "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, "bn.js": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, + "ethers>@ethersproject/sha2>hash.js": true, "pumpify>inherits": true } }, @@ -4486,19 +4177,119 @@ "@ensdomains/content-hash>multihashes>multibase>base-x": true } }, - "ethereumjs-util>ethereum-cryptography>hash.js": { - "packages": { - "@metamask/ppom-validator>elliptic>minimalistic-assert": true, - "pumpify>inherits": true - } - }, "ethereumjs-util>ethereum-cryptography>keccak": { "packages": { "browserify>buffer": true, "readable-stream": true } }, - "ethereumjs-util>ethereum-cryptography>scrypt-js": { + "ethereumjs-util>rlp": { + "packages": { + "bn.js": true, + "browserify>buffer": true + } + }, + "ethereumjs-wallet>randombytes": { + "globals": { + "crypto.getRandomValues": true + } + }, + "ethers": { + "packages": { + "@ethersproject/abi": true, + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/contracts": true, + "@ethersproject/hash": true, + "@ethersproject/hdnode": true, + "@ethersproject/wallet": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/basex": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/json-wallets": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/providers": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/rlp": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/signing-key": true, + "ethers>@ethersproject/solidity": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true, + "ethers>@ethersproject/units": true, + "ethers>@ethersproject/web": true, + "ethers>@ethersproject/wordlists": true + } + }, + "ethers>@ethersproject/abstract-provider": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true + } + }, + "ethers>@ethersproject/abstract-signer": { + "packages": { + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true + } + }, + "ethers>@ethersproject/address": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/rlp": true + } + }, + "ethers>@ethersproject/base64": { + "globals": { + "atob": true, + "btoa": true + }, + "packages": { + "@ethersproject/bytes": true + } + }, + "ethers>@ethersproject/basex": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/properties": true + } + }, + "ethers>@ethersproject/constants": { + "packages": { + "@ethersproject/bignumber": true + } + }, + "ethers>@ethersproject/json-wallets": { + "packages": { + "@ethersproject/bytes": true, + "@ethersproject/hdnode": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/json-wallets>aes-js": true, + "ethers>@ethersproject/json-wallets>scrypt-js": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/pbkdf2": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true + } + }, + "ethers>@ethersproject/json-wallets>aes-js": { + "globals": { + "define": true + } + }, + "ethers>@ethersproject/json-wallets>scrypt-js": { "globals": { "define": true, "setTimeout": true @@ -4507,15 +4298,179 @@ "browserify>timers-browserify": true } }, - "ethereumjs-util>rlp": { + "ethers>@ethersproject/keccak256": { "packages": { + "@ethersproject/bytes": true, + "@metamask/ethjs>js-sha3": true + } + }, + "ethers>@ethersproject/logger": { + "globals": { + "console": true + } + }, + "ethers>@ethersproject/pbkdf2": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/sha2": true + } + }, + "ethers>@ethersproject/properties": { + "packages": { + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/providers": { + "globals": { + "WebSocket": true, + "clearInterval": true, + "clearTimeout": true, + "console.log": true, + "console.warn": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/hash": true, + "ethers>@ethersproject/abstract-provider": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/basex": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/providers>@ethersproject/networks": true, + "ethers>@ethersproject/providers>@ethersproject/web": true, + "ethers>@ethersproject/providers>bech32": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true + } + }, + "ethers>@ethersproject/providers>@ethersproject/networks": { + "packages": { + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/providers>@ethersproject/web": { + "globals": { + "clearTimeout": true, + "fetch": true, + "setTimeout": true + }, + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true + } + }, + "ethers>@ethersproject/random": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/rlp": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/sha2": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/sha2>hash.js": true + } + }, + "ethers>@ethersproject/sha2>hash.js": { + "packages": { + "@metamask/ppom-validator>elliptic>minimalistic-assert": true, + "pumpify>inherits": true + } + }, + "ethers>@ethersproject/signing-key": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/signing-key>elliptic": true + } + }, + "ethers>@ethersproject/signing-key>elliptic": { + "packages": { + "@metamask/ppom-validator>elliptic>brorand": true, + "@metamask/ppom-validator>elliptic>hmac-drbg": true, + "@metamask/ppom-validator>elliptic>minimalistic-assert": true, + "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, "bn.js": true, - "browserify>buffer": true + "ethers>@ethersproject/sha2>hash.js": true, + "pumpify>inherits": true } }, - "ethereumjs-wallet>randombytes": { + "ethers>@ethersproject/solidity": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/strings": true + } + }, + "ethers>@ethersproject/strings": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/transactions": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/rlp": true, + "ethers>@ethersproject/signing-key": true + } + }, + "ethers>@ethersproject/units": { + "packages": { + "@ethersproject/bignumber": true, + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/web": { "globals": { - "crypto.getRandomValues": true + "clearTimeout": true, + "fetch": true, + "setTimeout": true + }, + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true + } + }, + "ethers>@ethersproject/wordlists": { + "packages": { + "@ethersproject/bytes": true, + "@ethersproject/hash": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true } }, "extension-port-stream": { diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index 8227536f34d6..6644098938f0 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -76,7 +76,15 @@ "TextEncoder": true }, "packages": { - "@metamask/assets-controllers>multiformats": true + "@ensdomains/content-hash>multicodec>uint8arrays>multiformats": true + } + }, + "@ensdomains/content-hash>multicodec>uint8arrays>multiformats": { + "globals": { + "TextDecoder": true, + "TextEncoder": true, + "console.warn": true, + "crypto.subtle.digest": true } }, "@ensdomains/content-hash>multihashes": { @@ -191,64 +199,27 @@ "console.log": true }, "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, - "@ethersproject/hash": true - } - }, - "@ethersproject/abi>@ethersproject/address": { - "packages": { - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true, - "@ethersproject/providers>@ethersproject/rlp": true - } - }, - "@ethersproject/abi>@ethersproject/constants": { - "packages": { - "@ethersproject/bignumber": true - } - }, - "@ethersproject/abi>@ethersproject/keccak256": { - "packages": { - "@ethersproject/bytes": true, - "@metamask/ethjs>js-sha3": true - } - }, - "@ethersproject/abi>@ethersproject/logger": { - "globals": { - "console": true - } - }, - "@ethersproject/abi>@ethersproject/properties": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true - } - }, - "@ethersproject/abi>@ethersproject/strings": { - "packages": { - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bytes": true + "@ethersproject/hash": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true } }, "@ethersproject/bignumber": { "packages": { - "@ethersproject/abi>@ethersproject/logger": true, "@ethersproject/bytes": true, - "bn.js": true + "bn.js": true, + "ethers>@ethersproject/logger": true } }, "@ethersproject/bytes": { "packages": { - "@ethersproject/abi>@ethersproject/logger": true + "ethers>@ethersproject/logger": true } }, "@ethersproject/contracts": { @@ -257,116 +228,41 @@ }, "packages": { "@ethersproject/abi": true, - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, - "@ethersproject/hash>@ethersproject/abstract-signer": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/wallet>@ethersproject/abstract-provider": true + "ethers>@ethersproject/abstract-provider": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/transactions": true } }, "@ethersproject/hash": { "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, - "@ethersproject/hash>@ethersproject/base64": true - } - }, - "@ethersproject/hash>@ethersproject/abstract-signer": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true - } - }, - "@ethersproject/hash>@ethersproject/base64": { - "globals": { - "atob": true, - "btoa": true - }, - "packages": { - "@ethersproject/bytes": true + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true } }, "@ethersproject/hdnode": { "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/basex": true, - "@ethersproject/hdnode>@ethersproject/pbkdf2": true, - "@ethersproject/hdnode>@ethersproject/sha2": true, - "@ethersproject/hdnode>@ethersproject/signing-key": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/hdnode>@ethersproject/wordlists": true - } - }, - "@ethersproject/hdnode>@ethersproject/basex": { - "packages": { - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/bytes": true - } - }, - "@ethersproject/hdnode>@ethersproject/pbkdf2": { - "packages": { - "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/sha2": true - } - }, - "@ethersproject/hdnode>@ethersproject/sha2": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bytes": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true - } - }, - "@ethersproject/hdnode>@ethersproject/signing-key": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/signing-key>elliptic": true - } - }, - "@ethersproject/hdnode>@ethersproject/signing-key>elliptic": { - "packages": { - "@metamask/ppom-validator>elliptic>brorand": true, - "@metamask/ppom-validator>elliptic>hmac-drbg": true, - "@metamask/ppom-validator>elliptic>minimalistic-assert": true, - "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, - "bn.js": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, - "pumpify>inherits": true - } - }, - "@ethersproject/hdnode>@ethersproject/transactions": { - "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/signing-key": true, - "@ethersproject/providers>@ethersproject/rlp": true - } - }, - "@ethersproject/hdnode>@ethersproject/wordlists": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bytes": true, - "@ethersproject/hash": true + "ethers>@ethersproject/basex": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/pbkdf2": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/signing-key": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true, + "ethers>@ethersproject/wordlists": true } }, "@ethersproject/providers": { @@ -380,24 +276,24 @@ "setTimeout": true }, "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bignumber": true, "@ethersproject/bytes": true, "@ethersproject/hash": true, - "@ethersproject/hash>@ethersproject/abstract-signer": true, - "@ethersproject/hash>@ethersproject/base64": true, - "@ethersproject/hdnode>@ethersproject/basex": true, - "@ethersproject/hdnode>@ethersproject/sha2": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, "@ethersproject/providers>@ethersproject/web": true, "@ethersproject/providers>bech32": true, - "@ethersproject/wallet>@ethersproject/abstract-provider": true, - "@ethersproject/wallet>@ethersproject/random": true, - "@metamask/test-bundler>@ethersproject/networks": true + "@metamask/test-bundler>@ethersproject/networks": true, + "ethers>@ethersproject/abstract-provider": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/basex": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true } }, "@ethersproject/providers>@ethersproject/random": { @@ -405,12 +301,6 @@ "crypto.getRandomValues": true } }, - "@ethersproject/providers>@ethersproject/rlp": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bytes": true - } - }, "@ethersproject/providers>@ethersproject/web": { "globals": { "clearTimeout": true, @@ -418,63 +308,28 @@ "setTimeout": true }, "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, "@ethersproject/bytes": true, - "@ethersproject/hash>@ethersproject/base64": true + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true } }, "@ethersproject/wallet": { "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, "@ethersproject/bytes": true, "@ethersproject/hash": true, - "@ethersproject/hash>@ethersproject/abstract-signer": true, "@ethersproject/hdnode": true, - "@ethersproject/hdnode>@ethersproject/signing-key": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/wallet>@ethersproject/abstract-provider": true, - "@ethersproject/wallet>@ethersproject/json-wallets": true, - "@ethersproject/wallet>@ethersproject/random": true - } - }, - "@ethersproject/wallet>@ethersproject/abstract-provider": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true - } - }, - "@ethersproject/wallet>@ethersproject/json-wallets": { - "packages": { - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bytes": true, - "@ethersproject/hdnode": true, - "@ethersproject/hdnode>@ethersproject/pbkdf2": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/wallet>@ethersproject/json-wallets>aes-js": true, - "@ethersproject/wallet>@ethersproject/random": true, - "ethereumjs-util>ethereum-cryptography>scrypt-js": true - } - }, - "@ethersproject/wallet>@ethersproject/json-wallets>aes-js": { - "globals": { - "define": true - } - }, - "@ethersproject/wallet>@ethersproject/random": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bytes": true + "ethers>@ethersproject/abstract-provider": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/json-wallets": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/signing-key": true, + "ethers>@ethersproject/transactions": true } }, "@keystonehq/bc-ur-registry-eth": { @@ -938,14 +793,13 @@ "setTimeout": true }, "packages": { + "@ensdomains/content-hash>multicodec>uint8arrays>multiformats": true, "@ethereumjs/tx>@ethereumjs/util": true, - "@ethersproject/abi>@ethersproject/address": true, "@ethersproject/contracts": true, "@ethersproject/providers": true, "@metamask/abi-utils": true, "@metamask/assets-controllers>@metamask/base-controller": true, "@metamask/assets-controllers>@metamask/polling-controller": true, - "@metamask/assets-controllers>multiformats": true, "@metamask/contract-metadata": true, "@metamask/controller-utils": true, "@metamask/eth-query": true, @@ -955,6 +809,7 @@ "@metamask/utils": true, "bn.js": true, "cockatiel": true, + "ethers>@ethersproject/address": true, "lodash": true, "single-call-balance-checker-abi": true, "uuid": true @@ -980,14 +835,6 @@ "uuid": true } }, - "@metamask/assets-controllers>multiformats": { - "globals": { - "TextDecoder": true, - "TextEncoder": true, - "console.warn": true, - "crypto.subtle.digest": true - } - }, "@metamask/base-controller": { "globals": { "setTimeout": true @@ -1209,26 +1056,11 @@ "packages": { "@ethereumjs/tx": true, "@metamask/eth-sig-util": true, - "@metamask/eth-snap-keyring>@metamask/utils": true, "@metamask/eth-snap-keyring>uuid": true, "@metamask/keyring-api": true, - "superstruct": true, - "webpack>events": true - } - }, - "@metamask/eth-snap-keyring>@metamask/utils": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - }, - "packages": { + "@metamask/utils": true, "@metamask/utils>@metamask/superstruct": true, - "@metamask/utils>@scure/base": true, - "@metamask/utils>pony-cause": true, - "@noble/hashes": true, - "browserify>buffer": true, - "nock>debug": true, - "semver": true + "webpack>events": true } }, "@metamask/eth-snap-keyring>uuid": { @@ -1601,9 +1433,9 @@ "@metamask/keyring-controller": { "packages": { "@ethereumjs/tx>@ethereumjs/util": true, + "@metamask/base-controller": true, "@metamask/browser-passworder": true, "@metamask/eth-sig-util": true, - "@metamask/keyring-controller>@metamask/base-controller": true, "@metamask/keyring-controller>@metamask/eth-hd-keyring": true, "@metamask/keyring-controller>@metamask/eth-simple-keyring": true, "@metamask/keyring-controller>ethereumjs-wallet": true, @@ -1611,14 +1443,6 @@ "@metamask/utils": true } }, - "@metamask/keyring-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/keyring-controller>@metamask/eth-hd-keyring": { "globals": { "TextEncoder": true @@ -1682,7 +1506,7 @@ "crypto-browserify>randombytes": true, "eth-lattice-keyring>gridplus-sdk>aes-js": true, "ethereumjs-util>ethereum-cryptography>bs58check": true, - "ethereumjs-util>ethereum-cryptography>scrypt-js": true, + "ethers>@ethersproject/json-wallets>scrypt-js": true, "uuid": true } }, @@ -1693,8 +1517,8 @@ "crypto-browserify>create-hmac": true, "crypto-browserify>randombytes": true, "ethereumjs-util>ethereum-cryptography>bs58check": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethers>@ethersproject/sha2>hash.js": true, "ganache>secp256k1": true, "koa>content-disposition>safe-buffer": true } @@ -2215,25 +2039,10 @@ "removeEventListener": true }, "packages": { - "@metamask/post-message-stream>@metamask/utils": true, + "@metamask/utils": true, "readable-stream": true } }, - "@metamask/post-message-stream>@metamask/utils": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - }, - "packages": { - "@metamask/utils>@metamask/superstruct": true, - "@metamask/utils>@scure/base": true, - "@metamask/utils>pony-cause": true, - "@noble/hashes": true, - "browserify>buffer": true, - "nock>debug": true, - "semver": true - } - }, "@metamask/ppom-validator": { "globals": { "URL": true, @@ -2309,7 +2118,7 @@ "@metamask/ppom-validator>elliptic>minimalistic-assert": true, "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, "bn.js": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, + "ethers>@ethersproject/sha2>hash.js": true, "pumpify>inherits": true } }, @@ -2326,7 +2135,7 @@ "packages": { "@metamask/ppom-validator>elliptic>minimalistic-assert": true, "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true + "ethers>@ethersproject/sha2>hash.js": true } }, "@metamask/profile-sync-controller": { @@ -2361,7 +2170,7 @@ "@metamask/controller-utils>@spruceid/siwe-parser>valid-url": true, "@metamask/profile-sync-controller>siwe>@spruceid/siwe-parser": true, "@metamask/profile-sync-controller>siwe>@stablelib/random": true, - "@metamask/test-bundler>ethers": true + "ethers": true } }, "@metamask/profile-sync-controller>siwe>@spruceid/siwe-parser": { @@ -2772,6 +2581,7 @@ "@metamask/utils": true, "browserify>browserify-zlib": true, "eslint>fast-deep-equal": true, + "immer": true, "readable-stream": true } }, @@ -2872,74 +2682,10 @@ }, "packages": { "@metamask/post-message-stream": true, - "@metamask/snaps-execution-environments>@metamask/snaps-utils": true, "@metamask/snaps-utils": true, "@metamask/utils": true } }, - "@metamask/snaps-execution-environments>@metamask/snaps-utils": { - "globals": { - "File": true, - "FileReader": true, - "TextDecoder": true, - "TextEncoder": true, - "URL": true, - "console.error": true, - "console.log": true, - "console.warn": true, - "crypto": true, - "document.body.appendChild": true, - "document.createElement": true, - "fetch": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/snaps-utils>@metamask/slip44": true, - "@metamask/rpc-errors": true, - "@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/permission-controller": true, - "@metamask/snaps-sdk": true, - "@metamask/snaps-sdk>@metamask/key-tree": true, - "@metamask/snaps-utils>cron-parser": true, - "@metamask/snaps-utils>fast-json-stable-stringify": true, - "@metamask/snaps-utils>fast-xml-parser": true, - "@metamask/snaps-utils>marked": true, - "@metamask/snaps-utils>rfdc": true, - "@metamask/snaps-utils>validate-npm-package-name": true, - "@metamask/utils": true, - "@metamask/utils>@metamask/superstruct": true, - "@metamask/utils>@scure/base": true, - "@noble/hashes": true, - "chalk": true, - "semver": true - } - }, - "@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, - "@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/permission-controller": { - "globals": { - "console.error": true - }, - "packages": { - "@metamask/controller-utils": true, - "@metamask/rpc-errors": true, - "@metamask/snaps-controllers>@metamask/json-rpc-engine": true, - "@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/base-controller": true, - "@metamask/snaps-execution-environments>nanoid": true, - "@metamask/utils": true, - "deep-freeze-strict": true, - "immer": true - } - }, - "@metamask/snaps-execution-environments>nanoid": { - "globals": { - "crypto.getRandomValues": true - } - }, "@metamask/snaps-rpc-methods": { "packages": { "@metamask/rpc-errors": true, @@ -3110,54 +2856,7 @@ }, "@metamask/test-bundler>@ethersproject/networks": { "packages": { - "@ethersproject/abi>@ethersproject/logger": true - } - }, - "@metamask/test-bundler>ethers": { - "packages": { - "@ethersproject/abi": true, - "@ethersproject/abi>@ethersproject/address": true, - "@ethersproject/abi>@ethersproject/constants": true, - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/properties": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true, - "@ethersproject/contracts": true, - "@ethersproject/hash": true, - "@ethersproject/hash>@ethersproject/abstract-signer": true, - "@ethersproject/hash>@ethersproject/base64": true, - "@ethersproject/hdnode": true, - "@ethersproject/hdnode>@ethersproject/basex": true, - "@ethersproject/hdnode>@ethersproject/sha2": true, - "@ethersproject/hdnode>@ethersproject/signing-key": true, - "@ethersproject/hdnode>@ethersproject/transactions": true, - "@ethersproject/hdnode>@ethersproject/wordlists": true, - "@ethersproject/providers": true, - "@ethersproject/providers>@ethersproject/rlp": true, - "@ethersproject/providers>@ethersproject/web": true, - "@ethersproject/wallet": true, - "@ethersproject/wallet>@ethersproject/json-wallets": true, - "@ethersproject/wallet>@ethersproject/random": true, - "@metamask/test-bundler>ethers>@ethersproject/solidity": true, - "@metamask/test-bundler>ethers>@ethersproject/units": true - } - }, - "@metamask/test-bundler>ethers>@ethersproject/solidity": { - "packages": { - "@ethersproject/abi>@ethersproject/keccak256": true, - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/abi>@ethersproject/strings": true, - "@ethersproject/bignumber": true, - "@ethersproject/bytes": true, - "@ethersproject/hdnode>@ethersproject/sha2": true - } - }, - "@metamask/test-bundler>ethers>@ethersproject/units": { - "packages": { - "@ethersproject/abi>@ethersproject/logger": true, - "@ethersproject/bignumber": true + "ethers>@ethersproject/logger": true } }, "@metamask/transaction-controller": { @@ -3174,6 +2873,7 @@ "@ethersproject/abi": true, "@ethersproject/contracts": true, "@ethersproject/providers": true, + "@metamask/base-controller": true, "@metamask/controller-utils": true, "@metamask/eth-query": true, "@metamask/gas-fee-controller": true, @@ -3181,7 +2881,6 @@ "@metamask/name-controller>async-mutex": true, "@metamask/network-controller": true, "@metamask/rpc-errors": true, - "@metamask/transaction-controller>@metamask/base-controller": true, "@metamask/transaction-controller>@metamask/nonce-tracker": true, "@metamask/utils": true, "bn.js": true, @@ -3193,14 +2892,6 @@ "webpack>events": true } }, - "@metamask/transaction-controller>@metamask/base-controller": { - "globals": { - "setTimeout": true - }, - "packages": { - "immer": true - } - }, "@metamask/transaction-controller>@metamask/nonce-tracker": { "packages": { "@ethersproject/providers": true, @@ -4344,7 +4035,7 @@ "eth-lattice-keyring>gridplus-sdk>secp256k1": true, "eth-lattice-keyring>gridplus-sdk>uuid": true, "ethereumjs-util>ethereum-cryptography>bs58check": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, + "ethers>@ethersproject/sha2>hash.js": true, "lodash": true } }, @@ -4438,7 +4129,7 @@ "@metamask/ppom-validator>elliptic>minimalistic-assert": true, "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, "bn.js": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, + "ethers>@ethersproject/sha2>hash.js": true, "pumpify>inherits": true } }, @@ -4469,7 +4160,7 @@ "@metamask/ppom-validator>elliptic>minimalistic-assert": true, "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, "bn.js": true, - "ethereumjs-util>ethereum-cryptography>hash.js": true, + "ethers>@ethersproject/sha2>hash.js": true, "pumpify>inherits": true } }, @@ -4578,19 +4269,119 @@ "@ensdomains/content-hash>multihashes>multibase>base-x": true } }, - "ethereumjs-util>ethereum-cryptography>hash.js": { - "packages": { - "@metamask/ppom-validator>elliptic>minimalistic-assert": true, - "pumpify>inherits": true - } - }, "ethereumjs-util>ethereum-cryptography>keccak": { "packages": { "browserify>buffer": true, "readable-stream": true } }, - "ethereumjs-util>ethereum-cryptography>scrypt-js": { + "ethereumjs-util>rlp": { + "packages": { + "bn.js": true, + "browserify>buffer": true + } + }, + "ethereumjs-wallet>randombytes": { + "globals": { + "crypto.getRandomValues": true + } + }, + "ethers": { + "packages": { + "@ethersproject/abi": true, + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/contracts": true, + "@ethersproject/hash": true, + "@ethersproject/hdnode": true, + "@ethersproject/wallet": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/basex": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/json-wallets": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/providers": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/rlp": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/signing-key": true, + "ethers>@ethersproject/solidity": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true, + "ethers>@ethersproject/units": true, + "ethers>@ethersproject/web": true, + "ethers>@ethersproject/wordlists": true + } + }, + "ethers>@ethersproject/abstract-provider": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true + } + }, + "ethers>@ethersproject/abstract-signer": { + "packages": { + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true + } + }, + "ethers>@ethersproject/address": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/rlp": true + } + }, + "ethers>@ethersproject/base64": { + "globals": { + "atob": true, + "btoa": true + }, + "packages": { + "@ethersproject/bytes": true + } + }, + "ethers>@ethersproject/basex": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/properties": true + } + }, + "ethers>@ethersproject/constants": { + "packages": { + "@ethersproject/bignumber": true + } + }, + "ethers>@ethersproject/json-wallets": { + "packages": { + "@ethersproject/bytes": true, + "@ethersproject/hdnode": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/json-wallets>aes-js": true, + "ethers>@ethersproject/json-wallets>scrypt-js": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/pbkdf2": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true + } + }, + "ethers>@ethersproject/json-wallets>aes-js": { + "globals": { + "define": true + } + }, + "ethers>@ethersproject/json-wallets>scrypt-js": { "globals": { "define": true, "setTimeout": true @@ -4599,15 +4390,179 @@ "browserify>timers-browserify": true } }, - "ethereumjs-util>rlp": { + "ethers>@ethersproject/keccak256": { "packages": { + "@ethersproject/bytes": true, + "@metamask/ethjs>js-sha3": true + } + }, + "ethers>@ethersproject/logger": { + "globals": { + "console": true + } + }, + "ethers>@ethersproject/pbkdf2": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/sha2": true + } + }, + "ethers>@ethersproject/properties": { + "packages": { + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/providers": { + "globals": { + "WebSocket": true, + "clearInterval": true, + "clearTimeout": true, + "console.log": true, + "console.warn": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/hash": true, + "ethers>@ethersproject/abstract-provider": true, + "ethers>@ethersproject/abstract-signer": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/basex": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/providers>@ethersproject/networks": true, + "ethers>@ethersproject/providers>@ethersproject/web": true, + "ethers>@ethersproject/providers>bech32": true, + "ethers>@ethersproject/random": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/strings": true, + "ethers>@ethersproject/transactions": true + } + }, + "ethers>@ethersproject/providers>@ethersproject/networks": { + "packages": { + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/providers>@ethersproject/web": { + "globals": { + "clearTimeout": true, + "fetch": true, + "setTimeout": true + }, + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true + } + }, + "ethers>@ethersproject/random": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/rlp": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/sha2": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/sha2>hash.js": true + } + }, + "ethers>@ethersproject/sha2>hash.js": { + "packages": { + "@metamask/ppom-validator>elliptic>minimalistic-assert": true, + "pumpify>inherits": true + } + }, + "ethers>@ethersproject/signing-key": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/signing-key>elliptic": true + } + }, + "ethers>@ethersproject/signing-key>elliptic": { + "packages": { + "@metamask/ppom-validator>elliptic>brorand": true, + "@metamask/ppom-validator>elliptic>hmac-drbg": true, + "@metamask/ppom-validator>elliptic>minimalistic-assert": true, + "@metamask/ppom-validator>elliptic>minimalistic-crypto-utils": true, "bn.js": true, - "browserify>buffer": true + "ethers>@ethersproject/sha2>hash.js": true, + "pumpify>inherits": true } }, - "ethereumjs-wallet>randombytes": { + "ethers>@ethersproject/solidity": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/sha2": true, + "ethers>@ethersproject/strings": true + } + }, + "ethers>@ethersproject/strings": { + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/transactions": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "ethers>@ethersproject/address": true, + "ethers>@ethersproject/constants": true, + "ethers>@ethersproject/keccak256": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/rlp": true, + "ethers>@ethersproject/signing-key": true + } + }, + "ethers>@ethersproject/units": { + "packages": { + "@ethersproject/bignumber": true, + "ethers>@ethersproject/logger": true + } + }, + "ethers>@ethersproject/web": { "globals": { - "crypto.getRandomValues": true + "clearTimeout": true, + "fetch": true, + "setTimeout": true + }, + "packages": { + "@ethersproject/bytes": true, + "ethers>@ethersproject/base64": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true + } + }, + "ethers>@ethersproject/wordlists": { + "packages": { + "@ethersproject/bytes": true, + "@ethersproject/hash": true, + "ethers>@ethersproject/logger": true, + "ethers>@ethersproject/properties": true, + "ethers>@ethersproject/strings": true } }, "extension-port-stream": { diff --git a/package.json b/package.json index 958ea252521c..e2bd400c9694 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "postinstall": "yarn webpack:clearcache", "env:e2e": "SEGMENT_HOST='https://api.segment.io' SEGMENT_WRITE_KEY='FAKE' yarn", "start": "yarn build:dev dev --apply-lavamoat=false --snow=false", - "start:skip-onboarding": "SKIP_ONBOARDING=true yarn start", + "start:with-state": "node ./app/scripts/start-with-wallet-state.mjs", "start:mv2": "ENABLE_MV3=false yarn build:dev dev --apply-lavamoat=false --snow=false", "start:flask": "yarn start --build-type flask", "start:mmi": "yarn start --build-type mmi", @@ -47,7 +47,7 @@ "test:unit:watch": "jest --watch", "test:unit:coverage": "jest --coverage", "test:unit:webpack": "tsx --test development/webpack/test/*.test.ts", - "test:unit:webpack:coverage": "nyc --reporter=html --reporter=json --reporter=text tsx --test development/webpack/test/*.test.ts", + "test:unit:webpack:coverage": "nyc --reporter=html --reporter=json --reporter=text --report-dir=./coverage/webpack tsx --test development/webpack/test/*.test.ts", "test:integration": "jest --config jest.integration.config.js", "test:integration:coverage": "jest --config jest.integration.config.js --coverage", "test:e2e:chrome": "SELENIUM_BROWSER=chrome node test/e2e/run-all.js", @@ -228,7 +228,7 @@ "semver@7.3.8": "^7.5.4", "@trezor/schema-utils@npm:1.0.2": "patch:@trezor/schema-utils@npm%3A1.0.2#~/.yarn/patches/@trezor-schema-utils-npm-1.0.2-7dd48689b2.patch", "lavamoat-core@npm:^15.1.1": "patch:lavamoat-core@npm%3A15.1.1#~/.yarn/patches/lavamoat-core-npm-15.1.1-51fbe39988.patch", - "@metamask/snaps-sdk": "^6.3.0", + "@metamask/snaps-sdk": "^6.5.1", "@swc/types@0.1.5": "^0.1.6", "@babel/runtime@npm:^7.7.6": "patch:@babel/runtime@npm%3A7.24.0#~/.yarn/patches/@babel-runtime-npm-7.24.0-7eb1dd11a2.patch", "@babel/runtime@npm:^7.9.2": "patch:@babel/runtime@npm%3A7.24.0#~/.yarn/patches/@babel-runtime-npm-7.24.0-7eb1dd11a2.patch", @@ -262,17 +262,13 @@ "@metamask/message-manager": "^10.1.0", "@metamask/network-controller@npm:^19.0.0": "patch:@metamask/network-controller@npm%3A20.2.0#~/.yarn/patches/@metamask-network-controller-npm-20.2.0-98b1a5ae59.patch", "@metamask/gas-fee-controller@npm:^15.1.1": "patch:@metamask/gas-fee-controller@npm%3A15.1.2#~/.yarn/patches/@metamask-gas-fee-controller-npm-15.1.2-db4d2976aa.patch", - "@metamask/snaps-controllers@npm:^8.1.1": "patch:@metamask/snaps-controllers@npm%3A9.5.0#~/.yarn/patches/@metamask-snaps-controllers-npm-9.5.0-8b21e3c072.patch", - "@metamask/snaps-controllers@npm:^9.5.0": "patch:@metamask/snaps-controllers@npm%3A9.5.0#~/.yarn/patches/@metamask-snaps-controllers-npm-9.5.0-8b21e3c072.patch", "@metamask/nonce-tracker@npm:^5.0.0": "patch:@metamask/nonce-tracker@npm%3A5.0.0#~/.yarn/patches/@metamask-nonce-tracker-npm-5.0.0-d81478218e.patch", - "@metamask/keyring-controller@npm:^16.0.0": "patch:@metamask/keyring-controller@npm%3A17.1.1#~/.yarn/patches/@metamask-keyring-controller-npm-17.1.1-098cb41930.patch", - "@metamask/keyring-controller@npm:^17.1.0": "patch:@metamask/keyring-controller@npm%3A17.1.1#~/.yarn/patches/@metamask-keyring-controller-npm-17.1.1-098cb41930.patch", "@trezor/connect-web@npm:^9.1.11": "patch:@trezor/connect-web@npm%3A9.3.0#~/.yarn/patches/@trezor-connect-web-npm-9.3.0-040ab10d9a.patch", "path-to-regexp": "1.9.0" }, "dependencies": { "@babel/runtime": "patch:@babel/runtime@npm%3A7.24.0#~/.yarn/patches/@babel-runtime-npm-7.24.0-7eb1dd11a2.patch", - "@blockaid/ppom_release": "^1.5.2", + "@blockaid/ppom_release": "^1.5.3", "@ensdomains/content-hash": "^2.5.7", "@ethereumjs/tx": "^4.1.1", "@ethersproject/abi": "^5.6.4", @@ -300,24 +296,25 @@ "@metamask-institutional/types": "^1.1.0", "@metamask/abi-utils": "^2.0.2", "@metamask/account-watcher": "^4.1.0", - "@metamask/accounts-controller": "^18.2.0", + "@metamask/accounts-controller": "^18.2.1", "@metamask/address-book-controller": "^5.0.0", "@metamask/announcement-controller": "^7.0.0", "@metamask/approval-controller": "^7.0.0", - "@metamask/assets-controllers": "^36.0.0", + "@metamask/assets-controllers": "^37.0.0", "@metamask/base-controller": "^7.0.0", - "@metamask/bitcoin-wallet-snap": "^0.5.0", + "@metamask/bitcoin-wallet-snap": "^0.6.0", "@metamask/browser-passworder": "^4.3.0", "@metamask/contract-metadata": "^2.5.0", "@metamask/controller-utils": "^11.2.0", "@metamask/design-tokens": "^4.0.0", "@metamask/ens-controller": "^13.0.0", + "@metamask/ens-resolver-snap": "^0.1.2", "@metamask/eth-json-rpc-filters": "^7.0.0", "@metamask/eth-json-rpc-middleware": "patch:@metamask/eth-json-rpc-middleware@npm%3A14.0.1#~/.yarn/patches/@metamask-eth-json-rpc-middleware-npm-14.0.1-b6c2ccbe8c.patch", "@metamask/eth-ledger-bridge-keyring": "^3.0.1", "@metamask/eth-query": "^4.0.0", "@metamask/eth-sig-util": "^7.0.1", - "@metamask/eth-snap-keyring": "^4.3.1", + "@metamask/eth-snap-keyring": "^4.3.3", "@metamask/eth-token-tracker": "^8.0.0", "@metamask/eth-trezor-keyring": "^3.1.0", "@metamask/etherscan-link": "^3.0.0", @@ -326,8 +323,8 @@ "@metamask/ethjs-query": "^0.7.1", "@metamask/gas-fee-controller": "^18.0.0", "@metamask/jazzicon": "^2.0.0", - "@metamask/keyring-api": "^8.0.0", - "@metamask/keyring-controller": "patch:@metamask/keyring-controller@npm%3A17.1.1#~/.yarn/patches/@metamask-keyring-controller-npm-17.1.1-098cb41930.patch", + "@metamask/keyring-api": "^8.1.0", + "@metamask/keyring-controller": "^17.2.1", "@metamask/logging-controller": "^6.0.0", "@metamask/logo": "^3.1.2", "@metamask/message-manager": "^10.1.0", @@ -336,7 +333,7 @@ "@metamask/name-controller": "^8.0.0", "@metamask/network-controller": "patch:@metamask/network-controller@npm%3A20.2.0#~/.yarn/patches/@metamask-network-controller-npm-20.2.0-98b1a5ae59.patch", "@metamask/notification-controller": "^6.0.0", - "@metamask/notification-services-controller": "^0.5.0", + "@metamask/notification-services-controller": "^0.7.0", "@metamask/object-multiplex": "^2.0.0", "@metamask/obs-store": "^9.0.0", "@metamask/permission-controller": "^10.0.0", @@ -344,7 +341,7 @@ "@metamask/phishing-controller": "^12.0.1", "@metamask/post-message-stream": "^8.0.0", "@metamask/ppom-validator": "0.34.0", - "@metamask/profile-sync-controller": "^0.5.0", + "@metamask/profile-sync-controller": "^0.8.0", "@metamask/providers": "^14.0.2", "@metamask/queued-request-controller": "^2.0.0", "@metamask/rate-limit-controller": "^6.0.0", @@ -354,12 +351,12 @@ "@metamask/selected-network-controller": "^15.0.2", "@metamask/signature-controller": "^19.0.0", "@metamask/smart-transactions-controller": "^13.0.0", - "@metamask/snaps-controllers": "^9.5.0", - "@metamask/snaps-execution-environments": "^6.6.2", - "@metamask/snaps-rpc-methods": "^11.0.0", - "@metamask/snaps-sdk": "^6.3.0", - "@metamask/snaps-utils": "^8.0.1", - "@metamask/transaction-controller": "^35.2.0", + "@metamask/snaps-controllers": "^9.7.0", + "@metamask/snaps-execution-environments": "^6.7.2", + "@metamask/snaps-rpc-methods": "^11.1.1", + "@metamask/snaps-sdk": "^6.5.1", + "@metamask/snaps-utils": "^8.1.1", + "@metamask/transaction-controller": "^37.0.0", "@metamask/user-operation-controller": "^13.0.0", "@metamask/utils": "^9.1.0", "@ngraveio/bc-ur": "^1.1.12", @@ -392,7 +389,6 @@ "eth-lattice-keyring": "^0.12.4", "eth-method-registry": "^4.0.0", "eth-rpc-errors": "^4.0.2", - "ethereum-ens-network-map": "^1.0.2", "ethereumjs-util": "^7.0.10", "extension-port-stream": "^3.0.0", "fast-json-patch": "^3.1.1", @@ -586,6 +582,7 @@ "eslint-plugin-react-hooks": "^4.2.0", "eslint-plugin-storybook": "^0.6.15", "eta": "^3.2.0", + "ethers": "5.7.0", "fake-indexeddb": "^4.0.1", "fancy-log": "^1.3.3", "fast-glob": "^3.2.2", @@ -610,7 +607,7 @@ "ini": "^3.0.0", "jest": "^29.7.0", "jest-canvas-mock": "^2.3.1", - "jest-environment-jsdom": "^29.7.0", + "jest-environment-jsdom": "patch:jest-environment-jsdom@npm%3A29.7.0#~/.yarn/patches/jest-environment-jsdom-npm-29.7.0-0b72dd0e0b.patch", "jsdom": "^16.7.0", "json-schema-to-ts": "^3.0.1", "koa": "^2.7.0", diff --git a/shared/constants/metametrics.ts b/shared/constants/metametrics.ts index 502f166c8e91..243b2409f1af 100644 --- a/shared/constants/metametrics.ts +++ b/shared/constants/metametrics.ts @@ -156,7 +156,7 @@ export type MetaMetricsEventFragment = { /** * The event name to fire when the fragment is closed in an affirmative action. */ - successEvent?: string; + successEvent: string; /** * The event name to fire when the fragment is closed with a rejection. */ @@ -169,7 +169,7 @@ export type MetaMetricsEventFragment = { /** * The event category to use for both the success and failure events. */ - category?: string; + category: string; /** * Should this fragment be persisted in state and progressed after the * extension is locked and unlocked. @@ -468,6 +468,10 @@ export enum MetaMetricsUserTrait { MmiIsCustodian = 'mmi_is_custodian', ///: END:ONLY_INCLUDE_IF PetnameAddressCount = 'petname_addresses_count', + /** + * Identified when the user selects a currency from settings + */ + CurrentCurrency = 'current_currency', } /** @@ -503,6 +507,8 @@ export enum MetaMetricsEventName { AccountPasswordCreated = 'Account Password Created', AccountReset = 'Account Reset', AccountRenamed = 'Account Renamed', + AccountsSyncAccountAdded = 'Accounts Sync Account Added', + AccountsSyncAccountNameUpdated = 'Accounts Sync Account Name Updated', ActivityDetailsOpened = 'Activity Details Opened', ActivityDetailsClosed = 'Activity Details Closed', AnalyticsPreferenceSelected = 'Analytics Preference Selected', @@ -514,6 +520,7 @@ export enum MetaMetricsEventName { BridgeLinkClicked = 'Bridge Link Clicked', BitcoinSupportToggled = 'Bitcoin Support Toggled', BitcoinTestnetSupportToggled = 'Bitcoin Testnet Support Toggled', + CurrentCurrency = 'Current Currency', DappViewed = 'Dapp Viewed', DecryptionApproved = 'Decryption Approved', DecryptionRejected = 'Decryption Rejected', @@ -569,7 +576,6 @@ export enum MetaMetricsEventName { OnboardingWalletSecurityPhraseWrittenDown = 'SRP Backup Confirm Display', OnboardingWalletSecurityPhraseConfirmed = 'SRP Backup Confirmed', OnboardingWalletCreationComplete = 'Wallet Created', - OnboardingWalletSetupComplete = 'Application Opened', OnboardingWalletAdvancedSettings = 'Settings Updated', OnboardingWalletImportAttempted = 'Wallet Import Attempted', OnboardingWalletVideoPlay = 'SRP Intro Video Played', @@ -763,6 +769,7 @@ export enum MetaMetricsEventCategory { NotificationSettings = 'Notification Settings', Petnames = 'Petnames', Phishing = 'Phishing', + ProfileSyncing = 'Profile Syncing', PushNotifications = 'Notifications', Retention = 'Retention', Send = 'Send', diff --git a/shared/lib/four-byte.ts b/shared/lib/four-byte.ts index 167dfc563b73..c8d67af7b1f4 100644 --- a/shared/lib/four-byte.ts +++ b/shared/lib/four-byte.ts @@ -57,7 +57,6 @@ export async function getMethodDataAsync( console.error(e); return null; }); - console.log('fourByteSig = ', fourByteSig); } if (!registry) { diff --git a/shared/lib/trace.test.ts b/shared/lib/trace.test.ts index fc3294924698..5154a930b7f9 100644 --- a/shared/lib/trace.test.ts +++ b/shared/lib/trace.test.ts @@ -37,6 +37,12 @@ describe('Trace', () => { beforeEach(() => { jest.resetAllMocks(); + globalThis.sentry = { + startSpan: startSpanMock, + startSpanManual: startSpanManualMock, + withIsolationScope: withIsolationScopeMock, + }; + startSpanMock.mockImplementation((_, fn) => fn({} as Span)); // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/shared/lib/trace.ts b/shared/lib/trace.ts index b9f59a2f2353..aaf3db7d46af 100644 --- a/shared/lib/trace.ts +++ b/shared/lib/trace.ts @@ -114,7 +114,7 @@ function traceCallback(request: TraceRequest, fn: TraceCallback): T { }; return startSpan(request, (spanOptions) => - Sentry.startSpan(spanOptions, callback), + sentryStartSpan(spanOptions, callback), ); } @@ -138,7 +138,7 @@ function startTrace(request: TraceRequest): TraceContext { }; return startSpan(request, (spanOptions) => - Sentry.startSpanManual(spanOptions, callback), + sentryStartSpanManual(spanOptions, callback), ); } @@ -157,7 +157,7 @@ function startSpan( startTime, }; - return Sentry.withIsolationScope((scope) => { + return sentryWithIsolationScope((scope: Sentry.Scope) => { scope.setTags(tags as Record); return callback(spanOptions); @@ -207,3 +207,44 @@ function tryCatchMaybePromise( return undefined; } + +function sentryStartSpan( + spanOptions: StartSpanOptions, + callback: (span: Sentry.Span | null) => T, +): T { + const actual = globalThis.sentry?.startSpan; + + if (!actual) { + return callback(null); + } + + return actual(spanOptions, callback); +} + +function sentryStartSpanManual( + spanOptions: StartSpanOptions, + callback: (span: Sentry.Span | null) => T, +): T { + const actual = globalThis.sentry?.startSpanManual; + + if (!actual) { + return callback(null); + } + + return actual(spanOptions, callback); +} + +function sentryWithIsolationScope(callback: (scope: Sentry.Scope) => T): T { + const actual = globalThis.sentry?.withIsolationScope; + + if (!actual) { + const scope = { + // eslint-disable-next-line no-empty-function + setTags: () => {}, + } as unknown as Sentry.Scope; + + return callback(scope); + } + + return actual(callback); +} diff --git a/shared/modules/conversion.utils.ts b/shared/modules/conversion.utils.ts index d9fd2262f843..75da336eb8e6 100644 --- a/shared/modules/conversion.utils.ts +++ b/shared/modules/conversion.utils.ts @@ -4,7 +4,7 @@ import { addHexPrefix, BN } from 'ethereumjs-util'; import { EtherDenomination } from '../constants/common'; import { Numeric, NumericValue } from './Numeric'; -export function decGWEIToHexWEI(decGWEI: number) { +export function decGWEIToHexWEI(decGWEI: NumericValue) { return new Numeric(decGWEI, 10, EtherDenomination.GWEI) .toBase(16) .toDenomination(EtherDenomination.WEI) diff --git a/shared/modules/hexstring-utils.test.js b/shared/modules/hexstring-utils.test.js index 74e444437310..5fe876428bcc 100644 --- a/shared/modules/hexstring-utils.test.js +++ b/shared/modules/hexstring-utils.test.js @@ -1,7 +1,50 @@ import { toChecksumAddress } from 'ethereumjs-util'; -import { isValidHexAddress } from './hexstring-utils'; +import { isPossibleAddress, isValidHexAddress } from './hexstring-utils'; describe('hexstring utils', function () { + describe('isPossibleAddress', function () { + it('should allow 40-char non-prefixed hex', function () { + const address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b825'; + const result = isPossibleAddress(address); + expect(result).toStrictEqual(true); + }); + it('should allow 42-char prefixed hex', function () { + const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825'; + const result = isPossibleAddress(address); + expect(result).toStrictEqual(true); + }); + it('should not allow 42-char prefixed non-hex', function () { + const address = '0xzzzz65c8e26263f6d9a1b5de9555d2931a33b825'; + const result = isPossibleAddress(address); + expect(result).toStrictEqual(false); + }); + it('should not allow 40-char non-prefixed non-hex', function () { + const address = 'zzzz65c8e26263f6d9a1b5de9555d2931a33b825'; + const result = isPossibleAddress(address); + expect(result).toStrictEqual(false); + }); + it('should not allow shorter prefixed hex strings', function () { + const address = '0x1234'; + const result = isPossibleAddress(address); + expect(result).toStrictEqual(false); + }); + it('should not allow shorter non-prefixed hex strings', function () { + const address = '1234'; + const result = isPossibleAddress(address); + expect(result).toStrictEqual(false); + }); + it('should not allow longer prefixed hex strings', function () { + const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825fdea65c8e262'; + const result = isPossibleAddress(address); + expect(result).toStrictEqual(false); + }); + it('should not allow longer non-prefixed hex strings', function () { + const address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b825fdea65c8e262'; + const result = isPossibleAddress(address); + expect(result).toStrictEqual(false); + }); + }); + describe('isValidHexAddress', function () { it('should allow 40-char non-prefixed hex', function () { const address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b825'; diff --git a/shared/modules/hexstring-utils.ts b/shared/modules/hexstring-utils.ts index b81dc1303f9c..84b052716738 100644 --- a/shared/modules/hexstring-utils.ts +++ b/shared/modules/hexstring-utils.ts @@ -66,6 +66,16 @@ export function isValidHexAddress( return isValidAddress(addressToCheck); } +/** + * Determines if a string is a possible ethereum address + * + * @param candidate - the input to check + * @returns true if the input is a 40 char hex string with optional 0x prefix, false otherwise + */ +export function isPossibleAddress(candidate: string) { + return /^(0x)?[0-9a-fA-F]{40}$/iu.test(candidate); +} + export function toChecksumHexAddress(address: string) { if (!address) { // our internal checksumAddress function that this method replaces would diff --git a/sonar-project.properties b/sonar-project.properties index 0455fa9634e2..1475b64f4acb 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,14 +1,15 @@ -sonar.projectKey=metamask-extension-private -sonar.organization=metamask +sonar.projectKey=metamask-extension +sonar.organization=consensys # Source -sonar.sources=app,development,offscreen,shared,types,ui +sonar.sources=app,development,offscreen,shared,test,types,ui sonar.exclusions=**/*.test.**,**/*.spec.**,app/images # Tests -sonar.tests=app,test,development,offscreen,shared,types,ui +sonar.tests=app,development,offscreen,shared,test,types,ui sonar.test.inclusions=**/*.test.**,**/*.spec.** -sonar.javascript.lcov.reportPaths=tests/coverage/lcov.info + +sonar.javascript.lcov.reportPaths=coverage/lcov.info # Fail CI job if quality gate failures -sonar.qualitygate.wait=false \ No newline at end of file +sonar.qualitygate.wait=false diff --git a/test/data/confirmations/typed_sign.ts b/test/data/confirmations/typed_sign.ts index 88985e1a52a7..8766fac9184c 100644 --- a/test/data/confirmations/typed_sign.ts +++ b/test/data/confirmations/typed_sign.ts @@ -1,3 +1,4 @@ +import { TransactionType } from '@metamask/transaction-controller'; import { MESSAGE_TYPE } from '../../../shared/constants/app'; import { SignatureRequestType } from '../../../ui/pages/confirmations/types/confirm'; @@ -10,7 +11,7 @@ export const unapprovedTypedSignMsgV1 = { }, status: 'unapproved', time: 1710505271872, - type: 'eth_signTypedData', + type: TransactionType.signTypedData, securityProviderResponse: null, msgParams: { from: '0x935e73edb9ff52e23bac7f7e043a1ecd06d05477', @@ -18,6 +19,7 @@ export const unapprovedTypedSignMsgV1 = { { type: 'string', name: 'Message', value: 'Hi, Alice!' }, { type: 'uint32', name: 'A number', value: '1337' }, ], + requestId: 11, signatureMethod: 'eth_signTypedData', version: 'V1', origin: 'https://metamask.github.io', @@ -65,12 +67,13 @@ export const unapprovedTypedSignMsgV3 = { }, status: 'unapproved', time: 1710249542175, - type: 'eth_signTypedData', + type: TransactionType.signTypedData, securityProviderResponse: null, msgParams: { data: JSON.stringify(rawMessageV3), from: '0x935e73edb9ff52e23bac7f7e043a1ecd06d05477', version: 'V3', + requestId: 12, signatureMethod: 'eth_signTypedData_v3', origin: 'https://metamask.github.io', }, @@ -129,12 +132,13 @@ export const unapprovedTypedSignMsgV4 = { status: 'unapproved', time: new Date().getTime(), chainid: '0x5', - type: 'eth_signTypedData', + type: TransactionType.signTypedData, securityProviderResponse: null, msgParams: { from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', data: JSON.stringify(rawMessageV4), origin: 'https://metamask.github.io', + requestId: 123456789, signatureMethod: MESSAGE_TYPE.ETH_SIGN_TYPED_DATA_V4, }, } as SignatureRequestType; @@ -148,11 +152,12 @@ export const orderSignatureMsg = { }, status: 'unapproved', time: 1722011224974, - type: 'eth_signTypedData', + type: TransactionType.signTypedData, msgParams: { data: '{"types":{"Order":[{"type":"uint8","name":"direction"},{"type":"address","name":"maker"},{"type":"address","name":"taker"},{"type":"uint256","name":"expiry"},{"type":"uint256","name":"nonce"},{"type":"address","name":"erc20Token"},{"type":"uint256","name":"erc20TokenAmount"},{"type":"Fee[]","name":"fees"},{"type":"address","name":"erc721Token"},{"type":"uint256","name":"erc721TokenId"},{"type":"Property[]","name":"erc721TokenProperties"}],"Fee":[{"type":"address","name":"recipient"},{"type":"uint256","name":"amount"},{"type":"bytes","name":"feeData"}],"Property":[{"type":"address","name":"propertyValidator"},{"type":"bytes","name":"propertyData"}],"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}]},"domain":{"name":"ZeroEx","version":"1.0.0","chainId":"0x1","verifyingContract":"0xdef1c0ded9bec7f1a1670819833240f027b25eff"},"primaryType":"Order","message":{"direction":"0","maker":"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc","taker":"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826","expiry":"2524604400","nonce":"100131415900000000000000000000000000000083840314483690155566137712510085002484","erc20Token":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","erc20TokenAmount":"42000000000000","fees":[],"erc721Token":"0x8a90CAb2b38dba80c64b7734e58Ee1dB38B8992e","erc721TokenId":"2516","erc721TokenProperties":[]}}', from: '0x935e73edb9ff52e23bac7f7e043a1ecd06d05477', version: 'V4', + requestId: 13, signatureMethod: 'eth_signTypedData_v4', origin: 'https://metamask.github.io', }, @@ -167,11 +172,12 @@ export const permitSignatureMsg = { }, status: 'unapproved', time: 1716826404122, - type: 'eth_signTypedData', + type: TransactionType.signTypedData, msgParams: { data: '{"types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Permit":[{"name":"owner","type":"address"},{"name":"spender","type":"address"},{"name":"value","type":"uint256"},{"name":"nonce","type":"uint256"},{"name":"deadline","type":"uint256"}]},"primaryType":"Permit","domain":{"name":"MyToken","version":"1","verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC","chainId":1},"message":{"owner":"0x935e73edb9ff52e23bac7f7e043a1ecd06d05477","spender":"0x5B38Da6a701c568545dCfcB03FcB875f56beddC4","value":3000,"nonce":0,"deadline":50000000000}}', from: '0x935e73edb9ff52e23bac7f7e043a1ecd06d05477', version: 'V4', + requestId: 14, signatureMethod: 'eth_signTypedData_v4', origin: 'https://metamask.github.io', }, @@ -186,11 +192,12 @@ export const permitBatchSignatureMsg = { }, status: 'unapproved', time: 1716826404122, - type: 'eth_signTypedData', + type: TransactionType.signTypedData, msgParams: { data: '{"types":{"PermitBatch":[{"name":"details","type":"PermitDetails[]"},{"name":"spender","type":"address"},{"name":"sigDeadline","type":"uint256"}],"PermitDetails":[{"name":"token","type":"address"},{"name":"amount","type":"uint160"},{"name":"expiration","type":"uint48"},{"name":"nonce","type":"uint48"}],"EIP712Domain":[{"name":"name","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}]},"domain":{"name":"Permit2","chainId":"1","verifyingContract":"0x000000000022d473030f116ddee9f6b43ac78ba3"},"primaryType":"PermitBatch","message":{"details":[{"token":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","amount":"1461501637330902918203684832716283019655932542975","expiration":"1722887542","nonce":"5"},{"token":"0xb0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","amount":"2461501637330902918203684832716283019655932542975","expiration":"1722887642","nonce":"6"}],"spender":"0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad","sigDeadline":"1720297342"}}', from: '0x935e73edb9ff52e23bac7f7e043a1ecd06d05477', version: 'V4', + requestId: 15, signatureMethod: 'eth_signTypedData_v4', origin: 'https://metamask.github.io', }, @@ -205,11 +212,12 @@ export const permitSingleSignatureMsg = { }, status: 'unapproved', time: 1716826404122, - type: 'eth_signTypedData', + type: TransactionType.signTypedData, msgParams: { data: '{"types":{"PermitSingle":[{"name":"details","type":"PermitDetails"},{"name":"spender","type":"address"},{"name":"sigDeadline","type":"uint256"}],"PermitDetails":[{"name":"token","type":"address"},{"name":"amount","type":"uint160"},{"name":"expiration","type":"uint48"},{"name":"nonce","type":"uint48"}],"EIP712Domain":[{"name":"name","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}]},"domain":{"name":"Permit2","chainId":"1","verifyingContract":"0x000000000022d473030f116ddee9f6b43ac78ba3"},"primaryType":"PermitSingle","message":{"details":{"token":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","amount":"1461501637330902918203684832716283019655932542975","expiration":"1722887542","nonce":"5"},"spender":"0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad","sigDeadline":"1720297342"}}', from: '0x935e73edb9ff52e23bac7f7e043a1ecd06d05477', version: 'V4', + requestId: 16, signatureMethod: 'eth_signTypedData_v4', origin: 'https://metamask.github.io', }, diff --git a/test/e2e/changedFilesUtil.js b/test/e2e/changedFilesUtil.js index 19615317e121..ca90a10980a2 100644 --- a/test/e2e/changedFilesUtil.js +++ b/test/e2e/changedFilesUtil.js @@ -1,4 +1,4 @@ -const fs = require('fs').promises; +const fs = require('fs'); const path = require('path'); const BASE_PATH = path.resolve(__dirname, '..', '..'); @@ -11,15 +11,17 @@ const CHANGED_FILES_PATH = path.join( /** * Reads the list of changed files from the git diff file. * - * @returns {Promise} An array of changed file paths. + * @returns {} An array of changed file paths. */ -async function readChangedFiles() { +function readChangedFiles() { try { - const data = await fs.readFile(CHANGED_FILES_PATH, 'utf8'); + const data = fs.readFileSync(CHANGED_FILES_PATH, 'utf8'); const changedFiles = data.split('\n'); return changedFiles; } catch (error) { - console.error('Error reading from file:', error); + if (error.code !== 'ENOENT') { + console.error('Error reading from file:', error); + } return []; } } @@ -27,10 +29,10 @@ async function readChangedFiles() { /** * Filters the list of changed files to include only E2E test files within the 'test/e2e/' directory. * - * @returns {Promise} An array of filtered E2E test file paths. + * @returns {} An array of filtered E2E test file paths. */ -async function filterE2eChangedFiles() { - const changedFiles = await readChangedFiles(); +function filterE2eChangedFiles() { + const changedFiles = readChangedFiles(); const e2eChangedFiles = changedFiles .filter( (file) => diff --git a/test/e2e/constants.ts b/test/e2e/constants.ts index 4dee1053aaee..e7fef587f533 100644 --- a/test/e2e/constants.ts +++ b/test/e2e/constants.ts @@ -39,5 +39,10 @@ export const VERIFYING_PAYMASTER = '0xbdbDEc38ed168331b1F7004cc9e5392A2272C1D7'; /* Default ganache ETH balance in decimal when first login */ export const DEFAULT_GANACHE_ETH_BALANCE_DEC = '25'; +/* Dapp host addresses and URL*/ +export const DAPP_HOST_ADDRESS = '127.0.0.1:8080'; +export const DAPP_URL = `http://${DAPP_HOST_ADDRESS}`; +export const DAPP_ONE_URL = 'http://127.0.0.1:8081'; + /* Default BTC address created using test SRP */ export const DEFAULT_BTC_ACCOUNT = 'bc1qg6whd6pc0cguh6gpp3ewujm53hv32ta9hdp252'; diff --git a/test/e2e/fixture-builder.js b/test/e2e/fixture-builder.js index 357cd95600f4..1d9401bf227f 100644 --- a/test/e2e/fixture-builder.js +++ b/test/e2e/fixture-builder.js @@ -2,14 +2,18 @@ const { WALLET_SNAP_PERMISSION_KEY, SnapCaveatType, } = require('@metamask/snaps-utils'); -const { merge } = require('lodash'); +const { merge, mergeWith } = require('lodash'); const { toHex } = require('@metamask/controller-utils'); const { mockNetworkState } = require('../stub/networks'); const { CHAIN_IDS } = require('../../shared/constants/network'); const { SMART_CONTRACTS } = require('./seeder/smart-contracts'); -const { DAPP_URL, DAPP_ONE_URL, ACCOUNT_1 } = require('./helpers'); -const { DEFAULT_FIXTURE_ACCOUNT, ERC_4337_ACCOUNT } = require('./constants'); +const { + DAPP_URL, + DAPP_ONE_URL, + DEFAULT_FIXTURE_ACCOUNT, + ERC_4337_ACCOUNT, +} = require('./constants'); const { defaultFixture, FIXTURE_STATE_METADATA_VERSION, @@ -234,6 +238,22 @@ class FixtureBuilder { return this.withNetworkController({ selectedNetworkClientId: 'mainnet' }); } + withNetworkControllerOnOptimism() { + return this.withNetworkController({ + networkConfigurations: { + networkConfigurationId: { + chainId: CHAIN_IDS.OPTIMISM, + nickname: 'Localhost 8545', + rpcPrefs: {}, + rpcUrl: 'https://mainnet.infura.io', + ticker: 'ETH', + networkConfigurationId: 'networkConfigurationId', + id: 'networkConfigurationId', + }, + }, + }); + } + withNetworkControllerDoubleGanache() { const ganacheNetworks = mockNetworkState( { @@ -345,6 +365,20 @@ class FixtureBuilder { }); } + withNotificationServicesController(data) { + mergeWith( + this.fixture.data.NotificationServicesController, + data, + (objValue, srcValue) => { + if (Array.isArray(objValue)) { + objValue.concat(srcValue); + } + return undefined; + }, + ); + return this; + } + withOnboardingController(data) { merge(this.fixture.data.OnboardingController, data); return this; @@ -811,587 +845,6 @@ class FixtureBuilder { return this; } - withTransactionControllerMultipleTransactions() { - return this.withTransactionController({ - transactions: { - '7087d1d7-f0e8-4c0f-a903-6d9daa392baf': { - chainId: CHAIN_IDS.LOCALHOST, - dappSuggestedGasFees: { - gas: '0x5208', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - }, - history: [ - { - chainId: CHAIN_IDS.LOCALHOST, - dappSuggestedGasFees: { - gas: '0x5208', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - }, - id: '7087d1d7-f0e8-4c0f-a903-6d9daa392baf', - loadingDefaults: true, - origin: 'https://metamask.github.io', - status: 'unapproved', - time: 1631545991949, - txParams: { - from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', - gas: '0x5208', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', - value: '0x29a2241af62c0000', - }, - type: 'simpleSend', - }, - [ - { - note: 'Added new unapproved transaction.', - op: 'replace', - path: '/loadingDefaults', - timestamp: 1631545992244, - value: false, - }, - { - op: 'add', - path: '/simulationData', - value: { - error: { - code: 'disabled', - message: 'Simulation disabled', - }, - tokenBalanceChanges: [], - }, - note: 'TransactionController#updateSimulationData - Update simulation data', - timestamp: 1631545992244, - }, - ], - ], - simulationData: { - error: { - code: 'disabled', - message: 'Simulation disabled', - }, - tokenBalanceChanges: [], - }, - id: '7087d1d7-f0e8-4c0f-a903-6d9daa392baf', - loadingDefaults: false, - origin: 'https://metamask.github.io', - status: 'unapproved', - time: 1631545991949, - txParams: { - from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', - gas: '0x5208', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', - value: '0x29a2241af62c0000', - }, - type: 'simpleSend', - }, - '6eab4240-3762-4581-abc5-cd91eab6964e': { - chainId: CHAIN_IDS.LOCALHOST, - dappSuggestedGasFees: { - gas: '0x5208', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - }, - history: [ - { - chainId: CHAIN_IDS.LOCALHOST, - dappSuggestedGasFees: { - gas: '0x5208', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - }, - id: '6eab4240-3762-4581-abc5-cd91eab6964e', - loadingDefaults: true, - origin: 'https://metamask.github.io', - status: 'unapproved', - time: 1631545994578, - txParams: { - from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', - gas: '0x5208', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', - value: '0x29a2241af62c0000', - }, - type: 'simpleSend', - }, - [ - { - note: 'Added new unapproved transaction.', - op: 'replace', - path: '/loadingDefaults', - timestamp: 1631545994695, - value: false, - }, - { - op: 'add', - path: '/simulationData', - value: { - error: { - code: 'disabled', - message: 'Simulation disabled', - }, - tokenBalanceChanges: [], - }, - note: 'TransactionController#updateSimulationData - Update simulation data', - timestamp: 1631545992244, - }, - ], - ], - simulationData: { - error: { - code: 'disabled', - message: 'Simulation disabled', - }, - tokenBalanceChanges: [], - }, - id: '6eab4240-3762-4581-abc5-cd91eab6964e', - loadingDefaults: false, - origin: 'https://metamask.github.io', - status: 'unapproved', - time: 1631545994578, - txParams: { - from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', - gas: '0x5208', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', - value: '0x29a2241af62c0000', - }, - type: 'simpleSend', - }, - 'c15eee26-11d6-4914-a70e-36ef9a3bcacb': { - chainId: CHAIN_IDS.LOCALHOST, - dappSuggestedGasFees: { - gas: '0x5208', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - }, - history: [ - { - chainId: CHAIN_IDS.LOCALHOST, - dappSuggestedGasFees: { - gas: '0x5208', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - }, - id: 'c15eee26-11d6-4914-a70e-36ef9a3bcacb', - loadingDefaults: true, - origin: 'https://metamask.github.io', - status: 'unapproved', - time: 1631545996673, - txParams: { - from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', - gas: '0x5208', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', - value: '0x29a2241af62c0000', - }, - type: 'simpleSend', - }, - [ - { - note: 'Added new unapproved transaction.', - op: 'replace', - path: '/loadingDefaults', - timestamp: 1631545996678, - value: false, - }, - { - op: 'add', - path: '/simulationData', - value: { - error: { - code: 'disabled', - message: 'Simulation disabled', - }, - tokenBalanceChanges: [], - }, - note: 'TransactionController#updateSimulationData - Update simulation data', - timestamp: 1631545992244, - }, - ], - ], - simulationData: { - error: { - code: 'disabled', - message: 'Simulation disabled', - }, - tokenBalanceChanges: [], - }, - id: 'c15eee26-11d6-4914-a70e-36ef9a3bcacb', - loadingDefaults: false, - origin: 'https://metamask.github.io', - status: 'unapproved', - time: 1631545996673, - txParams: { - from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', - gas: '0x5208', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', - value: '0x29a2241af62c0000', - }, - type: 'simpleSend', - }, - 'dfa9e5ad-d069-46b1-976e-a23734971d87': { - chainId: CHAIN_IDS.LOCALHOST, - dappSuggestedGasFees: { - gas: '0x5208', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - }, - history: [ - { - chainId: CHAIN_IDS.LOCALHOST, - dappSuggestedGasFees: { - gas: '0x5208', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - }, - id: 'dfa9e5ad-d069-46b1-976e-a23734971d87', - loadingDefaults: true, - origin: 'https://metamask.github.io', - status: 'unapproved', - time: 1631545998675, - txParams: { - from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', - gas: '0x5208', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', - value: '0x29a2241af62c0000', - }, - type: 'simpleSend', - }, - [ - { - note: 'Added new unapproved transaction.', - op: 'replace', - path: '/loadingDefaults', - timestamp: 1631545998677, - value: false, - }, - { - op: 'add', - path: '/simulationData', - value: { - error: { - code: 'disabled', - message: 'Simulation disabled', - }, - tokenBalanceChanges: [], - }, - note: 'TransactionController#updateSimulationData - Update simulation data', - timestamp: 1631545992244, - }, - ], - ], - simulationData: { - error: { - code: 'disabled', - message: 'Simulation disabled', - }, - tokenBalanceChanges: [], - }, - id: 'dfa9e5ad-d069-46b1-976e-a23734971d87', - loadingDefaults: false, - origin: 'https://metamask.github.io', - status: 'unapproved', - time: 1631545998675, - txParams: { - from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', - gas: '0x5208', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', - value: '0x29a2241af62c0000', - }, - type: 'simpleSend', - }, - }, - }); - } - - withTransactionControllerTypeOneTransaction() { - return this.withTransactionController({ - transactions: { - '13a01e77-a368-4bb9-aba9-e7435580e3b9': { - chainId: CHAIN_IDS.LOCALHOST, - history: [ - { - chainId: CHAIN_IDS.LOCALHOST, - id: '13a01e77-a368-4bb9-aba9-e7435580e3b9', - loadingDefaults: true, - origin: 'metamask', - status: 'unapproved', - time: 1617228030067, - txParams: { - from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', - gas: '0x61a8', - gasPrice: '0x2540be400', - to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970', - value: '0xde0b6b3a7640000', - }, - type: 'simpleSend', - }, - [ - { - note: 'Added new unapproved transaction.', - op: 'replace', - path: '/loadingDefaults', - timestamp: 1617228030069, - value: false, - }, - ], - ], - id: '13a01e77-a368-4bb9-aba9-e7435580e3b9', - loadingDefaults: false, - origin: 'metamask', - primaryTransaction: { - chainId: CHAIN_IDS.LOCALHOST, - id: '13a01e77-a368-4bb9-aba9-e7435580e3b9', - loadingDefaults: true, - origin: 'metamask', - status: 'unapproved', - time: 1617228030067, - txParams: { - from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', - gas: '0x61a8', - gasPrice: '0x2540be400', - to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970', - value: '0xde0b6b3a7640000', - }, - type: 'sentEther', - }, - status: 'unapproved', - time: 1617228030067, - txParams: { - from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', - gas: '0x61a8', - gasPrice: '0x2540be400', - to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970', - value: '0xde0b6b3a7640000', - }, - type: 'simpleSend', - }, - }, - }); - } - - withTransactionControllerTypeTwoTransaction() { - return this.withTransactionController({ - transactions: { - '13a01e77-a368-4bb9-aba9-e7435580e3b9': { - chainId: CHAIN_IDS.LOCALHOST, - history: [ - { - chainId: CHAIN_IDS.LOCALHOST, - id: '13a01e77-a368-4bb9-aba9-e7435580e3b9', - loadingDefaults: true, - origin: 'metamask', - status: 'unapproved', - time: 1617228030067, - txParams: { - from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', - gas: '0x61a8', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970', - type: '0x2', - value: '0xde0b6b3a7640000', - }, - type: 'simpleSend', - }, - [ - { - note: 'Added new unapproved transaction.', - op: 'replace', - path: '/loadingDefaults', - timestamp: 1617228030069, - value: false, - }, - ], - ], - id: '13a01e77-a368-4bb9-aba9-e7435580e3b9', - loadingDefaults: false, - origin: 'metamask', - primaryTransaction: { - chainId: CHAIN_IDS.LOCALHOST, - id: '13a01e77-a368-4bb9-aba9-e7435580e3b9', - loadingDefaults: true, - origin: 'metamask', - status: 'unapproved', - time: 1617228030067, - txParams: { - from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', - gas: '0x61a8', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970', - type: '0x2', - value: '0xde0b6b3a7640000', - }, - type: 'sentEther', - }, - status: 'unapproved', - time: 1617228030067, - txParams: { - from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', - gas: '0x61a8', - maxFeePerGas: '0x59682f0c', - maxPriorityFeePerGas: '0x59682f00', - to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970', - type: '0x2', - value: '0xde0b6b3a7640000', - }, - type: 'simpleSend', - }, - }, - }); - } - - withTransactionControllerOPLayer2Transaction() { - const FROM_ADDRESS = ACCOUNT_1; - const TRANSACTION_ID = 'f0fc75d0-181d-11ef-9546-8b2366f13afd'; - const TRANSACTION_TYPE = 'contractInteraction'; - const TEST_NETWORK_CLIENT_ID = 'networkConfigurationId'; - - return this.withTransactionController({ - transactions: { - [TRANSACTION_ID]: { - actionId: 3577139671, - chainId: '0xa', - dappSuggestedGasFees: { gas: '0x31f10' }, - defaultGasEstimates: { - estimateType: 'dappSuggested', - gas: '0x31f10', - maxFeePerGas: '0x3b014b3', - maxPriorityFeePerGas: '0x3b014b3', - }, - gasFeeEstimates: { gasPrice: '0x3b202d0', type: 'eth_gasPrice' }, - gasFeeEstimatesLoaded: true, - history: [ - { - actionId: 3577139671, - chainId: '0xa', - dappSuggestedGasFees: { gas: '0x31f10' }, - defaultGasEstimates: { - estimateType: 'dappSuggested', - gas: '0x31f10', - maxFeePerGas: '0x3b014b3', - maxPriorityFeePerGas: '0x3b014b3', - }, - id: TRANSACTION_ID, - layer1GasFee: '0x175283ae57', - networkClientId: TEST_NETWORK_CLIENT_ID, - origin: 'https://metamask.github.io', - securityAlertResponse: { - reason: 'loading', - result_type: 'validation_in_progress', - securityAlertId: '30626504-0069-4278-9e2e-3d7fba2e6aef', - }, - sendFlowHistory: [], - status: 'unapproved', - time: 1716370234797, - txParams: { - data: '0x608060405234801561001057600080fd5b5033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000808190555061023b806100686000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632e1a7d4d1461005c5780638da5cb5b1461009d578063d0e30db0146100f4575b600080fd5b34801561006857600080fd5b5061008760048036038101908080359060200190929190505050610112565b6040518082815260200191505060405180910390f35b3480156100a957600080fd5b506100b26101d0565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100fc6101f6565b6040518082815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561017057600080fd5b8160008082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501580156101c5573d6000803e3d6000fd5b506000549050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60003460008082825401925050819055506000549050905600a165627a7a72305820f237db3ec816a52589d82512117bc85bc08d3537683ffeff9059108caf3e5d400029', - from: FROM_ADDRESS, - gas: '0x31f10', - maxFeePerGas: '0x3b014b3', - maxPriorityFeePerGas: '0x3b014b3', - value: '0x0', - }, - type: TRANSACTION_TYPE, - userEditedGasLimit: false, - userFeeLevel: 'dappSuggested', - verifiedOnBlockchain: false, - }, - [ - { - note: 'TransactionController#updateSimulationData - Update simulation data', - op: 'add', - path: '/simulationData', - timestamp: 1716370235743, - value: { - error: { code: 'disabled', message: 'Simulation disabled' }, - tokenBalanceChanges: [], - }, - }, - ], - [ - { - note: 'TransactionController:updatesecurityAlertResponse - securityAlertResponse updated', - op: 'replace', - path: '/securityAlertResponse/result_type', - timestamp: 1716370236091, - value: 'Benign', - }, - { - op: 'replace', - path: '/securityAlertResponse/reason', - value: '', - }, - { - op: 'add', - path: '/securityAlertResponse/description', - value: '', - }, - { op: 'add', path: '/securityAlertResponse/features', value: [] }, - { - op: 'add', - path: '/securityAlertResponse/block', - value: 120385722, - }, - { - op: 'add', - path: '/gasFeeEstimates', - value: { gasPrice: '0x3b014b3', type: 'eth_gasPrice' }, - }, - { op: 'add', path: '/gasFeeEstimatesLoaded', value: true }, - ], - ], - id: TRANSACTION_ID, - layer1GasFee: '0x19fdabf615', - networkClientId: TEST_NETWORK_CLIENT_ID, - origin: 'https://metamask.github.io', - securityAlertResponse: { - block: 120385722, - description: '', - features: [], - reason: '', - result_type: 'Benign', - securityAlertId: '30626504-0069-4278-9e2e-3d7fba2e6aef', - }, - sendFlowHistory: [], - simulationData: { - error: { code: 'disabled', message: 'Simulation disabled' }, - tokenBalanceChanges: [], - }, - status: 'unapproved', - time: 1716370234797, - txParams: { - data: '0x608060405234801561001057600080fd5b5033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000808190555061023b806100686000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632e1a7d4d1461005c5780638da5cb5b1461009d578063d0e30db0146100f4575b600080fd5b34801561006857600080fd5b5061008760048036038101908080359060200190929190505050610112565b6040518082815260200191505060405180910390f35b3480156100a957600080fd5b506100b26101d0565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100fc6101f6565b6040518082815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561017057600080fd5b8160008082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501580156101c5573d6000803e3d6000fd5b506000549050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60003460008082825401925050819055506000549050905600a165627a7a72305820f237db3ec816a52589d82512117bc85bc08d3537683ffeff9059108caf3e5d400029', - from: FROM_ADDRESS, - gas: '0x31f10', - maxFeePerGas: '0x3b014b3', - maxPriorityFeePerGas: '0x3b014b3', - value: '0x0', - }, - type: TRANSACTION_TYPE, - userEditedGasLimit: false, - userFeeLevel: 'dappSuggested', - verifiedOnBlockchain: false, - }, - }, - }); - } - withTransactionControllerApprovedTransaction() { return this.withTransactionController({ transactions: { diff --git a/test/e2e/page-objects/flows/transaction.ts b/test/e2e/page-objects/flows/transaction.ts new file mode 100644 index 000000000000..e2fdbd652034 --- /dev/null +++ b/test/e2e/page-objects/flows/transaction.ts @@ -0,0 +1,40 @@ +import { TransactionParams } from '@metamask/transaction-controller'; +import { DEFAULT_FIXTURE_ACCOUNT } from '../../constants'; +import { Driver } from '../../webdriver/driver'; +import HomePage from '../pages/homepage'; +import SendTokenPage from '../pages/send/send-token-page'; +import TestDapp from '../pages/test-dapp'; + +export const createInternalTransaction = async (driver: Driver) => { + // Firefox has incorrect balance if send flow started too quickly. + await driver.delay(1000); + + const homePage = new HomePage(driver); + await homePage.startSendFlow(); + + const sendToPage = new SendTokenPage(driver); + await sendToPage.check_pageIsLoaded(); + await sendToPage.fillRecipient('0x2f318C334780961FB129D2a6c30D0763d9a5C970'); + await sendToPage.fillAmount('1'); + await sendToPage.goToNextScreen(); +}; + +export const createDappTransaction = async ( + driver: Driver, + override?: Partial, +) => { + const testDapp = new TestDapp(driver); + + await testDapp.request('eth_sendTransaction', [ + { + data: '0x', + from: DEFAULT_FIXTURE_ACCOUNT, + maxFeePerGas: '0x0', + maxPriorityFeePerGas: '0x0', + to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970', + value: '0x38d7ea4c68000', + type: '0x2', + ...override, + }, + ]); +}; diff --git a/test/e2e/page-objects/pages/account-list-page.ts b/test/e2e/page-objects/pages/account-list-page.ts new file mode 100644 index 000000000000..8550c092b23c --- /dev/null +++ b/test/e2e/page-objects/pages/account-list-page.ts @@ -0,0 +1,92 @@ +import { Driver } from '../../webdriver/driver'; + +class AccountListPage { + private driver: Driver; + + private accountListItem: object; + + private accountOptionsMenuButton: string; + + private hideUnhideAccountButton: string; + + private hiddenAccountsList: string; + + private hiddenAccountOptionsMenuButton: string; + + private pinnedIcon: string; + + private pinUnpinAccountButton: string; + + constructor(driver: Driver) { + this.driver = driver; + this.accountOptionsMenuButton = + '[data-testid="account-list-item-menu-button"]'; + this.hideUnhideAccountButton = '[data-testid="account-list-menu-hide"]'; + this.pinUnpinAccountButton = '[data-testid="account-list-menu-pin"]'; + this.hiddenAccountsList = '[data-testid="hidden-accounts-list"]'; + this.pinnedIcon = '[data-testid="account-pinned-icon"]'; + this.accountListItem = { + text: 'Account', + css: '.multichain-account-menu-popover__list--menu-item', + }; + this.hiddenAccountOptionsMenuButton = + '.multichain-account-menu-popover__list--menu-item-hidden-account [data-testid="account-list-item-menu-button"]'; + } + + async hideAccount(): Promise { + console.log(`Hide account in account list`); + await this.driver.clickElement(this.hideUnhideAccountButton); + } + + async openAccountOptionsMenu(): Promise { + console.log(`Open account option menu`); + await this.driver.clickElement(this.accountOptionsMenuButton); + } + + async openHiddenAccountOptions(): Promise { + console.log(`Open hidden accounts options menu`); + await this.driver.clickElement(this.hiddenAccountOptionsMenuButton); + } + + async openHiddenAccountsList(): Promise { + console.log(`Open hidden accounts option menu`); + await this.driver.clickElement(this.hiddenAccountsList); + } + + async pinAccount(): Promise { + console.log(`Pin account in account list`); + await this.driver.clickElement(this.pinUnpinAccountButton); + } + + async unhideAccount(): Promise { + console.log(`Unhide account in account list`); + await this.driver.clickElement(this.hideUnhideAccountButton); + } + + async unpinAccount(): Promise { + console.log(`Unpin account in account list`); + await this.driver.clickElement(this.pinUnpinAccountButton); + } + + async check_accountIsDisplayed(): Promise { + console.log(`Check that account is displayed in account list`); + await this.driver.waitForSelector(this.accountListItem); + } + + async check_accountIsPinned(): Promise { + console.log(`Check that account is pinned`); + await this.driver.waitForSelector(this.pinnedIcon); + } + + async check_accountIsUnpinned(): Promise { + console.log(`Check that account is unpinned`); + await this.driver.assertElementNotPresent(this.pinnedIcon); + } + + async check_hiddenAccountsListExists(): Promise { + console.log(`Check that hidden accounts list is displayed in account list`); + await this.driver.waitForSelector(this.hiddenAccountsList); + } +} + +export default AccountListPage; diff --git a/test/e2e/page-objects/pages/confirmations/legacy/navigation.ts b/test/e2e/page-objects/pages/confirmations/legacy/navigation.ts new file mode 100644 index 000000000000..ab04f85a4a2e --- /dev/null +++ b/test/e2e/page-objects/pages/confirmations/legacy/navigation.ts @@ -0,0 +1,57 @@ +import { Driver } from '../../../../webdriver/driver'; + +class ConfirmationNavigation { + private driver: Driver; + + private nextPageButton: string; + + private previousPageButton: string; + + private firstPageButton: string; + + private lastPageButton: string; + + private navigationTitle: string; + + constructor(driver: Driver) { + this.driver = driver; + this.nextPageButton = '[data-testid="next-page"]'; + this.previousPageButton = '[data-testid="previous-page"]'; + this.firstPageButton = '[data-testid="first-page"]'; + this.lastPageButton = '[data-testid="last-page"]'; + this.navigationTitle = '.confirm-page-container-navigation'; + } + + async clickNextPage(): Promise { + await this.driver.clickElement(this.nextPageButton); + } + + async clickPreviousPage(): Promise { + await this.driver.clickElement(this.previousPageButton); + } + + async clickFirstPage(): Promise { + await this.driver.clickElement(this.firstPageButton); + } + + async clickLastPage(): Promise { + await this.driver.clickElement(this.lastPageButton); + } + + async check_pageNumbers( + currentPage: number, + totalPages: number, + ): Promise { + try { + await this.driver.findElement({ + css: this.navigationTitle, + text: `${currentPage} of ${totalPages}`, + }); + } catch (e) { + console.log('Timeout while waiting for navigation page numbers', e); + throw e; + } + } +} + +export default ConfirmationNavigation; diff --git a/test/e2e/page-objects/pages/header-navbar.ts b/test/e2e/page-objects/pages/header-navbar.ts index add85e88b7b7..a6d58b6b1946 100644 --- a/test/e2e/page-objects/pages/header-navbar.ts +++ b/test/e2e/page-objects/pages/header-navbar.ts @@ -5,14 +5,25 @@ class HeaderNavbar { private accountMenuButton: string; + private accountOptionMenu: string; + + private lockMetaMaskButton: string; + constructor(driver: Driver) { this.driver = driver; this.accountMenuButton = '[data-testid="account-menu-icon"]'; + this.accountOptionMenu = '[data-testid="account-options-menu-button"]'; + this.lockMetaMaskButton = '[data-testid="global-menu-lock"]'; } async openAccountMenu(): Promise { await this.driver.clickElement(this.accountMenuButton); } + + async lockMetaMask(): Promise { + await this.driver.clickElement(this.accountOptionMenu); + await this.driver.clickElement(this.lockMetaMaskButton); + } } export default HeaderNavbar; diff --git a/test/e2e/page-objects/pages/homepage.ts b/test/e2e/page-objects/pages/homepage.ts index 5e596021a449..92c5e34f2a0e 100644 --- a/test/e2e/page-objects/pages/homepage.ts +++ b/test/e2e/page-objects/pages/homepage.ts @@ -20,6 +20,8 @@ class HomePage { private transactionAmountsInActivity: string; + private accountMenuButton: string; + public headerNavbar: HeaderNavbar; constructor(driver: Driver) { @@ -36,6 +38,7 @@ class HomePage { this.completedTransactions = '[data-testid="activity-list-item"]'; this.transactionAmountsInActivity = '[data-testid="transaction-list-item-primary-currency"]'; + this.accountMenuButton = '[data-testid="account-menu-icon"]'; } async check_pageIsLoaded(): Promise { @@ -81,6 +84,11 @@ class HomePage { await this.driver.clickElement(this.activityTab); } + async openAccountMenu(): Promise { + console.log(`Opening account menu`); + await this.driver.clickElement(this.accountMenuButton); + } + /** * This function checks if the specified number of confirmed transactions are displayed in the activity list on homepage. * It waits up to 10 seconds for the expected number of confirmed transactions to be visible. diff --git a/test/e2e/page-objects/pages/send/send-token-page.ts b/test/e2e/page-objects/pages/send/send-token-page.ts index b5b703814a5f..65727b106783 100644 --- a/test/e2e/page-objects/pages/send/send-token-page.ts +++ b/test/e2e/page-objects/pages/send/send-token-page.ts @@ -97,7 +97,6 @@ class SendTokenPage { }); await this.driver.waitForSelector({ text: address, - css: this.ensResolvedAddress, }); } diff --git a/test/e2e/page-objects/pages/test-dapp.ts b/test/e2e/page-objects/pages/test-dapp.ts new file mode 100644 index 000000000000..8c2fe513ca10 --- /dev/null +++ b/test/e2e/page-objects/pages/test-dapp.ts @@ -0,0 +1,37 @@ +import { Driver } from '../../webdriver/driver'; + +const DAPP_HOST_ADDRESS = '127.0.0.1:8080'; +const DAPP_URL = `http://${DAPP_HOST_ADDRESS}`; + +class TestDapp { + private driver: Driver; + + constructor(driver: Driver) { + this.driver = driver; + } + + async open({ + contractAddress, + url = DAPP_URL, + }: { + contractAddress?: string; + url?: string; + }) { + const dappUrl = contractAddress + ? `${url}/?contract=${contractAddress}` + : url; + + return await this.driver.openNewPage(dappUrl); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + async request(method: string, params: any[]) { + await this.open({ + url: `${DAPP_URL}/request?method=${method}¶ms=${JSON.stringify( + params, + )}`, + }); + } +} + +export default TestDapp; diff --git a/test/e2e/run-all.js b/test/e2e/run-all.js index 6150f5c71aa9..a0e5ee9d54e5 100644 --- a/test/e2e/run-all.js +++ b/test/e2e/run-all.js @@ -41,7 +41,7 @@ const RETRIES_FOR_NEW_OR_CHANGED_TESTS = 5; * @param {string[]} changedOrNewTests - List of changed or new test paths. * @returns {string} The updated full test list. */ -async function applyQualityGate(fullTestList, changedOrNewTests) { +function applyQualityGate(fullTestList, changedOrNewTests) { let qualityGatedList = fullTestList; if (changedOrNewTests.length > 0) { @@ -63,11 +63,11 @@ async function applyQualityGate(fullTestList, changedOrNewTests) { } // For running E2Es in parallel in CI -async function runningOnCircleCI(testPaths) { - const changedOrNewTests = await filterE2eChangedFiles(); +function runningOnCircleCI(testPaths) { + const changedOrNewTests = filterE2eChangedFiles(); console.log('Changed or new test list:', changedOrNewTests); - const fullTestList = await applyQualityGate( + const fullTestList = applyQualityGate( testPaths.join('\n'), changedOrNewTests, ); @@ -248,7 +248,7 @@ async function main() { let changedOrNewTests; if (process.env.CIRCLECI) { ({ fullTestList: myTestList, changedOrNewTests = [] } = - await runningOnCircleCI(testPaths)); + runningOnCircleCI(testPaths)); } else { myTestList = testPaths; } diff --git a/test/e2e/snaps/enums.js b/test/e2e/snaps/enums.js index a7a69e13a13c..2b1a6bc6532d 100644 --- a/test/e2e/snaps/enums.js +++ b/test/e2e/snaps/enums.js @@ -1,3 +1,3 @@ module.exports = { - TEST_SNAPS_WEBSITE_URL: 'https://metamask.github.io/snaps/test-snaps/2.13.0/', + TEST_SNAPS_WEBSITE_URL: 'https://metamask.github.io/snaps/test-snaps/2.13.1/', }; diff --git a/test/e2e/snaps/test-snap-metrics.spec.js b/test/e2e/snaps/test-snap-metrics.spec.js index 6856aab2fd08..a26671ca4261 100644 --- a/test/e2e/snaps/test-snap-metrics.spec.js +++ b/test/e2e/snaps/test-snap-metrics.spec.js @@ -234,7 +234,7 @@ describe('Test Snap Metrics', function () { assert.deepStrictEqual(events[1].properties, { snap_id: 'npm:@metamask/notification-example-snap', origin: 'https://metamask.github.io', - version: '2.1.3', + version: '2.1.4', category: 'Snaps', locale: 'en', chain_id: '0x539', @@ -501,7 +501,7 @@ describe('Test Snap Metrics', function () { const events = await getEventPayloads(driver, mockedEndpoints); assert.deepStrictEqual(events[0].properties, { snap_id: 'npm:@metamask/notification-example-snap', - version: '2.1.3', + version: '2.1.4', category: 'Snaps', locale: 'en', chain_id: '0x539', diff --git a/test/e2e/tests/account/account-hide-unhide.spec.js b/test/e2e/tests/account/account-hide-unhide.spec.js deleted file mode 100644 index 803954ea38e3..000000000000 --- a/test/e2e/tests/account/account-hide-unhide.spec.js +++ /dev/null @@ -1,63 +0,0 @@ -const { strict: assert } = require('assert'); -const { - defaultGanacheOptions, - withFixtures, - unlockWallet, -} = require('../../helpers'); -const FixtureBuilder = require('../../fixture-builder'); - -describe('Account list - hide/unhide functionality - ', function () { - it('hide account by clicking hide button', async function () { - await withFixtures( - { - fixtures: new FixtureBuilder().build(), - ganacheOptions: defaultGanacheOptions, - title: this.test.fullTitle(), - }, - async ({ driver }) => { - await unlockWallet(driver); - - await driver.clickElement('[data-testid="account-menu-icon"]'); - await driver.clickElement( - '[data-testid="account-list-item-menu-button"]', - ); - await driver.clickElement('[data-testid="account-list-menu-hide"]'); - const hiddenAccounts = await driver.findElement( - '.hidden-accounts-list', - ); - assert.equal(await hiddenAccounts.isDisplayed(), true); - }, - ); - }); - - it('unhide account by clicking show account button', async function () { - await withFixtures( - { - fixtures: new FixtureBuilder().build(), - ganacheOptions: defaultGanacheOptions, - title: this.test.fullTitle(), - }, - async ({ driver }) => { - await unlockWallet(driver); - - await driver.clickElement('[data-testid="account-menu-icon"]'); - await driver.clickElement( - '[data-testid="account-list-item-menu-button"]', - ); - await driver.clickElement('[data-testid="account-list-menu-hide"]'); - - await driver.clickElement('.hidden-accounts-list'); - - await driver.clickElement( - '.multichain-account-menu-popover__list--menu-item-hidden-account [data-testid="account-list-item-menu-button"]', - ); - await driver.clickElement('[data-testid="account-list-menu-hide"]'); - - const accounts = await driver.findElement( - '.multichain-account-menu-popover__list--menu-item', - ); - assert.equal(await accounts.isDisplayed(), true); - }, - ); - }); -}); diff --git a/test/e2e/tests/account/account-hide-unhide.spec.ts b/test/e2e/tests/account/account-hide-unhide.spec.ts new file mode 100644 index 000000000000..19523b0ab0ce --- /dev/null +++ b/test/e2e/tests/account/account-hide-unhide.spec.ts @@ -0,0 +1,35 @@ +import { Suite } from 'mocha'; +import { Driver } from '../../webdriver/driver'; +import { withFixtures, defaultGanacheOptions } from '../../helpers'; +import FixtureBuilder from '../../fixture-builder'; +import { loginWithBalanceValidation } from '../../page-objects/flows/login.flow'; +import HomePage from '../../page-objects/pages/homepage'; +import AccountListPage from '../../page-objects/pages/account-list-page'; + +describe('Account list - hide/unhide functionality', function (this: Suite) { + it('hide and unhide account by clicking hide and unhide button', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder().build(), + ganacheOptions: defaultGanacheOptions, + title: this.test?.fullTitle(), + }, + async ({ driver }: { driver: Driver }) => { + await loginWithBalanceValidation(driver); + new HomePage(driver).openAccountMenu(); + + // hide account + const accountListPage = new AccountListPage(driver); + await accountListPage.openAccountOptionsMenu(); + await accountListPage.hideAccount(); + await accountListPage.check_hiddenAccountsListExists(); + + // unhide account + await accountListPage.openHiddenAccountsList(); + await accountListPage.openHiddenAccountOptions(); + await accountListPage.unhideAccount(); + await accountListPage.check_accountIsDisplayed(); + }, + ); + }); +}); diff --git a/test/e2e/tests/account/account-pin-unpin.spec.js b/test/e2e/tests/account/account-pin-unpin.spec.js deleted file mode 100644 index dc4b6d564506..000000000000 --- a/test/e2e/tests/account/account-pin-unpin.spec.js +++ /dev/null @@ -1,71 +0,0 @@ -const { strict: assert } = require('assert'); -const { - defaultGanacheOptions, - withFixtures, - unlockWallet, -} = require('../../helpers'); -const FixtureBuilder = require('../../fixture-builder'); - -describe('Account list - pin/unpin functionality - ', function () { - it('pin and unpin account by clicking the pin/unpin button', async function () { - await withFixtures( - { - fixtures: new FixtureBuilder().build(), - ganacheOptions: defaultGanacheOptions, - title: this.test.fullTitle(), - }, - async ({ driver }) => { - const pinnedIconSelector = '.account-pinned-icon'; - await unlockWallet(driver); - - // pin account - await driver.clickElement('[data-testid="account-menu-icon"]'); - await driver.clickElement( - '[data-testid="account-list-item-menu-button"]', - ); - await driver.clickElement('[data-testid="account-list-menu-pin"]'); - const pinnedIcon = await driver.findElement(pinnedIconSelector); - assert.equal(await pinnedIcon.isDisplayed(), true); - - // unpin account - await driver.clickElement( - '[data-testid="account-list-item-menu-button"]', - ); - await driver.clickElement('[data-testid="account-list-menu-pin"]'); - - await driver.assertElementNotPresent(pinnedIconSelector, { - waitAtLeastGuard: 200, // A waitAtLeastGuard of 200ms is the best choice here - }); - }, - ); - }); - - it('account once hidden should be unpinned and remain so even if revealed again', async function () { - await withFixtures( - { - fixtures: new FixtureBuilder().build(), - ganacheOptions: defaultGanacheOptions, - title: this.test.fullTitle(), - }, - async ({ driver }) => { - await unlockWallet(driver); - - await driver.clickElement('[data-testid="account-menu-icon"]'); - await driver.clickElement( - '[data-testid="account-list-item-menu-button"]', - ); - await driver.clickElement('[data-testid="account-list-menu-pin"]'); - const pinnedIcon = await driver.findElement('.account-pinned-icon'); - assert.equal(await pinnedIcon.isDisplayed(), true); - await driver.clickElement( - '[data-testid="account-list-item-menu-button"]', - ); - await driver.clickElement('[data-testid="account-list-menu-hide"]'); - const hiddenAccounts = await driver.findElement( - '.hidden-accounts-list', - ); - assert.equal(await hiddenAccounts.isDisplayed(), true); - }, - ); - }); -}); diff --git a/test/e2e/tests/account/account-pin-unpin.spec.ts b/test/e2e/tests/account/account-pin-unpin.spec.ts new file mode 100644 index 000000000000..a37859dfa6a9 --- /dev/null +++ b/test/e2e/tests/account/account-pin-unpin.spec.ts @@ -0,0 +1,67 @@ +import { Suite } from 'mocha'; +import { Driver } from '../../webdriver/driver'; +import { withFixtures, defaultGanacheOptions } from '../../helpers'; +import FixtureBuilder from '../../fixture-builder'; +import { loginWithBalanceValidation } from '../../page-objects/flows/login.flow'; +import HomePage from '../../page-objects/pages/homepage'; +import AccountListPage from '../../page-objects/pages/account-list-page'; + +describe('Account list - pin/unpin functionality', function (this: Suite) { + it('pin and unpin account by clicking the pin/unpin button', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder().build(), + ganacheOptions: defaultGanacheOptions, + title: this.test?.fullTitle(), + }, + async ({ driver }: { driver: Driver }) => { + await loginWithBalanceValidation(driver); + new HomePage(driver).openAccountMenu(); + + // pin account + const accountListPage = new AccountListPage(driver); + await accountListPage.openAccountOptionsMenu(); + await accountListPage.pinAccount(); + await accountListPage.check_accountIsPinned(); + + // unpin account + await accountListPage.openAccountOptionsMenu(); + await accountListPage.unpinAccount(); + await accountListPage.check_accountIsUnpinned(); + }, + ); + }); + + it('account once hidden should be unpinned and remain so even if revealed again', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder().build(), + ganacheOptions: defaultGanacheOptions, + title: this.test?.fullTitle(), + }, + async ({ driver }: { driver: Driver }) => { + await loginWithBalanceValidation(driver); + new HomePage(driver).openAccountMenu(); + + // pin account + const accountListPage = new AccountListPage(driver); + await accountListPage.openAccountOptionsMenu(); + await accountListPage.pinAccount(); + await accountListPage.check_accountIsPinned(); + + // hide the same account and check the account is unpinned automatically + await accountListPage.openAccountOptionsMenu(); + await accountListPage.hideAccount(); + await accountListPage.check_hiddenAccountsListExists(); + await accountListPage.check_accountIsUnpinned(); + + // unhide the same account and check the account is still unpinned + await accountListPage.openHiddenAccountsList(); + await accountListPage.openHiddenAccountOptions(); + await accountListPage.unhideAccount(); + await accountListPage.check_accountIsDisplayed(); + await accountListPage.check_accountIsUnpinned(); + }, + ); + }); +}); diff --git a/test/e2e/tests/account/import-flow.spec.js b/test/e2e/tests/account/import-flow.spec.js index 3c05131090cc..045600cff4f4 100644 --- a/test/e2e/tests/account/import-flow.spec.js +++ b/test/e2e/tests/account/import-flow.spec.js @@ -132,7 +132,7 @@ describe('Import flow @no-mmi', function () { await locateAccountBalanceDOM(driver, ganacheServer); await openActionMenuAndStartSendFlow(driver); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', '0x2f318C334780961FB129D2a6c30D0763d9a5C970', ); await driver.fill('input[placeholder="0"]', '1'); diff --git a/test/e2e/tests/account/lock-account.spec.js b/test/e2e/tests/account/lock-account.spec.js deleted file mode 100644 index d384ff0020ae..000000000000 --- a/test/e2e/tests/account/lock-account.spec.js +++ /dev/null @@ -1,37 +0,0 @@ -const { strict: assert } = require('assert'); -const { - defaultGanacheOptions, - withFixtures, - unlockWallet, -} = require('../../helpers'); -const FixtureBuilder = require('../../fixture-builder'); - -describe('Lock and unlock', function () { - it('successfully unlocks after lock', async function () { - await withFixtures( - { - fixtures: new FixtureBuilder().build(), - ganacheOptions: defaultGanacheOptions, - title: this.test.fullTitle(), - }, - async ({ driver }) => { - await unlockWallet(driver); - - await driver.clickElement( - '[data-testid="account-options-menu-button"]', - ); - const lockButton = await driver.findClickableElement( - '[data-testid="global-menu-lock"]', - ); - assert.equal(await lockButton.getText(), 'Lock MetaMask'); - await lockButton.click(); - await unlockWallet(driver); - - const walletBalance = await driver.findElement( - '.eth-overview__primary-balance', - ); - assert.equal(/^25\s*ETH$/u.test(await walletBalance.getText()), true); - }, - ); - }); -}); diff --git a/test/e2e/tests/account/lock-account.spec.ts b/test/e2e/tests/account/lock-account.spec.ts new file mode 100644 index 000000000000..c4cc914978cb --- /dev/null +++ b/test/e2e/tests/account/lock-account.spec.ts @@ -0,0 +1,24 @@ +import { Suite } from 'mocha'; +import { defaultGanacheOptions, withFixtures } from '../../helpers'; +import FixtureBuilder from '../../fixture-builder'; +import HomePage from '../../page-objects/pages/homepage'; +import { Driver } from '../../webdriver/driver'; +import { loginWithBalanceValidation } from '../../page-objects/flows/login.flow'; + +describe('Lock and unlock', function (this: Suite) { + it('successfully unlocks after lock', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder().build(), + ganacheOptions: defaultGanacheOptions, + title: this.test?.fullTitle(), + }, + async ({ driver }: { driver: Driver }) => { + await loginWithBalanceValidation(driver); + const homePage = new HomePage(driver); + await homePage.headerNavbar.lockMetaMask(); + await loginWithBalanceValidation(driver); + }, + ); + }); +}); diff --git a/test/e2e/tests/account/lockdown.spec.js b/test/e2e/tests/account/lockdown.spec.ts similarity index 76% rename from test/e2e/tests/account/lockdown.spec.js rename to test/e2e/tests/account/lockdown.spec.ts index c0d5d52ee412..4307e1e33d6e 100644 --- a/test/e2e/tests/account/lockdown.spec.js +++ b/test/e2e/tests/account/lockdown.spec.ts @@ -1,13 +1,13 @@ -const { strict: assert } = require('assert'); -const { Browser } = require('selenium-webdriver'); -const { +import { strict as assert } from 'assert'; +import { Browser } from 'selenium-webdriver'; +import { getGlobalProperties, testIntrinsic, -} = require('../../../helpers/protect-intrinsics-helpers'); -const { convertToHexValue, withFixtures } = require('../../helpers'); -const { PAGES } = require('../../webdriver/driver'); -const FixtureBuilder = require('../../fixture-builder'); -const { isManifestV3 } = require('../../../../shared/modules/mv3.utils'); +} from '../../../helpers/protect-intrinsics-helpers'; +import { convertToHexValue, withFixtures } from '../../helpers'; +import { PAGES, Driver } from '../../webdriver/driver'; +import FixtureBuilder from '../../fixture-builder'; +import { isManifestV3 } from '../../../../shared/modules/mv3.utils'; const isFirefox = process.env.SELENIUM_BROWSER === Browser.FIREFOX; @@ -52,7 +52,7 @@ try { } `; -describe('lockdown', function () { +describe('lockdown', function (this: Mocha.Suite) { const ganacheOptions = { accounts: [ { @@ -66,12 +66,11 @@ describe('lockdown', function () { it('the UI environment is locked down', async function () { await withFixtures( { - // The fixtures used here is arbitrary. Any fixture would do. fixtures: new FixtureBuilder().build(), ganacheOptions, - title: this.test.fullTitle(), + title: this.test?.fullTitle(), }, - async ({ driver }) => { + async ({ driver }: { driver: Driver }) => { await driver.navigate(PAGES.HOME); assert.equal( await driver.executeScript(lockdownTestScript), @@ -85,12 +84,11 @@ describe('lockdown', function () { it('the background environment is locked down', async function () { await withFixtures( { - // The fixtures used here is arbitrary. Any fixture would do. fixtures: new FixtureBuilder().build(), ganacheOptions, - title: this.test.fullTitle(), + title: this.test?.fullTitle(), }, - async ({ driver }) => { + async ({ driver }: { driver: Driver }) => { if (isManifestV3) { // TODO: add logic for testing the Service-Worker on MV3 await driver.navigate(PAGES.OFFSCREEN); diff --git a/test/e2e/tests/account/metamask-responsive-ui.spec.js b/test/e2e/tests/account/metamask-responsive-ui.spec.js index d9e9aa2f965c..6afdb9062ac3 100644 --- a/test/e2e/tests/account/metamask-responsive-ui.spec.js +++ b/test/e2e/tests/account/metamask-responsive-ui.spec.js @@ -11,7 +11,7 @@ const FixtureBuilder = require('../../fixture-builder'); describe('MetaMask Responsive UI', function () { it('Creating a new wallet @no-mmi', async function () { - const driverOptions = { responsive: true }; + const driverOptions = { constrainWindowSize: true }; await withFixtures( { @@ -81,7 +81,7 @@ describe('MetaMask Responsive UI', function () { }); it('Importing existing wallet from lock page', async function () { - const driverOptions = { responsive: true }; + const driverOptions = { constrainWindowSize: true }; await withFixtures( { @@ -115,7 +115,7 @@ describe('MetaMask Responsive UI', function () { }); it('Send Transaction from responsive window', async function () { - const driverOptions = { responsive: true }; + const driverOptions = { constrainWindowSize: true }; await withFixtures( { fixtures: new FixtureBuilder().build(), @@ -132,7 +132,7 @@ describe('MetaMask Responsive UI', function () { // starts to send a transaction await openActionMenuAndStartSendFlow(driver); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', '0x2f318C334780961FB129D2a6c30D0763d9a5C970', ); diff --git a/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts b/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts index 3d28afff5790..2a815a025d18 100644 --- a/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts +++ b/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts @@ -1,6 +1,10 @@ /* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ +import { Mockttp } from 'mockttp'; import { openDapp, unlockWallet } from '../../../helpers'; +import { createDappTransaction } from '../../../page-objects/flows/transaction'; import GanacheContractAddressRegistry from '../../../seeder/ganache-contract-address-registry'; +import { Driver } from '../../../webdriver/driver'; +import { MockedEndpoint } from '../../../mock-e2e'; import { assertAdvancedGasDetails, confirmDepositTransaction, @@ -90,8 +94,9 @@ describe('Confirmation Redesign Contract Interaction Component', function () { redesignedConfirmationsEnabled: true, isRedesignedConfirmationsDeveloperEnabled: true, }, + useTransactionSimulations: false, }) - .withTransactionControllerOPLayer2Transaction() + .withNetworkControllerOnOptimism() .build(), ganacheOptions: { ...defaultGanacheOptionsForType2Transactions, @@ -100,9 +105,11 @@ describe('Confirmation Redesign Contract Interaction Component', function () { }, smartContract, title: this.test?.fullTitle(), + testSpecificMock: mockOptimismOracle, }, async ({ driver, contractRegistry }: TestSuiteArguments) => { await unlockWallet(driver); + await createLayer2Transaction(driver); const contractAddress = await ( contractRegistry as GanacheContractAddressRegistry @@ -110,9 +117,7 @@ describe('Confirmation Redesign Contract Interaction Component', function () { await openDapp(driver, contractAddress); - await driver.switchToWindowWithTitle( - WINDOW_TITLES.ExtensionInFullScreenView, - ); + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); await toggleAdvancedDetails(driver); @@ -279,3 +284,34 @@ describe('Confirmation Redesign Contract Interaction Component', function () { }); }); }); + +async function createLayer2Transaction(driver: Driver) { + await createDappTransaction(driver, { + data: '0x1234', + to: '0x581c3C1A2A4EBDE2A0Df29B5cf4c116E42945947', + }); +} + +async function mockOptimismOracle( + mockServer: Mockttp, +): Promise { + return [ + await mockServer + .forPost(/infura/u) + .withJsonBodyIncluding({ + method: 'eth_call', + params: [{ to: '0x420000000000000000000000000000000000000f' }], + }) + .thenCallback(() => { + return { + statusCode: 200, + json: { + jsonrpc: '2.0', + id: '1111111111111111', + result: + '0x0000000000000000000000000000000000000000000000000000000c895f9d79', + }, + }; + }), + ]; +} diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json index 5a4b95548315..f474b2492ba4 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json @@ -179,8 +179,6 @@ "rates": { "btc": { "conversionDate": 0, "conversionRate": "0" } }, "cryptocurrencies": ["btc"], "snaps": "object", - "snapStates": "object", - "unencryptedSnapStates": "object", "jobs": "object", "database": null, "lastUpdated": null, diff --git a/test/e2e/tests/metrics/traces.spec.ts b/test/e2e/tests/metrics/traces.spec.ts new file mode 100644 index 000000000000..62c4d7da9219 --- /dev/null +++ b/test/e2e/tests/metrics/traces.spec.ts @@ -0,0 +1,129 @@ +import { MockttpServer } from 'mockttp'; +import FixtureBuilder from '../../fixture-builder'; +import { + defaultGanacheOptions, + unlockWallet, + withFixtures, +} from '../../helpers'; +import { + expectMockRequest, + expectNoMockRequest, +} from '../../helpers/mock-server'; + +async function mockSentryCustomTrace(mockServer: MockttpServer) { + return [ + await mockServer + .forPost(/sentry/u) + .withBodyIncluding('"transaction":"UI Startup"') + .thenCallback(() => { + return { + statusCode: 200, + json: {}, + }; + }), + ]; +} + +async function mockSentryAutomatedTrace(mockServer: MockttpServer) { + return [ + await mockServer + .forPost(/sentry/u) + .withBodyIncluding('"transaction":"/home.html"') + .thenCallback(() => { + return { + statusCode: 200, + json: {}, + }; + }), + ]; +} + +describe('Traces', function () { + it('sends custom trace when opening UI if metrics enabled', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder() + .withMetaMetricsController({ + participateInMetaMetrics: true, + }) + .build(), + ganacheOptions: defaultGanacheOptions, + title: this.test?.fullTitle(), + testSpecificMock: mockSentryCustomTrace, + manifestFlags: { + doNotForceSentryForThisTest: true, + }, + }, + async ({ driver, mockedEndpoint }) => { + await unlockWallet(driver); + await expectMockRequest(driver, mockedEndpoint[0], { timeout: 3000 }); + }, + ); + }); + + it('does not send custom trace when opening UI if metrics disabled @no-mmi', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder() + .withMetaMetricsController({ + participateInMetaMetrics: false, + }) + .build(), + ganacheOptions: defaultGanacheOptions, + title: this.test?.fullTitle(), + testSpecificMock: mockSentryCustomTrace, + manifestFlags: { + doNotForceSentryForThisTest: true, + }, + }, + async ({ driver, mockedEndpoint }) => { + await unlockWallet(driver); + await expectNoMockRequest(driver, mockedEndpoint[0], { timeout: 3000 }); + }, + ); + }); + + it('sends automated trace when opening UI if metrics enabled', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder() + .withMetaMetricsController({ + participateInMetaMetrics: true, + }) + .build(), + ganacheOptions: defaultGanacheOptions, + title: this.test?.fullTitle(), + testSpecificMock: mockSentryAutomatedTrace, + manifestFlags: { + doNotForceSentryForThisTest: true, + }, + }, + async ({ driver, mockedEndpoint }) => { + await unlockWallet(driver); + await expectMockRequest(driver, mockedEndpoint[0], { timeout: 3000 }); + }, + ); + }); + + it('does not send automated trace when opening UI if metrics disabled @no-mmi', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder() + .withMetaMetricsController({ + participateInMetaMetrics: false, + }) + .build(), + ganacheOptions: defaultGanacheOptions, + title: this.test?.fullTitle(), + testSpecificMock: mockSentryAutomatedTrace, + manifestFlags: { + doNotForceSentryForThisTest: true, + }, + }, + async ({ driver, mockedEndpoint }) => { + await unlockWallet(driver); + await expectNoMockRequest(driver, mockedEndpoint[0], { timeout: 3000 }); + }, + ); + }); +}); diff --git a/test/e2e/tests/network/network-error.spec.js b/test/e2e/tests/network/network-error.spec.js index 02514f19718c..4d45734edf77 100644 --- a/test/e2e/tests/network/network-error.spec.js +++ b/test/e2e/tests/network/network-error.spec.js @@ -60,7 +60,7 @@ describe('Gas API fallback', function () { await openActionMenuAndStartSendFlow(driver); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', '0x2f318C334780961FB129D2a6c30D0763d9a5C970', ); diff --git a/test/e2e/tests/notifications/mocks.ts b/test/e2e/tests/notifications/mocks.ts index 290db7024360..5cceee276436 100644 --- a/test/e2e/tests/notifications/mocks.ts +++ b/test/e2e/tests/notifications/mocks.ts @@ -20,7 +20,7 @@ type MockResponse = { }; /** - * E2E mock setup for notification APIs (Auth, Storage, Notifications, Push Notifications) + * E2E mock setup for notification APIs (Auth, Storage, Notifications, Push Notifications, Profile syncing) * * @param server - server obj used to mock our endpoints */ diff --git a/test/e2e/tests/petnames/petnames-transactions.spec.js b/test/e2e/tests/petnames/petnames-transactions.spec.js index ed8115da4a0c..cc19e44a55eb 100644 --- a/test/e2e/tests/petnames/petnames-transactions.spec.js +++ b/test/e2e/tests/petnames/petnames-transactions.spec.js @@ -22,7 +22,7 @@ async function createDappSendTransaction(driver) { async function createWalletSendTransaction(driver, recipientAddress) { await openActionMenuAndStartSendFlow(driver); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', recipientAddress, ); diff --git a/test/e2e/tests/ppom/mocks/mock-server-json-rpc.ts b/test/e2e/tests/ppom/mocks/mock-server-json-rpc.ts index 2c560c20c522..ce197e462c80 100644 --- a/test/e2e/tests/ppom/mocks/mock-server-json-rpc.ts +++ b/test/e2e/tests/ppom/mocks/mock-server-json-rpc.ts @@ -43,7 +43,7 @@ const DEFAULT_VARIANT = 'default'; * ]); * ``` */ -async function mockServerJsonRpc( +export async function mockServerJsonRpc( mockServer: MockttpServer, listOfRequestConfigs: RequestConfig[], ) { diff --git a/test/e2e/tests/settings/change-language.spec.ts b/test/e2e/tests/settings/change-language.spec.ts index 578c27be84f6..aafb36059c9b 100644 --- a/test/e2e/tests/settings/change-language.spec.ts +++ b/test/e2e/tests/settings/change-language.spec.ts @@ -145,7 +145,11 @@ describe('Settings - general tab @no-mmi', function (this: Suite) { await changeLanguage(driver, languageIndex); await driver.navigate(); await driver.clickElement(selectors.ethOverviewSend); - await driver.fill(selectors.ensInput, 'test'); + await driver.pasteIntoField( + selectors.ensInput, + // use wrong checksum address; other inputs don't show error until snaps name-lookup has happened + '0xAAAA6BF26964aF9D7eEd9e03E53415D37aA96045', + ); // Validate the language change is reflected in the dialog message const isDialogMessageChanged = await driver.isElementPresent( diff --git a/test/e2e/tests/swap-send/swap-send-test-utils.ts b/test/e2e/tests/swap-send/swap-send-test-utils.ts index c5f4d8bb3d9c..121b297ac83b 100644 --- a/test/e2e/tests/swap-send/swap-send-test-utils.ts +++ b/test/e2e/tests/swap-send/swap-send-test-utils.ts @@ -21,7 +21,7 @@ export class SwapSendPage { fillRecipientAddressInput = async (address: string) => { await this.driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', address, ); }; @@ -266,7 +266,6 @@ export const getSwapSendFixtures = ( ) => { const ETH_CONVERSION_RATE_USD = 3010; return { - driverOptions: { responsive: true }, fixtures: new FixtureBuilder() .withPreferencesController({ featureFlags: {}, diff --git a/test/e2e/tests/tokens/custom-token-send-transfer.spec.js b/test/e2e/tests/tokens/custom-token-send-transfer.spec.js index fa87c9cfbe64..de2aa2addcf8 100644 --- a/test/e2e/tests/tokens/custom-token-send-transfer.spec.js +++ b/test/e2e/tests/tokens/custom-token-send-transfer.spec.js @@ -36,7 +36,7 @@ describe('Transfer custom tokens @no-mmi', function () { await driver.delay(500); await driver.clickElement('[data-testid="eth-overview-send"]'); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', recipientAddress, ); await driver.waitForSelector({ diff --git a/test/e2e/tests/tokens/nft/send-nft.spec.js b/test/e2e/tests/tokens/nft/send-nft.spec.js index 0fe23673a769..35585bbaf2ea 100644 --- a/test/e2e/tests/tokens/nft/send-nft.spec.js +++ b/test/e2e/tests/tokens/nft/send-nft.spec.js @@ -30,7 +30,7 @@ describe('Send NFT', function () { // TODO: Update Test when Multichain Send Flow is added await driver.clickElement({ text: 'Send', tag: 'button' }); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', '0xc427D562164062a23a5cFf596A4a3208e72Acd28', ); await driver.clickElement({ @@ -104,7 +104,7 @@ describe('Send NFT', function () { await driver.clickElement({ text: 'Send', tag: 'button' }); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', '0xc427D562164062a23a5cFf596A4a3208e72Acd28', ); @@ -164,7 +164,7 @@ describe('Send NFT', function () { await driver.clickElement({ text: 'Send', tag: 'button' }); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', '0xc427D562164062a23a5cFf596A4a3208e72Acd28', ); diff --git a/test/e2e/tests/tokens/send-erc20-to-contract.spec.js b/test/e2e/tests/tokens/send-erc20-to-contract.spec.js index a07bdea9bfdc..6e94b6377e67 100644 --- a/test/e2e/tests/tokens/send-erc20-to-contract.spec.js +++ b/test/e2e/tests/tokens/send-erc20-to-contract.spec.js @@ -36,7 +36,7 @@ describe('Send ERC20 token to contract address', function () { // Type contract address await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', contractAddress, ); diff --git a/test/e2e/tests/transaction/edit-gas-fee.spec.js b/test/e2e/tests/transaction/edit-gas-fee.spec.js index 5a1f32a56411..85ae4da3a31f 100644 --- a/test/e2e/tests/transaction/edit-gas-fee.spec.js +++ b/test/e2e/tests/transaction/edit-gas-fee.spec.js @@ -1,4 +1,8 @@ const { strict: assert } = require('assert'); +const { + createInternalTransaction, +} = require('../../page-objects/flows/transaction'); + const { withFixtures, openDapp, @@ -12,20 +16,18 @@ describe('Editing Confirm Transaction', function () { it('allows selecting high, medium, low gas estimates on edit gas fee popover @no-mmi', async function () { await withFixtures( { - fixtures: new FixtureBuilder() - .withTransactionControllerTypeTwoTransaction() - .build(), + fixtures: new FixtureBuilder().build(), ganacheOptions: generateGanacheOptions({ hardfork: 'london' }), title: this.test.fullTitle(), }, async ({ driver }) => { await unlockWallet(driver); + await createInternalTransaction(driver); - const transactionAmounts = await driver.findElements( - '.currency-display-component__text', - ); - const transactionAmount = transactionAmounts[0]; - assert.equal(await transactionAmount.getText(), '1'); + await driver.findElement({ + css: '.currency-display-component__text', + text: '1', + }); // update estimates to high await driver.clickElement('[data-testid="edit-gas-fee-icon"]'); @@ -87,20 +89,18 @@ describe('Editing Confirm Transaction', function () { it('allows accessing advance gas fee popover from edit gas fee popover', async function () { await withFixtures( { - fixtures: new FixtureBuilder() - .withTransactionControllerTypeTwoTransaction() - .build(), + fixtures: new FixtureBuilder().build(), ganacheOptions: generateGanacheOptions({ hardfork: 'london' }), title: this.test.fullTitle(), }, async ({ driver }) => { await unlockWallet(driver); + await createInternalTransaction(driver); - const transactionAmounts = await driver.findElements( - '.currency-display-component__text', - ); - const transactionAmount = transactionAmounts[0]; - assert.equal(await transactionAmount.getText(), '1'); + await driver.findElement({ + css: '.currency-display-component__text', + text: '1', + }); // update estimates to high await driver.clickElement('[data-testid="edit-gas-fee-icon"]'); diff --git a/test/e2e/tests/transaction/ens.spec.ts b/test/e2e/tests/transaction/ens.spec.ts index d9cd3f36b4e3..77d10d9b95ad 100644 --- a/test/e2e/tests/transaction/ens.spec.ts +++ b/test/e2e/tests/transaction/ens.spec.ts @@ -10,6 +10,7 @@ import FixtureBuilder from '../../fixture-builder'; import { loginWithBalanceValidation } from '../../page-objects/flows/login.flow'; import HomePage from '../../page-objects/pages/homepage'; import SendTokenPage from '../../page-objects/pages/send/send-token-page'; +import { mockServerJsonRpc } from '../ppom/mocks/mock-server-json-rpc'; describe('ENS', function (this: Suite) { const sampleAddress: string = '1111111111111111111111111111111111111111'; @@ -17,6 +18,8 @@ describe('ENS', function (this: Suite) { // Having 2 versions of the address is a bug(#25286) const shortSampleAddress = '0x1111...1111'; const shortSampleAddresV2 = '0x11111...11111'; + const chainId = 1; + const mockResolver = '226159d592e2b063810a10ebf6dcbada94ed68b8'; const sampleEnsDomain: string = 'test.eth'; const infuraUrl: string = @@ -59,17 +62,45 @@ describe('ENS', function (this: Suite) { }, })); - await mockServer - .forPost(infuraUrl) - .withJsonBodyIncluding({ method: 'eth_call' }) - .thenCallback(() => ({ - statusCode: 200, - json: { - jsonrpc: '2.0', - id: '1111111111111111', + await mockServerJsonRpc(mockServer, [ + ['eth_chainId', { result: `0x${chainId}` }], + [ + 'eth_call', + { + params: [ + { + to: '0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e', + data: '0x0178b8bfeb4f647bea6caa36333c816d7b46fdcb05f9466ecacc140ea8c66faf15b3d9f1', + }, + ], + result: `0x000000000000000000000000${mockResolver}`, + }, + ], + [ + 'eth_call', + { + params: [ + { + to: `0x${mockResolver}`, + data: '0x01ffc9a79061b92300000000000000000000000000000000000000000000000000000000', + }, + ], + result: `0x0000000000000000000000000000000000000000000000000000000000000000`, + }, + ], + [ + 'eth_call', + { + params: [ + { + to: `0x${mockResolver}`, + data: '0x3b3b57deeb4f647bea6caa36333c816d7b46fdcb05f9466ecacc140ea8c66faf15b3d9f1', + }, + ], result: `0x000000000000000000000000${sampleAddress}`, }, - })); + ], + ]); } it('domain resolves to a correct address', async function () { diff --git a/test/e2e/tests/transaction/gas-estimates.spec.js b/test/e2e/tests/transaction/gas-estimates.spec.js index c4ce94ee9631..263dfc85d904 100644 --- a/test/e2e/tests/transaction/gas-estimates.spec.js +++ b/test/e2e/tests/transaction/gas-estimates.spec.js @@ -30,7 +30,7 @@ describe('Gas estimates generated by MetaMask', function () { await openActionMenuAndStartSendFlow(driver); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', '0x2f318C334780961FB129D2a6c30D0763d9a5C970', ); @@ -72,7 +72,7 @@ describe('Gas estimates generated by MetaMask', function () { await openActionMenuAndStartSendFlow(driver); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', '0x2f318C334780961FB129D2a6c30D0763d9a5C970', ); @@ -111,7 +111,7 @@ describe('Gas estimates generated by MetaMask', function () { await openActionMenuAndStartSendFlow(driver); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', '0x2f318C334780961FB129D2a6c30D0763d9a5C970', ); @@ -145,7 +145,7 @@ describe('Gas estimates generated by MetaMask', function () { await openActionMenuAndStartSendFlow(driver); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', '0x2f318C334780961FB129D2a6c30D0763d9a5C970', ); @@ -191,7 +191,7 @@ describe('Gas estimates generated by MetaMask', function () { await openActionMenuAndStartSendFlow(driver); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', '0x2f318C334780961FB129D2a6c30D0763d9a5C970', ); @@ -220,7 +220,7 @@ describe('Gas estimates generated by MetaMask', function () { await openActionMenuAndStartSendFlow(driver); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', '0x2f318C334780961FB129D2a6c30D0763d9a5C970', ); diff --git a/test/e2e/tests/transaction/navigate-transactions.spec.js b/test/e2e/tests/transaction/navigate-transactions.spec.js index 66e2665162a7..63170d027874 100644 --- a/test/e2e/tests/transaction/navigate-transactions.spec.js +++ b/test/e2e/tests/transaction/navigate-transactions.spec.js @@ -1,104 +1,61 @@ -const { strict: assert } = require('assert'); +const { + createDappTransaction, +} = require('../../page-objects/flows/transaction'); + +const { + default: ConfirmationNavigation, +} = require('../../page-objects/pages/confirmations/legacy/navigation'); + const { withFixtures, openDapp, locateAccountBalanceDOM, unlockWallet, generateGanacheOptions, + WINDOW_TITLES, } = require('../../helpers'); const FixtureBuilder = require('../../fixture-builder'); +const TRANSACTION_COUNT = 4; + describe('Navigate transactions', function () { it('should navigate the unapproved transactions', async function () { await withFixtures( { fixtures: new FixtureBuilder() .withPreferencesControllerTxSimulationsDisabled() - .withTransactionControllerMultipleTransactions() + .withPermissionControllerConnectedToTestDapp() .build(), ganacheOptions: generateGanacheOptions({ hardfork: 'london' }), title: this.test.fullTitle(), + dapp: true, }, async ({ driver }) => { await unlockWallet(driver); + await createMultipleTransactions(driver, TRANSACTION_COUNT); - // Wait until total amount is loaded to mitigate flakiness on reject - await driver.findElement({ - tag: 'span', - text: '3.0000315', - }); + const navigation = new ConfirmationNavigation(driver); - // navigate transactions - await driver.clickElement('[data-testid="next-page"]'); - let navigationElement = await driver.findElement( - '.confirm-page-container-navigation', - ); - let navigationText = await navigationElement.getText(); - assert.equal( - navigationText.includes('2 of 4'), - true, - 'changed transaction right', - ); - await driver.clickElement('[data-testid="next-page"]'); - navigationElement = await driver.findElement( - '.confirm-page-container-navigation', - ); - navigationText = await navigationElement.getText(); - assert.equal( - navigationText.includes('3 of 4'), - true, - 'changed transaction right', - ); - await driver.clickElement('[data-testid="next-page"]'); - navigationElement = await driver.findElement( - '.confirm-page-container-navigation', - ); - navigationText = await navigationElement.getText(); - assert.equal( - navigationText.includes('4 of 4'), - true, - 'changed transaction right', - ); - await driver.clickElement('[data-testid="first-page"]'); - navigationElement = await driver.findElement( - '.confirm-page-container-navigation', - ); - navigationText = await navigationElement.getText(); - assert.equal( - navigationText.includes('1 of 4'), - true, - 'navigate to first transaction', - ); - await driver.clickElement('[data-testid="last-page"]'); - navigationElement = await driver.findElement( - '.confirm-page-container-navigation', - ); - navigationText = await navigationElement.getText(); - assert.equal( - navigationText.includes('4 of 4'), - true, - 'navigate to last transaction', - ); - await driver.clickElement('[data-testid="previous-page"]'); - navigationElement = await driver.findElement( - '.confirm-page-container-navigation', - ); - navigationText = await navigationElement.getText(); - assert.equal( - navigationText.includes('3 of 4'), - true, - 'changed transaction left', - ); - await driver.clickElement('[data-testid="previous-page"]'); - navigationElement = await driver.findElement( - '.confirm-page-container-navigation', - ); - navigationText = await navigationElement.getText(); - assert.equal( - navigationText.includes('2 of 4'), - true, - 'changed transaction left', - ); + await navigation.clickNextPage(); + await navigation.check_pageNumbers(2, 4); + + await navigation.clickNextPage(); + await navigation.check_pageNumbers(3, 4); + + await navigation.clickNextPage(); + await navigation.check_pageNumbers(4, 4); + + await navigation.clickFirstPage(); + await navigation.check_pageNumbers(1, 4); + + await navigation.clickLastPage(); + await navigation.check_pageNumbers(4, 4); + + await navigation.clickPreviousPage(); + await navigation.check_pageNumbers(3, 4); + + await navigation.clickPreviousPage(); + await navigation.check_pageNumbers(2, 4); }, ); }); @@ -110,48 +67,29 @@ describe('Navigate transactions', function () { fixtures: new FixtureBuilder() .withPermissionControllerConnectedToTestDapp() .withPreferencesControllerTxSimulationsDisabled() - .withTransactionControllerMultipleTransactions() .build(), ganacheOptions: generateGanacheOptions({ hardfork: 'london' }), title: this.test.fullTitle(), }, async ({ driver }) => { await unlockWallet(driver); + await createMultipleTransactions(driver, TRANSACTION_COUNT); - // Wait until total amount is loaded to mitigate flakiness on reject - await driver.findElement({ - tag: 'span', - text: '3.0000315', - }); + const navigation = new ConfirmationNavigation(driver); - await driver.clickElement('[data-testid="next-page"]'); - let navigationElement = await driver.findElement( - '.confirm-page-container-navigation', - ); - let navigationText = await navigationElement.getText(); - assert.equal( - navigationText.includes('2 of 4'), - true, - 'second transaction in focus', + await navigation.clickNextPage(); + await navigation.check_pageNumbers(2, 4); + + await driver.switchToWindowWithTitle( + WINDOW_TITLES.ExtensionInFullScreenView, ); // add transaction await openDapp(driver); await driver.clickElement({ text: 'Send', tag: 'button' }); - await driver.waitUntilXWindowHandles(3); - const windowHandles = await driver.getAllWindowHandles(); - const extension = windowHandles[0]; - await driver.switchToWindow(extension); - navigationElement = await driver.waitForSelector({ - css: '.confirm-page-container-navigation', - text: '2 of 5', - }); - navigationText = await navigationElement.getText(); - assert.equal( - navigationText.includes('2 of 5'), - true, - 'correct (same) transaction in focus', - ); + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); + + await navigation.check_pageNumbers(2, 5); }, ); }); @@ -161,32 +99,21 @@ describe('Navigate transactions', function () { { fixtures: new FixtureBuilder() .withPreferencesControllerTxSimulationsDisabled() - .withTransactionControllerMultipleTransactions() + .withPermissionControllerConnectedToTestDapp() .build(), ganacheOptions: generateGanacheOptions({ hardfork: 'london' }), title: this.test.fullTitle(), + dapp: true, }, async ({ driver }) => { await unlockWallet(driver); - - // Wait until total amount is loaded to mitigate flakiness on reject - await driver.findElement({ - tag: 'span', - text: '3.0000315', - }); + await createMultipleTransactions(driver, TRANSACTION_COUNT); // reject transaction await driver.clickElement({ text: 'Reject', tag: 'button' }); - const navigationElement = await driver.waitForSelector({ - css: '.confirm-page-container-navigation', - text: '1 of 3', - }); - const navigationText = await navigationElement.getText(); - assert.equal( - navigationText.includes('1 of 3'), - true, - 'transaction rejected', - ); + + const navigation = new ConfirmationNavigation(driver); + await navigation.check_pageNumbers(1, 3); }, ); }); @@ -196,32 +123,21 @@ describe('Navigate transactions', function () { { fixtures: new FixtureBuilder() .withPreferencesControllerTxSimulationsDisabled() - .withTransactionControllerMultipleTransactions() + .withPermissionControllerConnectedToTestDapp() .build(), ganacheOptions: generateGanacheOptions({ hardfork: 'london' }), title: this.test.fullTitle(), + dapp: true, }, async ({ driver }) => { await unlockWallet(driver); - - // Wait until total amount is loaded to mitigate flakiness on reject - await driver.findElement({ - tag: 'span', - text: '3.0000315', - }); + await createMultipleTransactions(driver, TRANSACTION_COUNT); // confirm transaction await driver.clickElement({ text: 'Confirm', tag: 'button' }); - const navigationElement = await driver.waitForSelector({ - css: '.confirm-page-container-navigation', - text: '1 of 3', - }); - const navigationText = await navigationElement.getText(); - assert.equal( - navigationText.includes('1 of 3'), - true, - 'transaction confirmed', - ); + + const navigation = new ConfirmationNavigation(driver); + await navigation.check_pageNumbers(1, 3); }, ); }); @@ -231,33 +147,39 @@ describe('Navigate transactions', function () { { fixtures: new FixtureBuilder() .withPreferencesControllerTxSimulationsDisabled() - .withTransactionControllerMultipleTransactions() + .withPermissionControllerConnectedToTestDapp() .build(), ganacheOptions: generateGanacheOptions({ hardfork: 'london' }), title: this.test.fullTitle(), + dapp: true, }, async ({ driver, ganacheServer }) => { await unlockWallet(driver); - - // Wait until the confirmation screen is stabilized to mitigate flakiness on reject: - // 1. Total amount is loaded - await driver.findElement({ - tag: 'span', - text: '3.0000315', - }); - // 2. Gas timing is loaded - await driver.findElement('[data-testid="gas-timing-time"]'); - // 3. Insufficient funds warning is not present - await driver.assertElementNotPresent({ - text: 'You do not have enough ETH', - tag: 'p', - }); + await createMultipleTransactions(driver, TRANSACTION_COUNT); // reject transactions await driver.clickElement({ text: 'Reject 4', tag: 'a' }); await driver.clickElement({ text: 'Reject all', tag: 'button' }); + + await driver.switchToWindowWithTitle( + WINDOW_TITLES.ExtensionInFullScreenView, + ); await locateAccountBalanceDOM(driver, ganacheServer); }, ); }); }); + +async function createMultipleTransactions(driver, count) { + for (let i = 0; i < count; i++) { + await createDappTransaction(driver); + } + + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); + + // Wait until total amount is loaded to mitigate flakiness on reject + await driver.findElement({ + tag: 'span', + text: '0.001', + }); +} diff --git a/test/e2e/tests/transaction/send-edit.spec.js b/test/e2e/tests/transaction/send-edit.spec.js index 95e5b3235ebd..953f2ebf3569 100644 --- a/test/e2e/tests/transaction/send-edit.spec.js +++ b/test/e2e/tests/transaction/send-edit.spec.js @@ -1,4 +1,8 @@ const { strict: assert } = require('assert'); +const { + createInternalTransaction, +} = require('../../page-objects/flows/transaction'); + const { defaultGanacheOptions, withFixtures, @@ -11,23 +15,23 @@ describe('Editing Confirm Transaction', function () { it('goes back from confirm page to edit eth value, gas price and gas limit', async function () { await withFixtures( { - fixtures: new FixtureBuilder() - .withTransactionControllerTypeOneTransaction() - .withConversionRateDisabled() - .build(), + fixtures: new FixtureBuilder().withConversionRateDisabled().build(), ganacheOptions: defaultGanacheOptions, title: this.test.fullTitle(), }, async ({ driver }) => { await unlockWallet(driver); - const transactionAmounts = await driver.findElements( - '.currency-display-component__text', - ); - const transactionAmount = transactionAmounts[0]; - assert.equal(await transactionAmount.getText(), '1'); + await createInternalTransaction(driver); - const transactionFee = transactionAmounts[1]; - assert.equal(await transactionFee.getText(), '0.00025'); + await driver.findElement({ + css: '.currency-display-component__text', + text: '1', + }); + + await driver.findElement({ + css: '.currency-display-component__text', + text: '1.000042', + }); await driver.clickElement( '.confirm-page-container-header__back-button', @@ -86,23 +90,23 @@ describe('Editing Confirm Transaction', function () { it('goes back from confirm page to edit eth value, baseFee, priorityFee and gas limit - 1559 V2', async function () { await withFixtures( { - fixtures: new FixtureBuilder() - .withTransactionControllerTypeTwoTransaction() - .withConversionRateDisabled() - .build(), + fixtures: new FixtureBuilder().withConversionRateDisabled().build(), ganacheOptions: generateGanacheOptions({ hardfork: 'london' }), title: this.test.fullTitle(), }, async ({ driver }) => { await unlockWallet(driver); - const transactionAmounts = await driver.findElements( - '.currency-display-component__text', - ); - const transactionAmount = transactionAmounts[0]; - assert.equal(await transactionAmount.getText(), '1'); + await createInternalTransaction(driver); - const transactionFee = transactionAmounts[1]; - assert.equal(await transactionFee.getText(), '0.0000375'); + await driver.findElement({ + css: '.currency-display-component__text', + text: '1', + }); + + await driver.findElement({ + css: '.currency-display-component__text', + text: '1.00043983', + }); await driver.clickElement( '.confirm-page-container-header__back-button', diff --git a/test/e2e/tests/transaction/send-eth.spec.js b/test/e2e/tests/transaction/send-eth.spec.js index 5c49bba0cf4e..36872115dcbe 100644 --- a/test/e2e/tests/transaction/send-eth.spec.js +++ b/test/e2e/tests/transaction/send-eth.spec.js @@ -27,7 +27,7 @@ describe('Send ETH', function () { await openActionMenuAndStartSendFlow(driver); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', '0x2f318C334780961FB129D2a6c30D0763d9a5C970', ); @@ -110,7 +110,7 @@ describe('Send ETH', function () { await openActionMenuAndStartSendFlow(driver); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', '0x2f318C334780961FB129D2a6c30D0763d9a5C970', ); @@ -172,7 +172,7 @@ describe('Send ETH', function () { await driver.clickElement('[data-testid="eth-overview-send"]'); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', contractAddress, ); @@ -442,7 +442,7 @@ describe('Send ETH', function () { await openActionMenuAndStartSendFlow(driver); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', '0xc427D562164062a23a5cFf596A4a3208e72Acd28', ); diff --git a/test/e2e/tests/transaction/send-hex-address.spec.js b/test/e2e/tests/transaction/send-hex-address.spec.js index 6adb6b5f9f6c..d93f1a0d5484 100644 --- a/test/e2e/tests/transaction/send-hex-address.spec.js +++ b/test/e2e/tests/transaction/send-hex-address.spec.js @@ -27,7 +27,7 @@ describe('Send ETH to a 40 character hexadecimal address', function () { await openActionMenuAndStartSendFlow(driver); // Paste address without hex prefix await driver.pasteIntoField( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', nonHexPrefixedAddress, ); await driver.findElement({ @@ -72,7 +72,7 @@ describe('Send ETH to a 40 character hexadecimal address', function () { await openActionMenuAndStartSendFlow(driver); // Type address without hex prefix await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', nonHexPrefixedAddress, ); await driver.findElement({ @@ -130,7 +130,7 @@ describe('Send ERC20 to a 40 character hexadecimal address', function () { await driver.clickElement('[data-testid="coin-overview-send"]'); // Paste address without hex prefix await driver.pasteIntoField( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', nonHexPrefixedAddress, ); await driver.findElement({ @@ -192,7 +192,7 @@ describe('Send ERC20 to a 40 character hexadecimal address', function () { // Type address without hex prefix await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', nonHexPrefixedAddress, ); await driver.findElement({ diff --git a/test/e2e/user-actions-benchmark.js b/test/e2e/user-actions-benchmark.js index 515764b6259b..5a851c59d61f 100644 --- a/test/e2e/user-actions-benchmark.js +++ b/test/e2e/user-actions-benchmark.js @@ -73,7 +73,7 @@ async function confirmTx() { await openActionMenuAndStartSendFlow(driver); await driver.fill( - 'input[placeholder="Enter public address (0x) or ENS name"]', + 'input[placeholder="Enter public address (0x) or domain name"]', '0x2f318C334780961FB129D2a6c30D0763d9a5C970', ); diff --git a/test/integration/confirmations/signatures/permit.test.tsx b/test/integration/confirmations/signatures/permit.test.tsx index f0a58da87b97..809ac988962f 100644 --- a/test/integration/confirmations/signatures/permit.test.tsx +++ b/test/integration/confirmations/signatures/permit.test.tsx @@ -1,4 +1,5 @@ -import { fireEvent, waitFor } from '@testing-library/react'; +import { act, fireEvent, waitFor, screen } from '@testing-library/react'; +import nock from 'nock'; import { ApprovalType } from '@metamask/controller-utils'; import mockMetaMaskState from '../../data/integration-init-state.json'; import { integrationTestRender } from '../../../lib/render-helpers'; @@ -72,11 +73,15 @@ describe('Permit Confirmation', () => { jest.resetAllMocks(); mockedBackgroundConnection.submitRequestToBackground.mockImplementation( createMockImplementation({ - getTokenStandardAndDetails: { decimal: '10' }, + getTokenStandardAndDetails: { decimals: '2' }, }), ); }); + afterEach(() => { + nock.cleanAll(); + }); + it('displays the header account modal with correct data', async () => { const account = mockMetaMaskState.internalAccounts.accounts[ @@ -89,33 +94,33 @@ describe('Permit Confirmation', () => { account.address, ); - const { getByTestId, queryByTestId } = await integrationTestRender({ - preloadedState: mockedMetaMaskState, - backgroundConnection: backgroundConnectionMocked, + await act(async () => { + await integrationTestRender({ + preloadedState: mockedMetaMaskState, + backgroundConnection: backgroundConnectionMocked, + }); }); - expect(getByTestId('header-account-name')).toHaveTextContent(accountName); - expect(getByTestId('header-network-display-name')).toHaveTextContent( - 'Chain 5', + expect(screen.getByTestId('header-account-name')).toHaveTextContent( + accountName, + ); + expect(screen.getByTestId('header-network-display-name')).toHaveTextContent( + 'Sepolia', ); - fireEvent.click(getByTestId('header-info__account-details-button')); - - await waitFor(() => { - expect( - getByTestId('confirmation-account-details-modal__account-name'), - ).toBeInTheDocument(); - }); + fireEvent.click(screen.getByTestId('header-info__account-details-button')); expect( - getByTestId('confirmation-account-details-modal__account-name'), + await screen.findByTestId( + 'confirmation-account-details-modal__account-name', + ), ).toHaveTextContent(accountName); - expect(getByTestId('address-copy-button-text')).toHaveTextContent( + expect(screen.getByTestId('address-copy-button-text')).toHaveTextContent( '0x0DCD5...3E7bc', ); expect( - getByTestId('confirmation-account-details-modal__account-balance'), - ).toHaveTextContent('1.58271596ETH'); + screen.getByTestId('confirmation-account-details-modal__account-balance'), + ).toHaveTextContent('1.582717SepoliaETH'); let confirmAccountDetailsModalMetricsEvent; @@ -147,12 +152,14 @@ describe('Permit Confirmation', () => { ); fireEvent.click( - getByTestId('confirmation-account-details-modal__close-button'), + screen.getByTestId('confirmation-account-details-modal__close-button'), ); await waitFor(() => { expect( - queryByTestId('confirmation-account-details-modal__account-name'), + screen.queryByTestId( + 'confirmation-account-details-modal__account-name', + ), ).not.toBeInTheDocument(); }); }); @@ -168,18 +175,52 @@ describe('Permit Confirmation', () => { account.address, ); - const { getByText } = await integrationTestRender({ - preloadedState: mockedMetaMaskState, - backgroundConnection: backgroundConnectionMocked, + await act(async () => { + await integrationTestRender({ + preloadedState: mockedMetaMaskState, + backgroundConnection: backgroundConnectionMocked, + }); }); - expect(getByText('Spending cap request')).toBeInTheDocument(); + expect(screen.getByText('Spending cap request')).toBeInTheDocument(); expect( - getByText('This site wants permission to spend your tokens.'), + screen.getByText('This site wants permission to spend your tokens.'), ).toBeInTheDocument(); }); it('displays the simulation section', async () => { + const scope = nock('https://price.api.cx.metamask.io') + .persist() + .get('/v2/chains/1/spot-prices') + .query({ + tokenAddresses: + '0x0000000000000000000000000000000000000000,0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC', + vsCurrency: 'ETH', + includeMarketData: 'true', + }) + .reply(200, { + '0xcccccccccccccccccccccccccccccccccccccccc': { + allTimeHigh: 12, + allTimeLow: 1, + circulatingSupply: 50000, + dilutedMarketCap: 50000, + high1d: 11, + low1d: 9.9, + marketCap: 10000, + marketCapPercentChange1d: 1, + price: 10, + priceChange1d: 0.5, + pricePercentChange1d: 1, + pricePercentChange1h: 0, + pricePercentChange1y: 80, + pricePercentChange7d: 2, + pricePercentChange14d: 5, + pricePercentChange30d: 10, + pricePercentChange200d: 50, + totalVolume: 100, + }, + }); + const account = mockMetaMaskState.internalAccounts.accounts[ mockMetaMaskState.internalAccounts @@ -190,12 +231,26 @@ describe('Permit Confirmation', () => { account.address, ); - const { getByTestId } = await integrationTestRender({ - preloadedState: mockedMetaMaskState, - backgroundConnection: backgroundConnectionMocked, + await act(async () => { + await integrationTestRender({ + preloadedState: { + ...mockedMetaMaskState, + selectedNetworkClientId: 'testNetworkConfigurationId', + providerConfig: { + type: 'rpc', + nickname: 'test mainnet', + chainId: '0x1', + ticker: 'ETH', + id: 'chain1', + }, + }, + backgroundConnection: backgroundConnectionMocked, + }); }); - const simulationSection = getByTestId('confirmation__simulation_section'); + const simulationSection = screen.getByTestId( + 'confirmation__simulation_section', + ); expect(simulationSection).toBeInTheDocument(); expect(simulationSection).toHaveTextContent('Estimated changes'); expect(simulationSection).toHaveTextContent( @@ -203,7 +258,17 @@ describe('Permit Confirmation', () => { ); expect(simulationSection).toHaveTextContent('Spending cap'); expect(simulationSection).toHaveTextContent('0xCcCCc...ccccC'); - expect(getByTestId('simulation-token-value')).toHaveTextContent('3,000'); + expect(screen.getByTestId('simulation-token-value')).toHaveTextContent( + '30', + ); + + const individualFiatDisplay = await screen.findByTestId( + 'individual-fiat-display', + ); + expect(individualFiatDisplay).toHaveTextContent('$166,836.00'); + + scope.done(); + expect(scope.isDone()).toBe(true); }); it('displays the MMI header warning when account signing is not the same as the account selected', async () => { @@ -221,9 +286,11 @@ describe('Permit Confirmation', () => { account.address, ); - const { getByText } = await integrationTestRender({ - preloadedState: mockedMetaMaskState, - backgroundConnection: backgroundConnectionMocked, + await act(async () => { + await integrationTestRender({ + preloadedState: mockedMetaMaskState, + backgroundConnection: backgroundConnectionMocked, + }); }); const mismatchAccountText = `Your selected account (${shortenAddress( @@ -232,6 +299,6 @@ describe('Permit Confirmation', () => { account.address, )})`; - expect(getByText(mismatchAccountText)).toBeInTheDocument(); + expect(screen.getByText(mismatchAccountText)).toBeInTheDocument(); }); }); diff --git a/test/integration/confirmations/signatures/personalSign.test.tsx b/test/integration/confirmations/signatures/personalSign.test.tsx index 528655924dbe..9737a3e30ad9 100644 --- a/test/integration/confirmations/signatures/personalSign.test.tsx +++ b/test/integration/confirmations/signatures/personalSign.test.tsx @@ -87,7 +87,7 @@ describe('PersonalSign Confirmation', () => { expect(getByTestId('header-account-name')).toHaveTextContent(accountName); expect(getByTestId('header-network-display-name')).toHaveTextContent( - 'Chain 5', + 'Sepolia', ); fireEvent.click(getByTestId('header-info__account-details-button')); @@ -106,7 +106,7 @@ describe('PersonalSign Confirmation', () => { ); expect( getByTestId('confirmation-account-details-modal__account-balance'), - ).toHaveTextContent('1.58271596ETH'); + ).toHaveTextContent('1.582717SepoliaETH'); let confirmAccountDetailsModalMetricsEvent; diff --git a/test/integration/confirmations/transactions/alerts.test.tsx b/test/integration/confirmations/transactions/alerts.test.tsx index 1e07ddcdd68d..74d37c858b0f 100644 --- a/test/integration/confirmations/transactions/alerts.test.tsx +++ b/test/integration/confirmations/transactions/alerts.test.tsx @@ -6,6 +6,7 @@ import mockMetaMaskState from '../../data/integration-init-state.json'; import { integrationTestRender } from '../../../lib/render-helpers'; import * as backgroundConnection from '../../../../ui/store/background-connection'; import { createMockImplementation, mock4byte } from '../../helpers'; +import { createTestProviderTools } from '../../../stub/provider'; import { getUnapprovedApproveTransaction } from './transactionDataHelpers'; jest.mock('../../../../ui/store/background-connection', () => ({ @@ -75,7 +76,17 @@ const setupSubmitRequestToBackgroundMocks = ( ); }; -describe('Contract Interaction Confirmation', () => { +describe('Contract Interaction Confirmation Alerts', () => { + beforeAll(() => { + const { provider } = createTestProviderTools({ + networkId: 'sepolia', + chainId: '0xaa36a7', + }); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + global.ethereumProvider = provider as any; + }); + beforeEach(() => { jest.resetAllMocks(); setupSubmitRequestToBackgroundMocks(); @@ -87,6 +98,11 @@ describe('Contract Interaction Confirmation', () => { nock.cleanAll(); }); + afterAll(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + delete (global as any).ethereumProvider; + }); + it('displays the alert when network is busy', async () => { const account = mockMetaMaskState.internalAccounts.accounts[ @@ -97,12 +113,12 @@ describe('Contract Interaction Confirmation', () => { const mockedMetaMaskState = getMetaMaskStateWithUnapprovedApproveTransaction(account.address); - const { findByTestId, getByTestId, queryByTestId } = + await act(async () => { await integrationTestRender({ preloadedState: { ...mockedMetaMaskState, gasFeeEstimatesByChainId: { - '0x5': { + '0xaa36a7': { gasFeeEstimates: { networkCongestion: 1.0005, }, @@ -111,29 +127,28 @@ describe('Contract Interaction Confirmation', () => { }, backgroundConnection: backgroundConnectionMocked, }); - - act(() => { - fireEvent.click(getByTestId('inline-alert')); }); - expect(await findByTestId('alert-modal')).toBeInTheDocument(); + fireEvent.click(screen.getByTestId('inline-alert')); + + expect(await screen.findByTestId('alert-modal')).toBeInTheDocument(); expect( - await findByTestId('alert-modal__selected-alert'), + await screen.findByTestId('alert-modal__selected-alert'), ).toBeInTheDocument(); - expect(await findByTestId('alert-modal__selected-alert')).toHaveTextContent( - 'Gas prices are high and estimates are less accurate.', - ); + expect( + await screen.findByTestId('alert-modal__selected-alert'), + ).toHaveTextContent('Gas prices are high and estimates are less accurate.'); - expect(await findByTestId('alert-modal-button')).toBeInTheDocument(); - const alertModalConfirmButton = await findByTestId('alert-modal-button'); + expect(await screen.findByTestId('alert-modal-button')).toBeInTheDocument(); + const alertModalConfirmButton = await screen.findByTestId( + 'alert-modal-button', + ); - act(() => { - fireEvent.click(alertModalConfirmButton); - }); + fireEvent.click(alertModalConfirmButton); - expect(queryByTestId('alert-modal')).not.toBeInTheDocument(); + expect(screen.queryByTestId('alert-modal')).not.toBeInTheDocument(); }); it('displays the alert when gas estimate fails', async () => { @@ -157,7 +172,7 @@ describe('Contract Interaction Confirmation', () => { }, }; - const { findByTestId, getByTestId, queryByTestId } = + await act(async () => { await integrationTestRender({ preloadedState: { ...mockedMetaMaskState, @@ -165,29 +180,30 @@ describe('Contract Interaction Confirmation', () => { }, backgroundConnection: backgroundConnectionMocked, }); - - act(() => { - fireEvent.click(getByTestId('inline-alert')); }); - expect(await findByTestId('alert-modal')).toBeInTheDocument(); + fireEvent.click(screen.getByTestId('inline-alert')); + + expect(await screen.findByTestId('alert-modal')).toBeInTheDocument(); expect( - await findByTestId('alert-modal__selected-alert'), + await screen.findByTestId('alert-modal__selected-alert'), ).toBeInTheDocument(); - expect(await findByTestId('alert-modal__selected-alert')).toHaveTextContent( + expect( + await screen.findByTestId('alert-modal__selected-alert'), + ).toHaveTextContent( 'We’re unable to provide an accurate fee and this estimate might be high. We suggest you to input a custom gas limit, but there’s a risk the transaction will still fail.', ); - expect(await findByTestId('alert-modal-button')).toBeInTheDocument(); - const alertModalConfirmButton = await findByTestId('alert-modal-button'); + expect(await screen.findByTestId('alert-modal-button')).toBeInTheDocument(); + const alertModalConfirmButton = await screen.findByTestId( + 'alert-modal-button', + ); - act(() => { - fireEvent.click(alertModalConfirmButton); - }); + fireEvent.click(alertModalConfirmButton); - expect(queryByTestId('alert-modal')).not.toBeInTheDocument(); + expect(screen.queryByTestId('alert-modal')).not.toBeInTheDocument(); }); it('displays the alert for insufficient gas', async () => { @@ -202,33 +218,35 @@ describe('Contract Interaction Confirmation', () => { const transaction = mockedMetaMaskState.transactions[0]; transaction.txParams.gas = '0x0'; - const { findByTestId, getByTestId } = await integrationTestRender({ - preloadedState: { - ...mockedMetaMaskState, - transactions: [transaction], - }, - backgroundConnection: backgroundConnectionMocked, + await act(async () => { + await integrationTestRender({ + preloadedState: { + ...mockedMetaMaskState, + transactions: [transaction], + }, + backgroundConnection: backgroundConnectionMocked, + }); }); - act(() => { - fireEvent.click(getByTestId('inline-alert')); - }); + fireEvent.click(screen.getByTestId('inline-alert')); - expect(await findByTestId('alert-modal')).toBeInTheDocument(); + expect(await screen.findByTestId('alert-modal')).toBeInTheDocument(); expect( - await findByTestId('alert-modal__selected-alert'), + await screen.findByTestId('alert-modal__selected-alert'), ).toBeInTheDocument(); - expect(await findByTestId('alert-modal__selected-alert')).toHaveTextContent( + expect( + await screen.findByTestId('alert-modal__selected-alert'), + ).toHaveTextContent( 'To continue with this transaction, you’ll need to increase the gas limit to 21000 or higher.', ); expect( - await findByTestId('alert-modal-action-showAdvancedGasModal'), + await screen.findByTestId('alert-modal-action-showAdvancedGasModal'), ).toBeInTheDocument(); expect( - await findByTestId('alert-modal-action-showAdvancedGasModal'), + await screen.findByTestId('alert-modal-action-showAdvancedGasModal'), ).toHaveTextContent('Update gas limit'); }); @@ -245,34 +263,36 @@ describe('Contract Interaction Confirmation', () => { const transaction = mockedMetaMaskState.transactions[0]; transaction.gasFeeEstimates.type = 'none'; - const { findByTestId, getByTestId } = await integrationTestRender({ - preloadedState: { - ...mockedMetaMaskState, - gasEstimateType: 'none', - transactions: [transaction], - }, - backgroundConnection: backgroundConnectionMocked, + await act(async () => { + await integrationTestRender({ + preloadedState: { + ...mockedMetaMaskState, + gasEstimateType: 'none', + transactions: [transaction], + }, + backgroundConnection: backgroundConnectionMocked, + }); }); - act(() => { - fireEvent.click(getByTestId('inline-alert')); - }); + fireEvent.click(screen.getByTestId('inline-alert')); - expect(await findByTestId('alert-modal')).toBeInTheDocument(); + expect(await screen.findByTestId('alert-modal')).toBeInTheDocument(); expect( - await findByTestId('alert-modal__selected-alert'), + await screen.findByTestId('alert-modal__selected-alert'), ).toBeInTheDocument(); - expect(await findByTestId('alert-modal__selected-alert')).toHaveTextContent( + expect( + await screen.findByTestId('alert-modal__selected-alert'), + ).toHaveTextContent( 'We can’t move forward with this transaction until you manually update the fee.', ); expect( - await findByTestId('alert-modal-action-showAdvancedGasModal'), + await screen.findByTestId('alert-modal-action-showAdvancedGasModal'), ).toBeInTheDocument(); expect( - await findByTestId('alert-modal-action-showAdvancedGasModal'), + await screen.findByTestId('alert-modal-action-showAdvancedGasModal'), ).toHaveTextContent('Update fee'); }); @@ -331,9 +351,7 @@ describe('Contract Interaction Confirmation', () => { expect(await screen.getByTestId('inline-alert')).toBeInTheDocument(); - act(() => { - fireEvent.click(screen.getByTestId('inline-alert')); - }); + fireEvent.click(screen.getByTestId('inline-alert')); expect(await screen.findByTestId('alert-modal')).toBeInTheDocument(); @@ -348,7 +366,7 @@ describe('Contract Interaction Confirmation', () => { ); }); - it('displays the alert for gas fees too', async () => { + it('displays the alert for gas fees too low', async () => { const account = mockMetaMaskState.internalAccounts.accounts[ mockMetaMaskState.internalAccounts @@ -372,9 +390,7 @@ describe('Contract Interaction Confirmation', () => { }); }); - act(() => { - fireEvent.click(screen.getByTestId('inline-alert')); - }); + fireEvent.click(screen.getByTestId('inline-alert')); expect(await screen.findByTestId('alert-modal')).toBeInTheDocument(); diff --git a/test/integration/confirmations/transactions/contract-interaction.test.tsx b/test/integration/confirmations/transactions/contract-interaction.test.tsx index 7d07dc31e7db..cd5953db50b8 100644 --- a/test/integration/confirmations/transactions/contract-interaction.test.tsx +++ b/test/integration/confirmations/transactions/contract-interaction.test.tsx @@ -1,4 +1,10 @@ -import { fireEvent, waitFor, within } from '@testing-library/react'; +import { + fireEvent, + waitFor, + within, + screen, + act, +} from '@testing-library/react'; import { ApprovalType } from '@metamask/controller-utils'; import nock from 'nock'; import { TransactionType } from '@metamask/transaction-controller'; @@ -46,12 +52,12 @@ const getMetaMaskStateWithUnapprovedContractInteraction = ({ }, nextNonce: '8', currencyRates: { - ETH: { + SepoliaETH: { conversionDate: 1721392020.645, conversionRate: 3404.13, usdConversionRate: 3404.13, }, - SepoliaETH: { + ETH: { conversionDate: 1721393858.083, conversionRate: 3414.67, usdConversionRate: 3414.67, @@ -166,36 +172,44 @@ describe('Contract Interaction Confirmation', () => { accountAddress: account.address, }); - const { getByTestId, queryByTestId, findByTestId } = + await act(async () => { await integrationTestRender({ preloadedState: mockedMetaMaskState, backgroundConnection: backgroundConnectionMocked, }); + }); - expect(getByTestId('header-account-name')).toHaveTextContent(accountName); - expect(getByTestId('header-network-display-name')).toHaveTextContent( - 'Chain 5', + expect(screen.getByTestId('header-account-name')).toHaveTextContent( + accountName, + ); + expect(screen.getByTestId('header-network-display-name')).toHaveTextContent( + 'Sepolia', ); - fireEvent.click(getByTestId('header-info__account-details-button')); + fireEvent.click(screen.getByTestId('header-info__account-details-button')); expect( - await findByTestId('confirmation-account-details-modal__account-name'), + await screen.findByTestId( + 'confirmation-account-details-modal__account-name', + ), ).toHaveTextContent(accountName); - expect(getByTestId('address-copy-button-text')).toHaveTextContent( + expect(screen.getByTestId('address-copy-button-text')).toHaveTextContent( '0x0DCD5...3E7bc', ); expect( - getByTestId('confirmation-account-details-modal__account-balance'), - ).toHaveTextContent('1.5827157ETH'); + screen.getByTestId('confirmation-account-details-modal__account-balance'), + ).toHaveTextContent('1.582717SepoliaETH'); let confirmAccountDetailsModalMetricsEvent; await waitFor(() => { confirmAccountDetailsModalMetricsEvent = mockedBackgroundConnection.submitRequestToBackground.mock.calls?.find( - (call) => call[0] === 'trackMetaMetricsEvent', + (call) => + call[0] === 'trackMetaMetricsEvent' && + call[1]?.[0].category === MetaMetricsEventCategory.Confirmations, ); + expect(confirmAccountDetailsModalMetricsEvent?.[0]).toBe( 'trackMetaMetricsEvent', ); @@ -216,12 +230,14 @@ describe('Contract Interaction Confirmation', () => { ); fireEvent.click( - getByTestId('confirmation-account-details-modal__close-button'), + screen.getByTestId('confirmation-account-details-modal__close-button'), ); await waitFor(() => { expect( - queryByTestId('confirmation-account-details-modal__account-name'), + screen.queryByTestId( + 'confirmation-account-details-modal__account-name', + ), ).not.toBeInTheDocument(); }); }); @@ -238,35 +254,38 @@ describe('Contract Interaction Confirmation', () => { accountAddress: account.address, }); - const { getByTestId, getByText, findByTestId } = + await act(async () => { await integrationTestRender({ preloadedState: mockedMetaMaskState, backgroundConnection: backgroundConnectionMocked, }); + }); - expect(getByText('Transaction request')).toBeInTheDocument(); + expect(screen.getByText('Transaction request')).toBeInTheDocument(); - const simulationSection = getByTestId('simulation-details-layout'); + const simulationSection = screen.getByTestId('simulation-details-layout'); expect(simulationSection).toBeInTheDocument(); expect(simulationSection).toHaveTextContent('Estimated changes'); - const simulationDetailsRow = await findByTestId('simulation-rows-incoming'); + const simulationDetailsRow = await screen.findByTestId( + 'simulation-rows-incoming', + ); expect(simulationSection).toContainElement(simulationDetailsRow); expect(simulationDetailsRow).toHaveTextContent('You receive'); expect(simulationDetailsRow).toContainElement( - getByTestId('simulation-details-asset-pill'), + screen.getByTestId('simulation-details-asset-pill'), ); expect(simulationDetailsRow).toContainElement( - getByTestId('simulation-details-amount-pill'), + screen.getByTestId('simulation-details-amount-pill'), ); - const transactionDetailsSection = getByTestId( + const transactionDetailsSection = screen.getByTestId( 'transaction-details-section', ); expect(transactionDetailsSection).toBeInTheDocument(); expect(transactionDetailsSection).toHaveTextContent('Request from'); expect(transactionDetailsSection).toHaveTextContent('Interacting with'); - const gasFeesSection = getByTestId('gas-fee-section'); + const gasFeesSection = screen.getByTestId('gas-fee-section'); expect(gasFeesSection).toBeInTheDocument(); const editGasFeesRow = @@ -274,11 +293,13 @@ describe('Contract Interaction Confirmation', () => { expect(editGasFeesRow).toHaveTextContent('Network fee'); const firstGasField = within(editGasFeesRow).getByTestId('first-gas-field'); - expect(firstGasField).toHaveTextContent('0.0084 ETH'); + expect(firstGasField).toHaveTextContent('0.0001 ETH'); const editGasFeeNativeCurrency = within(editGasFeesRow).getByTestId('native-currency'); - expect(editGasFeeNativeCurrency).toHaveTextContent('$28.50'); - expect(editGasFeesRow).toContainElement(getByTestId('edit-gas-fee-icon')); + expect(editGasFeeNativeCurrency).toHaveTextContent('$0.47'); + expect(editGasFeesRow).toContainElement( + screen.getByTestId('edit-gas-fee-icon'), + ); const gasFeeSpeed = within(gasFeesSection).getByTestId( 'gas-fee-details-speed', @@ -306,12 +327,14 @@ describe('Contract Interaction Confirmation', () => { showConfirmationAdvancedDetails: false, }); - const { getByTestId } = await integrationTestRender({ - preloadedState: mockedMetaMaskState, - backgroundConnection: backgroundConnectionMocked, + await act(async () => { + await integrationTestRender({ + preloadedState: mockedMetaMaskState, + backgroundConnection: backgroundConnectionMocked, + }); }); - fireEvent.click(getByTestId('header-advanced-details-button')); + fireEvent.click(screen.getByTestId('header-advanced-details-button')); await waitFor(() => { expect( @@ -341,9 +364,11 @@ describe('Contract Interaction Confirmation', () => { showConfirmationAdvancedDetails: true, }); - const { getByTestId } = await integrationTestRender({ - preloadedState: mockedMetaMaskState, - backgroundConnection: backgroundConnectionMocked, + await act(async () => { + await integrationTestRender({ + preloadedState: mockedMetaMaskState, + backgroundConnection: backgroundConnectionMocked, + }); }); await waitFor(() => { @@ -360,37 +385,41 @@ describe('Contract Interaction Confirmation', () => { transactionData: '0x3b4b13810000000000000000000000000000000000000000000000000000000000000001', contractAddress: '0x076146c765189d51be3160a2140cf80bfc73ad68', - chainId: '0x5', + chainId: '0xaa36a7', }, ]); }); - const gasFeesSection = getByTestId('gas-fee-section'); - const maxFee = getByTestId('gas-fee-details-max-fee'); + const gasFeesSection = screen.getByTestId('gas-fee-section'); + const maxFee = screen.getByTestId('gas-fee-details-max-fee'); expect(gasFeesSection).toContainElement(maxFee); expect(maxFee).toHaveTextContent('Max fee'); - expect(maxFee).toHaveTextContent('0.2313 ETH'); - expect(maxFee).toHaveTextContent('$787.37'); + expect(maxFee).toHaveTextContent('0.0023 ETH'); + expect(maxFee).toHaveTextContent('$7.72'); - const nonceSection = getByTestId('advanced-details-nonce-section'); + const nonceSection = screen.getByTestId('advanced-details-nonce-section'); expect(nonceSection).toBeInTheDocument(); expect(nonceSection).toHaveTextContent('Nonce'); expect(nonceSection).toContainElement( - getByTestId('advanced-details-displayed-nonce'), - ); - expect(getByTestId('advanced-details-displayed-nonce')).toHaveTextContent( - '9', + screen.getByTestId('advanced-details-displayed-nonce'), ); + expect( + screen.getByTestId('advanced-details-displayed-nonce'), + ).toHaveTextContent('9'); - const dataSection = getByTestId('advanced-details-data-section'); + const dataSection = screen.getByTestId('advanced-details-data-section'); expect(dataSection).toBeInTheDocument(); - const dataSectionFunction = getByTestId('advanced-details-data-function'); + const dataSectionFunction = screen.getByTestId( + 'advanced-details-data-function', + ); expect(dataSection).toContainElement(dataSectionFunction); expect(dataSectionFunction).toHaveTextContent('Function'); expect(dataSectionFunction).toHaveTextContent('mintNFTs'); - const transactionDataParams = getByTestId('advanced-details-data-param-0'); + const transactionDataParams = screen.getByTestId( + 'advanced-details-data-param-0', + ); expect(dataSection).toContainElement(transactionDataParams); expect(transactionDataParams).toHaveTextContent('Number Of Tokens'); expect(transactionDataParams).toHaveTextContent('1'); @@ -408,15 +437,17 @@ describe('Contract Interaction Confirmation', () => { account.address, ); - const { getByText } = await integrationTestRender({ - preloadedState: mockedMetaMaskState, - backgroundConnection: backgroundConnectionMocked, + await act(async () => { + await integrationTestRender({ + preloadedState: mockedMetaMaskState, + backgroundConnection: backgroundConnectionMocked, + }); }); const headingText = 'This is a deceptive request'; const bodyText = 'If you approve this request, a third party known for scams will take all your assets.'; - expect(getByText(headingText)).toBeInTheDocument(); - expect(getByText(bodyText)).toBeInTheDocument(); + expect(screen.getByText(headingText)).toBeInTheDocument(); + expect(screen.getByText(bodyText)).toBeInTheDocument(); }); }); diff --git a/test/integration/confirmations/transactions/erc20-approve.test.tsx b/test/integration/confirmations/transactions/erc20-approve.test.tsx index 824ca80e0b84..e2466ad8f596 100644 --- a/test/integration/confirmations/transactions/erc20-approve.test.tsx +++ b/test/integration/confirmations/transactions/erc20-approve.test.tsx @@ -1,28 +1,21 @@ import { ApprovalType } from '@metamask/controller-utils'; -import { waitFor } from '@testing-library/react'; +import { act, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import nock from 'nock'; -import { useIsNFT } from '../../../../ui/pages/confirmations/components/confirm/info/approve/hooks/use-is-nft'; import * as backgroundConnection from '../../../../ui/store/background-connection'; import { integrationTestRender } from '../../../lib/render-helpers'; import mockMetaMaskState from '../../data/integration-init-state.json'; import { createMockImplementation, mock4byte } from '../../helpers'; +import { TokenStandard } from '../../../../shared/constants/transaction'; +import { createTestProviderTools } from '../../../stub/provider'; import { getUnapprovedApproveTransaction } from './transactionDataHelpers'; jest.mock('../../../../ui/store/background-connection', () => ({ ...jest.requireActual('../../../../ui/store/background-connection'), submitRequestToBackground: jest.fn(), + callBackgroundMethod: jest.fn(), })); -jest.mock( - '../../../../ui/pages/confirmations/components/confirm/info/approve/hooks/use-is-nft', - () => ({ - ...jest.requireActual( - '../../../../ui/pages/confirmations/components/confirm/info/approve/hooks/use-is-nft', - ), - useIsNFT: jest.fn(), - }), -); - const mockedBackgroundConnection = jest.mocked(backgroundConnection); const backgroundConnectionMocked = { @@ -31,14 +24,21 @@ const backgroundConnectionMocked = { export const pendingTransactionId = '48a75190-45ca-11ef-9001-f3886ec2397c'; export const pendingTransactionTime = new Date().getTime(); -const getMetaMaskStateWithUnapprovedApproveTransaction = ( - accountAddress: string, -) => { +const getMetaMaskStateWithUnapprovedApproveTransaction = (opts?: { + showAdvanceDetails: boolean; +}) => { + const account = + mockMetaMaskState.internalAccounts.accounts[ + mockMetaMaskState.internalAccounts + .selectedAccount as keyof typeof mockMetaMaskState.internalAccounts.accounts + ]; + return { ...mockMetaMaskState, preferences: { ...mockMetaMaskState.preferences, redesignedConfirmationsEnabled: true, + showConfirmationAdvancedDetails: opts?.showAdvanceDetails ?? false, }, pendingApprovals: { [pendingTransactionId]: { @@ -55,9 +55,12 @@ const getMetaMaskStateWithUnapprovedApproveTransaction = ( }, pendingApprovalCount: 1, knownMethodData: { - '0x3b4b1381': { - name: 'Mint NFTs', + '0x095ea7b3': { + name: 'Approve', params: [ + { + type: 'address', + }, { type: 'uint256', }, @@ -66,7 +69,7 @@ const getMetaMaskStateWithUnapprovedApproveTransaction = ( }, transactions: [ getUnapprovedApproveTransaction( - accountAddress, + account.address, pendingTransactionId, pendingTransactionTime, ), @@ -83,7 +86,7 @@ const advancedDetailsMockedRequests = { decodeTransactionData: { data: [ { - name: 'approve', + name: 'Approve', params: [ { type: 'address', @@ -109,46 +112,261 @@ const setupSubmitRequestToBackgroundMocks = ( ...(mockRequests ?? {}), }), ); + + mockedBackgroundConnection.callBackgroundMethod.mockImplementation( + createMockImplementation({ addKnownMethodData: {} }), + ); }; -describe('ERC721 Approve Confirmation', () => { - let useIsNFTMock; +describe('ERC20 Approve Confirmation', () => { + beforeAll(() => { + const { provider } = createTestProviderTools({ + networkId: 'sepolia', + chainId: '0xaa36a7', + }); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + global.ethereumProvider = provider as any; + }); + beforeEach(() => { jest.resetAllMocks(); - setupSubmitRequestToBackgroundMocks(); - const APPROVE_NFT_HEX_SIG = '0x095ea7b3'; - mock4byte(APPROVE_NFT_HEX_SIG); - useIsNFTMock = jest - .fn() - .mockImplementation(() => ({ isNFT: false, decimals: '18' })); - (useIsNFT as jest.Mock).mockImplementation(useIsNFTMock); + setupSubmitRequestToBackgroundMocks({ + getTokenStandardAndDetails: { + standard: TokenStandard.ERC20, + }, + }); + const APPROVE_ERC20_HEX_SIG = '0x095ea7b3'; + const APPROVE_ERC20_TEXT_SIG = 'approve(address,uint256)'; + mock4byte(APPROVE_ERC20_HEX_SIG, APPROVE_ERC20_TEXT_SIG); }); afterEach(() => { nock.cleanAll(); }); + afterAll(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + delete (global as any).ethereumProvider; + }); + + it('displays spending cap request title', async () => { + const mockedMetaMaskState = + getMetaMaskStateWithUnapprovedApproveTransaction(); + + await act(async () => { + await integrationTestRender({ + preloadedState: mockedMetaMaskState, + backgroundConnection: backgroundConnectionMocked, + }); + }); + + expect(screen.getByText('Spending cap request')).toBeInTheDocument(); + expect( + screen.getByText('This site wants permission to withdraw your tokens'), + ).toBeInTheDocument(); + }); + + it('displays approve simulation section', async () => { + const mockedMetaMaskState = + getMetaMaskStateWithUnapprovedApproveTransaction(); + + await act(async () => { + await integrationTestRender({ + preloadedState: mockedMetaMaskState, + backgroundConnection: backgroundConnectionMocked, + }); + }); + + const simulationSection = screen.getByTestId( + 'confirmation__simulation_section', + ); + expect(simulationSection).toBeInTheDocument(); + + // TODO - fix this copy + expect(simulationSection).toHaveTextContent( + "You're giving someone else permission to withdraw NFTs from your account", + ); + expect(simulationSection).toHaveTextContent('Spending cap'); + const spendingCapValue = screen.getByTestId('simulation-token-value'); + expect(simulationSection).toContainElement(spendingCapValue); + expect(spendingCapValue).toHaveTextContent('1'); + expect(simulationSection).toHaveTextContent('0x07614...3ad68'); + }); + it('displays approve details with correct data', async () => { - const account = - mockMetaMaskState.internalAccounts.accounts[ - mockMetaMaskState.internalAccounts - .selectedAccount as keyof typeof mockMetaMaskState.internalAccounts.accounts - ]; + const testUser = userEvent.setup(); const mockedMetaMaskState = - getMetaMaskStateWithUnapprovedApproveTransaction(account.address); + getMetaMaskStateWithUnapprovedApproveTransaction(); - const { getByText } = await integrationTestRender({ - preloadedState: mockedMetaMaskState, - backgroundConnection: backgroundConnectionMocked, + await act(async () => { + await integrationTestRender({ + preloadedState: mockedMetaMaskState, + backgroundConnection: backgroundConnectionMocked, + }); }); - await waitFor(() => { - expect(getByText('Spending cap request')).toBeInTheDocument(); + const approveDetails = screen.getByTestId('confirmation__approve-details'); + expect(approveDetails).toBeInTheDocument(); + const approveDetailsSpender = screen.getByTestId( + 'confirmation__approve-spender', + ); + + expect(approveDetails).toContainElement(approveDetailsSpender); + expect(approveDetailsSpender).toHaveTextContent('Spender'); + expect(approveDetailsSpender).toHaveTextContent('0x2e0D7...5d09B'); + const spenderTooltip = screen.getByTestId( + 'confirmation__approve-spender-tooltip', + ); + expect(approveDetailsSpender).toContainElement(spenderTooltip); + await testUser.hover(spenderTooltip); + // TODO - fix this copy + const spenderTooltipContent = await screen.findByText( + 'This is the address that will be able to withdraw your NFTs.', + ); + expect(spenderTooltipContent).toBeInTheDocument(); + + const approveDetailsRequestFrom = screen.getByTestId( + 'transaction-details-origin-row', + ); + expect(approveDetails).toContainElement(approveDetailsRequestFrom); + expect(approveDetailsRequestFrom).toHaveTextContent('Request from'); + expect(approveDetailsRequestFrom).toHaveTextContent( + 'http://localhost:8086/', + ); + + const approveDetailsRequestFromTooltip = screen.getByTestId( + 'transaction-details-origin-row-tooltip', + ); + expect(approveDetailsRequestFrom).toContainElement( + approveDetailsRequestFromTooltip, + ); + await testUser.hover(approveDetailsRequestFromTooltip); + const requestFromTooltipContent = await screen.findByText( + 'This is the site asking for your confirmation.', + ); + expect(requestFromTooltipContent).toBeInTheDocument(); + }); + + it('displays spending cap section with correct data', async () => { + const testUser = userEvent.setup(); + + const mockedMetaMaskState = + getMetaMaskStateWithUnapprovedApproveTransaction(); + + await act(async () => { + await integrationTestRender({ + preloadedState: mockedMetaMaskState, + backgroundConnection: backgroundConnectionMocked, + }); }); - await waitFor(() => { - expect(getByText('Request from')).toBeInTheDocument(); + const spendingCapSection = screen.getByTestId( + 'confirmation__approve-spending-cap-section', + ); + expect(spendingCapSection).toBeInTheDocument(); + + expect(spendingCapSection).toHaveTextContent('Account balance'); + expect(spendingCapSection).toHaveTextContent('0'); + const spendingCapGroup = screen.getByTestId( + 'confirmation__approve-spending-cap-group', + ); + expect(spendingCapSection).toContainElement(spendingCapGroup); + expect(spendingCapGroup).toHaveTextContent('Spending cap'); + expect(spendingCapGroup).toHaveTextContent('1'); + + const spendingCapGroupTooltip = screen.getByTestId( + 'confirmation__approve-spending-cap-group-tooltip', + ); + expect(spendingCapGroup).toContainElement(spendingCapGroupTooltip); + await testUser.hover(spendingCapGroupTooltip); + const requestFromTooltipContent = await screen.findByText( + 'This is the amount of tokens the spender will be able to access on your behalf.', + ); + expect(requestFromTooltipContent).toBeInTheDocument(); + }); + + it('displays the advanced transaction details section', async () => { + const testUser = userEvent.setup(); + + const mockedMetaMaskState = + getMetaMaskStateWithUnapprovedApproveTransaction({ + showAdvanceDetails: true, + }); + + await act(async () => { + await integrationTestRender({ + preloadedState: mockedMetaMaskState, + backgroundConnection: backgroundConnectionMocked, + }); }); + + const approveDetails = screen.getByTestId('confirmation__approve-details'); + expect(approveDetails).toBeInTheDocument(); + + const approveDetailsRecipient = screen.getByTestId( + 'transaction-details-recipient-row', + ); + expect(approveDetails).toContainElement(approveDetailsRecipient); + expect(approveDetailsRecipient).toHaveTextContent('Interacting with'); + expect(approveDetailsRecipient).toHaveTextContent('0x07614...3ad68'); + + const approveDetailsRecipientTooltip = screen.getByTestId( + 'transaction-details-recipient-row-tooltip', + ); + expect(approveDetailsRecipient).toContainElement( + approveDetailsRecipientTooltip, + ); + await testUser.hover(approveDetailsRecipientTooltip); + const recipientTooltipContent = await screen.findByText( + "This is the contract you're interacting with. Protect yourself from scammers by verifying the details.", + ); + expect(recipientTooltipContent).toBeInTheDocument(); + + const approveMethodData = await screen.findByTestId( + 'transaction-details-method-data-row', + ); + expect(approveDetails).toContainElement(approveMethodData); + expect(approveMethodData).toHaveTextContent('Method'); + expect(approveMethodData).toHaveTextContent('Approve'); + const approveMethodDataTooltip = screen.getByTestId( + 'transaction-details-method-data-row-tooltip', + ); + expect(approveMethodData).toContainElement(approveMethodDataTooltip); + await testUser.hover(approveMethodDataTooltip); + const approveMethodDataTooltipContent = await screen.findByText( + 'Function executed based on decoded input data.', + ); + expect(approveMethodDataTooltipContent).toBeInTheDocument(); + + const approveDetailsNonce = screen.getByTestId( + 'advanced-details-nonce-section', + ); + expect(approveDetailsNonce).toBeInTheDocument(); + + const dataSection = screen.getByTestId('advanced-details-data-section'); + expect(dataSection).toBeInTheDocument(); + + const dataSectionFunction = screen.getByTestId( + 'advanced-details-data-function', + ); + expect(dataSection).toContainElement(dataSectionFunction); + expect(dataSectionFunction).toHaveTextContent('Function'); + expect(dataSectionFunction).toHaveTextContent('Approve'); + + const approveDataParams1 = screen.getByTestId( + 'advanced-details-data-param-0', + ); + expect(dataSection).toContainElement(approveDataParams1); + expect(approveDataParams1).toHaveTextContent('Param #1'); + expect(approveDataParams1).toHaveTextContent('0x2e0D7...5d09B'); + + const approveDataParams2 = screen.getByTestId( + 'advanced-details-data-param-1', + ); + expect(dataSection).toContainElement(approveDataParams2); + expect(approveDataParams2).toHaveTextContent('Param #2'); + expect(approveDataParams2).toHaveTextContent('1'); }); }); diff --git a/test/integration/confirmations/transactions/erc721-approve.test.tsx b/test/integration/confirmations/transactions/erc721-approve.test.tsx index 47f0e2121eb8..8a836dbd7568 100644 --- a/test/integration/confirmations/transactions/erc721-approve.test.tsx +++ b/test/integration/confirmations/transactions/erc721-approve.test.tsx @@ -1,28 +1,20 @@ import { ApprovalType } from '@metamask/controller-utils'; -import { waitFor } from '@testing-library/react'; +import { act, screen, waitFor } from '@testing-library/react'; import nock from 'nock'; -import { useIsNFT } from '../../../../ui/pages/confirmations/components/confirm/info/approve/hooks/use-is-nft'; import * as backgroundConnection from '../../../../ui/store/background-connection'; import { integrationTestRender } from '../../../lib/render-helpers'; import mockMetaMaskState from '../../data/integration-init-state.json'; import { createMockImplementation, mock4byte } from '../../helpers'; +import { TokenStandard } from '../../../../shared/constants/transaction'; +import { createTestProviderTools } from '../../../stub/provider'; import { getUnapprovedApproveTransaction } from './transactionDataHelpers'; jest.mock('../../../../ui/store/background-connection', () => ({ ...jest.requireActual('../../../../ui/store/background-connection'), submitRequestToBackground: jest.fn(), + callBackgroundMethod: jest.fn(), })); -jest.mock( - '../../../../ui/pages/confirmations/components/confirm/info/approve/hooks/use-is-nft', - () => ({ - ...jest.requireActual( - '../../../../ui/pages/confirmations/components/confirm/info/approve/hooks/use-is-nft', - ), - useIsNFT: jest.fn(), - }), -); - const mockedBackgroundConnection = jest.mocked(backgroundConnection); const backgroundConnectionMocked = { @@ -55,9 +47,12 @@ const getMetaMaskStateWithUnapprovedApproveTransaction = ( }, pendingApprovalCount: 1, knownMethodData: { - '0x3b4b1381': { - name: 'Mint NFTs', + '0x095ea7b3': { + name: 'Approve', params: [ + { + type: 'address', + }, { type: 'uint256', }, @@ -109,23 +104,43 @@ const setupSubmitRequestToBackgroundMocks = ( ...(mockRequests ?? {}), }), ); + + mockedBackgroundConnection.callBackgroundMethod.mockImplementation( + createMockImplementation({ addKnownMethodData: {} }), + ); }; describe('ERC721 Approve Confirmation', () => { - let useIsNFTMock; + beforeAll(() => { + const { provider } = createTestProviderTools({ + networkId: 'sepolia', + chainId: '0xaa36a7', + }); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + global.ethereumProvider = provider as any; + }); + beforeEach(() => { jest.resetAllMocks(); - setupSubmitRequestToBackgroundMocks(); + setupSubmitRequestToBackgroundMocks({ + getTokenStandardAndDetails: { + standard: TokenStandard.ERC721, + }, + }); const APPROVE_NFT_HEX_SIG = '0x095ea7b3'; mock4byte(APPROVE_NFT_HEX_SIG); - useIsNFTMock = jest.fn().mockImplementation(() => ({ isNFT: true })); - (useIsNFT as jest.Mock).mockImplementation(useIsNFTMock); }); afterEach(() => { nock.cleanAll(); }); + afterAll(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + delete (global as any).ethereumProvider; + }); + it('displays approve details with correct data', async () => { const account = mockMetaMaskState.internalAccounts.accounts[ @@ -136,17 +151,19 @@ describe('ERC721 Approve Confirmation', () => { const mockedMetaMaskState = getMetaMaskStateWithUnapprovedApproveTransaction(account.address); - const { getByText } = await integrationTestRender({ - preloadedState: mockedMetaMaskState, - backgroundConnection: backgroundConnectionMocked, + await act(async () => { + await integrationTestRender({ + preloadedState: mockedMetaMaskState, + backgroundConnection: backgroundConnectionMocked, + }); }); await waitFor(() => { - expect(getByText('Allowance request')).toBeInTheDocument(); + expect(screen.getByText('Allowance request')).toBeInTheDocument(); }); await waitFor(() => { - expect(getByText('Request from')).toBeInTheDocument(); + expect(screen.getByText('Request from')).toBeInTheDocument(); }); }); }); diff --git a/test/integration/confirmations/transactions/transactionDataHelpers.tsx b/test/integration/confirmations/transactions/transactionDataHelpers.tsx index 72fc0d2289f3..12550ea5e563 100644 --- a/test/integration/confirmations/transactions/transactionDataHelpers.tsx +++ b/test/integration/confirmations/transactions/transactionDataHelpers.tsx @@ -7,7 +7,7 @@ export const getUnapprovedTransaction = ( ) => { return { actionId: 4256525906, - chainId: '0x5', + chainId: '0xaa36a7', dappSuggestedGasFees: { gas: '0x16a92', }, diff --git a/test/integration/data/integration-init-state.json b/test/integration/data/integration-init-state.json index 0e935a7a9a8e..212ea5702868 100644 --- a/test/integration/data/integration-init-state.json +++ b/test/integration/data/integration-init-state.json @@ -26,18 +26,19 @@ } }, "accountsByChainId": { - "0x5": { + "0xaa36a7": { "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc": { + "address": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc", "balance": "0x15f6f0b9d4f8d000" } } }, "addSnapAccountEnabled": false, "addressBook": { - "0x5": { + "0xaa36a7": { "0xc42edfcc21ed14dda456aa0756c153f7985d8813": { "address": "0xc42edfcc21ed14dda456aa0756c153f7985d8813", - "chainId": "0x5", + "chainId": "0xaa36a7", "isEns": false, "memo": "", "name": "Address Book Account 1" @@ -45,7 +46,7 @@ } }, "advancedGasFee": { - "0x5": { + "0xaa36a7": { "maxBaseFee": "75", "priorityFee": "2" } @@ -92,6 +93,17 @@ "createdDate": null, "schemaName": "ERC721", "externalLink": null + }, + { + "address": "0x495f947276749Ce646f68AC8c248420045cb7b5e", + "description": null, + "name": "Punk Generator", + "logo": null, + "symbol": "PUNK", + "assetContractType": "non-fungible", + "createdDate": null, + "schemaName": "ERC1155", + "externalLink": null } ], "0x5": [ @@ -105,17 +117,6 @@ "createdDate": null, "schemaName": "ERC721", "externalLink": null - }, - { - "address": "0x495f947276749Ce646f68AC8c248420045cb7b5e", - "description": null, - "name": "Punk Generator", - "logo": null, - "symbol": "PUNK", - "assetContractType": "non-fungible", - "createdDate": null, - "schemaName": "ERC1155", - "externalLink": null } ], "0x99": [ @@ -155,7 +156,7 @@ "standard": "ERC721" } ], - "0xaa36a7": [ + "0x5": [ { "address": "0xDc7382Eb0Bc9C352A4CbA23c909bDA01e0206414", "tokenId": "1", @@ -165,7 +166,7 @@ "standard": "ERC721" } ], - "0x5": [ + "0xaa36a7": [ { "address": "0x495f947276749Ce646f68AC8c248420045cb7b5e", "tokenId": "58076532811975507823669075598676816378162417803895263482849101575514658701313", @@ -395,7 +396,7 @@ "networkCongestion": 0.10625 }, "gasFeeEstimatesByChainId": { - "0x5": { + "0xaa36a7": { "estimatedGasFeeTimeBounds": { "lowerTimeBound": 15000, "upperTimeBound": 60000 @@ -462,7 +463,7 @@ "0xe708": false, "0xfa": true, "0x5": false, - "0xaa36a7": true, + "0xaa36a7": false, "0xe704": true }, "internalAccounts": { @@ -656,18 +657,26 @@ }, "networkConfigurations": { "testNetworkConfigurationId": { - "rpcUrl": "https://testrpc.com", "chainId": "0x1", + "id": "testNetworkConfigurationId", "nickname": "Custom Mainnet RPC", - "type": "rpc", - "id": "testNetworkConfigurationId" + "rpcUrl": "https://testrpc.com", + "ticker": "ETH", + "type": "rpc" }, "goerli-network-id": { - "type": "rpc", "chainId": "0x5", - "ticker": "ETH", + "id": "goerli-network-id", "nickname": "Chain 5", - "id": "goerli-network-id" + "ticker": "ETH", + "type": "rpc" + }, + "sepolia": { + "type": "rpc", + "chainId": "0xaa36a7", + "ticker": "ETH", + "nickname": "Sepolia", + "id": "sepolia" } }, "networksMetadata": { @@ -682,11 +691,17 @@ "1559": true }, "status": "available" + }, + "testNetworkConfigurationId": { + "EIPS": { + "1559": true + }, + "status": "available" } }, "nftsDropdownState": { "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc": { - "0x5": { + "0xaa36a7": { "0x495f947276749Ce646f68AC8c248420045cb7b5e": false } } @@ -749,16 +764,16 @@ "previousAppVersion": "11.14.4", "previousMigrationVersion": 112, "providerConfig": { - "type": "rpc", - "nickname": "goerli", - "chainId": "0x5", + "type": "sepolia", + "nickname": "sepolia", + "chainId": "0xaa36a7", "ticker": "ETH", - "id": "chain5" + "id": "sepolia" }, "securityAlertsEnabled": true, "seedPhraseBackedUp": true, "selectedAddress": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc", - "selectedNetworkClientId": "goerli-network-id", + "selectedNetworkClientId": "sepolia", "showAccountBanner": false, "showBetaHeader": false, "showNetworkBanner": true, @@ -771,7 +786,7 @@ "liveness": true, "smartTransactions": { "0x1": [], - "0x5": [] + "0xaa36a7": [] }, "userOptInV2": true }, @@ -1264,7 +1279,7 @@ "id": 3387511061307736, "time": 1528133130531, "status": "confirmed", - "chainId": "0x5", + "chainId": "0xaa36a7", "loadingDefaults": false, "txParams": { "from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62", @@ -1279,7 +1294,7 @@ "id": 3387511061307736, "time": 1528133130531, "status": "unapproved", - "chainId": "0x5", + "chainId": "0xaa36a7", "loadingDefaults": true, "txParams": { "from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62", @@ -1396,7 +1411,7 @@ "id": 3387511061307737, "time": 1528133149983, "status": "confirmed", - "chainId": "0x5", + "chainId": "0xaa36a7", "loadingDefaults": false, "txParams": { "from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62", @@ -1411,7 +1426,7 @@ "id": 3387511061307737, "time": 1528133149983, "status": "unapproved", - "chainId": "0x5", + "chainId": "0xaa36a7", "loadingDefaults": true, "txParams": { "from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62", @@ -1528,7 +1543,7 @@ "id": 3387511061307738, "time": 1528133180635, "status": "confirmed", - "chainId": "0x5", + "chainId": "0xaa36a7", "loadingDefaults": false, "txParams": { "from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62", @@ -1543,7 +1558,7 @@ "id": 3387511061307738, "time": 1528133180635, "status": "unapproved", - "chainId": "0x5", + "chainId": "0xaa36a7", "loadingDefaults": true, "txParams": { "from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62", @@ -1660,7 +1675,7 @@ "id": 3387511061307739, "time": 1528133223918, "status": "confirmed", - "chainId": "0x5", + "chainId": "0xaa36a7", "loadingDefaults": false, "txParams": { "from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62", @@ -1676,7 +1691,7 @@ "id": 3387511061307739, "time": 1528133223918, "status": "unapproved", - "chainId": "0x5", + "chainId": "0xaa36a7", "loadingDefaults": true, "txParams": { "from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62", @@ -1797,7 +1812,7 @@ "id": 3387511061307740, "time": 1528133291381, "status": "confirmed", - "chainId": "0x5", + "chainId": "0xaa36a7", "loadingDefaults": false, "txParams": { "from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62", @@ -1813,7 +1828,7 @@ "id": 3387511061307740, "time": 1528133291381, "status": "unapproved", - "chainId": "0x5", + "chainId": "0xaa36a7", "loadingDefaults": true, "txParams": { "from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62", @@ -1931,7 +1946,7 @@ "id": 3387511061307741, "time": 1528133318440, "status": "rejected", - "chainId": "0x5", + "chainId": "0xaa36a7", "loadingDefaults": false, "txParams": { "from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62", @@ -1945,7 +1960,7 @@ "id": 3387511061307741, "time": 1528133318440, "status": "unapproved", - "chainId": "0x5", + "chainId": "0xaa36a7", "loadingDefaults": true, "txParams": { "from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62", @@ -2022,12 +2037,12 @@ "useTokenDetection": false, "useTransactionSimulations": true, "usedNetworks": { - "0x5": { - "rpcUrl": "https://goerli.infura.io/v3/8f8f7f9f6f4c4f3e8f8f7f9f6f4c4f3e", - "chainId": "0x5", - "nickname": "Goerli Test Network", + "0xaa36a7": { + "rpcUrl": "https://sepolia.infura.io/v3/8f8f7f9f6f4c4f3e8f8f7f9f6f4c4f3e", + "chainId": "0xaa36a7", + "nickname": "Sepolia Test Network", "ticker": "ETH", - "blockExplorerUrl": "https://goerli.etherscan.io" + "blockExplorerUrl": "https://sepolia.etherscan.io" } }, "userOperations": {}, diff --git a/test/integration/helpers.tsx b/test/integration/helpers.tsx index d975c5adc594..2576d282a341 100644 --- a/test/integration/helpers.tsx +++ b/test/integration/helpers.tsx @@ -9,7 +9,7 @@ export const createMockImplementation = (requests: Record) => { }; }; -export function mock4byte(hexSignature: string) { +export function mock4byte(hexSignature: string, textSignature?: string) { const mockEndpoint = nock('https://www.4byte.directory:443', { encodedQueryParams: true, }) @@ -21,7 +21,7 @@ export function mock4byte(hexSignature: string) { { id: 235447, created_at: '2021-09-14T02:07:09.805000Z', - text_signature: 'mintNFTs(uint256)', + text_signature: textSignature ?? 'mintNFTs(uint256)', hex_signature: hexSignature, bytes_signature: ';K\u0013 ', }, diff --git a/test/integration/onboarding/wallet-created.test.tsx b/test/integration/onboarding/wallet-created.test.tsx index fae425ad8a35..36ff7c8d3ecf 100644 --- a/test/integration/onboarding/wallet-created.test.tsx +++ b/test/integration/onboarding/wallet-created.test.tsx @@ -87,36 +87,5 @@ describe('Wallet Created Events', () => { expect(completeOnboardingBackgroundRequest).toBeTruthy(); }); - - await waitFor(() => { - const OnboardingWalletSetupCompleteEvent = - mockedBackgroundConnection.submitRequestToBackground.mock.calls?.find( - (call) => { - if (call[0] === 'trackMetaMetricsEvent') { - const callArgs = call[1] as unknown as Record[]; - - return ( - callArgs[0].event === - MetaMetricsEventName.OnboardingWalletSetupComplete - ); - } - - return false; - }, - ); - - expect(OnboardingWalletSetupCompleteEvent?.[1]).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - category: MetaMetricsEventCategory.Onboarding, - event: MetaMetricsEventName.OnboardingWalletSetupComplete, - properties: { - wallet_setup_type: 'new', - new_wallet: true, - }, - }), - ]), - ); - }); }); }); diff --git a/ui/__mocks__/ethereumjs-util.js b/ui/__mocks__/ethereumjs-util.js new file mode 100644 index 000000000000..d7af4a81162c --- /dev/null +++ b/ui/__mocks__/ethereumjs-util.js @@ -0,0 +1,6 @@ +// eslint-disable-next-line import/no-extraneous-dependencies, node/no-extraneous-require +const util = require('ethereumjs-util'); + +module.exports = { + ...util, +}; diff --git a/ui/components/app/app-components.scss b/ui/components/app/app-components.scss index cc9a08a53f1d..c5083af45104 100644 --- a/ui/components/app/app-components.scss +++ b/ui/components/app/app-components.scss @@ -51,7 +51,6 @@ @import 'recovery-phrase-reminder/index'; @import 'step-progress-bar/index.scss'; @import 'selected-account/index'; -@import 'smart-transactions/index'; @import 'srp-input/srp-input'; @import 'snaps/snap-privacy-warning/index'; @import 'tab-bar/index'; diff --git a/ui/components/app/assets/nfts/nft-details/__snapshots__/nft-details.test.js.snap b/ui/components/app/assets/nfts/nft-details/__snapshots__/nft-details.test.js.snap index d03df016c1b3..0a025bc47ff0 100644 --- a/ui/components/app/assets/nfts/nft-details/__snapshots__/nft-details.test.js.snap +++ b/ui/components/app/assets/nfts/nft-details/__snapshots__/nft-details.test.js.snap @@ -1,6 +1,189 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`NFT Details should match minimal props and state snapshot 1`] = ` +
+
+
+
+
+ +
+ +
+
+
+
+ +
+
+
+ C +
+
+
+ +
+
+
+
+

+ MUNK #1 +

+
+
+

+

+
+
+

+ Contract address +

+
+ + +
+
+
+

+ Token ID +

+

+ 1 +

+
+
+

+ Token standard +

+

+ ERC721 +

+
+
+ +
+
+
+ Disclaimer: MetaMask pulls the media file from the source url. This url sometimes gets changed by the marketplace on which the NFT was minted. +
+
+
+
+
+
+ +`; + +exports[`NFT Details should match minimal props and state snapshot 2`] = `
`; + +exports[`NFT Details should match minimal props and state snapshot 3`] = `
`; diff --git a/ui/components/app/assets/nfts/nft-details/__snapshots__/nft-full-image.test.js.snap b/ui/components/app/assets/nfts/nft-details/__snapshots__/nft-full-image.test.js.snap new file mode 100644 index 000000000000..dfedee737c93 --- /dev/null +++ b/ui/components/app/assets/nfts/nft-details/__snapshots__/nft-full-image.test.js.snap @@ -0,0 +1,84 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`NFT full image should match snapshot 1`] = ` +
+
+
+
+
+
+

+

+
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+`; + +exports[`NFT full image should match snapshot 2`] = `
`; diff --git a/ui/components/app/assets/nfts/nft-details/nft-details.test.js b/ui/components/app/assets/nfts/nft-details/nft-details.test.js index 65c3ba339e5f..350dc4813c6a 100644 --- a/ui/components/app/assets/nfts/nft-details/nft-details.test.js +++ b/ui/components/app/assets/nfts/nft-details/nft-details.test.js @@ -19,8 +19,17 @@ import { } from '../../../../../store/actions'; import { CHAIN_IDS } from '../../../../../../shared/constants/network'; import { mockNetworkState } from '../../../../../../test/stub/networks'; +import { + getAssetImageURL, + shortenAddress, +} from '../../../../../helpers/utils/util'; import NftDetails from './nft-details'; +jest.mock('../../../../../helpers/utils/util', () => ({ + getAssetImageURL: jest.fn(), + shortenAddress: jest.fn(), +})); + jest.mock('copy-to-clipboard'); const mockHistoryPush = jest.fn(); @@ -62,13 +71,20 @@ describe('NFT Details', () => { jest.clearAllMocks(); }); - it('should match minimal props and state snapshot', () => { + it('should match minimal props and state snapshot', async () => { + getAssetImageURL.mockResolvedValue( + 'https://bafybeiclzx7zfjvuiuwobn5ip3ogc236bjqfjzoblumf4pau4ep6dqramu.ipfs.dweb.link', + ); + shortenAddress.mockReturnValue('0xDc738...06414'); + const { container } = renderWithProvider( , mockStore, ); - expect(container).toMatchSnapshot(); + await waitFor(() => { + expect(container).toMatchSnapshot(); + }); }); it(`should route to '/' route when the back button is clicked`, () => { diff --git a/ui/components/app/assets/nfts/nft-details/nft-details.tsx b/ui/components/app/assets/nfts/nft-details/nft-details.tsx index 0064dc38976c..8a857da43989 100644 --- a/ui/components/app/assets/nfts/nft-details/nft-details.tsx +++ b/ui/components/app/assets/nfts/nft-details/nft-details.tsx @@ -18,10 +18,7 @@ import { AlignItems, } from '../../../../../helpers/constants/design-system'; import { useI18nContext } from '../../../../../hooks/useI18nContext'; -import { - getAssetImageURL, - shortenAddress, -} from '../../../../../helpers/utils/util'; +import { shortenAddress } from '../../../../../helpers/utils/util'; import { getNftImageAlt } from '../../../../../helpers/utils/nfts'; import { getCurrentChainId, @@ -73,6 +70,7 @@ import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../../../ import { getConversionRate } from '../../../../../ducks/metamask/metamask'; import { Numeric } from '../../../../../../shared/modules/Numeric'; import { addUrlProtocolPrefix } from '../../../../../../app/scripts/lib/util'; +import useGetAssetImageUrl from '../../../../../hooks/useGetAssetImageUrl'; import NftDetailInformationRow from './nft-detail-information-row'; import NftDetailInformationFrame from './nft-detail-information-frame'; import NftDetailDescription from './nft-detail-description'; @@ -110,9 +108,10 @@ export default function NftDetails({ nft }: { nft: Nft }) { const nftImageAlt = getNftImageAlt(nft); const nftSrcUrl = imageOriginal ?? image; - const nftImageURL = getAssetImageURL(imageOriginal ?? image, ipfsGateway); const isIpfsURL = nftSrcUrl?.startsWith('ipfs:'); - const isImageHosted = image?.startsWith('https:'); + const isImageHosted = + image?.startsWith('https:') || image?.startsWith('http:'); + const nftImageURL = useGetAssetImageUrl(imageOriginal ?? image, ipfsGateway); const hasFloorAskPrice = Boolean( collection?.floorAsk?.price?.amount?.usd && @@ -165,6 +164,7 @@ export default function NftDetails({ nft }: { nft: Nft }) { }; const { chainId } = currentChain; + useEffect(() => { trackEvent({ event: MetaMetricsEventName.NftDetailsOpened, diff --git a/ui/components/app/assets/nfts/nft-details/nft-full-image.test.js b/ui/components/app/assets/nfts/nft-details/nft-full-image.test.js new file mode 100644 index 000000000000..193025a402ac --- /dev/null +++ b/ui/components/app/assets/nfts/nft-details/nft-full-image.test.js @@ -0,0 +1,45 @@ +import { waitFor } from '@testing-library/react'; +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { toHex } from '@metamask/controller-utils'; +import { renderWithProvider } from '../../../../../../test/lib/render-helpers'; +import mockState from '../../../../../../test/data/mock-state.json'; +import NftFullImage from './nft-full-image'; + +const selectedAddress = + mockState.metamask.internalAccounts.accounts[ + mockState.metamask.internalAccounts.selectedAccount + ].address; +const nfts = mockState.metamask.allNfts[selectedAddress][toHex(5)]; +const mockAsset = nfts[0].address; +const mockId = nfts[0].tokenId; +jest.mock('react-router-dom', () => { + const original = jest.requireActual('react-router-dom'); + return { + ...original, + useHistory: () => ({ + push: jest.fn(), + }), + useParams: () => ({ + asset: mockAsset, + id: mockId, + }), + }; +}); + +describe('NFT full image', () => { + const mockStore = configureMockStore([thunk])(mockState); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should match snapshot', async () => { + const { container } = renderWithProvider(, mockStore); + + await waitFor(() => { + expect(container).toMatchSnapshot(); + }); + }); +}); diff --git a/ui/components/app/assets/nfts/nft-details/nft-full-image.tsx b/ui/components/app/assets/nfts/nft-details/nft-full-image.tsx index e951cfcdd6ea..f280749a1a35 100644 --- a/ui/components/app/assets/nfts/nft-details/nft-full-image.tsx +++ b/ui/components/app/assets/nfts/nft-details/nft-full-image.tsx @@ -1,7 +1,6 @@ import React, { useEffect, useState } from 'react'; import { useSelector } from 'react-redux'; import { useHistory, useParams } from 'react-router-dom'; -import { getAssetImageURL } from '../../../../../helpers/utils/util'; import { getNftImageAlt } from '../../../../../helpers/utils/nfts'; import { getCurrentNetwork, getIpfsGateway } from '../../../../../selectors'; @@ -23,6 +22,7 @@ import { } from '../../../../../helpers/constants/design-system'; import { useI18nContext } from '../../../../../hooks/useI18nContext'; import { ASSET_ROUTE } from '../../../../../helpers/constants/routes'; +import useGetAssetImageUrl from '../../../../../hooks/useGetAssetImageUrl'; export default function NftFullImage() { const t = useI18nContext(); @@ -40,10 +40,10 @@ export default function NftFullImage() { const ipfsGateway = useSelector(getIpfsGateway); const currentChain = useSelector(getCurrentNetwork); + const nftImageURL = useGetAssetImageUrl(imageOriginal ?? image, ipfsGateway); const nftImageAlt = getNftImageAlt(nft); const nftSrcUrl = imageOriginal ?? image; - const nftImageURL = getAssetImageURL(imageOriginal ?? image, ipfsGateway); const isIpfsURL = nftSrcUrl?.startsWith('ipfs:'); const isImageHosted = image?.startsWith('https:'); const history = useHistory(); diff --git a/ui/components/app/assets/nfts/nfts-items/collection-image.component.test.tsx b/ui/components/app/assets/nfts/nfts-items/collection-image.component.test.tsx new file mode 100644 index 000000000000..726ca26508b9 --- /dev/null +++ b/ui/components/app/assets/nfts/nfts-items/collection-image.component.test.tsx @@ -0,0 +1,86 @@ +import React from 'react'; +import { useSelector } from 'react-redux'; +import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { screen } from '@testing-library/react'; +import mockState from '../../../../../../test/data/mock-state.json'; +import { renderWithProvider } from '../../../../../../test/lib/render-helpers'; +import { getIpfsGateway, getOpenSeaEnabled } from '../../../../../selectors'; +import { CollectionImageComponent } from './collection-image.component'; + +jest.mock('react-redux', () => ({ + ...jest.requireActual('react-redux'), + useSelector: jest.fn(), +})); + +jest.mock('../../../../../selectors', () => ({ + ...jest.requireActual('../../../../../selectors'), + getIpfsGateway: jest.fn(), + getOpenSeaEnabled: jest.fn(), +})); +const mockStore = configureMockStore([thunk])(mockState); +describe('CollectionImageComponent', () => { + const useSelectorMock = useSelector as jest.Mock; + beforeEach(() => { + jest.resetAllMocks(); + }); + it('should show collection first letter when ipfs is not enabled', async () => { + useSelectorMock.mockImplementation((selector) => { + if (selector === getIpfsGateway) { + return undefined; + } + return undefined; + }); + + const props = { + collectionName: 'NFT Collection', + collectionImage: 'ipfs://', + }; + + const { getByText } = renderWithProvider( + , + mockStore, + ); + + expect(getByText('N')).toBeInTheDocument(); + }); + + it('should show collection first letter when opensea is not enabled', async () => { + useSelectorMock.mockImplementation((selector) => { + if (selector === getOpenSeaEnabled) { + return false; + } + return undefined; + }); + + const props = { + collectionName: 'Test NFT Collection', + collectionImage: 'https://image.png', + }; + + const { getByText } = renderWithProvider( + , + mockStore, + ); + + expect(getByText('T')).toBeInTheDocument(); + }); + + it('should show collection image', async () => { + useSelectorMock.mockImplementation((selector) => { + if (selector === getOpenSeaEnabled) { + return true; + } + return undefined; + }); + + const props = { + collectionName: 'Test NFT Collection', + collectionImage: 'https://image.png', + }; + + renderWithProvider(, mockStore); + + expect(screen.getAllByRole('img')).toHaveLength(1); + }); +}); diff --git a/ui/components/app/assets/nfts/nfts-items/collection-image.component.tsx b/ui/components/app/assets/nfts/nfts-items/collection-image.component.tsx new file mode 100644 index 000000000000..24f34714dd95 --- /dev/null +++ b/ui/components/app/assets/nfts/nfts-items/collection-image.component.tsx @@ -0,0 +1,53 @@ +import React from 'react'; + +import { useSelector } from 'react-redux'; + +import { getIpfsGateway, getOpenSeaEnabled } from '../../../../../selectors'; +import useGetAssetImageUrl from '../../../../../hooks/useGetAssetImageUrl'; +import { Box } from '../../../../component-library'; + +export const CollectionImageComponent = ({ + collectionImage, + collectionName, +}: { + collectionImage: string; + collectionName: string; +}) => { + const ipfsGateway = useSelector(getIpfsGateway); + const openSeaEnabled = useSelector(getOpenSeaEnabled); + const nftImageURL = useGetAssetImageUrl(collectionImage, ipfsGateway); + + const renderCollectionImage = () => { + if (collectionImage?.startsWith('ipfs') && !ipfsGateway) { + return ( +
+ {collectionName?.[0]?.toUpperCase() ?? null} +
+ ); + } + if (!openSeaEnabled && !collectionImage?.startsWith('ipfs')) { + return ( +
+ {collectionName?.[0]?.toUpperCase() ?? null} +
+ ); + } + + if (collectionImage) { + return ( + {collectionName} + ); + } + return ( +
+ {collectionName?.[0]?.toUpperCase() ?? null} +
+ ); + }; + + return {renderCollectionImage()}; +}; diff --git a/ui/components/app/assets/nfts/nfts-items/nfts-items.js b/ui/components/app/assets/nfts/nfts-items/nfts-items.js index 9e8196669b0e..c44de72b261b 100644 --- a/ui/components/app/assets/nfts/nfts-items/nfts-items.js +++ b/ui/components/app/assets/nfts/nfts-items/nfts-items.js @@ -1,4 +1,4 @@ -import React, { useContext, useEffect } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { useDispatch, useSelector } from 'react-redux'; import { useHistory } from 'react-router-dom'; @@ -22,7 +22,6 @@ import { getIpfsGateway, getSelectedInternalAccount, getCurrentNetwork, - getOpenSeaEnabled, } from '../../../../../selectors'; import { ASSET_ROUTE, @@ -46,6 +45,8 @@ import { MetaMetricsEventCategory, MetaMetricsEventName, } from '../../../../../../shared/constants/metametrics'; +import { isEqualCaseInsensitive } from '../../../../../../shared/modules/string-utils'; +import { CollectionImageComponent } from './collection-image.component'; const width = (isModal) => { const env = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP; @@ -78,7 +79,8 @@ export default function NftsItems({ const currentChain = useSelector(getCurrentNetwork); const t = useI18nContext(); const ipfsGateway = useSelector(getIpfsGateway); - const openSeaEnabled = useSelector(getOpenSeaEnabled); + + const [updatedNfts, setUpdatedNfts] = useState([]); const trackEvent = useContext(MetaMetricsContext); const sendAnalytics = useSelector(getSendAnalyticProperties); @@ -116,39 +118,40 @@ export default function NftsItems({ dispatch, ]); - const history = useHistory(); + const getAssetImageUrlAndUpdate = async (image, nft) => { + const nftImage = await getAssetImageURL(image, ipfsGateway); + const updatedNFt = { + ...nft, + ipfsImageUpdated: nftImage, + }; + return updatedNFt; + }; - const renderCollectionImage = (collectionImage, collectionName) => { - if (collectionImage?.startsWith('ipfs') && !ipfsGateway) { - return ( -
- {collectionName?.[0]?.toUpperCase() ?? null} -
- ); - } - if (!openSeaEnabled && !collectionImage?.startsWith('ipfs')) { - return ( -
- {collectionName?.[0]?.toUpperCase() ?? null} -
- ); - } + useEffect(() => { + const promisesArr = []; + const modifyItems = async () => { + for (const key of collectionsKeys) { + const { nfts } = collections[key]; + for (const singleNft of nfts) { + const { image, imageOriginal } = singleNft; - if (collectionImage) { - return ( - {collectionName} - ); - } - return ( -
- {collectionName?.[0]?.toUpperCase() ?? null} -
- ); - }; + const isImageHosted = + image?.startsWith('https:') || image?.startsWith('http:'); + if (!isImageHosted) { + promisesArr.push( + getAssetImageUrlAndUpdate(imageOriginal ?? image, singleNft), + ); + } + } + } + const settled = await Promise.all(promisesArr); + setUpdatedNfts(settled); + }; + + modifyItems(); + }, []); + + const history = useHistory(); const updateNftDropDownStateKey = (key, isExpanded) => { const newCurrentAccountState = { @@ -198,6 +201,19 @@ export default function NftsItems({ if (!nfts.length) { return null; } + const getSource = (isImageHosted, nft) => { + if (!isImageHosted) { + const found = updatedNfts.find( + (elm) => + elm.tokenId === nft.tokenId && + isEqualCaseInsensitive(elm.address, nft.address), + ); + if (found) { + return found.ipfsImageUpdated; + } + } + return nft.image; + }; const isExpanded = nftsDropdownState[selectedAddress]?.[chainId]?.[key]; return ( @@ -220,7 +236,10 @@ export default function NftsItems({ alignItems={AlignItems.center} className="nfts-items__collection-header" > - {renderCollectionImage(collectionImage, collectionName)} + { const { image, address, tokenId, name, imageOriginal, tokenURI } = nft; - const nftImage = getAssetImageURL( - imageOriginal ?? image, - ipfsGateway, - ); const nftImageAlt = getNftImageAlt(nft); - const isImageHosted = image?.startsWith('https:'); - const nftImageURL = imageOriginal?.startsWith('ipfs') - ? nftImage - : image; + const isImageHosted = + image?.startsWith('https:') || image?.startsWith('http:'); + + const source = getSource(isImageHosted, nft); + const isIpfsURL = ( imageOriginal ?? image ?? @@ -271,9 +287,8 @@ export default function NftsItems({ className="nfts-items__item-wrapper" > -
-
-
-

- Address -

-
-
-
- -

- 0xCcCCc...ccccC -

-
-
-
-
-
-
-

- Account -

-
-
-

- $834.32 -

-

- 0.05 ETH -

-
-
-
-
-`; diff --git a/ui/components/app/confirm/info/index.ts b/ui/components/app/confirm/info/index.ts deleted file mode 100644 index e23e44f519bb..000000000000 --- a/ui/components/app/confirm/info/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { ConfirmInfo } from './info'; diff --git a/ui/components/app/confirm/info/index.tsx b/ui/components/app/confirm/info/index.tsx deleted file mode 100644 index b247e432cc22..000000000000 --- a/ui/components/app/confirm/info/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from './info'; diff --git a/ui/components/app/confirm/info/info.stories.tsx b/ui/components/app/confirm/info/info.stories.tsx deleted file mode 100644 index d23726f39104..000000000000 --- a/ui/components/app/confirm/info/info.stories.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import React from 'react'; -import { ConfirmInfoRow } from './row'; -import { ConfirmInfo, ConfirmInfoRowConfig, ConfirmInfoRowType } from './info'; - -const mockRowConfigs: ConfirmInfoRowConfig[] = [ - { - label: 'Address', - type: ConfirmInfoRowType.Address, - rowProps: { - address: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC', - }, - }, - { - type: ConfirmInfoRowType.Divider, - }, - { - label: 'Origin', - type: ConfirmInfoRowType.UrlType, - rowProps: { - url: 'https://metamask.github.io', - }, - }, - { - label: 'Account', - type: ConfirmInfoRowType.ValueDouble, - rowProps: { - left: '$834.32', - right: '0.05 ETH', - }, - }, -]; - -const ConfirmInfoStory = { - title: 'Components/App/Confirm/Info', - component: ConfirmInfoRow, - - args: { rowConfigs: [...mockRowConfigs] }, - argTypes: { - rowConfigs: { - control: { - type: 'object', - }, - }, - }, -}; - -export const DefaultStory = (args) => ; - -DefaultStory.storyName = 'Default'; - -export default ConfirmInfoStory; diff --git a/ui/components/app/confirm/info/info.test.tsx b/ui/components/app/confirm/info/info.test.tsx deleted file mode 100644 index 113d964fd1f6..000000000000 --- a/ui/components/app/confirm/info/info.test.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import React from 'react'; -import mockState from '../../../../../test/data/mock-state.json'; -import { renderWithProvider } from '../../../../../test/lib/render-helpers'; -import configureStore from '../../../../store/store'; -import { ConfirmInfo, ConfirmInfoRowConfig, ConfirmInfoRowType } from './info'; - -const mockRowConfigs: ConfirmInfoRowConfig[] = [ - { - label: 'Address', - type: ConfirmInfoRowType.Address, - rowProps: { - address: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC', - }, - }, - { - type: ConfirmInfoRowType.Divider, - }, - { - label: 'Account', - type: ConfirmInfoRowType.ValueDouble, - rowProps: { - left: '$834.32', - right: '0.05 ETH', - }, - }, -]; - -describe('ConfirmInfo', () => { - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const render = (storeOverrides: Record = {}) => { - const store = configureStore({ - ...mockState.metamask, - metamask: { ...mockState.metamask }, - ...storeOverrides, - }); - - return renderWithProvider( - , - store, - ); - }; - - it('should match snapshot', () => { - const { container } = render(mockRowConfigs); - expect(container).toMatchSnapshot(); - }); - - it('renders the correct number of rows provided', () => { - const { container } = render(mockRowConfigs); - const numOfDividers = mockRowConfigs.filter( - (rowConfig) => rowConfig.type === ConfirmInfoRowType.Divider, - ).length; - - expect(container.querySelectorAll('.confirm-info-row')).toHaveLength( - mockRowConfigs.length - numOfDividers, - ); - }); -}); diff --git a/ui/components/app/confirm/info/info.tsx b/ui/components/app/confirm/info/info.tsx deleted file mode 100644 index 9edd0a22ec49..000000000000 --- a/ui/components/app/confirm/info/info.tsx +++ /dev/null @@ -1,131 +0,0 @@ -import React from 'react'; - -import { captureException } from '@sentry/browser'; - -import { - BackgroundColor, - BorderRadius, - Display, - FlexDirection, -} from '../../../../helpers/constants/design-system'; -import { Box } from '../../../component-library'; -import { - ConfirmInfoRow, - ConfirmInfoRowAddress, - ConfirmInfoRowAddressProps, - ConfirmInfoRowDivider, - ConfirmInfoRowProps, - ConfirmInfoRowText, - ConfirmInfoRowTextProps, - ConfirmInfoRowUrl, - ConfirmInfoRowUrlProps, - ConfirmInfoRowValueDouble, - ConfirmInfoRowValueDoubleProps, - ConfirmInfoRowVariant, -} from './row'; - -export enum ConfirmInfoRowType { - Address = 'address', - Divider = 'divider', - Text = 'text', - UrlType = 'url', - ValueDouble = 'value-double', -} - -type ConfirmInfoTypeProps = - | ConfirmInfoRowAddressProps - | ConfirmInfoRowTextProps - | ConfirmInfoRowUrlProps - | ConfirmInfoRowValueDoubleProps; - -// TODO: Replace `any` with type -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const TYPE_TO_COMPONENT: Record = { - [ConfirmInfoRowType.Address]: ({ address }: ConfirmInfoRowAddressProps) => { - return ; - }, - [ConfirmInfoRowType.Divider]: () => { - return ; - }, - [ConfirmInfoRowType.Text]: ({ text }: ConfirmInfoRowTextProps) => { - return ; - }, - [ConfirmInfoRowType.UrlType]: ({ url }: ConfirmInfoRowUrlProps) => { - return ; - }, - [ConfirmInfoRowType.ValueDouble]: ({ - left, - right, - }: ConfirmInfoRowValueDoubleProps) => { - return ; - }, -}; - -export type ConfirmInfoRowConfig = { - /** The display label text. This should be required unless it is a 'divider' variant */ - label?: ConfirmInfoRowProps['label']; - - /** Optional, and likely needed, props passed to the row */ - rowProps?: ConfirmInfoTypeProps; - - /** The type of the row e.g. address, divider, value-double */ - type: ConfirmInfoRowType; - - /** Optional row variant */ - variant?: ConfirmInfoRowVariant; -}; - -type ConfirmInfoProps = { - rowConfigs: ConfirmInfoRowConfig[]; -}; - -/** - * ConfirmInfo receives a custom config object and displays a list of ConfirmInfoRow components - * - * @param options - * @param options.rowConfigs - */ -export const ConfirmInfo: React.FC = ({ - rowConfigs = [], -}) => ( - - {rowConfigs.map((rowConfig: ConfirmInfoRowConfig, index) => { - const { label, rowProps, type, variant } = rowConfig; - const component = TYPE_TO_COMPONENT[type]; - - if (!component) { - const error = new Error(`ConfirmInfo: Unknown row type: ${type}`); - console.error(error); - captureException(error); - return null; - } - - if (type === ConfirmInfoRowType.Divider) { - const key = `confirm-info-divider-${rowConfigs - .map(({ label: _label }) => _label) - .concat('-')}-${index}`; - - return ( - - - - ); - } - - const key = `confirm-info-row-${label}-${index}`; - - return ( - - - {component(rowProps)} - - - ); - })} - -); diff --git a/ui/components/app/confirm/info/row/row.tsx b/ui/components/app/confirm/info/row/row.tsx index 6b6470c98017..0dd0b9b110b8 100644 --- a/ui/components/app/confirm/info/row/row.tsx +++ b/ui/components/app/confirm/info/row/row.tsx @@ -128,6 +128,9 @@ export const ConfirmInfoRow: React.FC = ({ marginLeft={1} color={TOOLTIP_ICON_COLORS[variant] as unknown as IconColor} size={IconSize.Sm} + {...(dataTestId + ? { 'data-testid': `${dataTestId}-tooltip` } + : {})} /> )} diff --git a/ui/components/app/confirm/info/row/value-double.tsx b/ui/components/app/confirm/info/row/value-double.tsx index adf7510ba2bd..b58016541c07 100644 --- a/ui/components/app/confirm/info/row/value-double.tsx +++ b/ui/components/app/confirm/info/row/value-double.tsx @@ -33,7 +33,7 @@ export const ConfirmInfoRowValueDouble = ({ flexDirection={FlexDirection.Row} alignItems={AlignItems.center} flexWrap={FlexWrap.Wrap} - gap={2} + gap={1} > {left} {right} diff --git a/ui/components/app/metamask-template-renderer/safe-component-list.js b/ui/components/app/metamask-template-renderer/safe-component-list.js index 40932c2fbb4a..5756c5cbed2b 100644 --- a/ui/components/app/metamask-template-renderer/safe-component-list.js +++ b/ui/components/app/metamask-template-renderer/safe-component-list.js @@ -42,6 +42,7 @@ import { SnapUIRadioGroup } from '../snaps/snap-ui-radio-group'; import { SnapUICheckbox } from '../snaps/snap-ui-checkbox'; import { SnapUITooltip } from '../snaps/snap-ui-tooltip'; import { SnapUICard } from '../snaps/snap-ui-card'; +import { SnapUIAddress } from '../snaps/snap-ui-address'; import { SnapUISelector } from '../snaps/snap-ui-selector'; import { SnapFooterButton } from '../snaps/snap-footer-button'; ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) @@ -104,6 +105,7 @@ export const safeComponentList = { SnapUITooltip, SnapUICard, SnapUISelector, + SnapUIAddress, SnapFooterButton, FormTextField, ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) diff --git a/ui/components/app/modals/new-account-modal/new-account-modal.test.tsx b/ui/components/app/modals/new-account-modal/new-account-modal.test.tsx index 4c3fdf8de3e2..bb078773cd66 100644 --- a/ui/components/app/modals/new-account-modal/new-account-modal.test.tsx +++ b/ui/components/app/modals/new-account-modal/new-account-modal.test.tsx @@ -79,7 +79,7 @@ describe('NewAccountModal', () => { await waitFor(() => { expect(mockSubmitRequestToBackground).toHaveBeenNthCalledWith( 2, - 'getState', + 'getStatePatches', undefined, ); }); diff --git a/ui/components/app/snaps/snap-footer-button/snap-footer-button.tsx b/ui/components/app/snaps/snap-footer-button/snap-footer-button.tsx index 04f84b64f23c..e2b8c9609714 100644 --- a/ui/components/app/snaps/snap-footer-button/snap-footer-button.tsx +++ b/ui/components/app/snaps/snap-footer-button/snap-footer-button.tsx @@ -1,6 +1,16 @@ import React, { FunctionComponent, MouseEvent as ReactMouseEvent } from 'react'; -import { ButtonVariant, UserInputEventType } from '@metamask/snaps-sdk'; -import { Button, ButtonSize, IconSize } from '../../../component-library'; +import { + ButtonType, + ButtonVariant, + UserInputEventType, +} from '@metamask/snaps-sdk'; +import { useSelector } from 'react-redux'; +import { + Button, + ButtonLinkProps, + ButtonSize, + IconSize, +} from '../../../component-library'; import { AlignItems, Display, @@ -8,6 +18,7 @@ import { } from '../../../../helpers/constants/design-system'; import { useSnapInterfaceContext } from '../../../../contexts/snaps'; import { SnapIcon } from '../snap-icon'; +import { getHideSnapBranding } from '../../../../selectors'; type SnapFooterButtonProps = { name?: string; @@ -15,17 +26,26 @@ type SnapFooterButtonProps = { onCancel?: () => void; }; -export const SnapFooterButton: FunctionComponent = ({ +export const SnapFooterButton: FunctionComponent< + SnapFooterButtonProps & ButtonLinkProps<'button'> +> = ({ onCancel, name, children, isSnapAction = false, + type, + form, ...props }) => { const { handleEvent, snapId } = useSnapInterfaceContext(); + const hideSnapBranding = useSelector((state) => + getHideSnapBranding(state, snapId), + ); const handleSnapAction = (event: ReactMouseEvent) => { - event.preventDefault(); + if (type === ButtonType.Button) { + event.preventDefault(); + } handleEvent({ event: UserInputEventType.ButtonClickEvent, @@ -38,6 +58,8 @@ export const SnapFooterButton: FunctionComponent = ({ return (
renders component for approve request 1`] = ` >
@@ -214,6 +217,7 @@ exports[` renders component for approve request 1`] = ` >
@@ -254,6 +258,7 @@ exports[` renders component for approve request 1`] = ` >
@@ -320,6 +325,7 @@ exports[` renders component for approve request 1`] = `
renders component for approve request 1`] = ` />
renders component for approve request 1`] = ` >
@@ -430,6 +438,7 @@ exports[` renders component for approve request 1`] = ` >
@@ -442,13 +451,13 @@ exports[` renders component for approve request 1`] = ` class="mm-box mm-text mm-text--body-md mm-box--margin-right-1 mm-box--color-text-default" data-testid="first-gas-field" > - 0.004 ETH + 0.0001 ETH

- $2.20 + $0.04

@@ -540,12 +550,12 @@ exports[` renders component for approve request 1`] = `

- 0.1094 ETH + 0.0011 ETH

- $60.83 + $0.60

@@ -674,6 +684,7 @@ exports[` renders component for approve request 1`] = ` > @@ -762,6 +773,7 @@ exports[` renders component for approve request 1`] = ` > diff --git a/ui/pages/confirmations/components/confirm/info/approve/approve-details/__snapshots__/approve-details.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/approve/approve-details/__snapshots__/approve-details.test.tsx.snap index c31eb7dcfbd0..5491908cdffd 100644 --- a/ui/pages/confirmations/components/confirm/info/approve/approve-details/__snapshots__/approve-details.test.tsx.snap +++ b/ui/pages/confirmations/components/confirm/info/approve/approve-details/__snapshots__/approve-details.test.tsx.snap @@ -4,6 +4,7 @@ exports[` renders component for approve details 1`] = `
{ return ( <> - + @@ -50,7 +54,7 @@ export const ApproveDetails = () => { ); return ( - + {showAdvancedDetails && ( diff --git a/ui/pages/confirmations/components/confirm/info/approve/spending-cap/__snapshots__/spending-cap.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/approve/spending-cap/__snapshots__/spending-cap.test.tsx.snap index d249b4ba843b..dafe44df8e70 100644 --- a/ui/pages/confirmations/components/confirm/info/approve/spending-cap/__snapshots__/spending-cap.test.tsx.snap +++ b/ui/pages/confirmations/components/confirm/info/approve/spending-cap/__snapshots__/spending-cap.test.tsx.snap @@ -4,6 +4,7 @@ exports[` renders component 1`] = `
renders component 1`] = ` />
renders component 1`] = ` >
diff --git a/ui/pages/confirmations/components/confirm/info/approve/spending-cap/spending-cap.tsx b/ui/pages/confirmations/components/confirm/info/approve/spending-cap/spending-cap.tsx index 73f0ef773fa0..2ebd9d8e7e4e 100644 --- a/ui/pages/confirmations/components/confirm/info/approve/spending-cap/spending-cap.tsx +++ b/ui/pages/confirmations/components/confirm/info/approve/spending-cap/spending-cap.tsx @@ -62,6 +62,7 @@ const SpendingCapGroup = ({ {spendingCap === SPENDING_CAP_UNLIMITED_MSG ? ( {SpendingCapElement} @@ -105,7 +106,7 @@ export const SpendingCap = ({ } return ( - + diff --git a/ui/pages/confirmations/components/confirm/info/base-transaction-info/__snapshots__/base-transaction-info.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/base-transaction-info/__snapshots__/base-transaction-info.test.tsx.snap index de72d2c1cfac..127e5a8311f7 100644 --- a/ui/pages/confirmations/components/confirm/info/base-transaction-info/__snapshots__/base-transaction-info.test.tsx.snap +++ b/ui/pages/confirmations/components/confirm/info/base-transaction-info/__snapshots__/base-transaction-info.test.tsx.snap @@ -113,6 +113,7 @@ exports[` renders component for contract interaction requ >
@@ -153,6 +154,7 @@ exports[` renders component for contract interaction requ >
@@ -246,6 +248,7 @@ exports[` renders component for contract interaction requ >
@@ -258,13 +261,13 @@ exports[` renders component for contract interaction requ class="mm-box mm-text mm-text--body-md mm-box--margin-right-1 mm-box--color-text-default" data-testid="first-gas-field" > - 0.004 ETH + 0.0001 ETH

- $2.20 + $0.04

@@ -513,6 +517,7 @@ exports[` renders component for contract interaction requ >
@@ -606,6 +611,7 @@ exports[` renders component for contract interaction requ >
@@ -618,13 +624,13 @@ exports[` renders component for contract interaction requ class="mm-box mm-text mm-text--body-md mm-box--margin-right-1 mm-box--color-text-default" data-testid="first-gas-field" > - 0.004 ETH + 0.0001 ETH

- $2.20 + $0.04

@@ -870,6 +877,7 @@ exports[` renders component for contract interaction requ > @@ -963,6 +971,7 @@ exports[` renders component for contract interaction requ > @@ -975,13 +984,13 @@ exports[` renders component for contract interaction requ class="mm-box mm-text mm-text--body-md mm-box--margin-right-1 mm-box--color-text-default" data-testid="first-gas-field" > - 0.004 ETH + 0.0001 ETH

- $2.20 + $0.04

)} - {isSnapCustomUIDialog && ( + {isSnapCustomUIDialog && !hideSnapBranding && ( ({ + currentConfirmation, + isScrollToBottomCompleted, + setIsScrollToBottomCompleted, + }), + [ + currentConfirmation, + isScrollToBottomCompleted, + setIsScrollToBottomCompleted, + ], + ); + return ( - - {children} - + {children} ); }; diff --git a/ui/pages/confirmations/hooks/useConfirmationAlertMetrics.ts b/ui/pages/confirmations/hooks/useConfirmationAlertMetrics.ts index 9bb3238b0232..c9af8a9d03ad 100644 --- a/ui/pages/confirmations/hooks/useConfirmationAlertMetrics.ts +++ b/ui/pages/confirmations/hooks/useConfirmationAlertMetrics.ts @@ -2,13 +2,11 @@ import { useCallback, useEffect, useState } from 'react'; import { validate as isUuid } from 'uuid'; import useAlerts from '../../../hooks/useAlerts'; -import { updateEventFragment } from '../../../store/actions'; -import { SignatureRequestType } from '../types/confirm'; import { isSignatureTransactionType } from '../utils'; import { Alert } from '../../../ducks/confirm-alerts/confirm-alerts'; import { useConfirmContext } from '../context/confirm'; -import { generateSignatureUniqueId } from '../../../helpers/utils/metrics'; import { AlertsName } from './alerts/constants'; +import { useSignatureEventFragment } from './useSignatureEventFragment'; import { useTransactionEventFragment } from './useTransactionEventFragment'; export type AlertMetricsProperties = { @@ -48,6 +46,7 @@ export function useConfirmationAlertMetrics() { const { currentConfirmation } = useConfirmContext(); const ownerId = currentConfirmation?.id ?? ''; const { alerts, isAlertConfirmed } = useAlerts(ownerId); + const { updateSignatureEventFragment } = useSignatureEventFragment(); const { updateTransactionEventFragment } = useTransactionEventFragment(); const [metricsProperties, setMetricsProperties] = @@ -116,12 +115,7 @@ export function useConfirmationAlertMetrics() { } if (isSignatureTransactionType(currentConfirmation)) { - const requestId = (currentConfirmation as SignatureRequestType).msgParams - ?.requestId as number; - const fragmentUniqueId = generateSignatureUniqueId(requestId); - updateEventFragment(fragmentUniqueId, { - properties, - }); + updateSignatureEventFragment({ properties }); } else { updateTransactionEventFragment({ properties }, ownerId); } diff --git a/ui/pages/confirmations/hooks/useSignatureEventFragment.test.tsx b/ui/pages/confirmations/hooks/useSignatureEventFragment.test.tsx new file mode 100644 index 000000000000..4da597c72937 --- /dev/null +++ b/ui/pages/confirmations/hooks/useSignatureEventFragment.test.tsx @@ -0,0 +1,67 @@ +import { getMockTypedSignConfirmStateForRequest } from '../../../../test/data/confirmations/helper'; +import { renderHookWithConfirmContextProvider } from '../../../../test/lib/confirmations/render-helpers'; +import { orderSignatureMsg } from '../../../../test/data/confirmations/typed_sign'; +import { generateSignatureUniqueId } from '../../../helpers/utils/metrics'; +import { updateEventFragment } from '../../../store/actions'; +import { SignatureRequestType } from '../types/confirm'; +import { useSignatureEventFragment } from './useSignatureEventFragment'; + +const renderUseSignatureEventFragment = (signature: SignatureRequestType) => { + const mockState = getMockTypedSignConfirmStateForRequest(signature); + + return renderHookWithConfirmContextProvider( + () => useSignatureEventFragment(), + mockState, + ); +}; + +jest.mock('../../../store/actions', () => ({ + updateEventFragment: jest.fn(), +})); + +describe('useSignatureEventFragment', () => { + afterEach(jest.clearAllMocks); + + describe('updateSignatureEventFragment', () => { + it('should call updateEventFragment to update the signature event fragment', () => { + const mockUpdateProps = { + event_name1: 'test_event 1', + event_name2: 'test_event 2', + }; + const expectedFragmentId = generateSignatureUniqueId( + orderSignatureMsg.msgParams.requestId, + ); + + const { result } = renderUseSignatureEventFragment(orderSignatureMsg); + const { updateSignatureEventFragment } = result.current; + + updateSignatureEventFragment(mockUpdateProps); + + expect(updateEventFragment).toHaveBeenCalledWith( + expectedFragmentId, + mockUpdateProps, + ); + }); + + it('should not call updateEventFragment if no signature requestId was found', () => { + const mockSignatureWithoutRequestId = { + ...orderSignatureMsg, + msgParams: { + data: orderSignatureMsg.msgParams.data, + from: orderSignatureMsg.msgParams.from, + version: orderSignatureMsg.msgParams.version, + signatureMethod: orderSignatureMsg.msgParams.signatureMethod, + origin: orderSignatureMsg.msgParams.origin, + }, + }; + const { result } = renderUseSignatureEventFragment( + mockSignatureWithoutRequestId, + ); + const { updateSignatureEventFragment } = result.current; + + updateSignatureEventFragment(); + + expect(updateEventFragment).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/ui/pages/confirmations/hooks/useSignatureEventFragment.ts b/ui/pages/confirmations/hooks/useSignatureEventFragment.ts new file mode 100644 index 000000000000..82fa8f452641 --- /dev/null +++ b/ui/pages/confirmations/hooks/useSignatureEventFragment.ts @@ -0,0 +1,36 @@ +import { useCallback } from 'react'; +import { generateSignatureUniqueId } from '../../../helpers/utils/metrics'; +import { updateEventFragment } from '../../../store/actions'; +import { useConfirmContext } from '../context/confirm'; +import { SignatureRequestType } from '../types/confirm'; +import { isSignatureTransactionType } from '../utils'; + +import type { MetaMetricsEventFragment } from '../../../../shared/constants/metametrics'; + +/** + * When a signature has been requested, there should be an event fragment created for it in + * {@see {@link app/scripts/lib/createRPCMethodTrackingMiddleware.js}. + * This hook method is used to update an existing signature event fragment for a signature confirmation. + */ +export const useSignatureEventFragment = () => { + const { currentConfirmation } = useConfirmContext(); + + const requestId = + isSignatureTransactionType(currentConfirmation) && + ((currentConfirmation as SignatureRequestType)?.msgParams + ?.requestId as number); + const fragmentId = requestId ? generateSignatureUniqueId(requestId) : null; + + const updateSignatureEventFragment = useCallback( + async (fragmentPayload: Partial) => { + if (!fragmentId) { + return; + } + + updateEventFragment(fragmentId, fragmentPayload); + }, + [fragmentId], + ); + + return { updateSignatureEventFragment }; +}; diff --git a/ui/pages/confirmations/send/send-content/add-recipient/domain-input.component.js b/ui/pages/confirmations/send/send-content/add-recipient/domain-input.component.js index 5eef93681a3c..0b2514f12414 100644 --- a/ui/pages/confirmations/send/send-content/add-recipient/domain-input.component.js +++ b/ui/pages/confirmations/send/send-content/add-recipient/domain-input.component.js @@ -4,11 +4,7 @@ import classnames from 'classnames'; import { isHexString } from '@metamask/utils'; import { addHexPrefix } from '../../../../../../app/scripts/lib/util'; -import { - IS_FLASK, - isValidDomainName, - shortenAddress, -} from '../../../../../helpers/utils/util'; +import { shortenAddress } from '../../../../../helpers/utils/util'; import { isBurnAddress, isValidHexAddress, @@ -87,9 +83,7 @@ export default class DomainInput extends Component { return null; } - if ((IS_FLASK && !isHexString(input)) || isValidDomainName(input)) { - lookupDomainName(input); - } else { + if (isHexString(input)) { resetDomainResolution(); if ( onValidAddressTyped && @@ -98,6 +92,8 @@ export default class DomainInput extends Component { ) { onValidAddressTyped(addHexPrefix(input)); } + } else { + lookupDomainName(input); } return null; @@ -167,11 +163,7 @@ export default class DomainInput extends Component { className="ens-input__wrapper__input" type="text" dir="auto" - placeholder={ - IS_FLASK - ? t('recipientAddressPlaceholderFlask') - : t('recipientAddressPlaceholder') - } + placeholder={t('recipientAddressPlaceholderNew')} onChange={this.onChange} onPaste={this.onPaste} spellCheck="false" diff --git a/ui/pages/confirmations/send/send.constants.js b/ui/pages/confirmations/send/send.constants.js index b13fd3e8e4e4..acf129412135 100644 --- a/ui/pages/confirmations/send/send.constants.js +++ b/ui/pages/confirmations/send/send.constants.js @@ -32,18 +32,11 @@ const NEGATIVE_ETH_ERROR = 'negativeETH'; const NEGATIVE_OR_ZERO_AMOUNT_TOKENS_ERROR = 'negativeOrZeroAmountToken'; const FLOAT_TOKENS_ERROR = 'floatAmountToken'; const INVALID_RECIPIENT_ADDRESS_ERROR = 'invalidAddressRecipient'; -const INVALID_RECIPIENT_ADDRESS_NOT_ETH_NETWORK_ERROR = - 'invalidAddressRecipientNotEthNetwork'; const REQUIRED_ERROR = 'required'; const KNOWN_RECIPIENT_ADDRESS_WARNING = 'knownAddressRecipient'; const CONTRACT_ADDRESS_ERROR = 'contractAddressError'; const CONFUSING_ENS_ERROR = 'confusingEnsDomain'; -const ENS_NO_ADDRESS_FOR_NAME = 'noAddressForName'; -const ENS_NOT_FOUND_ON_NETWORK = 'ensNotFoundOnCurrentNetwork'; -const ENS_ILLEGAL_CHARACTER = 'ensIllegalCharacter'; const ENS_UNKNOWN_ERROR = 'ensUnknownError'; -const ENS_REGISTRATION_ERROR = 'ensRegistrationError'; -const DOMAIN_NOT_SUPPORTED_ON_NETWORK = 'domainNotSupportedOnNetwork'; const NO_RESOLUTION_FOR_DOMAIN = 'noDomainResolution'; const SWAPS_NO_QUOTES = 'swapQuotesNotAvailableErrorTitle'; const SWAPS_QUOTES_ERROR = 'swapFetchingQuotesErrorTitle'; @@ -62,12 +55,7 @@ export { INVALID_RECIPIENT_ADDRESS_ERROR, KNOWN_RECIPIENT_ADDRESS_WARNING, CONTRACT_ADDRESS_ERROR, - INVALID_RECIPIENT_ADDRESS_NOT_ETH_NETWORK_ERROR, - ENS_NO_ADDRESS_FOR_NAME, - ENS_NOT_FOUND_ON_NETWORK, - ENS_ILLEGAL_CHARACTER, ENS_UNKNOWN_ERROR, - ENS_REGISTRATION_ERROR, MIN_GAS_LIMIT_DEC, MIN_GAS_PRICE_DEC, MIN_GAS_PRICE_GWEI, @@ -83,7 +71,6 @@ export { NFT_TRANSFER_FROM_FUNCTION_SIGNATURE, NFT_SAFE_TRANSFER_FROM_FUNCTION_SIGNATURE, RECIPIENT_TYPES, - DOMAIN_NOT_SUPPORTED_ON_NETWORK, SWAPS_NO_QUOTES, SWAPS_QUOTES_ERROR, }; diff --git a/ui/pages/confirmations/utils/token.test.ts b/ui/pages/confirmations/utils/token.test.ts new file mode 100644 index 000000000000..e71813713d79 --- /dev/null +++ b/ui/pages/confirmations/utils/token.test.ts @@ -0,0 +1,50 @@ +import { getTokenStandardAndDetails } from '../../../store/actions'; +import { ERC20_DEFAULT_DECIMALS } from '../constants/token'; +import { fetchErc20Decimals } from './token'; + +const MOCK_ADDRESS = '0x514910771af9ca656af840dff83e8264ecf986ca'; +const MOCK_DECIMALS = 36; + +jest.mock('../../../store/actions', () => ({ + getTokenStandardAndDetails: jest.fn(), +})); + +describe('fetchErc20Decimals', () => { + afterEach(() => { + jest.clearAllMocks(); + + /** Reset memoized function using getTokenStandardAndDetails for each test */ + fetchErc20Decimals?.cache?.clear?.(); + }); + + it(`should return the default number, ${ERC20_DEFAULT_DECIMALS}, if no decimals were found from details`, async () => { + (getTokenStandardAndDetails as jest.Mock).mockResolvedValue({}); + const decimals = await fetchErc20Decimals(MOCK_ADDRESS); + + expect(decimals).toBe(ERC20_DEFAULT_DECIMALS); + }); + + it('should return the decimals for a given token address', async () => { + (getTokenStandardAndDetails as jest.Mock).mockResolvedValue({ + decimals: MOCK_DECIMALS, + }); + const decimals = await fetchErc20Decimals(MOCK_ADDRESS); + + expect(decimals).toBe(MOCK_DECIMALS); + }); + + it('should memoize the result for the same token addresses', async () => { + (getTokenStandardAndDetails as jest.Mock).mockResolvedValue({ + decimals: MOCK_DECIMALS, + }); + + const firstCallResult = await fetchErc20Decimals(MOCK_ADDRESS); + const secondCallResult = await fetchErc20Decimals(MOCK_ADDRESS); + + expect(firstCallResult).toBe(secondCallResult); + expect(getTokenStandardAndDetails).toHaveBeenCalledTimes(1); + + await fetchErc20Decimals('0xDifferentAddress'); + expect(getTokenStandardAndDetails).toHaveBeenCalledTimes(2); + }); +}); diff --git a/ui/pages/confirmations/utils/token.ts b/ui/pages/confirmations/utils/token.ts new file mode 100644 index 000000000000..1f94280129a9 --- /dev/null +++ b/ui/pages/confirmations/utils/token.ts @@ -0,0 +1,32 @@ +import { memoize } from 'lodash'; +import { Hex } from '@metamask/utils'; +import { getTokenStandardAndDetails } from '../../../store/actions'; + +export const ERC20_DEFAULT_DECIMALS = 18; + +/** + * Fetches the decimals for the given token address. + * + * @param {Hex | string} address - The ethereum token contract address. It is expected to be in hex format. + * We currently accept strings since we have a patch that accepts a custom string + * {@see .yarn/patches/@metamask-eth-json-rpc-middleware-npm-14.0.1-b6c2ccbe8c.patch} + */ +export const fetchErc20Decimals = memoize( + async (address: Hex | string): Promise => { + try { + const { decimals: decStr } = await getTokenStandardAndDetails(address); + if (!decStr) { + return ERC20_DEFAULT_DECIMALS; + } + for (const radix of [10, 16]) { + const parsedDec = parseInt(decStr, radix); + if (isFinite(parsedDec)) { + return parsedDec; + } + } + return ERC20_DEFAULT_DECIMALS; + } catch { + return ERC20_DEFAULT_DECIMALS; + } + }, +); diff --git a/ui/pages/home/home.component.js b/ui/pages/home/home.component.js index 1c746869ad10..19b76a881c6c 100644 --- a/ui/pages/home/home.component.js +++ b/ui/pages/home/home.component.js @@ -13,7 +13,7 @@ import TermsOfUsePopup from '../../components/app/terms-of-use-popup'; import RecoveryPhraseReminder from '../../components/app/recovery-phrase-reminder'; import WhatsNewPopup from '../../components/app/whats-new-popup'; import { FirstTimeFlowType } from '../../../shared/constants/onboarding'; -import SmartTransactionsOptInModal from '../../components/app/smart-transactions/smart-transactions-opt-in-modal'; +import SmartTransactionsOptInModal from '../smart-transactions/components/smart-transactions-opt-in-modal'; ///: END:ONLY_INCLUDE_IF import HomeNotification from '../../components/app/home-notification'; import MultipleNotifications from '../../components/app/multiple-notifications'; diff --git a/ui/pages/onboarding-flow/pin-extension/pin-extension.js b/ui/pages/onboarding-flow/pin-extension/pin-extension.js index ab7fbd2d66bb..216bb1416cdf 100644 --- a/ui/pages/onboarding-flow/pin-extension/pin-extension.js +++ b/ui/pages/onboarding-flow/pin-extension/pin-extension.js @@ -1,12 +1,11 @@ import React, { ///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask) useState, - useContext, ///: END:ONLY_INCLUDE_IF } from 'react'; import { useHistory } from 'react-router-dom'; ///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask) -import { useDispatch, useSelector } from 'react-redux'; +import { useDispatch } from 'react-redux'; import { Carousel } from 'react-responsive-carousel'; import { setCompletedOnboarding } from '../../../store/actions'; ///: END:ONLY_INCLUDE_IF @@ -31,13 +30,6 @@ import OnboardingPinMmiBillboard from '../../institutional/pin-mmi-billboard/pin ///: END:ONLY_INCLUDE_IF import { Text } from '../../../components/component-library'; ///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask) -import { MetaMetricsContext } from '../../../contexts/metametrics'; -import { getFirstTimeFlowType } from '../../../selectors'; -import { - MetaMetricsEventCategory, - MetaMetricsEventName, -} from '../../../../shared/constants/metametrics'; -import { FirstTimeFlowType } from '../../../../shared/constants/onboarding'; import OnboardingPinBillboard from './pin-billboard'; ///: END:ONLY_INCLUDE_IF @@ -47,8 +39,6 @@ export default function OnboardingPinExtension() { ///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask) const [selectedIndex, setSelectedIndex] = useState(0); const dispatch = useDispatch(); - const trackEvent = useContext(MetaMetricsContext); - const firstTimeFlowType = useSelector(getFirstTimeFlowType); ///: END:ONLY_INCLUDE_IF ///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask) @@ -57,15 +47,6 @@ export default function OnboardingPinExtension() { setSelectedIndex(1); } else { await dispatch(setCompletedOnboarding()); - trackEvent({ - category: MetaMetricsEventCategory.Onboarding, - event: MetaMetricsEventName.OnboardingWalletSetupComplete, - properties: { - wallet_setup_type: - firstTimeFlowType === FirstTimeFlowType.import ? 'import' : 'new', - new_wallet: firstTimeFlowType === FirstTimeFlowType.create, - }, - }); history.push(DEFAULT_ROUTE); } }; diff --git a/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js b/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js index 3012fe9808f2..9f1bb0dcf8c3 100644 --- a/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js +++ b/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js @@ -277,10 +277,11 @@ export default function PrivacySettings() { category: MetaMetricsEventCategory.Onboarding, event: MetaMetricsEventName.SettingsUpdated, properties: { - settings_group: 'advanced', + settings_group: 'onboarding_advanced_configuration', settings_type: 'basic_functionality', old_value: false, new_value: true, + was_profile_syncing_on: false, }, }); } diff --git a/ui/pages/pages.scss b/ui/pages/pages.scss index 01641f29774a..2578286032d2 100644 --- a/ui/pages/pages.scss +++ b/ui/pages/pages.scss @@ -22,10 +22,10 @@ @import 'onboarding-flow/index'; @import 'permissions-connect/index'; @import 'settings/index'; +@import 'smart-transactions/index'; @import 'snaps/snaps-list/index'; @import 'snaps/snap-view/index'; @import 'create-snap-account/index'; -@import 'smart-transactions/smart-transaction-status-page/index'; @import 'remove-snap-account/index'; @import 'swaps/index'; @import 'token-details/index'; diff --git a/ui/pages/settings/contact-list-tab/add-contact/add-contact.component.js b/ui/pages/settings/contact-list-tab/add-contact/add-contact.component.js index e2a0586fddcf..76f706bb8320 100644 --- a/ui/pages/settings/contact-list-tab/add-contact/add-contact.component.js +++ b/ui/pages/settings/contact-list-tab/add-contact/add-contact.component.js @@ -149,9 +149,6 @@ export default class AddContact extends PureComponent { return ( { diff --git a/ui/pages/settings/settings-tab/settings-tab.component.js b/ui/pages/settings/settings-tab/settings-tab.component.js index 45407ece008d..d798b62f77ba 100644 --- a/ui/pages/settings/settings-tab/settings-tab.component.js +++ b/ui/pages/settings/settings-tab/settings-tab.component.js @@ -119,7 +119,16 @@ export default class SettingsTab extends PureComponent { id="select-currency" options={currencyOptions} selectedOption={currentCurrency} - onChange={(newCurrency) => setCurrentCurrency(newCurrency)} + onChange={(newCurrency) => { + setCurrentCurrency(newCurrency); + this.context.trackEvent({ + category: MetaMetricsEventCategory.Settings, + event: MetaMetricsEventName.CurrentCurrency, + properties: { + current_currency: newCurrency, + }, + }); + }} /> diff --git a/ui/components/app/smart-transactions/__snapshots__/smart-transactions-opt-in-modal.test.tsx.snap b/ui/pages/smart-transactions/components/__snapshots__/smart-transactions-opt-in-modal.test.tsx.snap similarity index 100% rename from ui/components/app/smart-transactions/__snapshots__/smart-transactions-opt-in-modal.test.tsx.snap rename to ui/pages/smart-transactions/components/__snapshots__/smart-transactions-opt-in-modal.test.tsx.snap diff --git a/ui/components/app/smart-transactions/index.scss b/ui/pages/smart-transactions/components/index.scss similarity index 100% rename from ui/components/app/smart-transactions/index.scss rename to ui/pages/smart-transactions/components/index.scss diff --git a/ui/components/app/smart-transactions/smart-transactions-opt-in-modal.test.tsx b/ui/pages/smart-transactions/components/smart-transactions-opt-in-modal.test.tsx similarity index 100% rename from ui/components/app/smart-transactions/smart-transactions-opt-in-modal.test.tsx rename to ui/pages/smart-transactions/components/smart-transactions-opt-in-modal.test.tsx diff --git a/ui/components/app/smart-transactions/smart-transactions-opt-in-modal.tsx b/ui/pages/smart-transactions/components/smart-transactions-opt-in-modal.tsx similarity index 99% rename from ui/components/app/smart-transactions/smart-transactions-opt-in-modal.tsx rename to ui/pages/smart-transactions/components/smart-transactions-opt-in-modal.tsx index 5b8ff09f9237..78055de42831 100644 --- a/ui/components/app/smart-transactions/smart-transactions-opt-in-modal.tsx +++ b/ui/pages/smart-transactions/components/smart-transactions-opt-in-modal.tsx @@ -27,7 +27,7 @@ import { ButtonLinkSize, Icon, IconName, -} from '../../component-library'; +} from '../../../components/component-library'; import { setSmartTransactionsOptInStatus } from '../../../store/actions'; import { SMART_TRANSACTIONS_LEARN_MORE_URL } from '../../../../shared/constants/smartTransactions'; diff --git a/ui/pages/smart-transactions/index.scss b/ui/pages/smart-transactions/index.scss new file mode 100644 index 000000000000..8ef1b35cd611 --- /dev/null +++ b/ui/pages/smart-transactions/index.scss @@ -0,0 +1,2 @@ +@import './smart-transaction-status-page/index'; +@import './components/index'; diff --git a/ui/pages/snaps/snap-view/snap-view.js b/ui/pages/snaps/snap-view/snap-view.js index 5ef406fe9123..3cc5cd999047 100644 --- a/ui/pages/snaps/snap-view/snap-view.js +++ b/ui/pages/snaps/snap-view/snap-view.js @@ -99,19 +99,21 @@ function SnapView() { }} > - - } - > + {!snap.hideSnapBranding && ( + + } + /> + )} { + return installedSnaps[snapId]?.hideSnapBranding; + }, +); + /** * Get a memoized version of the target subject metadata. */ @@ -1262,7 +1272,7 @@ export function getKnownMethodData(state, data) { const fourBytePrefix = prefixedData.slice(0, 10); const { knownMethodData, use4ByteResolution } = state.metamask; // If 4byte setting is off, we do not want to return the knownMethodData - return use4ByteResolution ? knownMethodData?.[fourBytePrefix] : undefined; + return use4ByteResolution ? knownMethodData?.[fourBytePrefix] ?? {} : {}; } export function getFeatureFlags(state) { diff --git a/ui/selectors/transactions.js b/ui/selectors/transactions.js index 5e1303ef2e57..2c5fb8fe4b98 100644 --- a/ui/selectors/transactions.js +++ b/ui/selectors/transactions.js @@ -45,7 +45,7 @@ export const getTransactions = createDeepEqualSelector( return []; } - return transactions.sort((a, b) => a.time - b.time); // Ascending + return [...transactions].sort((a, b) => a.time - b.time); // Ascending }, (transactions) => transactions, ); @@ -84,7 +84,10 @@ export const getAllUnapprovedTransactions = createDeepEqualSelector( return []; } - const sortedTransactions = transactions.sort((a, b) => a.time - b.time); + const sortedTransactions = [...transactions].sort( + (a, b) => a.time - b.time, + ); + return filterAndShapeUnapprovedTransactions(sortedTransactions); }, (transactions) => transactions, @@ -220,7 +223,7 @@ export const transactionsSelector = createSelector( (subSelectorTxList = [], selectedAddressTxList = []) => { const txsToRender = selectedAddressTxList.concat(subSelectorTxList); - return txsToRender.sort((a, b) => b.time - a.time); + return [...txsToRender].sort((a, b) => b.time - a.time); }, ); diff --git a/ui/store/actions.test.js b/ui/store/actions.test.js index 543390be7d15..213fa3fcf6c8 100644 --- a/ui/store/actions.test.js +++ b/ui/store/actions.test.js @@ -51,8 +51,6 @@ const defaultState = { }; const mockStore = (state = defaultState) => configureStore(middleware)(state); -const baseMockState = defaultState.metamask; - describe('Actions', () => { let background; @@ -60,7 +58,7 @@ describe('Actions', () => { beforeEach(async () => { background = sinon.createStubInstance(MetaMaskController, { - getState: sinon.stub().callsFake((cb) => cb(null, baseMockState)), + getState: sinon.stub().callsFake((cb) => cb(null, [])), }); background.signMessage = sinon.stub(); @@ -68,6 +66,7 @@ describe('Actions', () => { background.signTypedMessage = sinon.stub(); background.abortTransactionSigning = sinon.stub(); background.toggleExternalServices = sinon.stub(); + background.getStatePatches = sinon.stub().callsFake((cb) => cb(null, [])); }); describe('#tryUnlockMetamask', () => { @@ -88,10 +87,6 @@ describe('Actions', () => { { type: 'SHOW_LOADING_INDICATION', payload: undefined }, { type: 'UNLOCK_IN_PROGRESS' }, { type: 'UNLOCK_SUCCEEDED', value: undefined }, - { - type: 'UPDATE_METAMASK_STATE', - value: baseMockState, - }, { type: 'HIDE_LOADING_INDICATION' }, ]; @@ -155,10 +150,6 @@ describe('Actions', () => { const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', payload: undefined }, - { - type: 'UPDATE_METAMASK_STATE', - value: baseMockState, - }, { type: 'SHOW_ACCOUNTS_PAGE' }, { type: 'HIDE_LOADING_INDICATION' }, ]; @@ -246,46 +237,12 @@ describe('Actions', () => { it('calls removeAccount in background and expect actions to show account', async () => { const store = mockStore(); - background.getState.callsFake((cb) => - cb(null, { - ...mockNetworkState({ chainId: CHAIN_IDS.MAINNET }), - currentLocale: 'test', - accounts: { - '0xAnotherAddress': { - balance: '0x0', - }, - }, - internalAccounts: { - accounts: { - '22497cc9-e791-42b8-adef-2f13ef216b86': { - address: '0xAnotherAddress', - id: '22497cc9-e791-42b8-adef-2f13ef216b86', - metadata: { - name: 'Test Account 2', - keyring: { - type: 'HD Key Tree', - }, - }, - options: {}, - methods: ETH_EOA_METHODS, - type: EthAccountType.Eoa, - }, - }, - selectedAccount: '22497cc9-e791-42b8-adef-2f13ef216b86', - }, - }), - ); - const removeAccount = background.removeAccount.callsFake((_, cb) => cb()); setBackgroundConnection(background); const expectedActions = [ 'SHOW_LOADING_INDICATION', - 'SELECTED_ADDRESS_CHANGED', - 'ACCOUNT_CHANGED', - 'SELECTED_ACCOUNT_CHANGED', - 'UPDATE_METAMASK_STATE', 'HIDE_LOADING_INDICATION', 'SHOW_ACCOUNTS_PAGE', ]; @@ -702,7 +659,7 @@ describe('Actions', () => { background.getApi.returns({ updateTransaction: updateTransactionStub, - getState: sinon.stub().callsFake((cb) => cb(null, baseMockState)), + getStatePatches: sinon.stub().callsFake((cb) => cb(null, [])), }); setBackgroundConnection(background.getApi()); @@ -725,11 +682,7 @@ describe('Actions', () => { updateTransaction: (_, callback) => { callback(new Error('error')); }, - getState: sinon.stub().callsFake((cb) => - cb(null, { - currentLocale: 'test', - }), - ), + getStatePatches: sinon.stub().callsFake((cb) => cb(null, [])), }); setBackgroundConnection(background.getApi()); @@ -916,7 +869,7 @@ describe('Actions', () => { background.getApi.returns({ addToken: addTokenStub, - getState: sinon.stub().callsFake((cb) => cb(null, baseMockState)), + getStatePatches: sinon.stub().callsFake((cb) => cb(null, [])), }); setBackgroundConnection(background.getApi()); @@ -947,17 +900,13 @@ describe('Actions', () => { background.getApi.returns({ addToken: addTokenStub, - getState: sinon.stub().callsFake((cb) => cb(null, baseMockState)), + getStatePatches: sinon.stub().callsFake((cb) => cb(null, [])), }); setBackgroundConnection(background.getApi()); const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', payload: undefined }, - { - type: 'UPDATE_METAMASK_STATE', - value: baseMockState, - }, { type: 'HIDE_LOADING_INDICATION' }, ]; @@ -986,7 +935,7 @@ describe('Actions', () => { background.getApi.returns({ ignoreTokens: ignoreTokensStub, - getState: sinon.stub().callsFake((cb) => cb(null, baseMockState)), + getStatePatches: sinon.stub().callsFake((cb) => cb(null, [])), }); setBackgroundConnection(background.getApi()); @@ -1002,7 +951,7 @@ describe('Actions', () => { background.getApi.returns({ ignoreTokens: sinon.stub().callsFake((_, cb) => cb(new Error('error'))), - getState: sinon.stub().callsFake((cb) => cb(null, baseMockState)), + getStatePatches: sinon.stub().callsFake((cb) => cb(null, [])), }); setBackgroundConnection(background.getApi()); @@ -1010,10 +959,6 @@ describe('Actions', () => { const expectedActions = [ { type: 'SHOW_LOADING_INDICATION', payload: undefined }, { type: 'DISPLAY_WARNING', payload: 'error' }, - { - type: 'UPDATE_METAMASK_STATE', - value: baseMockState, - }, { type: 'HIDE_LOADING_INDICATION' }, ]; @@ -1270,7 +1215,7 @@ describe('Actions', () => { background.getApi.returns({ setAddressBook: setAddressBookStub, - getState: sinon.stub().callsFake((cb) => cb(null, baseMockState)), + getStatePatches: sinon.stub().callsFake((cb) => cb(null, [])), }); setBackgroundConnection(background.getApi()); @@ -1862,13 +1807,7 @@ describe('Actions', () => { setBackgroundConnection(background); - const expectedActions = [ - { type: 'HIDE_LOADING_INDICATION' }, - { - type: 'UPDATE_METAMASK_STATE', - value: baseMockState, - }, - ]; + const expectedActions = [{ type: 'HIDE_LOADING_INDICATION' }]; await expect( store.dispatch(actions.markPasswordForgotten('test')), @@ -1917,40 +1856,7 @@ describe('Actions', () => { rejectPendingApproval: sinon.stub().callsFake((_1, _2, cb) => { cb(); }), - getState: sinon.stub().callsFake((cb) => - cb(null, { - ...mockNetworkState({ chainId: CHAIN_IDS.MAINNET }), - currentLocale: 'test', - accounts: { - '0xFirstAddress': { - balance: '0x0', - }, - }, - internalAccounts: { - accounts: { - '8e110453-2231-4e62-82de-29b913dfef4b': { - address: '0xFirstAddress', - id: '8e110453-2231-4e62-82de-29b913dfef4b', - metadata: { - name: 'Test Account 2', - keyring: { - type: 'HD Key Tree', - }, - }, - options: {}, - methods: ETH_EOA_METHODS, - type: EthAccountType.Eoa, - }, - }, - selectedAccount: '8e110453-2231-4e62-82de-29b913dfef4b', - }, - cachedBalances: { - '0x1': { - '0xFirstAddress': '0x0', - }, - }, - }), - ), + getStatePatches: sinon.stub().callsFake((cb) => cb(null, [])), }); setBackgroundConnection(background.getApi()); @@ -2531,6 +2437,7 @@ describe('Actions', () => { expect(store.getActions()).toStrictEqual(expectedActions); }); }); + describe('#createMetaMetricsDataDeletionTask', () => { afterEach(() => { sinon.restore(); @@ -2570,4 +2477,29 @@ describe('Actions', () => { expect(updateDataDeletionTaskStatusStub.callCount).toStrictEqual(1); }); }); + + describe('syncInternalAccountsWithUserStorage', () => { + afterEach(() => { + sinon.restore(); + }); + + it('calls syncInternalAccountsWithUserStorage in the background', async () => { + const store = mockStore(); + + const syncInternalAccountsWithUserStorageStub = sinon + .stub() + .callsFake((cb) => cb()); + + background.getApi.returns({ + syncInternalAccountsWithUserStorage: + syncInternalAccountsWithUserStorageStub, + }); + setBackgroundConnection(background.getApi()); + + await store.dispatch(actions.syncInternalAccountsWithUserStorage()); + expect(syncInternalAccountsWithUserStorageStub.calledOnceWith()).toBe( + true, + ); + }); + }); }); diff --git a/ui/store/actions.ts b/ui/store/actions.ts index 499acba711bd..c3d234100a1a 100644 --- a/ui/store/actions.ts +++ b/ui/store/actions.ts @@ -38,6 +38,7 @@ import { import { InterfaceState } from '@metamask/snaps-sdk'; import { KeyringTypes } from '@metamask/keyring-controller'; import type { NotificationServicesController } from '@metamask/notification-services-controller'; +import { Patch } from 'immer'; import switchDirection from '../../shared/lib/switch-direction'; import { ENVIRONMENT_TYPE_NOTIFICATION, @@ -422,8 +423,6 @@ export function importNewAccount( AnyAction > { return async (dispatch: MetaMaskReduxDispatch) => { - let newState; - dispatch(showLoadingIndication(loadingMessage)); try { @@ -432,16 +431,11 @@ export function importNewAccount( strategy, args, ]); - log.debug(`background.getState`); - newState = await submitRequestToBackground< - MetaMaskReduxState['metamask'] - >('getState'); } finally { dispatch(hideLoadingIndication()); } - dispatch(updateMetamaskState(newState)); - return newState; + return await forceUpdateMetamaskState(dispatch); }; } @@ -679,18 +673,17 @@ export function decryptMsgInline( return async (dispatch: MetaMaskReduxDispatch) => { log.debug(`actions calling background.decryptMessageInline`); - let newState; try { - newState = await submitRequestToBackground< - MetaMaskReduxState['metamask'] - >('decryptMessageInline', [decryptedMsgData]); + await submitRequestToBackground('decryptMessageInline', [ + decryptedMsgData, + ]); } catch (error) { logErrorWithMessage(error); dispatch(displayWarning(error)); throw error; } - dispatch(updateMetamaskState(newState)); + const newState = await forceUpdateMetamaskState(dispatch); return newState.unapprovedDecryptMsgs[decryptedMsgData.metamaskId]; }; } @@ -708,11 +701,8 @@ export function decryptMsg( dispatch(showLoadingIndication()); log.debug(`actions calling background.decryptMessage`); - let newState: MetaMaskReduxState['metamask']; try { - newState = await submitRequestToBackground< - MetaMaskReduxState['metamask'] - >('decryptMessage', [decryptedMsgData]); + await submitRequestToBackground('decryptMessage', [decryptedMsgData]); } catch (error) { logErrorWithMessage(error); dispatch(displayWarning(error)); @@ -721,7 +711,7 @@ export function decryptMsg( dispatch(hideLoadingIndication()); } - dispatch(updateMetamaskState(newState)); + await forceUpdateMetamaskState(dispatch); dispatch(completedTx(decryptedMsgData.metamaskId)); dispatch(closeCurrentNotificationWindow()); return decryptedMsgData; @@ -741,11 +731,11 @@ export function encryptionPublicKeyMsg( dispatch(showLoadingIndication()); log.debug(`actions calling background.encryptionPublicKey`); - let newState: MetaMaskReduxState['metamask']; try { - newState = await submitRequestToBackground< - MetaMaskReduxState['metamask'] - >('encryptionPublicKey', [msgData]); + await submitRequestToBackground( + 'encryptionPublicKey', + [msgData], + ); } catch (error) { logErrorWithMessage(error); dispatch(displayWarning(error)); @@ -754,7 +744,7 @@ export function encryptionPublicKeyMsg( dispatch(hideLoadingIndication()); } - dispatch(updateMetamaskState(newState)); + await forceUpdateMetamaskState(dispatch); dispatch(completedTx(msgData.metamaskId)); dispatch(closeCurrentNotificationWindow()); return msgData; @@ -768,27 +758,6 @@ export function updateCustomNonce(value: string) { }; } -const updateMetamaskStateFromBackground = (): Promise< - MetaMaskReduxState['metamask'] -> => { - log.debug(`background.getState`); - - return new Promise((resolve, reject) => { - callBackgroundMethod( - 'getState', - [], - (error, newState) => { - if (error) { - reject(error); - return; - } - - resolve(newState as MetaMaskReduxState['metamask']); - }, - ); - }); -}; - /** * TODO: update previousGasParams to use typed gas params object * TODO: Not a thunk, but rather a wrapper around a background call @@ -963,8 +932,7 @@ export function updateTransaction( try { dispatch(updateTransactionParams(txMeta.id, txMeta.txParams)); - const newState = await updateMetamaskStateFromBackground(); - dispatch(updateMetamaskState(newState)); + await forceUpdateMetamaskState(dispatch); dispatch(showConfTxPage({ id: txMeta.id })); return txMeta; } finally { @@ -1014,7 +982,6 @@ export function addTransactionAndRouteToConfirmationPage( dispatch(displayWarning(error)); throw error; } - return null; }; } @@ -1101,8 +1068,7 @@ export function updateAndApproveTx( }, ); }) - .then(() => updateMetamaskStateFromBackground()) - .then((newState) => dispatch(updateMetamaskState(newState))) + .then(() => forceUpdateMetamaskState(dispatch)) .then(() => { if (!getIsSendActive()) { dispatch(resetSendState()); @@ -1347,16 +1313,16 @@ export function cancelDecryptMsg( return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); - let newState; try { - newState = await submitRequestToBackground< - MetaMaskReduxState['metamask'] - >('cancelDecryptMessage', [msgData.id]); + await submitRequestToBackground( + 'cancelDecryptMessage', + [msgData.id], + ); } finally { dispatch(hideLoadingIndication()); } - dispatch(updateMetamaskState(newState)); + await forceUpdateMetamaskState(dispatch); dispatch(completedTx(msgData.id)); dispatch(closeCurrentNotificationWindow()); return msgData; @@ -1374,16 +1340,16 @@ export function cancelEncryptionPublicKeyMsg( return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); - let newState; try { - newState = await submitRequestToBackground< - MetaMaskReduxState['metamask'] - >('cancelEncryptionPublicKey', [msgData.id]); + await submitRequestToBackground( + 'cancelEncryptionPublicKey', + [msgData.id], + ); } finally { dispatch(hideLoadingIndication()); } - dispatch(updateMetamaskState(newState)); + await forceUpdateMetamaskState(dispatch); dispatch(completedTx(msgData.id)); dispatch(closeCurrentNotificationWindow()); return msgData; @@ -1418,8 +1384,7 @@ export function cancelTx( }, ); }) - .then(() => updateMetamaskStateFromBackground()) - .then((newState) => dispatch(updateMetamaskState(newState))) + .then(() => forceUpdateMetamaskState(dispatch)) .then(() => { dispatch(resetSendState()); dispatch(completedTx(txMeta.id)); @@ -1472,8 +1437,7 @@ export function cancelTxs( await Promise.all(cancellations); - const newState = await updateMetamaskStateFromBackground(); - dispatch(updateMetamaskState(newState)); + await forceUpdateMetamaskState(dispatch); dispatch(resetSendState()); txIds.forEach((id) => { @@ -1560,13 +1524,18 @@ export function unlockSucceeded(message?: string) { } export function updateMetamaskState( - newState: MetaMaskReduxState['metamask'], + patches: Patch[], ): ThunkAction { return (dispatch, getState) => { const state = getState(); const providerConfig = getProviderConfig(state); const { metamask: currentState } = state; + if (!patches?.length) { + return currentState; + } + + const newState = applyPatches(currentState, patches); const { currentLocale } = currentState; const currentInternalAccount = getSelectedInternalAccount(state); const selectedAddress = currentInternalAccount?.address; @@ -1658,6 +1627,8 @@ export function updateMetamaskState( ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) updateCustodyState(dispatch, newState, getState()); ///: END:ONLY_INCLUDE_IF + + return newState; }; } @@ -1685,13 +1656,12 @@ export function lockMetamask(): ThunkAction< dispatch(showLoadingIndication()); return backgroundSetLocked() - .then(() => updateMetamaskStateFromBackground()) + .then(() => forceUpdateMetamaskState(dispatch)) .catch((error) => { dispatch(displayWarning(error.message)); return Promise.reject(error); }) - .then((newState) => { - dispatch(updateMetamaskState(newState)); + .then(() => { dispatch(hideLoadingIndication()); dispatch({ type: actionConstants.LOCK_METAMASK }); }) @@ -2289,12 +2259,12 @@ export function createCancelTransaction( const { id } = currentNetworkTxList[currentNetworkTxList.length - 1]; newTxId = id; - resolve(newState); + resolve(); } }, ); }) - .then((newState) => dispatch(updateMetamaskState(newState))) + .then(() => forceUpdateMetamaskState(dispatch)) .then(() => newTxId); }; } @@ -2324,12 +2294,12 @@ export function createSpeedUpTransaction( const currentNetworkTxList = getCurrentNetworkTransactions(newState); newTx = currentNetworkTxList[currentNetworkTxList.length - 1]; - resolve(newState); + resolve(); } }, ); }) - .then((newState) => dispatch(updateMetamaskState(newState))) + .then(() => forceUpdateMetamaskState(dispatch)) .then(() => newTx); }; } @@ -2356,12 +2326,12 @@ export function createRetryTransaction( const currentNetworkTxList = getCurrentNetworkTransactions(newState); newTx = currentNetworkTxList[currentNetworkTxList.length - 1]; - resolve(newState); + resolve(); } }, ); }) - .then((newState) => dispatch(updateMetamaskState(newState))) + .then(() => forceUpdateMetamaskState(dispatch)) .then(() => newTx); }; } @@ -3160,20 +3130,18 @@ export function setServiceWorkerKeepAlivePreference( export async function forceUpdateMetamaskState( dispatch: MetaMaskReduxDispatch, ) { - log.debug(`background.getState`); + let pendingPatches: Patch[] | undefined; - let newState; try { - newState = await submitRequestToBackground( - 'getState', + pendingPatches = await submitRequestToBackground( + 'getStatePatches', ); } catch (error) { dispatch(displayWarning(error)); throw error; } - dispatch(updateMetamaskState(newState)); - return newState; + return dispatch(updateMetamaskState(pendingPatches)); } export function toggleAccountMenu() { @@ -4570,7 +4538,7 @@ export function createTransactionEventFragment( export function updateEventFragment( id: string, - payload: MetaMetricsEventFragment, + payload: Partial, ) { return submitRequestToBackground('updateEventFragment', [id, payload]); } @@ -5384,6 +5352,33 @@ export function fetchAndUpdateMetamaskNotifications(): ThunkAction< }; } +/** + * Synchronizes accounts data with user storage between devices. + * + * This function sends a request to the background script to sync accounts data and update the state accordingly. + * If the operation encounters an error, it logs the error message and rethrows the error to ensure it is handled appropriately. + * + * @returns A thunk action that, when dispatched, attempts to synchronize accounts data with user storage between devices. + */ +export function syncInternalAccountsWithUserStorage(): ThunkAction< + void, + MetaMaskReduxState, + unknown, + AnyAction +> { + return async () => { + try { + const response = await submitRequestToBackground( + 'syncInternalAccountsWithUserStorage', + ); + return response; + } catch (error) { + logErrorWithMessage(error); + throw error; + } + }; +} + /** * Marks MetaMask notifications as read. * @@ -5637,3 +5632,33 @@ export async function endBackgroundTrace(request: EndTraceRequest) { { ...request, timestamp }, ]); } + +/** + * Apply the state patches from the background. + * Intentionally not using immer as a temporary measure to avoid + * freezing the resulting state and requiring further fixes + * to remove direct state mutations. + * + * @param oldState - The current state. + * @param patches - The patches to apply. + * Only supports 'replace' operations with a single path element. + * @returns The new state. + */ +function applyPatches( + oldState: Record, + patches: Patch[], +): Record { + const newState = { ...oldState }; + + for (const patch of patches) { + const { op, path, value } = patch; + + if (op === 'replace') { + newState[path[0]] = value; + } else { + throw new Error(`Unsupported patch operation: ${op}`); + } + } + + return newState; +} diff --git a/yarn.lock b/yarn.lock index 6e95a70c1e1d..c0f966b21c98 100644 --- a/yarn.lock +++ b/yarn.lock @@ -50,6 +50,13 @@ __metadata: languageName: node linkType: hard +"@adraffy/ens-normalize@npm:1.10.1": + version: 1.10.1 + resolution: "@adraffy/ens-normalize@npm:1.10.1" + checksum: 10/4cb938c4abb88a346d50cb0ea44243ab3574330c81d4f5aaaf9dfee584b96189d0faa404de0fcbef5a1b73909ea4ebc3e63d84bd23f9949e5c8d4085207a5091 + languageName: node + linkType: hard + "@ampproject/remapping@npm:^2.2.0": version: 2.2.1 resolution: "@ampproject/remapping@npm:2.2.1" @@ -1704,10 +1711,10 @@ __metadata: languageName: node linkType: hard -"@blockaid/ppom_release@npm:^1.5.2": - version: 1.5.2 - resolution: "@blockaid/ppom_release@npm:1.5.2" - checksum: 10/b47af74e8a315d996abb8371a7b28f9923bf78272cc408b2307024e2050b57f36c53b6b9a57b276b0910b449ebb384897e293abad356131ccf65c6c3c5ca31ae +"@blockaid/ppom_release@npm:^1.5.3": + version: 1.5.3 + resolution: "@blockaid/ppom_release@npm:1.5.3" + checksum: 10/3e8a16866b477eef247c4a65c80d361e7429389e7e760c0497bc69269526e2325fa15cdbf93455c1655877a7760c6b4fc9ce87d80f0290483160632300bcfbc8 languageName: node linkType: hard @@ -2666,6 +2673,15 @@ __metadata: languageName: node linkType: hard +"@ethersproject/networks@npm:5.7.0": + version: 5.7.0 + resolution: "@ethersproject/networks@npm:5.7.0" + dependencies: + "@ethersproject/logger": "npm:^5.7.0" + checksum: 10/c77efcd4ee44fe17fea448f135b6a6393d6c42122e725730ced37b7f2e3137e48c6712f3ff3d07d7fb4ddb0222bb404ad3088964b8db579620054788a8110101 + languageName: node + linkType: hard + "@ethersproject/networks@npm:5.7.1, @ethersproject/networks@npm:^5.7.0": version: 5.7.1 resolution: "@ethersproject/networks@npm:5.7.1" @@ -2694,6 +2710,34 @@ __metadata: languageName: node linkType: hard +"@ethersproject/providers@npm:5.7.0": + version: 5.7.0 + resolution: "@ethersproject/providers@npm:5.7.0" + dependencies: + "@ethersproject/abstract-provider": "npm:^5.7.0" + "@ethersproject/abstract-signer": "npm:^5.7.0" + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/base64": "npm:^5.7.0" + "@ethersproject/basex": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/constants": "npm:^5.7.0" + "@ethersproject/hash": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/networks": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/random": "npm:^5.7.0" + "@ethersproject/rlp": "npm:^5.7.0" + "@ethersproject/sha2": "npm:^5.7.0" + "@ethersproject/strings": "npm:^5.7.0" + "@ethersproject/transactions": "npm:^5.7.0" + "@ethersproject/web": "npm:^5.7.0" + bech32: "npm:1.1.4" + ws: "npm:7.4.6" + checksum: 10/8d8e57ba80250ef4960de294baec9e6a1bd9cc79fa6820ac346d4180069d2929f272881bd6b16cd53a596368ba359bd5dd8e3e4d82b0afa883881e9ff937db44 + languageName: node + linkType: hard + "@ethersproject/providers@npm:5.7.2, @ethersproject/providers@npm:^5.7.0, @ethersproject/providers@npm:^5.7.2": version: 5.7.2 resolution: "@ethersproject/providers@npm:5.7.2" @@ -2843,6 +2887,19 @@ __metadata: languageName: node linkType: hard +"@ethersproject/web@npm:5.7.0": + version: 5.7.0 + resolution: "@ethersproject/web@npm:5.7.0" + dependencies: + "@ethersproject/base64": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/strings": "npm:^5.7.0" + checksum: 10/ed1509b1cd1d4cf9fbb34383dfa5d70ae1b8450f86a623ca851f01bbdb41d9e2c69ffdb6b015c03082ea885cd1f7fdde16960976fc163618e170686d15558793 + languageName: node + linkType: hard + "@ethersproject/web@npm:5.7.1, @ethersproject/web@npm:^5.7.0": version: 5.7.1 resolution: "@ethersproject/web@npm:5.7.1" @@ -4695,7 +4752,7 @@ __metadata: languageName: node linkType: hard -"@metamask/abi-utils@npm:^2.0.2, @metamask/abi-utils@npm:^2.0.4": +"@metamask/abi-utils@npm:^2.0.2, @metamask/abi-utils@npm:^2.0.3, @metamask/abi-utils@npm:^2.0.4": version: 2.0.4 resolution: "@metamask/abi-utils@npm:2.0.4" dependencies: @@ -4743,16 +4800,16 @@ __metadata: languageName: node linkType: hard -"@metamask/accounts-controller@npm:^18.2.0": - version: 18.2.0 - resolution: "@metamask/accounts-controller@npm:18.2.0" +"@metamask/accounts-controller@npm:^18.2.1": + version: 18.2.1 + resolution: "@metamask/accounts-controller@npm:18.2.1" dependencies: "@ethereumjs/util": "npm:^8.1.0" - "@metamask/base-controller": "npm:^7.0.0" - "@metamask/eth-snap-keyring": "npm:^4.3.1" + "@metamask/base-controller": "npm:^7.0.1" + "@metamask/eth-snap-keyring": "npm:^4.3.3" "@metamask/keyring-api": "npm:^8.1.0" - "@metamask/snaps-sdk": "npm:^6.1.1" - "@metamask/snaps-utils": "npm:^7.8.1" + "@metamask/snaps-sdk": "npm:^6.5.0" + "@metamask/snaps-utils": "npm:^8.1.1" "@metamask/utils": "npm:^9.1.0" deepmerge: "npm:^4.2.2" ethereum-cryptography: "npm:^2.1.2" @@ -4760,8 +4817,8 @@ __metadata: uuid: "npm:^8.3.2" peerDependencies: "@metamask/keyring-controller": ^17.0.0 - "@metamask/snaps-controllers": ^9.3.0 - checksum: 10/dc352195621252682eb4cf60e4abc26afe8ae1111574e0e64e7d2e2e1e3ab5c2be906ee586496e12a134b175db00ebd0a68b1a0cd200cb5d298185a683fe68e4 + "@metamask/snaps-controllers": ^9.7.0 + checksum: 10/cad8d68e5c5d8b349fcf5bfd6bc900cccbb5ad54bdcf2678a4469f7b3118064ca26bedafaafa89bea6ddce6f0cfb22af8eb8b7958bbd6cfce916f19a91a8e770 languageName: node linkType: hard @@ -4792,7 +4849,7 @@ __metadata: languageName: node linkType: hard -"@metamask/approval-controller@npm:^7.0.0, @metamask/approval-controller@npm:^7.0.1, @metamask/approval-controller@npm:^7.0.2": +"@metamask/approval-controller@npm:^7.0.0, @metamask/approval-controller@npm:^7.0.2": version: 7.0.2 resolution: "@metamask/approval-controller@npm:7.0.2" dependencies: @@ -4804,45 +4861,41 @@ __metadata: languageName: node linkType: hard -"@metamask/assets-controllers@npm:^36.0.0": - version: 36.0.0 - resolution: "@metamask/assets-controllers@npm:36.0.0" +"@metamask/assets-controllers@npm:^37.0.0": + version: 37.0.0 + resolution: "@metamask/assets-controllers@npm:37.0.0" dependencies: "@ethereumjs/util": "npm:^8.1.0" "@ethersproject/address": "npm:^5.7.0" "@ethersproject/bignumber": "npm:^5.7.0" "@ethersproject/contracts": "npm:^5.7.0" "@ethersproject/providers": "npm:^5.7.0" - "@metamask/abi-utils": "npm:^2.0.2" - "@metamask/accounts-controller": "npm:^17.2.0" - "@metamask/approval-controller": "npm:^7.0.1" - "@metamask/base-controller": "npm:^6.0.1" + "@metamask/abi-utils": "npm:^2.0.3" + "@metamask/base-controller": "npm:^6.0.2" "@metamask/contract-metadata": "npm:^2.4.0" - "@metamask/controller-utils": "npm:^11.0.1" + "@metamask/controller-utils": "npm:^11.0.2" "@metamask/eth-query": "npm:^4.0.0" - "@metamask/keyring-controller": "npm:^17.1.0" "@metamask/metamask-eth-abis": "npm:^3.1.1" - "@metamask/network-controller": "npm:^20.0.0" - "@metamask/polling-controller": "npm:^9.0.0" - "@metamask/preferences-controller": "npm:^13.0.0" + "@metamask/polling-controller": "npm:^9.0.1" "@metamask/rpc-errors": "npm:^6.3.1" - "@metamask/utils": "npm:^9.0.0" + "@metamask/utils": "npm:^9.1.0" "@types/bn.js": "npm:^5.1.5" "@types/uuid": "npm:^8.3.0" async-mutex: "npm:^0.5.0" bn.js: "npm:^5.2.1" cockatiel: "npm:^3.1.2" + immer: "npm:^9.0.6" lodash: "npm:^4.17.21" - multiformats: "npm:^9.5.2" + multiformats: "npm:^13.1.0" single-call-balance-checker-abi: "npm:^1.0.0" uuid: "npm:^8.3.2" peerDependencies: - "@metamask/accounts-controller": ^17.0.0 + "@metamask/accounts-controller": ^18.0.0 "@metamask/approval-controller": ^7.0.0 "@metamask/keyring-controller": ^17.0.0 "@metamask/network-controller": ^20.0.0 "@metamask/preferences-controller": ^13.0.0 - checksum: 10/7855bf544e77c4a1dc233748941981b9f09f1633cc1f7aac06cdc6555e7ee2690cff0866d55ae5ea012c6d05bf61511b39f886ae9b1c498a9154bf9520cdf199 + checksum: 10/89798930cb80a134263ce82db736feebd064fe6c999ddcf41ca86fad81cfadbb9e37d1919a6384aaf6d3aa0cb520684e7b8228da3b9bc1e70e7aea174a69c4ac languageName: node linkType: hard @@ -4870,7 +4923,7 @@ __metadata: languageName: node linkType: hard -"@metamask/base-controller@npm:^6.0.0, @metamask/base-controller@npm:^6.0.1, @metamask/base-controller@npm:^6.0.2, @metamask/base-controller@npm:^6.0.3": +"@metamask/base-controller@npm:^6.0.0, @metamask/base-controller@npm:^6.0.2": version: 6.0.3 resolution: "@metamask/base-controller@npm:6.0.3" dependencies: @@ -4880,20 +4933,20 @@ __metadata: languageName: node linkType: hard -"@metamask/base-controller@npm:^7.0.0": - version: 7.0.0 - resolution: "@metamask/base-controller@npm:7.0.0" +"@metamask/base-controller@npm:^7.0.0, @metamask/base-controller@npm:^7.0.1": + version: 7.0.1 + resolution: "@metamask/base-controller@npm:7.0.1" dependencies: "@metamask/utils": "npm:^9.1.0" immer: "npm:^9.0.6" - checksum: 10/0ea307da4a7863224fd1fc83039165dbd06d2725922d4d4cf5854f5e7894e789a3c277f1e4592a38ae002de869217a26550f3b9687c259fc29153984dc5b4a4c + checksum: 10/774b6d68ac95a5ec187e890d321bede50065f8a6f1ba7b49a19f5971366274054ac0e401548b51d3b014d0bca5d650409fb554dd13ce120e7fb3495b4e8e67b1 languageName: node linkType: hard -"@metamask/bitcoin-wallet-snap@npm:^0.5.0": - version: 0.5.0 - resolution: "@metamask/bitcoin-wallet-snap@npm:0.5.0" - checksum: 10/eeb2c11316d58fcd26b73c11b6c8cd6ed0c5d4beb28ae3237bc08c8100fbdde4f8e38ad3efb25c85f8a6722cfec8290bbbfee71718d54735beb86064a9e9435c +"@metamask/bitcoin-wallet-snap@npm:^0.6.0": + version: 0.6.0 + resolution: "@metamask/bitcoin-wallet-snap@npm:0.6.0" + checksum: 10/baf4d7a43ddb5f210437c722e90abc6a3b4056390cc1d075e1a09acb82e934db338fce36fb897560e7f9ecd8ff3fcbd4795b3076dc7243af7ac93ea5d47b63f5 languageName: node linkType: hard @@ -4923,9 +4976,9 @@ __metadata: languageName: node linkType: hard -"@metamask/controller-utils@npm:^11.0.0, @metamask/controller-utils@npm:^11.0.1, @metamask/controller-utils@npm:^11.0.2, @metamask/controller-utils@npm:^11.1.0, @metamask/controller-utils@npm:^11.2.0": - version: 11.2.0 - resolution: "@metamask/controller-utils@npm:11.2.0" +"@metamask/controller-utils@npm:^11.0.0, @metamask/controller-utils@npm:^11.0.2, @metamask/controller-utils@npm:^11.1.0, @metamask/controller-utils@npm:^11.2.0, @metamask/controller-utils@npm:^11.3.0": + version: 11.3.0 + resolution: "@metamask/controller-utils@npm:11.3.0" dependencies: "@ethereumjs/util": "npm:^8.1.0" "@metamask/eth-query": "npm:^4.0.0" @@ -4936,7 +4989,7 @@ __metadata: bn.js: "npm:^5.2.1" eth-ens-namehash: "npm:^2.0.8" fast-deep-equal: "npm:^3.1.3" - checksum: 10/8c8630a635c5eeeb8ef46b14a12779a5005d8112668500bfb513186dee3f68b94dcf43ce6eddf42c38382828cd7ba28657b627d0eb617207a25b6ee78eae6b08 + checksum: 10/3200228d1f4ea5fa095228db4e5050529caf0470e072382eb8f7571bb9b07515516ca9e846b7751388399d9ae967e4985dafd6120902ef6c998e98f4eb36d964 languageName: node linkType: hard @@ -4984,6 +5037,16 @@ __metadata: languageName: node linkType: hard +"@metamask/ens-resolver-snap@npm:^0.1.2": + version: 0.1.2 + resolution: "@metamask/ens-resolver-snap@npm:0.1.2" + dependencies: + "@metamask/snaps-sdk": "npm:^6.2.0" + ethers: "npm:^6.13.1" + checksum: 10/0dae3dff8815ad11805ec0c0d339a2fba9216ea8bd03a60ef9e3b7f330c45a15ae0136b8b735b20454ebe9183e4c2e15570ac2b22cf9fecfde00db853d7bcc23 + languageName: node + linkType: hard + "@metamask/eslint-config-jest@npm:^9.0.0": version: 9.0.0 resolution: "@metamask/eslint-config-jest@npm:9.0.0" @@ -5266,21 +5329,21 @@ __metadata: languageName: node linkType: hard -"@metamask/eth-snap-keyring@npm:^4.3.1": - version: 4.3.1 - resolution: "@metamask/eth-snap-keyring@npm:4.3.1" +"@metamask/eth-snap-keyring@npm:^4.3.1, @metamask/eth-snap-keyring@npm:^4.3.3": + version: 4.3.3 + resolution: "@metamask/eth-snap-keyring@npm:4.3.3" dependencies: "@ethereumjs/tx": "npm:^4.2.0" - "@metamask/eth-sig-util": "npm:^7.0.1" - "@metamask/keyring-api": "npm:^8.0.0" - "@metamask/snaps-controllers": "npm:^8.1.1" - "@metamask/snaps-sdk": "npm:^4.2.0" - "@metamask/snaps-utils": "npm:^7.4.0" - "@metamask/utils": "npm:^8.4.0" + "@metamask/eth-sig-util": "npm:^7.0.3" + "@metamask/keyring-api": "npm:^8.1.0" + "@metamask/snaps-controllers": "npm:^9.6.0" + "@metamask/snaps-sdk": "npm:^6.4.0" + "@metamask/snaps-utils": "npm:^7.8.0" + "@metamask/superstruct": "npm:^3.1.0" + "@metamask/utils": "npm:^9.2.1" "@types/uuid": "npm:^9.0.1" - superstruct: "npm:^1.0.3" uuid: "npm:^9.0.0" - checksum: 10/6362a499e8e25413bf8039c06e66939104bdb69b9dc22df5a44dd55e32304cffb869d4969755e8b4f3234749c6f382d8bbcdfeafe5a75064e85fa43307dbefee + checksum: 10/035c82afef82a4cee7bc63b5c4f152a132b683017ec90a4b614764a4bc7adcca8faccf78c25adcddca2d29eee2fed08706f07d72afb93640956b86e862d4f555 languageName: node linkType: hard @@ -5579,45 +5642,24 @@ __metadata: languageName: node linkType: hard -"@metamask/keyring-controller@npm:17.1.1": - version: 17.1.1 - resolution: "@metamask/keyring-controller@npm:17.1.1" +"@metamask/keyring-controller@npm:^17.1.0, @metamask/keyring-controller@npm:^17.2.1": + version: 17.2.1 + resolution: "@metamask/keyring-controller@npm:17.2.1" dependencies: "@ethereumjs/util": "npm:^8.1.0" "@keystonehq/metamask-airgapped-keyring": "npm:^0.14.1" - "@metamask/base-controller": "npm:^6.0.1" + "@metamask/base-controller": "npm:^7.0.1" "@metamask/browser-passworder": "npm:^4.3.0" "@metamask/eth-hd-keyring": "npm:^7.0.1" "@metamask/eth-sig-util": "npm:^7.0.1" "@metamask/eth-simple-keyring": "npm:^6.0.1" - "@metamask/keyring-api": "npm:^8.0.0" - "@metamask/message-manager": "npm:^10.0.1" - "@metamask/utils": "npm:^9.0.0" - async-mutex: "npm:^0.5.0" - ethereumjs-wallet: "npm:^1.0.1" - immer: "npm:^9.0.6" - checksum: 10/441bd01b42658819281ef45ebfb214d3282db2cf523284314ca8e6786e7c06fa564a6799e506edc67153d2b51126a8aca3b67762bbb5221c382f70c81a81db29 - languageName: node - linkType: hard - -"@metamask/keyring-controller@patch:@metamask/keyring-controller@npm%3A17.1.1#~/.yarn/patches/@metamask-keyring-controller-npm-17.1.1-098cb41930.patch": - version: 17.1.1 - resolution: "@metamask/keyring-controller@patch:@metamask/keyring-controller@npm%3A17.1.1#~/.yarn/patches/@metamask-keyring-controller-npm-17.1.1-098cb41930.patch::version=17.1.1&hash=1c0f1d" - dependencies: - "@ethereumjs/util": "npm:^8.1.0" - "@keystonehq/metamask-airgapped-keyring": "npm:^0.14.1" - "@metamask/base-controller": "npm:^6.0.1" - "@metamask/browser-passworder": "npm:^4.3.0" - "@metamask/eth-hd-keyring": "npm:^7.0.1" - "@metamask/eth-sig-util": "npm:^7.0.1" - "@metamask/eth-simple-keyring": "npm:^6.0.1" - "@metamask/keyring-api": "npm:^8.0.0" - "@metamask/message-manager": "npm:^10.0.1" - "@metamask/utils": "npm:^9.0.0" + "@metamask/keyring-api": "npm:^8.1.0" + "@metamask/message-manager": "npm:^10.1.1" + "@metamask/utils": "npm:^9.1.0" async-mutex: "npm:^0.5.0" ethereumjs-wallet: "npm:^1.0.1" immer: "npm:^9.0.6" - checksum: 10/ea04fde80dd6f1bc9f7ee4c4631aeaeb149c8fd16bb8879f5d9edaf077a655866deef31d95357f152558fcc22c993ae1a8a42533ebc6b66fe60897b83a2e8d39 + checksum: 10/051cfc790d74a64c2e8139dbcdb38e845d10f3a3a85792ece6b38b0f239057f553c6f74b49e79dd6748093f1bf3b82d484d927aead3aa891247839b1fac8df66 languageName: node linkType: hard @@ -5784,21 +5826,21 @@ __metadata: languageName: node linkType: hard -"@metamask/notification-services-controller@npm:^0.5.0": - version: 0.5.0 - resolution: "@metamask/notification-services-controller@npm:0.5.0" +"@metamask/notification-services-controller@npm:^0.7.0": + version: 0.7.0 + resolution: "@metamask/notification-services-controller@npm:0.7.0" dependencies: "@contentful/rich-text-html-renderer": "npm:^16.5.2" - "@metamask/base-controller": "npm:^7.0.0" - "@metamask/controller-utils": "npm:^11.2.0" + "@metamask/base-controller": "npm:^7.0.1" + "@metamask/controller-utils": "npm:^11.3.0" bignumber.js: "npm:^4.1.0" firebase: "npm:^10.11.0" loglevel: "npm:^1.8.1" uuid: "npm:^8.3.2" peerDependencies: "@metamask/keyring-controller": ^17.0.0 - "@metamask/profile-sync-controller": ^0.5.0 - checksum: 10/e945cbf0b7138d22f1078844575dc89c990ddc6669724d1ce0db5ad43c74a86da1c5e1ab12614afbcc5c49125b09365689de2a2c9548af426932f4c1397a66bd + "@metamask/profile-sync-controller": ^0.0.0 + checksum: 10/1fc72086686aeef4c72d9eb7726d086a147a4079c178a6de23269fa39a3d861c54fe6dfe79bd9b5c8bf9afa278371408092bd37f3e8f814e65c7aca3573655f5 languageName: node linkType: hard @@ -5891,33 +5933,19 @@ __metadata: languageName: node linkType: hard -"@metamask/phishing-controller@npm:^10.1.1": - version: 10.1.1 - resolution: "@metamask/phishing-controller@npm:10.1.1" - dependencies: - "@metamask/base-controller": "npm:^6.0.2" - "@metamask/controller-utils": "npm:^11.0.2" - "@types/punycode": "npm:^2.1.0" - eth-phishing-detect: "npm:^1.2.0" - fastest-levenshtein: "npm:^1.0.16" - punycode: "npm:^2.1.1" - checksum: 10/4c6723d62a3a0b071fbf4c2b227a2eef6daa5f742bce80677bdf96312393c427d0d3c183ffcc13e065464c6c644f2b556c56e79161757bbccb525d4b34ee46b0 - languageName: node - linkType: hard - -"@metamask/phishing-controller@npm:^12.0.1": - version: 12.0.1 - resolution: "@metamask/phishing-controller@npm:12.0.1" +"@metamask/phishing-controller@npm:^12.0.1, @metamask/phishing-controller@npm:^12.0.2": + version: 12.0.2 + resolution: "@metamask/phishing-controller@npm:12.0.2" dependencies: "@metamask/base-controller": "npm:^7.0.0" - "@metamask/controller-utils": "npm:^11.1.0" + "@metamask/controller-utils": "npm:^11.2.0" "@noble/hashes": "npm:^1.4.0" "@types/punycode": "npm:^2.1.0" eth-phishing-detect: "npm:^1.2.0" ethereum-cryptography: "npm:^2.1.2" fastest-levenshtein: "npm:^1.0.16" punycode: "npm:^2.1.1" - checksum: 10/3f7c69434a783251657f333495fbee1cb8a02ffb731cf430fcd21812482bf1237948c498db74b55fb4e1e6976d71932f4b11c39a26f9e367ffd26a69efa2583e + checksum: 10/78781e1b781c838e303677157616fb3b5e581030fe8f0ed8913f6b75fbcb7ee2ba59a44831936cc68cca8b295ef6546761b40ea3277d810b68d8ed39a58d0e29 languageName: node linkType: hard @@ -5953,30 +5981,29 @@ __metadata: languageName: node linkType: hard -"@metamask/polling-controller@npm:^9.0.0": - version: 9.0.0 - resolution: "@metamask/polling-controller@npm:9.0.0" +"@metamask/polling-controller@npm:^9.0.1": + version: 9.0.1 + resolution: "@metamask/polling-controller@npm:9.0.1" dependencies: - "@metamask/base-controller": "npm:^6.0.0" - "@metamask/controller-utils": "npm:^11.0.0" - "@metamask/network-controller": "npm:^20.0.0" - "@metamask/utils": "npm:^8.3.0" + "@metamask/base-controller": "npm:^6.0.2" + "@metamask/controller-utils": "npm:^11.0.2" + "@metamask/utils": "npm:^9.1.0" "@types/uuid": "npm:^8.3.0" fast-json-stable-stringify: "npm:^2.1.0" uuid: "npm:^8.3.2" peerDependencies: "@metamask/network-controller": ^20.0.0 - checksum: 10/5e3abd84dcb3fb128add949bbda78a34d509f56b71d27f60f8ff3fd5de116424dc9e202c812c5f3c233d1489740c376b9de47f28faa387e64a198d246f962baf + checksum: 10/e9e8c51013290a2e4b2817ba1e0915783474f6a55fe614e20acf92bf707e300bec1fa612c8019ae9afe9635d018fb5d5b106c8027446ba12767220db91cf1ee5 languageName: node linkType: hard -"@metamask/post-message-stream@npm:^8.0.0, @metamask/post-message-stream@npm:^8.1.0": - version: 8.1.0 - resolution: "@metamask/post-message-stream@npm:8.1.0" +"@metamask/post-message-stream@npm:^8.0.0, @metamask/post-message-stream@npm:^8.1.1": + version: 8.1.1 + resolution: "@metamask/post-message-stream@npm:8.1.1" dependencies: - "@metamask/utils": "npm:^8.1.0" + "@metamask/utils": "npm:^9.0.0" readable-stream: "npm:3.6.2" - checksum: 10/0a4f06250e2162b86d0b618e234e3caa3361767af95d0fd86c654aa33352f1948477a1e39d8a40804614f6d8ee29916e63b4f6c70792a0bfc93b2fffaf6fd4c2 + checksum: 10/8218d321abe734522aefaf6b44e4203966c3feaf83e2de6e68eef9dbe92b7fb47fe7fd82eae362147b1d741cc58d78bcc95d8bf02058e260ad2fb978104c96cf languageName: node linkType: hard @@ -5998,25 +6025,13 @@ __metadata: languageName: node linkType: hard -"@metamask/preferences-controller@npm:^13.0.0": - version: 13.0.0 - resolution: "@metamask/preferences-controller@npm:13.0.0" - dependencies: - "@metamask/base-controller": "npm:^6.0.0" - "@metamask/controller-utils": "npm:^11.0.0" - peerDependencies: - "@metamask/keyring-controller": ^17.0.0 - checksum: 10/99d39de8adb9a43bbb5972d70feabfba6bac0c1d71d1567838e506e661f7fd293205e2c83361f7166ce72b38437d79cd0da8a7a14dd584f59b5f583dcb4d769b - languageName: node - linkType: hard - -"@metamask/profile-sync-controller@npm:^0.5.0": - version: 0.5.0 - resolution: "@metamask/profile-sync-controller@npm:0.5.0" +"@metamask/profile-sync-controller@npm:^0.8.0": + version: 0.8.0 + resolution: "@metamask/profile-sync-controller@npm:0.8.0" dependencies: - "@metamask/base-controller": "npm:^7.0.0" - "@metamask/snaps-sdk": "npm:^6.1.1" - "@metamask/snaps-utils": "npm:^7.8.1" + "@metamask/base-controller": "npm:^7.0.1" + "@metamask/snaps-sdk": "npm:^6.5.0" + "@metamask/snaps-utils": "npm:^8.1.1" "@noble/ciphers": "npm:^0.5.2" "@noble/hashes": "npm:^1.4.0" immer: "npm:^9.0.6" @@ -6025,8 +6040,8 @@ __metadata: peerDependencies: "@metamask/accounts-controller": ^18.1.1 "@metamask/keyring-controller": ^17.2.0 - "@metamask/snaps-controllers": ^9.3.0 - checksum: 10/96a31ca2692af85100bd690aa290d6c954378aa14be0dd507afda46c37d761c5e398da4e93ed0f6f7f97267a82def7f4b12b45805cd7673381a6404f810511ff + "@metamask/snaps-controllers": ^9.7.0 + checksum: 10/613e2e87615f1db4a1a4559895a74c2b89c15720e831440eec0916aa96305f3db9b3e0926ac4a5d7532c462baaa18a117e2b9aa107949777163488c203cfea05 languageName: node linkType: hard @@ -6071,8 +6086,8 @@ __metadata: linkType: hard "@metamask/providers@npm:^17.1.2": - version: 17.1.2 - resolution: "@metamask/providers@npm:17.1.2" + version: 17.2.0 + resolution: "@metamask/providers@npm:17.2.0" dependencies: "@metamask/json-rpc-engine": "npm:^9.0.1" "@metamask/json-rpc-middleware-stream": "npm:^8.0.1" @@ -6087,7 +6102,7 @@ __metadata: readable-stream: "npm:^3.6.2" peerDependencies: webextension-polyfill: ^0.10.0 || ^0.11.0 || ^0.12.0 - checksum: 10/bf555f9774e340d4497c09c980094e759a198f11c5a78b403e639cf01904b9ec3b19a5e9f53567465dd8739da4138e2021ac9a404a99b1a6022add12a4b19a31 + checksum: 10/b2fc93cdc059528bfeb14a61d6153f9a5f2679e5c6640648c16cd4e5067f758a67c2c6abab962615e878e6b9d7f1bbcd3632584ad7e57ec9df8c16f47b13e608 languageName: node linkType: hard @@ -6224,9 +6239,9 @@ __metadata: languageName: node linkType: hard -"@metamask/snaps-controllers@npm:9.5.0": - version: 9.5.0 - resolution: "@metamask/snaps-controllers@npm:9.5.0" +"@metamask/snaps-controllers@npm:^9.6.0, @metamask/snaps-controllers@npm:^9.7.0": + version: 9.7.0 + resolution: "@metamask/snaps-controllers@npm:9.7.0" dependencies: "@metamask/approval-controller": "npm:^7.0.2" "@metamask/base-controller": "npm:^6.0.2" @@ -6234,14 +6249,14 @@ __metadata: "@metamask/json-rpc-middleware-stream": "npm:^8.0.2" "@metamask/object-multiplex": "npm:^2.0.0" "@metamask/permission-controller": "npm:^11.0.0" - "@metamask/phishing-controller": "npm:^10.1.1" - "@metamask/post-message-stream": "npm:^8.1.0" + "@metamask/phishing-controller": "npm:^12.0.2" + "@metamask/post-message-stream": "npm:^8.1.1" "@metamask/rpc-errors": "npm:^6.3.1" "@metamask/snaps-registry": "npm:^3.2.1" - "@metamask/snaps-rpc-methods": "npm:^11.0.0" - "@metamask/snaps-sdk": "npm:^6.3.0" - "@metamask/snaps-utils": "npm:^8.0.1" - "@metamask/utils": "npm:^9.1.0" + "@metamask/snaps-rpc-methods": "npm:^11.1.1" + "@metamask/snaps-sdk": "npm:^6.5.0" + "@metamask/snaps-utils": "npm:^8.1.1" + "@metamask/utils": "npm:^9.2.1" "@xstate/fsm": "npm:^2.0.0" browserify-zlib: "npm:^0.2.0" concat-stream: "npm:^2.0.0" @@ -6253,67 +6268,30 @@ __metadata: readable-web-to-node-stream: "npm:^3.0.2" tar-stream: "npm:^3.1.7" peerDependencies: - "@metamask/snaps-execution-environments": ^6.6.2 + "@metamask/snaps-execution-environments": ^6.7.1 peerDependenciesMeta: "@metamask/snaps-execution-environments": optional: true - checksum: 10/a71ba096205e9c62ac13b7cc00d34a565072945d9d7bf06aea2f057e1281d4c594871bd7928403dc7a0597dca023b21a222d5c30c1fa306891f5e51baab1df51 + checksum: 10/8a353819e60330ef3e338a40b1115d4c830b92b1cc0c92afb2b34bf46fbc906e6da5f905654e1d486cacd40b7025ec74d3cd01cb935090035ce9f1021ce5469f languageName: node linkType: hard -"@metamask/snaps-controllers@patch:@metamask/snaps-controllers@npm%3A9.5.0#~/.yarn/patches/@metamask-snaps-controllers-npm-9.5.0-8b21e3c072.patch": - version: 9.5.0 - resolution: "@metamask/snaps-controllers@patch:@metamask/snaps-controllers@npm%3A9.5.0#~/.yarn/patches/@metamask-snaps-controllers-npm-9.5.0-8b21e3c072.patch::version=9.5.0&hash=916653" +"@metamask/snaps-execution-environments@npm:^6.7.2": + version: 6.7.2 + resolution: "@metamask/snaps-execution-environments@npm:6.7.2" dependencies: - "@metamask/approval-controller": "npm:^7.0.2" - "@metamask/base-controller": "npm:^6.0.2" "@metamask/json-rpc-engine": "npm:^9.0.2" - "@metamask/json-rpc-middleware-stream": "npm:^8.0.2" "@metamask/object-multiplex": "npm:^2.0.0" - "@metamask/permission-controller": "npm:^11.0.0" - "@metamask/phishing-controller": "npm:^10.1.1" - "@metamask/post-message-stream": "npm:^8.1.0" - "@metamask/rpc-errors": "npm:^6.3.1" - "@metamask/snaps-registry": "npm:^3.2.1" - "@metamask/snaps-rpc-methods": "npm:^11.0.0" - "@metamask/snaps-sdk": "npm:^6.3.0" - "@metamask/snaps-utils": "npm:^8.0.1" - "@metamask/utils": "npm:^9.1.0" - "@xstate/fsm": "npm:^2.0.0" - browserify-zlib: "npm:^0.2.0" - concat-stream: "npm:^2.0.0" - fast-deep-equal: "npm:^3.1.3" - get-npm-tarball-url: "npm:^2.0.3" - immer: "npm:^9.0.6" - nanoid: "npm:^3.1.31" - readable-stream: "npm:^3.6.2" - readable-web-to-node-stream: "npm:^3.0.2" - tar-stream: "npm:^3.1.7" - peerDependencies: - "@metamask/snaps-execution-environments": ^6.6.2 - peerDependenciesMeta: - "@metamask/snaps-execution-environments": - optional: true - checksum: 10/42c94e15e68bc3d45bd28d50f03f0a90e8c8e36e89c3011a565f211da57979ebf5e780125eeb95507b403b6fc1f93a42b5e628a49bb0b0861fba56f82118b5b6 - languageName: node - linkType: hard - -"@metamask/snaps-execution-environments@npm:^6.6.2": - version: 6.6.2 - resolution: "@metamask/snaps-execution-environments@npm:6.6.2" - dependencies: - "@metamask/json-rpc-engine": "npm:^9.0.2" - "@metamask/object-multiplex": "npm:^2.0.0" - "@metamask/post-message-stream": "npm:^8.1.0" + "@metamask/post-message-stream": "npm:^8.1.1" "@metamask/providers": "npm:^17.1.2" "@metamask/rpc-errors": "npm:^6.3.1" - "@metamask/snaps-sdk": "npm:^6.1.0" - "@metamask/snaps-utils": "npm:^7.8.1" + "@metamask/snaps-sdk": "npm:^6.5.0" + "@metamask/snaps-utils": "npm:^8.1.1" "@metamask/superstruct": "npm:^3.1.0" - "@metamask/utils": "npm:^9.1.0" + "@metamask/utils": "npm:^9.2.1" nanoid: "npm:^3.1.31" readable-stream: "npm:^3.6.2" - checksum: 10/b06b03f784b7c20ac9f39f9bec8a7e2e06ebcd8678659e01745d73f1c08bd2605352144bc8ecab7d6b0a7db69ebf62febad517a5c8a1309aa1e173049ce350e7 + checksum: 10/4b8ec4c0f6e628feeffd92fe4378fd204d2ed78012a1ed5282b24b00c78cebc3b6d7cb1306903b045a2ca887ecc0adafb2c96da4a19f2730a268f4912b36bec3 languageName: node linkType: hard @@ -6329,36 +6307,36 @@ __metadata: languageName: node linkType: hard -"@metamask/snaps-rpc-methods@npm:^11.0.0": - version: 11.0.0 - resolution: "@metamask/snaps-rpc-methods@npm:11.0.0" +"@metamask/snaps-rpc-methods@npm:^11.1.1": + version: 11.1.1 + resolution: "@metamask/snaps-rpc-methods@npm:11.1.1" dependencies: "@metamask/key-tree": "npm:^9.1.2" "@metamask/permission-controller": "npm:^11.0.0" "@metamask/rpc-errors": "npm:^6.3.1" - "@metamask/snaps-sdk": "npm:^6.2.0" - "@metamask/snaps-utils": "npm:^8.0.0" + "@metamask/snaps-sdk": "npm:^6.5.0" + "@metamask/snaps-utils": "npm:^8.1.1" "@metamask/superstruct": "npm:^3.1.0" - "@metamask/utils": "npm:^9.1.0" + "@metamask/utils": "npm:^9.2.1" "@noble/hashes": "npm:^1.3.1" - checksum: 10/2e594d7f9fde910e87525a6ded9a162d2ea8631249b7868ca710df0d8d25c127674079956976c7443e30c96bedb84bf818748a01aad41cfe69f88524781b994f + checksum: 10/e23279dabc6f4ffe2c6c4a7003a624cd5e79b558d7981ec12c23e54a5da25cb7be9bc7bddfa8b2ce84af28a89b42076a2c14ab004b7a976a4426bf1e1de71b5b languageName: node linkType: hard -"@metamask/snaps-sdk@npm:^6.3.0": - version: 6.3.0 - resolution: "@metamask/snaps-sdk@npm:6.3.0" +"@metamask/snaps-sdk@npm:^6.5.1": + version: 6.5.1 + resolution: "@metamask/snaps-sdk@npm:6.5.1" dependencies: "@metamask/key-tree": "npm:^9.1.2" "@metamask/providers": "npm:^17.1.2" "@metamask/rpc-errors": "npm:^6.3.1" "@metamask/superstruct": "npm:^3.1.0" - "@metamask/utils": "npm:^9.1.0" - checksum: 10/9978532c964973c570ec075000cd3940ce19c873047015f8372c8c589d971ce1f2c7e653afcceed69ad2f910ceacc0f6bd5e4c72446e6f6b4fd1cdbcba362fca + "@metamask/utils": "npm:^9.2.1" + checksum: 10/7831fb2ca61a32ad43e971de9307b221f6bd2f65c84a3286f350cfdd2396166c58db6cd2fac9711654a211c8dc2049e591a79ab720b3f5ad562e434f75e95d32 languageName: node linkType: hard -"@metamask/snaps-utils@npm:^7.4.0, @metamask/snaps-utils@npm:^7.8.1": +"@metamask/snaps-utils@npm:^7.4.0, @metamask/snaps-utils@npm:^7.8.0": version: 7.8.1 resolution: "@metamask/snaps-utils@npm:7.8.1" dependencies: @@ -6389,9 +6367,9 @@ __metadata: languageName: node linkType: hard -"@metamask/snaps-utils@npm:^8.0.0, @metamask/snaps-utils@npm:^8.0.1": - version: 8.0.1 - resolution: "@metamask/snaps-utils@npm:8.0.1" +"@metamask/snaps-utils@npm:^8.1.1": + version: 8.1.1 + resolution: "@metamask/snaps-utils@npm:8.1.1" dependencies: "@babel/core": "npm:^7.23.2" "@babel/types": "npm:^7.23.0" @@ -6401,9 +6379,9 @@ __metadata: "@metamask/rpc-errors": "npm:^6.3.1" "@metamask/slip44": "npm:^4.0.0" "@metamask/snaps-registry": "npm:^3.2.1" - "@metamask/snaps-sdk": "npm:^6.2.1" + "@metamask/snaps-sdk": "npm:^6.5.0" "@metamask/superstruct": "npm:^3.1.0" - "@metamask/utils": "npm:^9.1.0" + "@metamask/utils": "npm:^9.2.1" "@noble/hashes": "npm:^1.3.1" "@scure/base": "npm:^1.1.1" chalk: "npm:^4.1.2" @@ -6416,7 +6394,7 @@ __metadata: semver: "npm:^7.5.4" ses: "npm:^1.1.0" validate-npm-package-name: "npm:^5.0.0" - checksum: 10/4c0d58ad04f1e4c625dd01aaf171de0f538afc2003ac928159deee5ebed6d490ccd50575ad585b4f6846aa8d00bccd8f1ea4b32f124e6427873fb985cae8513f + checksum: 10/f4ceb52a1f9578993c88c82a67f4f041309af51c83ff5caa3fed080f36b54d14ea7da807ce1cf19a13600dd0e77c51af70398e8c7bb78f0ba99a037f4d22610f languageName: node linkType: hard @@ -6501,9 +6479,9 @@ __metadata: languageName: node linkType: hard -"@metamask/transaction-controller@npm:^35.2.0": - version: 35.2.0 - resolution: "@metamask/transaction-controller@npm:35.2.0" +"@metamask/transaction-controller@npm:^37.0.0": + version: 37.0.0 + resolution: "@metamask/transaction-controller@npm:37.0.0" dependencies: "@ethereumjs/common": "npm:^3.2.0" "@ethereumjs/tx": "npm:^4.2.0" @@ -6511,8 +6489,8 @@ __metadata: "@ethersproject/abi": "npm:^5.7.0" "@ethersproject/contracts": "npm:^5.7.0" "@ethersproject/providers": "npm:^5.7.0" - "@metamask/base-controller": "npm:^6.0.3" - "@metamask/controller-utils": "npm:^11.0.2" + "@metamask/base-controller": "npm:^7.0.1" + "@metamask/controller-utils": "npm:^11.3.0" "@metamask/eth-query": "npm:^4.0.0" "@metamask/metamask-eth-abis": "npm:^3.1.1" "@metamask/nonce-tracker": "npm:^6.0.0" @@ -6528,9 +6506,9 @@ __metadata: "@babel/runtime": ^7.23.9 "@metamask/accounts-controller": ^18.0.0 "@metamask/approval-controller": ^7.0.0 - "@metamask/gas-fee-controller": ^19.0.0 - "@metamask/network-controller": ^20.0.0 - checksum: 10/93af57d96860e4363b53ac1365742d77ca82689faf9ececca84309e15298a43a92e76a7ea3871b52b2a1785ff96e003db23e921ad6b4a4b65eddaa12d5edf570 + "@metamask/gas-fee-controller": ^20.0.0 + "@metamask/network-controller": ^21.0.0 + checksum: 10/b4608260cb86ad1a867926b983a21050a2be899f17af909ad2403b5148eada348b0fbb3f7ecef9ebc7cf8d28c040ce4d6f5009709328cda00fab61e10fa94de6 languageName: node linkType: hard @@ -6564,7 +6542,7 @@ __metadata: languageName: node linkType: hard -"@metamask/utils@npm:^8.1.0, @metamask/utils@npm:^8.2.0, @metamask/utils@npm:^8.3.0, @metamask/utils@npm:^8.4.0": +"@metamask/utils@npm:^8.1.0, @metamask/utils@npm:^8.2.0, @metamask/utils@npm:^8.3.0": version: 8.5.0 resolution: "@metamask/utils@npm:8.5.0" dependencies: @@ -6581,9 +6559,9 @@ __metadata: languageName: node linkType: hard -"@metamask/utils@npm:^9.0.0, @metamask/utils@npm:^9.1.0": - version: 9.1.0 - resolution: "@metamask/utils@npm:9.1.0" +"@metamask/utils@npm:^9.0.0, @metamask/utils@npm:^9.1.0, @metamask/utils@npm:^9.2.1": + version: 9.2.1 + resolution: "@metamask/utils@npm:9.2.1" dependencies: "@ethereumjs/tx": "npm:^4.2.0" "@metamask/superstruct": "npm:^3.1.0" @@ -6594,7 +6572,7 @@ __metadata: pony-cause: "npm:^2.1.10" semver: "npm:^7.5.4" uuid: "npm:^9.0.1" - checksum: 10/7335e151a51be92e86868dc48b3ee78c376d4edd5d758d334176027247637ab22839d8f663bd02542c0a19b05ecec456bedab5f36436689cf3d953ca36d91781 + checksum: 10/2192797afd91af19898e107afeaf63e89b61dc7285e0a75d0cc814b5b288e4cdfc856781b01904034c4d2c1efd9bdab512af24c7e4dfe7b77a03f1f3d9dec7e8 languageName: node linkType: hard @@ -6648,9 +6626,18 @@ __metadata: linkType: hard "@noble/ciphers@npm:^0.5.1, @noble/ciphers@npm:^0.5.2": - version: 0.5.2 - resolution: "@noble/ciphers@npm:0.5.2" - checksum: 10/47a5958954249d5edb49aff48ae6fbfff4d4e5a6bb221c010ebc8e7470c410e9208a2f3f6bf8b7eca83057277478f4ccbdbdcf1bfd324608b334b9f9d28a9fbb + version: 0.5.3 + resolution: "@noble/ciphers@npm:0.5.3" + checksum: 10/af0ad96b5807feace93e63549e05de6f5e305b36e2e95f02d90532893fbc3af3f19b9621b6de4caa98303659e5df2e7aa082064e5d4a82e6f38c728d48dfae5d + languageName: node + linkType: hard + +"@noble/curves@npm:1.2.0": + version: 1.2.0 + resolution: "@noble/curves@npm:1.2.0" + dependencies: + "@noble/hashes": "npm:1.3.2" + checksum: 10/94e02e9571a9fd42a3263362451849d2f54405cb3ce9fa7c45bc6b9b36dcd7d1d20e2e1e14cfded24937a13d82f1e60eefc4d7a14982ce0bc219a9fc0f51d1f9 languageName: node linkType: hard @@ -6670,6 +6657,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:1.3.2": + version: 1.3.2 + resolution: "@noble/hashes@npm:1.3.2" + checksum: 10/685f59d2d44d88e738114b71011d343a9f7dce9dfb0a121f1489132f9247baa60bc985e5ec6f3213d114fbd1e1168e7294644e46cbd0ce2eba37994f28eeb51b + languageName: node + linkType: hard + "@noble/hashes@npm:1.4.0, @noble/hashes@npm:^1.1.2, @noble/hashes@npm:^1.2.0, @noble/hashes@npm:^1.3.1, @noble/hashes@npm:^1.3.2, @noble/hashes@npm:^1.3.3, @noble/hashes@npm:^1.4.0, @noble/hashes@npm:~1.4.0": version: 1.4.0 resolution: "@noble/hashes@npm:1.4.0" @@ -9443,7 +9437,7 @@ __metadata: languageName: node linkType: hard -"@swc/types@npm:0.1.7, @swc/types@npm:^0.1.5": +"@swc/types@npm:0.1.7": version: 0.1.7 resolution: "@swc/types@npm:0.1.7" dependencies: @@ -9452,6 +9446,15 @@ __metadata: languageName: node linkType: hard +"@swc/types@npm:^0.1.5": + version: 0.1.12 + resolution: "@swc/types@npm:0.1.12" + dependencies: + "@swc/counter": "npm:^0.1.3" + checksum: 10/92dbbc70cd068ea30fb6fbdc1ae8599d6c058a5d09b2923d6e4e24fab5ad7c86a19dd01f349a8e03e300a9321e06911a24df18303b40e307fbd4109372cef2ef + languageName: node + linkType: hard + "@szmarczak/http-timer@npm:^4.0.5": version: 4.0.6 resolution: "@szmarczak/http-timer@npm:4.0.6" @@ -10683,6 +10686,13 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:18.15.13": + version: 18.15.13 + resolution: "@types/node@npm:18.15.13" + checksum: 10/b9bbe923573797ef7c5fd2641a6793489e25d9369c32aeadcaa5c7c175c85b42eb12d6fe173f6781ab6f42eaa1ebd9576a419eeaa2a1ec810094adb8adaa9a54 + languageName: node + linkType: hard + "@types/node@npm:^12.12.54": version: 12.20.55 resolution: "@types/node@npm:12.20.55" @@ -12084,6 +12094,13 @@ __metadata: languageName: node linkType: hard +"aes-js@npm:4.0.0-beta.5": + version: 4.0.0-beta.5 + resolution: "aes-js@npm:4.0.0-beta.5" + checksum: 10/8f745da2e8fb38e91297a8ec13c2febe3219f8383303cd4ed4660ca67190242ccfd5fdc2f0d1642fd1ea934818fb871cd4cc28d3f28e812e3dc6c3d0f1f97c24 + languageName: node + linkType: hard + "aes-js@npm:^3.1.1, aes-js@npm:^3.1.2": version: 3.1.2 resolution: "aes-js@npm:3.1.2" @@ -18486,13 +18503,6 @@ __metadata: languageName: node linkType: hard -"ethereum-ens-network-map@npm:^1.0.2": - version: 1.0.2 - resolution: "ethereum-ens-network-map@npm:1.0.2" - checksum: 10/34fa160f2b1ee8ec31bfe3dcec7b4becd4a6110acde171f43b9c28e0adc126dbded9dc6747d03088b6c99f04582887e6a23cb24b718321712c85208965835ea1 - languageName: node - linkType: hard - "ethereumjs-util@npm:7.1.5, ethereumjs-util@npm:^7.1.2": version: 7.1.5 resolution: "ethereumjs-util@npm:7.1.5" @@ -18535,6 +18545,44 @@ __metadata: languageName: node linkType: hard +"ethers@npm:5.7.0": + version: 5.7.0 + resolution: "ethers@npm:5.7.0" + dependencies: + "@ethersproject/abi": "npm:5.7.0" + "@ethersproject/abstract-provider": "npm:5.7.0" + "@ethersproject/abstract-signer": "npm:5.7.0" + "@ethersproject/address": "npm:5.7.0" + "@ethersproject/base64": "npm:5.7.0" + "@ethersproject/basex": "npm:5.7.0" + "@ethersproject/bignumber": "npm:5.7.0" + "@ethersproject/bytes": "npm:5.7.0" + "@ethersproject/constants": "npm:5.7.0" + "@ethersproject/contracts": "npm:5.7.0" + "@ethersproject/hash": "npm:5.7.0" + "@ethersproject/hdnode": "npm:5.7.0" + "@ethersproject/json-wallets": "npm:5.7.0" + "@ethersproject/keccak256": "npm:5.7.0" + "@ethersproject/logger": "npm:5.7.0" + "@ethersproject/networks": "npm:5.7.0" + "@ethersproject/pbkdf2": "npm:5.7.0" + "@ethersproject/properties": "npm:5.7.0" + "@ethersproject/providers": "npm:5.7.0" + "@ethersproject/random": "npm:5.7.0" + "@ethersproject/rlp": "npm:5.7.0" + "@ethersproject/sha2": "npm:5.7.0" + "@ethersproject/signing-key": "npm:5.7.0" + "@ethersproject/solidity": "npm:5.7.0" + "@ethersproject/strings": "npm:5.7.0" + "@ethersproject/transactions": "npm:5.7.0" + "@ethersproject/units": "npm:5.7.0" + "@ethersproject/wallet": "npm:5.7.0" + "@ethersproject/web": "npm:5.7.0" + "@ethersproject/wordlists": "npm:5.7.0" + checksum: 10/6b3cb82233573d8cc7edae9ade5d59a95c451dbb828a5aaba81a1959495c76d99e3a7a73f783f92e3f46fe17b18b7042ade627f409583ba89c2d6cbcdd76edcb + languageName: node + linkType: hard + "ethers@npm:^5.7.0, ethers@npm:^5.7.2": version: 5.7.2 resolution: "ethers@npm:5.7.2" @@ -18573,6 +18621,21 @@ __metadata: languageName: node linkType: hard +"ethers@npm:^6.13.1": + version: 6.13.2 + resolution: "ethers@npm:6.13.2" + dependencies: + "@adraffy/ens-normalize": "npm:1.10.1" + "@noble/curves": "npm:1.2.0" + "@noble/hashes": "npm:1.3.2" + "@types/node": "npm:18.15.13" + aes-js: "npm:4.0.0-beta.5" + tslib: "npm:2.4.0" + ws: "npm:8.17.1" + checksum: 10/e611c2e2c5340982dfd1f004895f55abda11748a7edec9e6315226dec42d58aa61b827dd389ec904db5f9a244c475ae795e528da579251fdf62e914bde12809e + languageName: node + linkType: hard + "ethjs-abi@npm:0.2.1, ethjs-abi@npm:^0.2.0": version: 0.2.1 resolution: "ethjs-abi@npm:0.2.1" @@ -23313,7 +23376,7 @@ __metadata: languageName: node linkType: hard -"jest-environment-jsdom@npm:^29.7.0": +"jest-environment-jsdom@npm:29.7.0": version: 29.7.0 resolution: "jest-environment-jsdom@npm:29.7.0" dependencies: @@ -23334,6 +23397,27 @@ __metadata: languageName: node linkType: hard +"jest-environment-jsdom@patch:jest-environment-jsdom@npm%3A29.7.0#~/.yarn/patches/jest-environment-jsdom-npm-29.7.0-0b72dd0e0b.patch": + version: 29.7.0 + resolution: "jest-environment-jsdom@patch:jest-environment-jsdom@npm%3A29.7.0#~/.yarn/patches/jest-environment-jsdom-npm-29.7.0-0b72dd0e0b.patch::version=29.7.0&hash=a6aa71" + dependencies: + "@jest/environment": "npm:^29.7.0" + "@jest/fake-timers": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/jsdom": "npm:^20.0.0" + "@types/node": "npm:*" + jest-mock: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jsdom: "npm:^20.0.0" + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + checksum: 10/ccc6dc855d841cbcaac17c3f8b25bd63827c7766bf4ee555ee7b7c2b9707ae172659be4a813fdddbdd2a933d9d6c23a97e13924e176a68cf44299c57bf1e3009 + languageName: node + linkType: hard + "jest-environment-node@npm:^29.6.4, jest-environment-node@npm:^29.7.0": version: 29.7.0 resolution: "jest-environment-node@npm:29.7.0" @@ -25936,7 +26020,7 @@ __metadata: "@babel/preset-typescript": "npm:^7.23.2" "@babel/register": "npm:^7.22.15" "@babel/runtime": "patch:@babel/runtime@npm%3A7.24.0#~/.yarn/patches/@babel-runtime-npm-7.24.0-7eb1dd11a2.patch" - "@blockaid/ppom_release": "npm:^1.5.2" + "@blockaid/ppom_release": "npm:^1.5.3" "@ensdomains/content-hash": "npm:^2.5.7" "@ethereumjs/tx": "npm:^4.1.1" "@ethersproject/abi": "npm:^5.6.4" @@ -25969,21 +26053,22 @@ __metadata: "@metamask-institutional/types": "npm:^1.1.0" "@metamask/abi-utils": "npm:^2.0.2" "@metamask/account-watcher": "npm:^4.1.0" - "@metamask/accounts-controller": "npm:^18.2.0" + "@metamask/accounts-controller": "npm:^18.2.1" "@metamask/address-book-controller": "npm:^5.0.0" "@metamask/announcement-controller": "npm:^7.0.0" "@metamask/api-specs": "npm:^0.9.3" "@metamask/approval-controller": "npm:^7.0.0" - "@metamask/assets-controllers": "npm:^36.0.0" + "@metamask/assets-controllers": "npm:^37.0.0" "@metamask/auto-changelog": "npm:^2.1.0" "@metamask/base-controller": "npm:^7.0.0" - "@metamask/bitcoin-wallet-snap": "npm:^0.5.0" + "@metamask/bitcoin-wallet-snap": "npm:^0.6.0" "@metamask/browser-passworder": "npm:^4.3.0" "@metamask/build-utils": "npm:^3.0.0" "@metamask/contract-metadata": "npm:^2.5.0" "@metamask/controller-utils": "npm:^11.2.0" "@metamask/design-tokens": "npm:^4.0.0" "@metamask/ens-controller": "npm:^13.0.0" + "@metamask/ens-resolver-snap": "npm:^0.1.2" "@metamask/eslint-config": "npm:^9.0.0" "@metamask/eslint-config-jest": "npm:^9.0.0" "@metamask/eslint-config-mocha": "npm:^9.0.0" @@ -25995,7 +26080,7 @@ __metadata: "@metamask/eth-ledger-bridge-keyring": "npm:^3.0.1" "@metamask/eth-query": "npm:^4.0.0" "@metamask/eth-sig-util": "npm:^7.0.1" - "@metamask/eth-snap-keyring": "npm:^4.3.1" + "@metamask/eth-snap-keyring": "npm:^4.3.3" "@metamask/eth-token-tracker": "npm:^8.0.0" "@metamask/eth-trezor-keyring": "npm:^3.1.0" "@metamask/etherscan-link": "npm:^3.0.0" @@ -26005,8 +26090,8 @@ __metadata: "@metamask/forwarder": "npm:^1.1.0" "@metamask/gas-fee-controller": "npm:^18.0.0" "@metamask/jazzicon": "npm:^2.0.0" - "@metamask/keyring-api": "npm:^8.0.0" - "@metamask/keyring-controller": "patch:@metamask/keyring-controller@npm%3A17.1.1#~/.yarn/patches/@metamask-keyring-controller-npm-17.1.1-098cb41930.patch" + "@metamask/keyring-api": "npm:^8.1.0" + "@metamask/keyring-controller": "npm:^17.2.1" "@metamask/logging-controller": "npm:^6.0.0" "@metamask/logo": "npm:^3.1.2" "@metamask/message-manager": "npm:^10.1.0" @@ -26015,7 +26100,7 @@ __metadata: "@metamask/name-controller": "npm:^8.0.0" "@metamask/network-controller": "patch:@metamask/network-controller@npm%3A20.2.0#~/.yarn/patches/@metamask-network-controller-npm-20.2.0-98b1a5ae59.patch" "@metamask/notification-controller": "npm:^6.0.0" - "@metamask/notification-services-controller": "npm:^0.5.0" + "@metamask/notification-services-controller": "npm:^0.7.0" "@metamask/object-multiplex": "npm:^2.0.0" "@metamask/obs-store": "npm:^9.0.0" "@metamask/permission-controller": "npm:^10.0.0" @@ -26024,7 +26109,7 @@ __metadata: "@metamask/phishing-warning": "npm:^4.0.0" "@metamask/post-message-stream": "npm:^8.0.0" "@metamask/ppom-validator": "npm:0.34.0" - "@metamask/profile-sync-controller": "npm:^0.5.0" + "@metamask/profile-sync-controller": "npm:^0.8.0" "@metamask/providers": "npm:^14.0.2" "@metamask/queued-request-controller": "npm:^2.0.0" "@metamask/rate-limit-controller": "npm:^6.0.0" @@ -26034,14 +26119,14 @@ __metadata: "@metamask/selected-network-controller": "npm:^15.0.2" "@metamask/signature-controller": "npm:^19.0.0" "@metamask/smart-transactions-controller": "npm:^13.0.0" - "@metamask/snaps-controllers": "npm:^9.5.0" - "@metamask/snaps-execution-environments": "npm:^6.6.2" - "@metamask/snaps-rpc-methods": "npm:^11.0.0" - "@metamask/snaps-sdk": "npm:^6.3.0" - "@metamask/snaps-utils": "npm:^8.0.1" + "@metamask/snaps-controllers": "npm:^9.7.0" + "@metamask/snaps-execution-environments": "npm:^6.7.2" + "@metamask/snaps-rpc-methods": "npm:^11.1.1" + "@metamask/snaps-sdk": "npm:^6.5.1" + "@metamask/snaps-utils": "npm:^8.1.1" "@metamask/test-bundler": "npm:^1.0.0" "@metamask/test-dapp": "npm:^8.4.0" - "@metamask/transaction-controller": "npm:^35.2.0" + "@metamask/transaction-controller": "npm:^37.0.0" "@metamask/user-operation-controller": "npm:^13.0.0" "@metamask/utils": "npm:^9.1.0" "@ngraveio/bc-ur": "npm:^1.1.12" @@ -26182,8 +26267,8 @@ __metadata: eth-lattice-keyring: "npm:^0.12.4" eth-method-registry: "npm:^4.0.0" eth-rpc-errors: "npm:^4.0.2" - ethereum-ens-network-map: "npm:^1.0.2" ethereumjs-util: "npm:^7.0.10" + ethers: "npm:5.7.0" extension-port-stream: "npm:^3.0.0" fake-indexeddb: "npm:^4.0.1" fancy-log: "npm:^1.3.3" @@ -26216,7 +26301,7 @@ __metadata: is-retry-allowed: "npm:^2.2.0" jest: "npm:^29.7.0" jest-canvas-mock: "npm:^2.3.1" - jest-environment-jsdom: "npm:^29.7.0" + jest-environment-jsdom: "patch:jest-environment-jsdom@npm%3A29.7.0#~/.yarn/patches/jest-environment-jsdom-npm-29.7.0-0b72dd0e0b.patch" jest-junit: "npm:^14.0.1" jsdom: "npm:^16.7.0" json-rpc-engine: "npm:^6.1.0" @@ -27293,7 +27378,14 @@ __metadata: languageName: node linkType: hard -"multiformats@npm:^9.4.2, multiformats@npm:^9.5.2": +"multiformats@npm:^13.1.0": + version: 13.2.2 + resolution: "multiformats@npm:13.2.2" + checksum: 10/6e673320e9b06d5fdbbf2bde0d3132f13fac94fb40f36d646265b5c38eba4a28c40a2c76b4efa0c1a23517fe87320e540e9ef7f28d71c1cc3239c91bf6770ce6 + languageName: node + linkType: hard + +"multiformats@npm:^9.4.2": version: 9.9.0 resolution: "multiformats@npm:9.9.0" checksum: 10/ad55c7d480d22f4258a68fd88aa2aab744fe0cb1e68d732fc886f67d858b37e3aa6c2cec12b2960ead7730d43be690931485238569952d8a3d7f90fdc726c652 @@ -34866,6 +34958,13 @@ __metadata: languageName: node linkType: hard +"tslib@npm:2.4.0": + version: 2.4.0 + resolution: "tslib@npm:2.4.0" + checksum: 10/d8379e68b36caf082c1905ec25d17df8261e1d68ddc1abfd6c91158a064f6e4402039ae7c02cf4c81d12e3a2a2c7cd8ea2f57b233eb80136a2e3e7279daf2911 + languageName: node + linkType: hard + "tslib@npm:^1.13.0, tslib@npm:^1.8.1, tslib@npm:^1.9.0": version: 1.14.1 resolution: "tslib@npm:1.14.1" @@ -36996,7 +37095,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:*, ws@npm:>=8.14.2, ws@npm:^8.0.0, ws@npm:^8.11.0, ws@npm:^8.16.0, ws@npm:^8.17.1, ws@npm:^8.2.3, ws@npm:^8.5.0, ws@npm:^8.8.0": +"ws@npm:*, ws@npm:8.17.1, ws@npm:>=8.14.2, ws@npm:^8.0.0, ws@npm:^8.11.0, ws@npm:^8.16.0, ws@npm:^8.17.1, ws@npm:^8.2.3, ws@npm:^8.5.0, ws@npm:^8.8.0": version: 8.17.1 resolution: "ws@npm:8.17.1" peerDependencies: