From ace7b0cda9585dabdc561c648f7d6c721275ae63 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 15 Nov 2022 14:22:08 -0330 Subject: [PATCH] Revert "Revert "Merge pull request #16353 from MetaMask/Version-v10.22.0"" This reverts commit d91ce9c4b5044e906f254516a95d87ed74f794d6. --- .circleci/config.yml | 37 +- .circleci/scripts/bundle-stats-commit.sh | 22 + .circleci/scripts/chrome-install.sh | 4 +- .github/workflows/cla.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/crowdin_action.yml | 2 +- .iyarc | 3 - .storybook/test-data.js | 8 - CHANGELOG.md | 1 + app/_locales/de/messages.json | 20 - app/_locales/el/messages.json | 20 - app/_locales/en/messages.json | 51 +- app/_locales/es/messages.json | 20 - app/_locales/es_419/messages.json | 16 - app/_locales/fr/messages.json | 20 - app/_locales/hi/messages.json | 20 - app/_locales/id/messages.json | 20 - app/_locales/it/messages.json | 16 - app/_locales/ja/messages.json | 20 - app/_locales/ko/messages.json | 20 - app/_locales/ph/messages.json | 16 - app/_locales/pt/messages.json | 20 - app/_locales/pt_BR/messages.json | 16 - app/_locales/ru/messages.json | 20 - app/_locales/tl/messages.json | 20 - app/_locales/tr/messages.json | 20 - app/_locales/vi/messages.json | 20 - app/_locales/zh/messages.json | 4114 ---------------- app/_locales/zh_CN/messages.json | 20 - app/images/aurora.png | Bin 0 -> 48350 bytes app/images/icons/icon-search-filled.svg | 2 +- app/scripts/background.js | 55 +- app/scripts/controllers/metametrics.js | 56 +- app/scripts/controllers/metametrics.test.js | 5 - app/scripts/controllers/threebox.js | 305 -- app/scripts/controllers/transactions/index.js | 2 +- app/scripts/lib/createMetaRPCHandler.js | 7 +- .../lib/get-first-preferred-lang-code.js | 4 +- app/scripts/lib/local-store.js | 50 +- app/scripts/lib/local-store.test.js | 79 + app/scripts/lib/network-store.js | 25 +- app/scripts/lib/segment/analytics.js | 275 ++ app/scripts/lib/segment/analytics.test.js | 116 + .../lib/{segment.js => segment/index.js} | 4 +- app/scripts/lib/setupSentry.js | 7 +- app/scripts/lib/util.js | 12 + .../metamask-controller.actions.test.js | 138 + app/scripts/metamask-controller.js | 152 +- app/scripts/metamask-controller.test.js | 57 +- app/scripts/migrations/075.js | 23 + app/scripts/migrations/075.test.js | 63 + app/scripts/migrations/index.js | 2 + app/scripts/ui.js | 107 +- development/generate-lavamoat-policies.js | 13 +- development/mock-3box.js | 68 - .../files-to-convert.json | 1 - .../generating-fixture-data.md | 7 - jest.config.js | 2 +- lavamoat/browserify/beta/policy.json | 2811 ++--------- lavamoat/browserify/flask/policy.json | 2850 ++--------- lavamoat/browserify/main/policy.json | 2811 ++--------- lavamoat/browserify/policy-override.json | 5 - lavamoat/build-system/policy.json | 76 +- package.json | 47 +- ...tonehq+bc-ur-registry+0.5.0-alpha.5.patch} | 309 +- patches/secp256k1+3.8.0.patch | 37 - shared/constants/alarms.js | 2 + shared/constants/metametrics.js | 8 +- shared/constants/network.ts | 20 + shared/modules/provider-injection.js | 1 - test/e2e/benchmark.js | 24 +- test/e2e/fixture-builder.js | 1103 +++++ test/e2e/fixture-server.js | 18 +- test/e2e/fixtures/address-entry/state.json | 169 - test/e2e/fixtures/connected-state/state.json | 200 - test/e2e/fixtures/custom-rpc/state.json | 170 - test/e2e/fixtures/custom-token/state.json | 178 - test/e2e/fixtures/eip-1559-v2-dapp/state.json | 160 - test/e2e/fixtures/eip-1559-v2/state.json | 229 - test/e2e/fixtures/import-ui/state.json | 272 -- test/e2e/fixtures/imported-account/state.json | 157 - test/e2e/fixtures/localization/state.json | 156 - test/e2e/fixtures/metrics-enabled/state.json | 200 - .../fixtures/navigate-transactions/state.json | 442 -- test/e2e/fixtures/onboarding/state.json | 59 - test/e2e/fixtures/send-edit-v2/state.json | 229 - test/e2e/fixtures/send-edit/state.json | 235 - test/e2e/fixtures/special-settings/state.json | 158 - test/e2e/fixtures/threebox-enabled/state.json | 155 - test/e2e/helpers.js | 23 +- .../test-json-import-account-file.json | 0 test/e2e/lavamoat-stats.js | 66 +- test/e2e/mock-3box/threebox-mock-server.js | 57 - test/e2e/mock-e2e.js | 13 +- test/e2e/mv3-perf-stats/init-load-stats.js | 72 +- test/e2e/mv3-stats.js | 72 +- test/e2e/restore/MetaMaskUserData.json | 50 + test/e2e/run-all.js | 19 +- test/e2e/snaps/enums.js | 2 +- test/e2e/snaps/test-snap-bip-32.spec.js | 157 + test/e2e/snaps/test-snap-bip-44.spec.js | 32 +- test/e2e/snaps/test-snap-confirm.spec.js | 28 +- test/e2e/snaps/test-snap-error.spec.js | 27 +- test/e2e/snaps/test-snap-get-snaps.spec.js | 92 + test/e2e/snaps/test-snap-managestate.spec.js | 23 +- test/e2e/snaps/test-snap-notification.spec.js | 23 +- test/e2e/snaps/test-snap-update.spec.js | 24 +- test/e2e/swaps/shared.js | 71 + test/e2e/{tests => swaps}/swap-eth.spec.js | 52 +- test/e2e/swaps/swaps-notifications.spec.js | 130 + test/e2e/tests/account-details.spec.js | 3 +- test/e2e/tests/add-account.spec.js | 7 +- test/e2e/tests/add-hide-token.spec.js | 35 +- test/e2e/tests/address-book.spec.js | 123 +- test/e2e/tests/advanced-settings.spec.js | 5 +- test/e2e/tests/auto-lock.spec.js | 3 +- ...{backup.spec.js => backup-restore.spec.js} | 51 +- test/e2e/tests/chain-interactions.spec.js | 9 +- test/e2e/tests/collectibles.spec.js | 17 +- test/e2e/tests/contract-interactions.spec.js | 5 +- test/e2e/tests/custom-rpc-history.spec.js | 55 +- .../tests/custom-token-add-approve.spec.js | 17 +- test/e2e/tests/dapp-interactions.spec.js | 23 +- test/e2e/tests/edit-gas-fee.spec.js | 35 +- test/e2e/tests/encrypt-decrypt.spec.js | 93 + test/e2e/tests/errors.spec.js | 8 +- test/e2e/tests/eth-sign.spec.js | 5 +- test/e2e/tests/failing-contract.spec.js | 5 +- test/e2e/tests/from-import-ui.spec.js | 23 +- test/e2e/tests/gas-api-fallback.spec.js | 70 + test/e2e/tests/incremental-security.spec.js | 4 +- test/e2e/tests/localization.spec.js | 16 +- test/e2e/tests/lock-account.spec.js | 3 +- test/e2e/tests/lockdown.spec.js | 3 +- test/e2e/tests/metamask-responsive-ui.spec.js | 7 +- test/e2e/tests/metrics.spec.js | 8 +- test/e2e/tests/navigate-transactions.spec.js | 22 +- test/e2e/tests/permissions.spec.js | 3 +- test/e2e/tests/personal-sign.spec.js | 5 +- test/e2e/tests/phishing-detection.spec.js | 9 +- test/e2e/tests/portfolio-site.spec.js | 3 +- test/e2e/tests/provider-api.spec.js | 9 +- test/e2e/tests/send-edit.spec.js | 12 +- test/e2e/tests/send-eth.spec.js | 17 +- test/e2e/tests/send-hex-address.spec.js | 13 +- test/e2e/tests/send-to-contract.spec.js | 5 +- test/e2e/tests/settings-general.spec.js | 3 +- test/e2e/tests/settings-search.spec.js | 19 +- test/e2e/tests/signature-request.spec.js | 13 +- test/e2e/tests/simple-send.spec.js | 7 +- test/e2e/tests/state-logs.spec.js | 3 +- .../tests/stuck-approved-transaction.spec.js | 47 + test/e2e/tests/threebox.spec.js | 92 - test/e2e/tests/token-details.spec.js | 3 +- test/e2e/user-actions-benchmark.js | 5 +- test/e2e/webdriver/driver.js | 8 + test/env.js | 9 + test/jest/index.js | 2 +- test/jest/mock-store.js | 17 +- ui/components/app/app-components.scss | 1 + .../approve-content-card.js | 241 + .../app/approve-content-card/index.js | 1 + .../app/approve-content-card/index.scss | 51 + .../app/asset-list-item/asset-list-item.js | 1 + ...onfirm-page-container-content.component.js | 42 +- .../confirm-page-container.component.js | 22 +- .../confirm-page-container.container.js | 12 +- .../confirm-page-container/flask/index.scss | 5 + .../flask/snap-insight.js | 17 +- .../edit-gas-display.component.js | 1 + .../contract-details-modal.js | 146 +- .../contract-details-modal.stories.js | 67 +- .../modals/contract-details-modal/index.scss | 10 +- .../reject-transactions.test.js.snap | 52 + .../reject-transactions.test.js | 49 +- .../transaction-confirmed.test.js.snap | 42 + .../transaction-confirmed.test.js | 34 +- .../permissions-connect-header.component.js | 3 + .../selected-account-component.test.js.snap | 56 + .../selected-account-component.test.js | 42 +- .../selected-account.component.js | 1 + .../signature-request-original.test.js.snap | 6 +- .../app/signature-request-siwe/index.scss | 19 +- .../signature-request-siwe-header/index.scss | 4 + .../signature-request-siwe-header.js | 21 +- .../signature-request-siwe-header.stories.js | 12 + .../signature-request-siwe-icon/index.js | 25 + .../signature-request-siwe-icon/index.scss | 5 + .../signature-request-siwe-icon.stories.js | 11 + .../signature-request-siwe-tag/index.js | 45 + .../signature-request-siwe-tag.stories.js | 18 + .../signature-request-siwe.js | 18 +- .../__snapshots__/token-cell.test.js.snap | 105 + .../app/token-cell/token-cell.test.js | 77 +- ...action-activity-log.component.test.js.snap | 103 + ...transaction-activity-log.component.test.js | 204 +- ...ction-breakdown-row.component.test.js.snap | 29 + ...ransaction-breakdown-row.component.test.js | 39 +- .../transaction-status.component.test.js.snap | 60 + .../transaction-status.component.test.js | 77 +- ...-preferenced-currency-display.test.js.snap | 24 + ...erenced-currency-display.component.test.js | 41 - .../user-preferenced-currency-display.test.js | 29 + ...er-preferenced-currency-input.test.js.snap | 45 + ...eferenced-currency-input.component.test.js | 31 - ...eferenced-currency-input.container.test.js | 32 - .../user-preferenced-currency-input.test.js | 20 + .../user-preferenced-token-input.test.js.snap | 31 + ...-preferenced-token-input.component.test.js | 32 - ...-preferenced-token-input.container.test.js | 29 - .../user-preferenced-token-input.test.js | 26 + .../avatar-account/README.mdx | 43 + .../avatar-account.constants.js | 12 + .../avatar-account/avatar-account.js | 54 + .../avatar-account/avatar-account.scss | 5 + .../avatar-account/avatar-account.stories.js | 59 + .../avatar-account/avatar-account.test.js | 23 + .../component-library/avatar-account/index.js | 1 + .../avatar-favicon/README.mdx | 44 + .../avatar-favicon/avatar-favicon.js | 82 + .../avatar-favicon/avatar-favicon.scss | 5 + .../avatar-favicon/avatar-favicon.stories.js | 57 + .../avatar-favicon/avatar-favicon.test.js | 46 + .../component-library/avatar-favicon/index.js | 1 + .../avatar-with-badge/README.mdx | 37 + .../avatar-with-badge.constants.js | 4 + .../avatar-with-badge/avatar-with-badge.js | 56 + .../avatar-with-badge/avatar-with-badge.scss | 16 + .../avatar-with-badge.stories.js | 91 + .../avatar-with-badge.test.js | 90 + .../avatar-with-badge/index.js | 1 + .../base-avatar/base-avatar.scss | 2 + .../component-library/button-base/README.mdx | 130 + .../button-base/button-base.js | 139 + .../button-base/button-base.scss | 79 + .../button-base/button-base.stories.js | 168 + .../button-base/button-base.test.js | 91 + .../button-base/button.constants.js | 8 + .../component-library/button-base/index.js | 2 + .../component-library/button-link/README.mdx | 73 + .../button-link/button-link.constants.js | 8 + .../button-link/button-link.js | 45 + .../button-link/button-link.scss | 43 + .../button-link/button-link.stories.js | 156 + .../button-link/button-link.test.js | 84 + .../component-library/button-link/index.js | 1 + .../button-primary/README.mdx | 57 + .../button-primary.constants.js | 7 + .../button-primary/button-primary.js | 45 + .../button-primary/button-primary.scss | 43 + .../button-primary/button-primary.stories.js | 133 + .../button-primary/button-primary.test.js | 97 + .../component-library/button-primary/index.js | 1 + .../button-secondary/README.mdx | 57 + .../button-secondary.constants.js | 7 + .../button-secondary/button-secondary.js | 45 + .../button-secondary/button-secondary.scss | 51 + .../button-secondary.stories.js | 133 + .../button-secondary/button-secondary.test.js | 101 + .../button-secondary/index.js | 1 + .../component-library-components.scss | 10 + ui/components/component-library/icon/icon.js | 2 +- .../component-library/tag/README.mdx | 21 + ui/components/component-library/tag/index.js | 1 + ui/components/component-library/tag/tag.js | 50 + ui/components/component-library/tag/tag.scss | 6 + .../component-library/tag/tag.stories.js | 26 + .../component-library/tag/tag.test.js | 13 + .../text-field-base/README.mdx | 302 ++ .../text-field-base/index.js | 5 + .../text-field-base.constants.js | 12 + .../text-field-base/text-field-base.js | 259 + .../text-field-base/text-field-base.scss | 53 + .../text-field-base.stories.js | 381 ++ .../text-field-base/text-field-base.test.js | 238 + .../component-library/text-field/README.mdx | 73 + .../component-library/text-field/index.js | 2 + .../text-field/text-field.constants.js | 7 + .../text-field/text-field.js | 108 + .../text-field/text-field.scss | 10 + .../text-field/text-field.stories.js | 247 + .../text-field/text-field.test.js | 161 + .../component-library/text/README.mdx | 3 + ui/components/component-library/text/text.js | 111 +- .../component-library/text/text.scss | 8 + .../component-library/text/text.stories.js | 19 +- .../component-library/text/text.test.js | 5 + ...nt-mismatch-warning.component.test.js.snap | 36 + ...cccount-mismatch-warning.component.test.js | 50 +- .../actionable-message/actionable-message.js | 7 +- .../ui/alert/__snapshots__/index.test.js.snap | 15 + ui/components/ui/alert/index.test.js | 23 +- ui/components/ui/box/README.mdx | 83 +- ui/components/ui/box/box.js | 118 +- ui/components/ui/box/box.scss | 14 +- ui/components/ui/box/box.stories.js | 78 +- ui/components/ui/box/box.test.js | 70 +- .../breadcrumbs.component.test.js.snap | 19 + .../breadcrumbs/breadcrumbs.component.test.js | 26 +- .../confusable.component.test.js.snap | 58 + .../confusable/confusable.component.test.js | 39 +- .../contract-token-values.js | 29 +- .../currency-display.component.test.js.snap | 54 + .../currency-display.component.test.js | 63 +- .../error-message.component.test.js.snap | 35 + .../error-message.component.test.js | 34 +- .../hex-to-decimal.component.test.js.snap | 21 + .../hex-to-decimal.component.test.js | 28 +- .../list-item.component.test.js.snap | 135 + .../ui/list-item/list-item.component.test.js | 89 +- ui/components/ui/nft-info/index.js | 1 + ui/components/ui/nft-info/index.scss | 9 + ui/components/ui/nft-info/nft-info.js | 64 + ui/components/ui/nft-info/nft-info.stories.js | 29 + .../ui/review-spending-cap/index.scss | 2 +- .../review-spending-cap.js | 4 +- ui/components/ui/site-origin/site-origin.js | 11 +- .../ui/site-origin/site-origin.test.js | 24 + ui/components/ui/ui-components.scss | 1 + ui/ducks/app/app.js | 18 - ui/ducks/ens.js | 27 +- ui/ducks/swaps/swaps.js | 16 +- ui/ducks/swaps/swaps.test.js | 708 ++- ui/helpers/constants/design-system.js | 13 +- ui/helpers/constants/settings.js | 14 +- ui/helpers/utils/settings-search.test.js | 8 +- ui/hooks/flask/useTransactionInsightSnap.js | 2 +- .../confirm-approve-content.component.js | 17 +- ui/pages/confirm-approve/confirm-approve.js | 291 +- .../confirm-transaction-base.component.js | 21 +- .../confirm-transaction-base.container.js | 24 +- .../transaction-alerts/transaction-alerts.js | 54 +- .../transaction-alerts.test.js | 24 - .../import-with-seed-phrase.component.js | 5 +- .../import-with-seed-phrase.container.js | 6 +- .../confirm-seed-phrase-component.test.js | 3 - .../confirm-seed-phrase.component.js | 4 +- .../confirm-seed-phrase.container.js | 6 +- .../seed-phrase/seed-phrase-intro/index.scss | 5 +- ui/pages/home/home.component.js | 60 +- ui/pages/home/home.container.js | 25 +- .../__snapshots__/reveal-seed.test.js.snap | 92 + ui/pages/keychains/restore-vault.js | 6 - ui/pages/keychains/reveal-seed.js | 1 + ui/pages/keychains/reveal-seed.test.js | 48 +- .../creation-successful.js | 9 +- ui/pages/pages.scss | 1 + ui/pages/permissions-connect/flask/util.js | 4 +- .../advanced-tab/advanced-tab.component.js | 54 - .../advanced-tab.component.test.js | 17 +- .../advanced-tab/advanced-tab.container.js | 13 - .../advanced-tab/advanced-tab.stories.js | 14 - ui/pages/settings/info-tab/index.scss | 4 + .../settings/info-tab/info-tab.component.js | 16 + .../networks-form/networks-form.js | 33 +- .../networks-form/networks-form.test.js | 23 +- .../__snapshots__/awaiting-swap.test.js.snap | 2 +- ui/pages/swaps/awaiting-swap/awaiting-swap.js | 1 + .../swaps/awaiting-swap/awaiting-swap.test.js | 128 +- ui/pages/swaps/build-quote/build-quote.js | 54 +- .../swaps/build-quote/build-quote.test.js | 120 +- .../create-new-swap/create-new-swap.test.js | 53 + .../dropdown-input-pair.test.js | 15 + .../dropdown-search-list.test.js.snap | 1 + .../dropdown-search-list.js | 4 + .../dropdown-search-list.test.js | 19 + .../exchange-rate-display.test.js.snap | 2 + .../exchange-rate-display.js | 2 + .../exchange-rate-display.test.js | 16 +- .../__snapshots__/fee-card.test.js.snap | 29 + ui/pages/swaps/fee-card/fee-card.js | 4 +- ui/pages/swaps/fee-card/fee-card.test.js | 22 + ui/pages/swaps/import-token/import-token.js | 5 +- .../main-quote-summary.test.js.snap | 2 + .../searchable-item-list.test.js.snap | 1 + .../item-list.component.test.js.snap | 51 + .../item-list/item-list.component.js | 2 + .../item-list/item-list.component.test.js | 82 + .../list-item-search.component.js | 41 +- .../list-item-search.component.test.js | 111 + .../searchable-item-list.js | 2 +- .../quote-details/quote-details.test.js | 33 + .../__snapshots__/sort-list.test.js.snap | 4 + .../sort-list/sort-list.js | 5 + .../sort-list/sort-list.test.js | 30 +- .../slippage-buttons.test.js.snap | 4 +- .../slippage-buttons/slippage-buttons.js | 1 + .../slippage-buttons/slippage-buttons.test.js | 85 +- .../smart-transaction-status.test.js | 129 + .../swaps/swaps-footer/swaps-footer.test.js | 13 +- ui/pages/swaps/swaps.util.test.js | 51 +- .../view-on-block-explorer.test.js | 15 +- .../__snapshots__/view-quote.test.js.snap | 4 + ui/pages/swaps/view-quote/view-quote.js | 108 +- ui/pages/token-allowance/index.js | 1 + ui/pages/token-allowance/index.scss | 41 + ui/pages/token-allowance/token-allowance.js | 438 ++ .../token-allowance.stories.js | 201 + .../__snapshots__/unlock-page.test.js.snap | 101 + ui/pages/unlock-page/unlock-page.component.js | 2 + .../unlock-page/unlock-page.component.test.js | 29 - .../unlock-page/unlock-page.container.test.js | 48 - ui/pages/unlock-page/unlock-page.test.js | 65 + ui/selectors/permissions.js | 2 +- ui/selectors/selectors.js | 62 +- ui/store/actions.js | 102 - yarn.lock | 4221 +---------------- 407 files changed, 15238 insertions(+), 22572 deletions(-) delete mode 100644 app/_locales/zh/messages.json create mode 100644 app/images/aurora.png delete mode 100644 app/scripts/controllers/threebox.js create mode 100644 app/scripts/lib/local-store.test.js create mode 100644 app/scripts/lib/segment/analytics.js create mode 100644 app/scripts/lib/segment/analytics.test.js rename app/scripts/lib/{segment.js => segment/index.js} (96%) create mode 100644 app/scripts/migrations/075.js create mode 100644 app/scripts/migrations/075.test.js delete mode 100644 development/mock-3box.js rename test/e2e/fixtures/README.md => docs/generating-fixture-data.md (63%) rename patches/{@keystonehq+bc-ur-registry+0.4.4.patch => @keystonehq+bc-ur-registry+0.5.0-alpha.5.patch} (87%) delete mode 100644 patches/secp256k1+3.8.0.patch create mode 100644 test/e2e/fixture-builder.js delete mode 100644 test/e2e/fixtures/address-entry/state.json delete mode 100644 test/e2e/fixtures/connected-state/state.json delete mode 100644 test/e2e/fixtures/custom-rpc/state.json delete mode 100644 test/e2e/fixtures/custom-token/state.json delete mode 100644 test/e2e/fixtures/eip-1559-v2-dapp/state.json delete mode 100644 test/e2e/fixtures/eip-1559-v2/state.json delete mode 100644 test/e2e/fixtures/import-ui/state.json delete mode 100644 test/e2e/fixtures/imported-account/state.json delete mode 100644 test/e2e/fixtures/localization/state.json delete mode 100644 test/e2e/fixtures/metrics-enabled/state.json delete mode 100644 test/e2e/fixtures/navigate-transactions/state.json delete mode 100644 test/e2e/fixtures/onboarding/state.json delete mode 100644 test/e2e/fixtures/send-edit-v2/state.json delete mode 100644 test/e2e/fixtures/send-edit/state.json delete mode 100644 test/e2e/fixtures/special-settings/state.json delete mode 100644 test/e2e/fixtures/threebox-enabled/state.json rename test/e2e/{fixtures => }/import-utc-json/test-json-import-account-file.json (100%) delete mode 100644 test/e2e/mock-3box/threebox-mock-server.js create mode 100644 test/e2e/restore/MetaMaskUserData.json create mode 100644 test/e2e/snaps/test-snap-bip-32.spec.js create mode 100644 test/e2e/snaps/test-snap-get-snaps.spec.js create mode 100644 test/e2e/swaps/shared.js rename test/e2e/{tests => swaps}/swap-eth.spec.js (59%) create mode 100644 test/e2e/swaps/swaps-notifications.spec.js rename test/e2e/tests/{backup.spec.js => backup-restore.spec.js} (56%) create mode 100644 test/e2e/tests/encrypt-decrypt.spec.js create mode 100644 test/e2e/tests/gas-api-fallback.spec.js create mode 100644 test/e2e/tests/stuck-approved-transaction.spec.js delete mode 100644 test/e2e/tests/threebox.spec.js create mode 100644 ui/components/app/approve-content-card/approve-content-card.js create mode 100644 ui/components/app/approve-content-card/index.js create mode 100644 ui/components/app/approve-content-card/index.scss create mode 100644 ui/components/app/modals/reject-transactions/__snapshots__/reject-transactions.test.js.snap create mode 100644 ui/components/app/modals/transaction-confirmed/__snapshots__/transaction-confirmed.test.js.snap create mode 100644 ui/components/app/selected-account/__snapshots__/selected-account-component.test.js.snap create mode 100644 ui/components/app/signature-request-siwe/signature-request-siwe-icon/index.js create mode 100644 ui/components/app/signature-request-siwe/signature-request-siwe-icon/index.scss create mode 100644 ui/components/app/signature-request-siwe/signature-request-siwe-icon/signature-request-siwe-icon.stories.js create mode 100644 ui/components/app/signature-request-siwe/signature-request-siwe-tag/index.js create mode 100644 ui/components/app/signature-request-siwe/signature-request-siwe-tag/signature-request-siwe-tag.stories.js create mode 100644 ui/components/app/token-cell/__snapshots__/token-cell.test.js.snap create mode 100644 ui/components/app/transaction-activity-log/__snapshots__/transaction-activity-log.component.test.js.snap create mode 100644 ui/components/app/transaction-breakdown/transaction-breakdown-row/__snapshots__/transaction-breakdown-row.component.test.js.snap create mode 100644 ui/components/app/transaction-status/__snapshots__/transaction-status.component.test.js.snap create mode 100644 ui/components/app/user-preferenced-currency-display/__snapshots__/user-preferenced-currency-display.test.js.snap delete mode 100644 ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.test.js create mode 100644 ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.test.js create mode 100644 ui/components/app/user-preferenced-currency-input/__snapshots__/user-preferenced-currency-input.test.js.snap delete mode 100644 ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.component.test.js delete mode 100644 ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.test.js create mode 100644 ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.test.js create mode 100644 ui/components/app/user-preferenced-token-input/__snapshots__/user-preferenced-token-input.test.js.snap delete mode 100644 ui/components/app/user-preferenced-token-input/user-preferenced-token-input.component.test.js delete mode 100644 ui/components/app/user-preferenced-token-input/user-preferenced-token-input.container.test.js create mode 100644 ui/components/app/user-preferenced-token-input/user-preferenced-token-input.test.js create mode 100644 ui/components/component-library/avatar-account/README.mdx create mode 100644 ui/components/component-library/avatar-account/avatar-account.constants.js create mode 100644 ui/components/component-library/avatar-account/avatar-account.js create mode 100644 ui/components/component-library/avatar-account/avatar-account.scss create mode 100644 ui/components/component-library/avatar-account/avatar-account.stories.js create mode 100644 ui/components/component-library/avatar-account/avatar-account.test.js create mode 100644 ui/components/component-library/avatar-account/index.js create mode 100644 ui/components/component-library/avatar-favicon/README.mdx create mode 100644 ui/components/component-library/avatar-favicon/avatar-favicon.js create mode 100644 ui/components/component-library/avatar-favicon/avatar-favicon.scss create mode 100644 ui/components/component-library/avatar-favicon/avatar-favicon.stories.js create mode 100644 ui/components/component-library/avatar-favicon/avatar-favicon.test.js create mode 100644 ui/components/component-library/avatar-favicon/index.js create mode 100644 ui/components/component-library/avatar-with-badge/README.mdx create mode 100644 ui/components/component-library/avatar-with-badge/avatar-with-badge.constants.js create mode 100644 ui/components/component-library/avatar-with-badge/avatar-with-badge.js create mode 100644 ui/components/component-library/avatar-with-badge/avatar-with-badge.scss create mode 100644 ui/components/component-library/avatar-with-badge/avatar-with-badge.stories.js create mode 100644 ui/components/component-library/avatar-with-badge/avatar-with-badge.test.js create mode 100644 ui/components/component-library/avatar-with-badge/index.js create mode 100644 ui/components/component-library/button-base/README.mdx create mode 100644 ui/components/component-library/button-base/button-base.js create mode 100644 ui/components/component-library/button-base/button-base.scss create mode 100644 ui/components/component-library/button-base/button-base.stories.js create mode 100644 ui/components/component-library/button-base/button-base.test.js create mode 100644 ui/components/component-library/button-base/button.constants.js create mode 100644 ui/components/component-library/button-base/index.js create mode 100644 ui/components/component-library/button-link/README.mdx create mode 100644 ui/components/component-library/button-link/button-link.constants.js create mode 100644 ui/components/component-library/button-link/button-link.js create mode 100644 ui/components/component-library/button-link/button-link.scss create mode 100644 ui/components/component-library/button-link/button-link.stories.js create mode 100644 ui/components/component-library/button-link/button-link.test.js create mode 100644 ui/components/component-library/button-link/index.js create mode 100644 ui/components/component-library/button-primary/README.mdx create mode 100644 ui/components/component-library/button-primary/button-primary.constants.js create mode 100644 ui/components/component-library/button-primary/button-primary.js create mode 100644 ui/components/component-library/button-primary/button-primary.scss create mode 100644 ui/components/component-library/button-primary/button-primary.stories.js create mode 100644 ui/components/component-library/button-primary/button-primary.test.js create mode 100644 ui/components/component-library/button-primary/index.js create mode 100644 ui/components/component-library/button-secondary/README.mdx create mode 100644 ui/components/component-library/button-secondary/button-secondary.constants.js create mode 100644 ui/components/component-library/button-secondary/button-secondary.js create mode 100644 ui/components/component-library/button-secondary/button-secondary.scss create mode 100644 ui/components/component-library/button-secondary/button-secondary.stories.js create mode 100644 ui/components/component-library/button-secondary/button-secondary.test.js create mode 100644 ui/components/component-library/button-secondary/index.js create mode 100644 ui/components/component-library/tag/README.mdx create mode 100644 ui/components/component-library/tag/index.js create mode 100644 ui/components/component-library/tag/tag.js create mode 100644 ui/components/component-library/tag/tag.scss create mode 100644 ui/components/component-library/tag/tag.stories.js create mode 100644 ui/components/component-library/tag/tag.test.js create mode 100644 ui/components/component-library/text-field-base/README.mdx create mode 100644 ui/components/component-library/text-field-base/index.js create mode 100644 ui/components/component-library/text-field-base/text-field-base.constants.js create mode 100644 ui/components/component-library/text-field-base/text-field-base.js create mode 100644 ui/components/component-library/text-field-base/text-field-base.scss create mode 100644 ui/components/component-library/text-field-base/text-field-base.stories.js create mode 100644 ui/components/component-library/text-field-base/text-field-base.test.js create mode 100644 ui/components/component-library/text-field/README.mdx create mode 100644 ui/components/component-library/text-field/index.js create mode 100644 ui/components/component-library/text-field/text-field.constants.js create mode 100644 ui/components/component-library/text-field/text-field.js create mode 100644 ui/components/component-library/text-field/text-field.scss create mode 100644 ui/components/component-library/text-field/text-field.stories.js create mode 100644 ui/components/component-library/text-field/text-field.test.js create mode 100644 ui/components/ui/account-mismatch-warning/__snapshots__/acccount-mismatch-warning.component.test.js.snap create mode 100644 ui/components/ui/alert/__snapshots__/index.test.js.snap create mode 100644 ui/components/ui/breadcrumbs/__snapshots__/breadcrumbs.component.test.js.snap create mode 100644 ui/components/ui/confusable/__snapshots__/confusable.component.test.js.snap create mode 100644 ui/components/ui/currency-display/__snapshots__/currency-display.component.test.js.snap create mode 100644 ui/components/ui/error-message/__snapshots__/error-message.component.test.js.snap create mode 100644 ui/components/ui/hex-to-decimal/__snapshots__/hex-to-decimal.component.test.js.snap create mode 100644 ui/components/ui/list-item/__snapshots__/list-item.component.test.js.snap create mode 100644 ui/components/ui/nft-info/index.js create mode 100644 ui/components/ui/nft-info/index.scss create mode 100644 ui/components/ui/nft-info/nft-info.js create mode 100644 ui/components/ui/nft-info/nft-info.stories.js create mode 100644 ui/components/ui/site-origin/site-origin.test.js create mode 100644 ui/pages/keychains/__snapshots__/reveal-seed.test.js.snap create mode 100644 ui/pages/swaps/searchable-item-list/item-list/__snapshots__/item-list.component.test.js.snap create mode 100644 ui/pages/swaps/searchable-item-list/item-list/item-list.component.test.js create mode 100644 ui/pages/swaps/searchable-item-list/list-item-search/list-item-search.component.test.js create mode 100644 ui/pages/swaps/select-quote-popover/quote-details/quote-details.test.js create mode 100644 ui/pages/token-allowance/index.js create mode 100644 ui/pages/token-allowance/index.scss create mode 100644 ui/pages/token-allowance/token-allowance.js create mode 100644 ui/pages/token-allowance/token-allowance.stories.js create mode 100644 ui/pages/unlock-page/__snapshots__/unlock-page.test.js.snap delete mode 100644 ui/pages/unlock-page/unlock-page.component.test.js delete mode 100644 ui/pages/unlock-page/unlock-page.container.test.js create mode 100644 ui/pages/unlock-page/unlock-page.test.js diff --git a/.circleci/config.yml b/.circleci/config.yml index 852794659..7d1068879 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -90,6 +90,9 @@ workflows: - test-e2e-firefox-snaps: requires: - prep-build-test-flask + - test-e2e-chrome-mv3: + requires: + - prep-build-test-mv3 - test-unit: requires: - prep-deps @@ -386,7 +389,7 @@ jobs: - builds-test prep-build-storybook: - executor: node-browsers + executor: node-browsers-medium-plus steps: - checkout - attach_workspace: @@ -537,6 +540,33 @@ jobs: - store_artifacts: path: test-artifacts destination: test-artifacts + + test-e2e-chrome-mv3: + executor: node-browsers + steps: + - checkout + - run: + name: Re-Install Chrome + command: ./.circleci/scripts/chrome-install.sh + - attach_workspace: + at: . + - run: + name: Move test build to dist + command: mv ./dist-test-mv3 ./dist + - run: + name: Move test zips to builds + command: mv ./builds-test-mv3 ./builds + - run: + name: test:e2e:chrome + command: | + if .circleci/scripts/test-run-e2e.sh + then + yarn test:e2e:chrome --retries 2 || echo "Temporarily suppressing MV3 e2e test failures" + fi + no_output_timeout: 20m + - store_artifacts: + path: test-artifacts + destination: test-artifacts test-e2e-firefox-snaps: executor: node-browsers @@ -644,7 +674,7 @@ jobs: root: . paths: - test-artifacts - + user-actions-benchmark: executor: node-browsers-medium-plus steps: @@ -697,6 +727,9 @@ jobs: - run: name: Run page load benchmark command: yarn mv3:stats:chrome --out test-artifacts/chrome/mv3 + - run: + name: Install jq + command: sudo apt install jq -y - run: name: Record bundle size at commit command: ./.circleci/scripts/bundle-stats-commit.sh diff --git a/.circleci/scripts/bundle-stats-commit.sh b/.circleci/scripts/bundle-stats-commit.sh index 31f0ca9d5..b7cb44ac7 100755 --- a/.circleci/scripts/bundle-stats-commit.sh +++ b/.circleci/scripts/bundle-stats-commit.sh @@ -50,6 +50,28 @@ cp temp/stats/bundle_size_data.temp.js temp/stats/bundle_size_data.js echo " }" >> temp/stats/bundle_size_data.js +if [ -f temp/stats/bundle_size_data.json ]; then + # copy bundle_size_data.json in bundle_size_data.temp.json without last 2 lines + head -$(($(wc -l < temp/stats/bundle_size_data.json) - 2)) temp/stats/bundle_size_data.json > bundle_size_stats.temp.json + + { + echo "},"; + echo "\"$CIRCLE_SHA1\":"; + cat test-artifacts/chrome/mv3/bundle_size_stats.json; + echo "}"; + } >> bundle_size_stats.temp.json +else + { + echo "{"; + echo "\"$CIRCLE_SHA1\":"; + cat test-artifacts/chrome/mv3/bundle_size_stats.json; + echo "}"; + } > bundle_size_stats.temp.json +fi + +jq . bundle_size_stats.temp.json > temp/stats/bundle_size_data.json +rm bundle_size_stats.temp.json + cd temp git add . diff --git a/.circleci/scripts/chrome-install.sh b/.circleci/scripts/chrome-install.sh index 083b6bbaf..691475a29 100755 --- a/.circleci/scripts/chrome-install.sh +++ b/.circleci/scripts/chrome-install.sh @@ -5,12 +5,12 @@ set -u set -o pipefail # To get the latest version, see -CHROME_VERSION='105.0.5195.102-1' +CHROME_VERSION='107.0.5304.87-1' CHROME_BINARY="google-chrome-stable_${CHROME_VERSION}_amd64.deb" CHROME_BINARY_URL="https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/${CHROME_BINARY}" # To retrieve this checksum, run the `wget` and `shasum` commands below -CHROME_BINARY_SHA512SUM='3a1f2267ae009424ee8c623c3f78760d969dc1f3acb490e103e667d11e52cf0d955f201aeb3892dd41f33e68625af77ca5a20244b5be718f794eccb07a4c0413' +CHROME_BINARY_SHA512SUM='07b443bc1382431da84f6812b7e19f1149aa195fb8b3d28834630cc5964fb9d12124abbf4ec1c98d5c0513cdf16c2a3f16a74518c984aaf57ca418b3cd36a4e2' wget -O "${CHROME_BINARY}" -t 5 "${CHROME_BINARY_URL}" diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index 0f7977000..93758bae9 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -8,7 +8,7 @@ on: jobs: CLABot: if: github.event_name == 'pull_request_target' || contains(github.event.comment.html_url, '/pull/') - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 permissions: pull-requests: write contents: write diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index f945eb7b7..6f004d274 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -23,7 +23,7 @@ on: jobs: analyze: name: Analyze - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 permissions: actions: read contents: read diff --git a/.github/workflows/crowdin_action.yml b/.github/workflows/crowdin_action.yml index a77592321..f476277ed 100644 --- a/.github/workflows/crowdin_action.yml +++ b/.github/workflows/crowdin_action.yml @@ -13,7 +13,7 @@ on: jobs: synchronize-with-crowdin: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: diff --git a/.iyarc b/.iyarc index bbd5d06c1..316510d7d 100644 --- a/.iyarc +++ b/.iyarc @@ -1,5 +1,2 @@ # improved-yarn-audit advisory exclusions -GHSA-93q8-gq69-wqmw GHSA-257v-vj4p-3w2h -GHSA-wm7h-9275-46v2 -GHSA-pfrx-2q88-qq97 diff --git a/.storybook/test-data.js b/.storybook/test-data.js index 1a2b4b9a6..52fcf393e 100644 --- a/.storybook/test-data.js +++ b/.storybook/test-data.js @@ -1383,12 +1383,6 @@ const state = { }, }, }, - threeBoxSyncingAllowed: false, - showRestorePrompt: true, - threeBoxLastUpdated: 0, - threeBoxAddress: null, - threeBoxSynced: false, - threeBoxDisabled: false, swapsState: { quotes: {}, fetchParams: null, @@ -1479,8 +1473,6 @@ const state = { }, networksTabSelectedRpcUrl: '', loadingMethodData: false, - show3BoxModalAfterImport: false, - threeBoxLastUpdated: null, requestAccountTabs: {}, openMetaMaskTabs: {}, currentWindowTab: {}, diff --git a/CHANGELOG.md b/CHANGELOG.md index c9f96c2e2..b3fc97d99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3298,6 +3298,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.22.1...HEAD [10.22.1]: https://github.com/MetaMask/metamask-extension/compare/v10.22.0...v10.22.1 +[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.22.0...HEAD [10.22.0]: https://github.com/MetaMask/metamask-extension/compare/v10.21.2...v10.22.0 [10.21.2]: https://github.com/MetaMask/metamask-extension/compare/v10.21.1...v10.21.2 [10.21.1]: https://github.com/MetaMask/metamask-extension/compare/v10.21.0...v10.21.1 diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index 60cc6016d..9bb059502 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -47,10 +47,6 @@ "SIWEAddressInvalid": { "message": "Die Adresse in der Anmeldeanfrage entspricht nicht der Adresse des Kontos, mit dem Sie sich anmelden." }, - "SIWEDomainInvalid": { - "message": "Die Webseite, auf der Sie sich anmelden möchten ($1) entspricht nicht der Domain der Anmeldeanfrage. Bitte seien Sie vorsichtig.", - "description": "$1 represents the website domain" - }, "SIWEDomainWarningBody": { "message": "Die Webseite ($1) bittet Sie, sich in der falschen Domain anzumelden. Dies könnte ein Phishing-Angriff sein.", "description": "$1 represents the website domain" @@ -882,9 +878,6 @@ "data": { "message": "Daten" }, - "dataBackupFoundInfo": { - "message": "Einige Ihrer Kontodaten wurden während einer früheren MetaMask-Installation gesichert. Dies könnte Ihre Einstellungen, Kontakte und Token umfassen. Möchten Sie diese Daten jetzt wiederherstellen?" - }, "dataBackupSeemsCorrupt": { "message": "Ihre Daten konnten nicht wiederhergestellt werden. Die Datei scheint beschädigt zu sein." }, @@ -2869,10 +2862,6 @@ "restoreUserDataDescription": { "message": "Sie können die Benutzereinstellungen, die bevorzugte Einstellungen und Kontoadressen umfassen, aus einer vormals gesicherten JSON-Datei wiederherstellen." }, - "restoreWalletPreferences": { - "message": "$1 hat ein Backup Ihrer Daten gefunden. Möchten Sie die Präferenzen Ihrer Wallet wiederherstellen?", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "Transaktion wiederholen" }, @@ -3845,15 +3834,6 @@ "syncWithMobileTitle": { "message": "Mit Mobilgerät synchronisieren" }, - "syncWithThreeBox": { - "message": "Daten mit 3Box synchronisieren (experimentell)" - }, - "syncWithThreeBoxDescription": { - "message": "Aktivieren Sie, um Ihre Einstellungen mit 3Box zu sichern. Diese Funktion ist derzeit experimentell; verwenden Sie diese auf eigene Gefahr." - }, - "syncWithThreeBoxDisabled": { - "message": "3Box wurde aufgrund eines Fehlers während der ersten Synchronisation deaktiviert" - }, "tenPercentIncreased": { "message": "10% Erhöhung" }, diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json index c2b53fd54..51ca24c9d 100644 --- a/app/_locales/el/messages.json +++ b/app/_locales/el/messages.json @@ -47,10 +47,6 @@ "SIWEAddressInvalid": { "message": "Η διεύθυνση στο αίτημα σύνδεσης δεν ταιριάζει με τη διεύθυνση του λογαριασμού που χρησιμοποιείτε για να συνδεθείτε." }, - "SIWEDomainInvalid": { - "message": "Ο ιστότοπος στον οποίο προσπαθείτε να συνδεθείτε ($1) δεν ταιριάζει με τον τομέα στο αίτημα σύνδεσης. Προχωρήστε με προσοχή.", - "description": "$1 represents the website domain" - }, "SIWEDomainWarningBody": { "message": "Ο ιστότοπος ($1) σάς ζητά να συνδεθείτε σε λάθος τομέα. Μπορεί να πρόκειται για επίθεση ηλεκτρονικού ψαρέματος.", "description": "$1 represents the website domain" @@ -882,9 +878,6 @@ "data": { "message": "Δεδομένα" }, - "dataBackupFoundInfo": { - "message": "Ορισμένα από τα δεδομένα του λογαριασμού σας δημιουργήθηκαν σε προηγούμενη εγκατάσταση του MetaMask. Αυτό θα μπορούσε να περιλαμβάνει τις ρυθμίσεις, τις επαφές και τα διακριτικά σας. Θα θέλατε να επαναφέρετε αυτά τα δεδομένα τώρα;" - }, "dataBackupSeemsCorrupt": { "message": "Δεν μπορείτε να επαναφέρετε τα δεδομένα σας. Το αρχείο φαίνεται να είναι κατεστραμμένο." }, @@ -2869,10 +2862,6 @@ "restoreUserDataDescription": { "message": "Μπορείτε να επαναφέρετε τις ρυθμίσεις χρήστη που περιλαμβάνουν τις προτιμήσεις και τις διευθύνσεις λογαριασμών από ένα αρχείο JSON για το οποίο έχει δημιουργηθεί στο παρελθόν αντίγραφο ασφαλείας." }, - "restoreWalletPreferences": { - "message": "Βρέθηκε ένα αντίγραφο ασφαλείας των δεδομένων σας από το $1. Θα θέλατε να επαναφέρετε τις προτιμήσεις του πορτοφολιού σας;", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "Επανάληψη Συναλλαγής" }, @@ -3845,15 +3834,6 @@ "syncWithMobileTitle": { "message": "Συγχρονισμός με κινητό" }, - "syncWithThreeBox": { - "message": "Συγχρονισμός δεδομένων με 3Box (πειραματικό)" - }, - "syncWithThreeBoxDescription": { - "message": "Ενεργοποιήστε για να δημιουργηθούν αντίγραφα ασφαλείας των ρυθμίσεων σας με το 3Box. Αυτή η λειτουργία είναι επί του παρόντος πειραματική. Χρησιμοποιήστε τη με δική σας ευθύνη." - }, - "syncWithThreeBoxDisabled": { - "message": "Το 3Box έχει απενεργοποιηθεί λόγω σφάλματος κατά τον αρχικό συγχρονισμό" - }, "tenPercentIncreased": { "message": "10% αύξηση" }, diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 80fc1c056..71eaf9cd9 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -47,14 +47,19 @@ "SIWEAddressInvalid": { "message": "The address in the sign-in request does not match the address of the account you are using to sign in." }, - "SIWEDomainInvalid": { - "message": "The website you are attempting to sign in to ($1) does not match the domain in the sign-in request. Proceed with caution.", - "description": "$1 represents the website domain" + "SIWEDomainInvalidText": { + "message": "The site you're attempting to sign into doesn't match the domain in the request. Proceed with caution." + }, + "SIWEDomainInvalidTitle": { + "message": "Deceptive site request." }, "SIWEDomainWarningBody": { "message": "The website ($1) is asking you to sign in to the wrong domain. This may be a phishing attack.", "description": "$1 represents the website domain" }, + "SIWEDomainWarningLabel": { + "message": "Unsafe" + }, "SIWELabelChainID": { "message": "Chain ID:" }, @@ -448,6 +453,15 @@ "betaPortfolioSite": { "message": "beta portfolio site" }, + "betaTerms": { + "message": "BETA Terms of use" + }, + "betaWalletCreationSuccessReminder1": { + "message": "MetaMask BETA can’t recover your Secret Recovery Phrase." + }, + "betaWalletCreationSuccessReminder2": { + "message": "MetaMask BETA will never ask you for your Secret Recovery Phrase." + }, "betaWelcome": { "message": "Welcome to MetaMask Beta" }, @@ -891,9 +905,6 @@ "data": { "message": "Data" }, - "dataBackupFoundInfo": { - "message": "Some of your account data was backed up during a previous installation of MetaMask. This could include your settings, contacts, and tokens. Would you like to restore this data now?" - }, "dataBackupSeemsCorrupt": { "message": "Can not restore your data. The file appears to be corrupt." }, @@ -2897,10 +2908,6 @@ "restoreUserDataDescription": { "message": "You can restore user settings containing preferences and account addresses from a previously backed up JSON file." }, - "restoreWalletPreferences": { - "message": "A backup of your data from $1 has been found. Would you like to restore your wallet preferences?", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "Retry transaction" }, @@ -2922,6 +2929,9 @@ "revealTheSeedPhrase": { "message": "Reveal seed phrase" }, + "reviewSpendingCap": { + "message": "Review your spending cap" + }, "revokeAllTokensTitle": { "message": "Revoke permission to access all of your $1?", "description": "$1 is the symbol of the token for which the user is revoking approval" @@ -3117,6 +3127,9 @@ "message": "Approve $1 with no spend limit", "description": "The token symbol that is being approved" }, + "setSpendingCap": { + "message": "Set a spending cap for your" + }, "settings": { "message": "Settings" }, @@ -3880,15 +3893,6 @@ "syncWithMobileTitle": { "message": "Sync with mobile" }, - "syncWithThreeBox": { - "message": "Sync data with 3Box (experimental)" - }, - "syncWithThreeBoxDescription": { - "message": "Turn on to have your settings backed up with 3Box. This feature is currently experimental; use at your own risk." - }, - "syncWithThreeBoxDisabled": { - "message": "3Box has been disabled due to an error during the initial sync" - }, "tenPercentIncreased": { "message": "10% increase" }, @@ -4219,6 +4223,9 @@ "userName": { "message": "Username" }, + "verifyContractDetails": { + "message": "Verify contract details" + }, "verifyThisTokenDecimalOn": { "message": "Token decimal can be found on $1", "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" @@ -4231,6 +4238,9 @@ "message": "Verify this token on $1 and make sure this is the token you want to trade.", "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" }, + "view": { + "message": "View" + }, "viewAccount": { "message": "View account" }, @@ -4240,6 +4250,9 @@ "viewContact": { "message": "View contact" }, + "viewDetails": { + "message": "View details" + }, "viewFullTransactionDetails": { "message": "View full transaction details" }, diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index a71dd9366..d30487cb1 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -47,10 +47,6 @@ "SIWEAddressInvalid": { "message": "La dirección de la solicitud de inicio de sesión no coincide con la dirección de la cuenta que está utilizando para iniciar sesión." }, - "SIWEDomainInvalid": { - "message": "El sitio web en el que intenta iniciar sesión ($1) no coincide con el dominio de la solicitud de inicio de sesión. Proceda con precaución.", - "description": "$1 represents the website domain" - }, "SIWEDomainWarningBody": { "message": "El sitio web ($1) le pide que inicie sesión en un dominio incorrecto. Esto puede ser un ataque de phishing.", "description": "$1 represents the website domain" @@ -882,9 +878,6 @@ "data": { "message": "Datos" }, - "dataBackupFoundInfo": { - "message": "Se crearon copias de seguridad de algunos de los datos de la cuenta durante una instalación anterior de MetaMask. Esto podría incluir configuraciones, contactos y tokens. ¿Le gustaría restaurar estos datos ahora?" - }, "dataBackupSeemsCorrupt": { "message": "No se pueden restaurar sus datos. El archivo parece estar corrupto." }, @@ -2869,10 +2862,6 @@ "restoreUserDataDescription": { "message": "Puede restaurar la configuración del usuario que contiene preferencias y direcciones de cuenta desde en un archivo JSON previamente respaldado." }, - "restoreWalletPreferences": { - "message": "Se encontró una copia de seguridad de los datos de $1. ¿Desea restaurar las preferencias de cartera?", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "Reintentar transacción" }, @@ -3845,15 +3834,6 @@ "syncWithMobileTitle": { "message": "Sincronizar con dispositivo móvil" }, - "syncWithThreeBox": { - "message": "Sincronizar datos con 3Box (experimental)" - }, - "syncWithThreeBoxDescription": { - "message": "Active esta opción para crear una copia de seguridad de la configuración con 3Box. Actualmente, esta función es experimental. Úsela bajo su propio riesgo." - }, - "syncWithThreeBoxDisabled": { - "message": "3Box se deshabilitó debido a un error durante la sincronización inicial" - }, "tenPercentIncreased": { "message": "10% de aumento" }, diff --git a/app/_locales/es_419/messages.json b/app/_locales/es_419/messages.json index 92fd1dcec..1051bb56a 100644 --- a/app/_locales/es_419/messages.json +++ b/app/_locales/es_419/messages.json @@ -627,9 +627,6 @@ "data": { "message": "Datos" }, - "dataBackupFoundInfo": { - "message": "Se crearon copias de seguridad de algunos de los datos de la cuenta durante una instalación anterior de MetaMask. Esto podría incluir configuraciones, contactos y tokens. ¿Quiere restaurar estos datos ahora?" - }, "dataHex": { "message": "Hex" }, @@ -2188,10 +2185,6 @@ "restore": { "message": "Restaurar" }, - "restoreWalletPreferences": { - "message": "Se encontró una copia de seguridad de los datos de $1. ¿Desea restaurar las preferencias de cartera?", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "Reintentar transacción" }, @@ -2903,15 +2896,6 @@ "syncWithMobileTitle": { "message": "Sincronizar con dispositivo móvil" }, - "syncWithThreeBox": { - "message": "Sincronizar datos con 3Box (experimental)" - }, - "syncWithThreeBoxDescription": { - "message": "Active esta opción para crear una copia de seguridad de la configuración con 3Box. Actualmente, esta función es experimental. Úsela bajo su propio riesgo." - }, - "syncWithThreeBoxDisabled": { - "message": "3Box se deshabilitó debido a un error durante la sincronización inicial" - }, "tenPercentIncreased": { "message": "10% de aumento" }, diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index 0397a1bab..4207d700a 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -47,10 +47,6 @@ "SIWEAddressInvalid": { "message": "L'adresse figurant dans la demande de connexion ne correspond pas à l'adresse du compte que vous utilisez pour vous connecter." }, - "SIWEDomainInvalid": { - "message": "Le nom de domaine du site Web auquel vous tentez de vous connecter ($1) ne correspond pas au nom de domaine indiqué dans la demande de connexion. Procédez avec prudence.", - "description": "$1 represents the website domain" - }, "SIWEDomainWarningBody": { "message": "Le site Web ($1) vous demande de vous connecter au mauvais nom domaine. Il peut s'agir d'une tentative d'hameçonnage.", "description": "$1 represents the website domain" @@ -882,9 +878,6 @@ "data": { "message": "Données" }, - "dataBackupFoundInfo": { - "message": "Certaines données de votre compte ont été sauvegardées lors d’une précédente installation de MetaMask. Il peut s’agir de vos paramètres, contacts et jetons. Souhaitez-vous restaurer ces données maintenant ?" - }, "dataBackupSeemsCorrupt": { "message": "Impossible de restaurer vos données. Le fichier semble corrompu." }, @@ -2869,10 +2862,6 @@ "restoreUserDataDescription": { "message": "Vous pouvez restaurer les paramètres de l’utilisateur qui contiennent les préférences et les adresses de compte à partir d’un fichier JSON précédemment sauvegardé." }, - "restoreWalletPreferences": { - "message": "Une sauvegarde de vos données de $1 a été trouvée. Voulez-vous restaurer vos préférences de portefeuille ?", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "Retenter la transaction" }, @@ -3845,15 +3834,6 @@ "syncWithMobileTitle": { "message": "Synchroniser avec le mobile" }, - "syncWithThreeBox": { - "message": "Synchronisation des données avec 3Box (expérimental)" - }, - "syncWithThreeBoxDescription": { - "message": "Activez cette fonction pour que vos paramètres soient sauvegardés avec 3Box. Cette fonction est actuellement expérimentale ; utilisez-la avec prudence." - }, - "syncWithThreeBoxDisabled": { - "message": "3Box a été désactivé en raison d’une erreur lors de la synchronisation initiale" - }, "tenPercentIncreased": { "message": "Augmentation de 10 %" }, diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index acffa1aa5..21bf38605 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -47,10 +47,6 @@ "SIWEAddressInvalid": { "message": "साइन-इन अनुरोध का पता उस अकाउंट के पते से मेल नहीं खाता जिसका उपयोग आप साइन इन करने के लिए कर रहे हैं।" }, - "SIWEDomainInvalid": { - "message": "जिस वेबसाइट में ($1) आप साइन इन करने की कोशिश कर रहे हैं वह साइन-इन अनुरोध के डोमेन से मेल नहीं खाती। सावधानी के साथ आगे बढ़ें।", - "description": "$1 represents the website domain" - }, "SIWEDomainWarningBody": { "message": "वेबसाइट ($1) आपसे गलत डोमेन में साइन इन करने के लिए कह रही है। यह एक फिशिंग अटैक हो सकता है।", "description": "$1 represents the website domain" @@ -882,9 +878,6 @@ "data": { "message": "डेटा" }, - "dataBackupFoundInfo": { - "message": "MetaMask की पिछली स्थापना के दौरान आपके कुछ खाता डेटा का बैकअप लिया गया था। इसमें आपकी सेटिंग, संपर्क और टोकन शामिल हो सकते हैं। क्या आप अब इस डेटा को पुनर्स्थापित करना चाहेंगे?" - }, "dataBackupSeemsCorrupt": { "message": "आपका डेटा रीस्टोर नहीं किया जा सकता। लगता है फ़ाइल करप्ट हुई है।" }, @@ -2869,10 +2862,6 @@ "restoreUserDataDescription": { "message": "वरीयताएँ और अकाउंट एड्रेस से युक्त यूजर सेटिंग्स को आप पहले से बैकअप की गई JSON फ़ाइल से रीस्टोर सकते हैं।" }, - "restoreWalletPreferences": { - "message": "$1 से आपके डेटा का बैकअप मिला है। क्या आप अपनी वॉलेट वरीयताओं को पुनर्स्थापित करना चाहते हैं?", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "लेनदेन का पुनः प्रयास करें" }, @@ -3845,15 +3834,6 @@ "syncWithMobileTitle": { "message": "मोबाइल के साथ सिंक करें" }, - "syncWithThreeBox": { - "message": "3Box के साथ डेटा सिंक करें (प्रयोगात्मक)" - }, - "syncWithThreeBoxDescription": { - "message": "3Box के साथ अपनी सेटिंग का बैकअप लेने के लिए चालू करें। यह सुविधा वर्तमान में प्रयोगात्मक है; अपने जोखिम पर इस्तेमाल करें।" - }, - "syncWithThreeBoxDisabled": { - "message": "प्रारंभिक सिंक के दौरान एक त्रुटि के कारण 3Box को अक्षम कर दिया गया है" - }, "tenPercentIncreased": { "message": "10% बढ़ोत्तरी" }, diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index 7bb3b2a3b..b96e385c9 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -47,10 +47,6 @@ "SIWEAddressInvalid": { "message": "Alamat pada permintaan masuk tidak sesuai dengan alamat akun yang Anda gunakan untuk masuk." }, - "SIWEDomainInvalid": { - "message": "Situs web yang Anda coba masuki ($1) tidak sesuai dengan domain pada permintaan masuk. Lanjutkan dengan hati-hati.", - "description": "$1 represents the website domain" - }, "SIWEDomainWarningBody": { "message": "Situs web ($1) meminta Anda untuk masuk ke domain yang salah. Kemungkinan ini merupakan serangan pengelabuan.", "description": "$1 represents the website domain" @@ -882,9 +878,6 @@ "data": { "message": "Data" }, - "dataBackupFoundInfo": { - "message": "Beberapa data akun Anda telah dicadangkan selama pemasangan MetaMask yang lalu. Ini bisa mencakup pengaturan, kontak, dan token Anda. Apakah Anda ingin memulihkan data ini sekarang?" - }, "dataBackupSeemsCorrupt": { "message": "Tidak dapat memulihkan data Anda. File tampaknya rusak." }, @@ -2869,10 +2862,6 @@ "restoreUserDataDescription": { "message": "Anda dapat memulihkan pengaturan pengguna yang berisi preferensi dan alamat akun dari berkas JSON yang dicadangkan sebelumnya." }, - "restoreWalletPreferences": { - "message": "Cadangan data Anda dari $1 telah ditemukan. Pulihkan preferensi dompet Anda?", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "Coba lagi transaksi" }, @@ -3845,15 +3834,6 @@ "syncWithMobileTitle": { "message": "Sinkronkan dengan seluler" }, - "syncWithThreeBox": { - "message": "Sinkronkan data dengan 3Box (eksperimen)" - }, - "syncWithThreeBoxDescription": { - "message": "Aktifkan agar pengaturan Anda dicadangkan dengan 3Box. Fitur ini sekarang sedang dalam masa percobaan; risiko ditanggung sendiri." - }, - "syncWithThreeBoxDisabled": { - "message": "3Box telah dinonaktifkan karena terjadi galat selama sinkronisasi awal" - }, "tenPercentIncreased": { "message": "Meningkat 10%" }, diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index 4e4421202..4b5cf3a06 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -361,9 +361,6 @@ "customToken": { "message": "Token Personalizzato" }, - "dataBackupFoundInfo": { - "message": "Alcuni dati sul tuo account sono state salvate durante una installazione precedente di MetaMask. Questi includono le impostazioni, i contatti, e i token. Vuoi ripristinare questi dati?" - }, "decimal": { "message": "Precisione Decimali" }, @@ -1100,10 +1097,6 @@ "restore": { "message": "Ripristina" }, - "restoreWalletPreferences": { - "message": "È stato trovato un backup dei tuoi dati da $1. Vuoi ripristinare le preferenze del portafoglio?", - "description": "$1 is the date at which the data was backed up" - }, "reusedTokenNameWarning": { "message": "Un token usa un simbolo già usato da un altro token, ciò può confondere o ingannare." }, @@ -1533,15 +1526,6 @@ "syncWithMobileTitle": { "message": "Sincronizza con dispositivo mobile" }, - "syncWithThreeBox": { - "message": "Sincronizza dati con 3Box (sperimentale)" - }, - "syncWithThreeBoxDescription": { - "message": "Attiva per avere le tue impostazioni salvate su 3Box. Questa funzionalità è attualmente sperimentale; usala a tuo rischio." - }, - "syncWithThreeBoxDisabled": { - "message": "3Box è stato disabilitato a causa di un errore durante la sincronizzazione iniziale" - }, "terms": { "message": "Termini di Uso" }, diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index 6dc90033e..0cd2ad431 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -47,10 +47,6 @@ "SIWEAddressInvalid": { "message": "サインインリクエストのアドレスが、サインインに使用しているアカウントのアドレスと一致していません。" }, - "SIWEDomainInvalid": { - "message": "サインインしようとしている Web サイト ($1) が、サインインリクエストのドメインと一致していません。慎重に進めてください。", - "description": "$1 represents the website domain" - }, "SIWEDomainWarningBody": { "message": "Web サイト ($1) が正しくないドメインへのサインインを要求しています。フィッシング攻撃の可能性があります。", "description": "$1 represents the website domain" @@ -882,9 +878,6 @@ "data": { "message": "データ" }, - "dataBackupFoundInfo": { - "message": "一部のアカウントデータはMetaMaskの前回のインストール時にバックアップされました。これには、設定、連絡先、およびトークンが含まれている可能性があります。このデータを今すぐ復元しますか?" - }, "dataBackupSeemsCorrupt": { "message": "データを復元できません。ファイルが破損しているようです。" }, @@ -2869,10 +2862,6 @@ "restoreUserDataDescription": { "message": "以前バックアップされた JSON ファイルから、設定とアカウントアドレスを含むユーザー設定を復元できます。" }, - "restoreWalletPreferences": { - "message": "$1のデータのバックアップが見つかりました。ウォレットの基本設定を復元しますか?", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "トランザクションを再試行" }, @@ -3845,15 +3834,6 @@ "syncWithMobileTitle": { "message": "モバイルと同期" }, - "syncWithThreeBox": { - "message": "データを3Boxと同期 (試験的機能)" - }, - "syncWithThreeBoxDescription": { - "message": "これをオンにすると、設定が3Boxでバックアップされます。この機能は現在試験段階にあります。自己責任でご利用ください。" - }, - "syncWithThreeBoxDisabled": { - "message": "3Boxは、最初の同期中のエラーのため、無効化されました" - }, "tenPercentIncreased": { "message": "10% の増加" }, diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index 6641eaa84..ca183dfdc 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -47,10 +47,6 @@ "SIWEAddressInvalid": { "message": "로그인 요청 주소가 현재 로그인 계정의 주소와 일치하지 않습니다." }, - "SIWEDomainInvalid": { - "message": "($1) 로그인을 시도하는 웹사이트가 로그인 요청 도메인과 일치하지 않습니다. 주의하여 진행하세요.", - "description": "$1 represents the website domain" - }, "SIWEDomainWarningBody": { "message": "($1) 웹사이트가 잘못된 도메인에 로그인하도록 요청하고 있습니다. 이는 피싱 공격일 수도 있습니다.", "description": "$1 represents the website domain" @@ -882,9 +878,6 @@ "data": { "message": "데이터" }, - "dataBackupFoundInfo": { - "message": "일부 계정 데이터가 이전의 MetaMask 설치 도중에 백업되었습니다. 여기에는 설정, 연락처, 토큰이 포함될 수 있습니다. 지금 이 데이터를 복구할까요?" - }, "dataBackupSeemsCorrupt": { "message": "사용자 데이터를 복원할 수 없습니다. 파일이 손상된 것 같습니다." }, @@ -2869,10 +2862,6 @@ "restoreUserDataDescription": { "message": "이전에 백업한 JSON 파일에서 기본 설정과 계정 주소가 포함된 사용자 설정을 복원할 수 있습니다." }, - "restoreWalletPreferences": { - "message": "$1의 데이터 백업이 발견되었습니다. 지갑 환경설정을 복원할까요?", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "트랜잭션 재시도" }, @@ -3845,15 +3834,6 @@ "syncWithMobileTitle": { "message": "모바일과 동기화" }, - "syncWithThreeBox": { - "message": "3Box로 데이터 동기화(실험적 기능)" - }, - "syncWithThreeBoxDescription": { - "message": "이 기능을 켜면 3Box를 이용해 설정을 백업합니다. 현재 실험 중인 기능이므로 본인의 책임 하에 사용해야 합니다." - }, - "syncWithThreeBoxDisabled": { - "message": "초기 동기화 도중 오류가 발생하여 3Box가 비활성화되었습니다." - }, "tenPercentIncreased": { "message": "10% 인상" }, diff --git a/app/_locales/ph/messages.json b/app/_locales/ph/messages.json index 15d729216..f1a2bc71f 100644 --- a/app/_locales/ph/messages.json +++ b/app/_locales/ph/messages.json @@ -430,9 +430,6 @@ "customToken": { "message": "Custom na Token" }, - "dataBackupFoundInfo": { - "message": "Ang ilan sa data ng iyong account ay na-back up sa nakaraang pag-install ng MetaMask. Maaaring kasama rito ang iyong mga setting, contact, at token. Gusto mo na bang i-restore ang data na ito ngayon?" - }, "decimal": { "message": "Decimal ng Token" }, @@ -1380,10 +1377,6 @@ "restore": { "message": "I-restore" }, - "restoreWalletPreferences": { - "message": "Nakita ang backup ng iyong data mula sa $1. Gusto mo bang i-restore ang mga kagustuhan mo sa wallet?", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "Subukan Ulit ang Transaksyon" }, @@ -1952,15 +1945,6 @@ "syncWithMobileTitle": { "message": "I-sync sa mobile" }, - "syncWithThreeBox": { - "message": "I-sync ang data sa 3Box (pinag-eeksperimentuhan)" - }, - "syncWithThreeBoxDescription": { - "message": "I-on para ma-back up ang iyong mga setting sa 3Box. Kasalukuyang pinag-eeksperimentuhan ang feature na ito; gamitin sa sarili mong pagpapasya." - }, - "syncWithThreeBoxDisabled": { - "message": "Na-disable ang 3Box dahil sa isang error sa unang pag-sync" - }, "terms": { "message": "Mga Tuntunin ng Paggamit" }, diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json index 749fa337a..122d69b45 100644 --- a/app/_locales/pt/messages.json +++ b/app/_locales/pt/messages.json @@ -47,10 +47,6 @@ "SIWEAddressInvalid": { "message": "O endereço na solicitação de entrada não coincide com o endereço da conta que você está usando para entrar." }, - "SIWEDomainInvalid": { - "message": "O site em que você está tentando entrar ($1) não coincide com o domínio na solicitação de entrada. Prossiga com cautela.", - "description": "$1 represents the website domain" - }, "SIWEDomainWarningBody": { "message": "O site ($1) está solicitando que você entre no domínio incorreto. Pode-se tratar de um ataque de phishing.", "description": "$1 represents the website domain" @@ -882,9 +878,6 @@ "data": { "message": "Dados" }, - "dataBackupFoundInfo": { - "message": "Foi feito o backup de alguns dos dados da sua conta durante uma instalação anterior da MetaMask. Isso pode incluir configurações, contatos e tokens. Gostaria de restaurar esses dados agora?" - }, "dataBackupSeemsCorrupt": { "message": "Não é possível restaurar seus dados. O arquivo parece estar corrompido." }, @@ -2869,10 +2862,6 @@ "restoreUserDataDescription": { "message": "Você pode restaurar as configurações do usuário contendo preferências e endereços de contas a partir de um arquivo de backup JSON." }, - "restoreWalletPreferences": { - "message": "Encontramos um backup dos seus dados de $1. Gostaria de restaurar as preferências da sua carteira?", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "Tentar transação novamente" }, @@ -3845,15 +3834,6 @@ "syncWithMobileTitle": { "message": "Sincronizar com dispositivo móvel" }, - "syncWithThreeBox": { - "message": "Sincronizar dados com 3Box (experimental)" - }, - "syncWithThreeBoxDescription": { - "message": "Ative para fazer backup das suas configurações com o 3Box. Esse recurso é experimental; use por sua conta e risco." - }, - "syncWithThreeBoxDisabled": { - "message": "O 3Box foi desabilitado por conta de um erro durante a sincronização inicial" - }, "tenPercentIncreased": { "message": "10% de aumento" }, diff --git a/app/_locales/pt_BR/messages.json b/app/_locales/pt_BR/messages.json index 2755f4967..0f4b63ef3 100644 --- a/app/_locales/pt_BR/messages.json +++ b/app/_locales/pt_BR/messages.json @@ -627,9 +627,6 @@ "data": { "message": "Dados" }, - "dataBackupFoundInfo": { - "message": "Foi feito o backup de alguns dos dados da sua conta durante uma instalação anterior da MetaMask. Isso pode incluir configurações, contatos e tokens. Gostaria de restaurar esses dados agora?" - }, "dataHex": { "message": "Hex" }, @@ -2172,10 +2169,6 @@ "restore": { "message": "Restaurar" }, - "restoreWalletPreferences": { - "message": "Encontramos um backup dos seus dados de $1. Gostaria de restaurar as preferências da sua carteira?", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "Tentar transação novamente" }, @@ -2887,15 +2880,6 @@ "syncWithMobileTitle": { "message": "Sincronizar com dispositivo móvel" }, - "syncWithThreeBox": { - "message": "Sincronizar dados com 3Box (experimental)" - }, - "syncWithThreeBoxDescription": { - "message": "Ative para fazer backup das suas configurações com o 3Box. Esse recurso é experimental; use por sua conta e risco." - }, - "syncWithThreeBoxDisabled": { - "message": "O 3Box foi desabilitado por conta de um erro durante a sincronização inicial" - }, "tenPercentIncreased": { "message": "10% de aumento" }, diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index b0f1991c7..b354c2f9b 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -47,10 +47,6 @@ "SIWEAddressInvalid": { "message": "Адрес в запросе на вход не соответствует адресу счета, который вы используете для входа." }, - "SIWEDomainInvalid": { - "message": "Веб-сайт, на который вы пытаетесь войти ($1), не соответствует домену в запросе на вход. Действуйте с осторожностью.", - "description": "$1 represents the website domain" - }, "SIWEDomainWarningBody": { "message": "Веб-сайт ($1) просит вас войти в неправильный домен. Это может быть фишинговая атака.", "description": "$1 represents the website domain" @@ -882,9 +878,6 @@ "data": { "message": "Данные" }, - "dataBackupFoundInfo": { - "message": "Некоторые данные вашего счета были скопированы во время предыдущей установки MetaMask. Они могли включать ваши настройки, контакты и токены. Хотите восстановить эти данные сейчас?" - }, "dataBackupSeemsCorrupt": { "message": "Не удается восстановить ваши данные. Файл, по-видимому, поврежден." }, @@ -2869,10 +2862,6 @@ "restoreUserDataDescription": { "message": "Вы можете восстановить пользовательские настройки, содержащие настройки и адреса аккаунтов, из ранее сохраненного файла JSON." }, - "restoreWalletPreferences": { - "message": "Найдена резервная копия ваших данных из $1. Хотите восстановить настройки кошелька?", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "Повторить транзакцию" }, @@ -3845,15 +3834,6 @@ "syncWithMobileTitle": { "message": "Синхронизировать с мобильным устройством" }, - "syncWithThreeBox": { - "message": "Синхронизировать данные с 3Box (экспериментальная функция)" - }, - "syncWithThreeBoxDescription": { - "message": "Включите, чтобы скопировать ваши настройки с помощью 3Box. Эта функция в настоящее время является экспериментальной. Используйте ее на свой страх и риск." - }, - "syncWithThreeBoxDisabled": { - "message": "3Box отключен из-за ошибки во время первоначальной синхронизации" - }, "tenPercentIncreased": { "message": "Увеличение на 10%" }, diff --git a/app/_locales/tl/messages.json b/app/_locales/tl/messages.json index 6e98da100..a5167c5c9 100644 --- a/app/_locales/tl/messages.json +++ b/app/_locales/tl/messages.json @@ -47,10 +47,6 @@ "SIWEAddressInvalid": { "message": "Ang address sa request sa pag-sign in ay hindi tugma sa address ng account na ginagamit mo sa pag-sign in." }, - "SIWEDomainInvalid": { - "message": "Ang website kung saan mo sinusubukang mag-sign in sa ($1) ay hindi tugma sa domain sa request sa pag-sign in. Magpatuloy nang may pag-iingat.", - "description": "$1 represents the website domain" - }, "SIWEDomainWarningBody": { "message": "Hinihiling sa iyo ng website ($1) na mag-sign in sa maling domain. Posibleng phishing na pag-atake ito.", "description": "$1 represents the website domain" @@ -882,9 +878,6 @@ "data": { "message": "Datos" }, - "dataBackupFoundInfo": { - "message": "Ang ilan sa data ng iyong account ay na-back up sa nakaraang pag-install ng MetaMask. Maaaring kasama rito ang iyong mga setting, contact, at token. Gusto mo bang i-restore na ang data na ito?" - }, "dataBackupSeemsCorrupt": { "message": "Hindi maibalik ang iyong datos. Mukhang sira ang file." }, @@ -2869,10 +2862,6 @@ "restoreUserDataDescription": { "message": "Maaari mong ibalik ang mga setting ng user na naglalaman ng mga kagustuhan at mga address ng account mula sa isang dating na-back up na JSON file." }, - "restoreWalletPreferences": { - "message": "Nakita ang backup ng iyong data mula sa $1. Gusto mo bang i-restore ang mga kagustuhan mo sa wallet?", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "Subukan Ulit ang Transaksyon" }, @@ -3845,15 +3834,6 @@ "syncWithMobileTitle": { "message": "I-sync sa mobile" }, - "syncWithThreeBox": { - "message": "I-sync ang data sa 3Box (pinag-eeksperimentuhan)" - }, - "syncWithThreeBoxDescription": { - "message": "I-on para ma-back up ang iyong mga setting sa 3Box. Kasalukuyang pinag-eeksperimentuhan ang feature na ito; gamitin sa sarili mong pagpapasya." - }, - "syncWithThreeBoxDisabled": { - "message": "Na-disable ang 3Box dahil sa isang error sa unang pag-sync" - }, "tenPercentIncreased": { "message": "10% na dagdag" }, diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json index 0471fa14e..71d8b4c85 100644 --- a/app/_locales/tr/messages.json +++ b/app/_locales/tr/messages.json @@ -47,10 +47,6 @@ "SIWEAddressInvalid": { "message": "Giriş talebindeki adres, giriş yapmak için kullandığınız hesapla uyumlu değil." }, - "SIWEDomainInvalid": { - "message": "Giriş yapmaya çalıştığınız web sitesi ($1) giriş talebindeki alan ile uyumlu değil. Dikkati olarak ilerleyin.", - "description": "$1 represents the website domain" - }, "SIWEDomainWarningBody": { "message": "Web sitesi ($1) yanlış alana giriş yapmanızı istiyor. Bu bir dolandırıcılık saldırısı olabilir.", "description": "$1 represents the website domain" @@ -882,9 +878,6 @@ "data": { "message": "Veri" }, - "dataBackupFoundInfo": { - "message": "MetaMask'ın önceki bir kurulumu sırasında hesap verilerinizden bazıları yedeklenmiştir. Buna ayarlar, kişiler ve tokenler dahil olabilir. Bu verileri şimdi geri yüklemek ister misiniz?" - }, "dataBackupSeemsCorrupt": { "message": "Verileriniz geri yüklenemedi. Dosyanın bozuk olduğu algılandı." }, @@ -2869,10 +2862,6 @@ "restoreUserDataDescription": { "message": "Tercihleri ve hesap adreslerini içeren kullanıcı ayarlarını daha önce yedeklenmiş bir JSON dosyasından geri yükleyebilirsiniz." }, - "restoreWalletPreferences": { - "message": "Verilerinizin $1 tarihinden bir yedeği bulundu. Cüzdan tercihlerinizi geri yüklemek ister misiniz?", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "İşlemi Tekrar Dene" }, @@ -3845,15 +3834,6 @@ "syncWithMobileTitle": { "message": "Mobil ile senkronize et" }, - "syncWithThreeBox": { - "message": "Verileri 3Box ile senkronize et (deneysel)" - }, - "syncWithThreeBoxDescription": { - "message": "Ayarlarınızın 3Box ile yedeklenmesini sağlamak için açın. Bu özellik şu anda deney aşamasındadır; kullanım riski size aittir." - }, - "syncWithThreeBoxDisabled": { - "message": "İlk senkronizasyon işlemi sırasındaki bir hata nedeniyle 3Box devre dışı bırakıldı" - }, "tenPercentIncreased": { "message": "%10 artış" }, diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index 013c95dca..f50799c83 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -47,10 +47,6 @@ "SIWEAddressInvalid": { "message": "Địa chỉ trong yêu cầu đăng nhập không trùng khớp với địa chỉ của tài khoản bạn đang sử dụng để đăng nhập." }, - "SIWEDomainInvalid": { - "message": "Trang web bạn đang cố gắng đăng nhập vào ($1) không trùng khớp với tên miền trong yêu cầu đăng nhập. Hãy thực hiện cẩn thận.", - "description": "$1 represents the website domain" - }, "SIWEDomainWarningBody": { "message": "Trang web ($1) đang yêu cầu bạn đăng nhập vào một tên miền không đúng. Đây có thể là một cuộc tấn công lừa đảo.", "description": "$1 represents the website domain" @@ -882,9 +878,6 @@ "data": { "message": "Dữ liệu" }, - "dataBackupFoundInfo": { - "message": "Một số dữ liệu tài khoản của bạn đã được sao lưu trong lần cài đặt MetaMask trước đó. Dữ liệu này có thể bao gồm các tùy chọn cài đặt, danh bạ và token. Bạn có muốn khôi phục dữ liệu này bây giờ không?" - }, "dataBackupSeemsCorrupt": { "message": "Không thể khôi phục dữ liệu của bạn. Tập tin có vẻ đã bị hỏng." }, @@ -2869,10 +2862,6 @@ "restoreUserDataDescription": { "message": "Bạn có thể khôi phục cài đặt người dùng chứa các tùy chọn và địa chỉ tài khoản từ tập tin JSON đã sao lưu trước đó." }, - "restoreWalletPreferences": { - "message": "Đã tìm thấy bản sao lưu dữ liệu của bạn từ $1. Bạn có muốn khôi phục các tùy chọn ưu tiên trong ví của mình không?", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "Thử lại giao dịch" }, @@ -3845,15 +3834,6 @@ "syncWithMobileTitle": { "message": "Đồng bộ với thiết bị di động" }, - "syncWithThreeBox": { - "message": "Đồng bộ dữ liệu với 3Box (thử nghiệm)" - }, - "syncWithThreeBoxDescription": { - "message": "Bật để sao lưu các tùy chọn cài đặt của bạn với 3Box. Tính năng này hiện đang trong giai đoạn thử nghiệm; bạn tự chịu rủi ro khi sử dụng." - }, - "syncWithThreeBoxDisabled": { - "message": "Đã tắt 3Box do có lỗi xảy ra trong quá trình đồng bộ ban đầu" - }, "tenPercentIncreased": { "message": "Tăng 10%" }, diff --git a/app/_locales/zh/messages.json b/app/_locales/zh/messages.json deleted file mode 100644 index ce6a95c56..000000000 --- a/app/_locales/zh/messages.json +++ /dev/null @@ -1,4114 +0,0 @@ -{ - "QRHardwareInvalidTransactionTitle": { - "message": "错误" - }, - "QRHardwareMismatchedSignId": { - "message": "不一致的交易数据。请查看交易详情。" - }, - "QRHardwarePubkeyAccountOutOfRange": { - "message": "暂无更多账户。若想访问下方未列出的其他账户,请重新连接您的硬件钱包并选择它。" - }, - "QRHardwareScanInstructions": { - "message": "将二维码放在摄像头前。屏幕是模糊的,但不影响对二维码的读取。" - }, - "QRHardwareSignRequestCancel": { - "message": "拒绝" - }, - "QRHardwareSignRequestDescription": { - "message": "使用钱包签名后,点击“获取签名”以接收签名" - }, - "QRHardwareSignRequestGetSignature": { - "message": "获取签名" - }, - "QRHardwareSignRequestSubtitle": { - "message": "用您的钱包扫描二维码" - }, - "QRHardwareSignRequestTitle": { - "message": "请求签名" - }, - "QRHardwareUnknownQRCodeTitle": { - "message": "错误" - }, - "QRHardwareUnknownWalletQRCode": { - "message": "非法二维码,请扫描硬件钱包的同步二维码。" - }, - "QRHardwareWalletImporterTitle": { - "message": "扫描二维码" - }, - "QRHardwareWalletSteps1Description": { - "message": "连接通过二维码通信的气隙硬件钱包。官方支持的气隙硬件钱包包括:" - }, - "QRHardwareWalletSteps1Title": { - "message": "基于二维码的硬件钱包" - }, - "QRHardwareWalletSteps2Description": { - "message": "AirGap Vault & Ngrave (即将上线)" - }, - "about": { - "message": "关于" - }, - "acceleratingATransaction": { - "message": "* 通过使用更高的燃料价格来加速交易,会增加其更快地被网络处理的机会,但这并不总是得到保证。" - }, - "acceptTermsOfUse": { - "message": "我已阅读并同意 $1", - "description": "$1 is the `terms` message" - }, - "accessAndSpendNotice": { - "message": "$1 可以访问并使用此最大金额", - "description": "$1 is the url of the site requesting ability to spend" - }, - "accessAndSpendNoticeNFT": { - "message": "$1可以访问并使用此资产", - "description": "$1 is the url of the site requesting ability to spend" - }, - "accessYourWalletWithSRP": { - "message": "使用账户助记词访问钱包" - }, - "accessYourWalletWithSRPDescription": { - "message": "MetaMask无法恢复您的密码。我们将使用您的助记词来验证您的所有权、恢复您的钱包并设置新密码。首先,请输入创建钱包时获得的助记词。$1", - "description": "$1 is the words 'Learn More' from key 'learnMore', separated here so that it can be added as a link" - }, - "accessingYourCamera": { - "message": "正在访问您的相机……" - }, - "account": { - "message": "账户" - }, - "accountDetails": { - "message": "账户详情" - }, - "accountIdenticon": { - "message": "账户哈希头像" - }, - "accountName": { - "message": "账户名称" - }, - "accountNameDuplicate": { - "message": "此账户名称已存在", - "description": "This is an error message shown when the user enters a new account name that matches an existing account name" - }, - "accountOptions": { - "message": "账户选项" - }, - "accountSelectionRequired": { - "message": "您需要选择一个账户!" - }, - "active": { - "message": "活跃" - }, - "activity": { - "message": "活动" - }, - "activityLog": { - "message": "活动日志" - }, - "add": { - "message": "添加" - }, - "addANetwork": { - "message": "添加网络" - }, - "addANetworkManually": { - "message": "手动添加网络" - }, - "addANickname": { - "message": "添加昵称" - }, - "addAcquiredTokens": { - "message": "添加您使用 MetaMask 获得的代币" - }, - "addAlias": { - "message": "添加别名" - }, - "addContact": { - "message": "添加联系信息" - }, - "addCustomToken": { - "message": "添加自定义代币" - }, - "addCustomTokenByContractAddress": { - "message": "找不到代币?您可以通过粘贴其地址手动添加任何代币。代币合约地址可以在 $1 上找到。", - "description": "$1 is a blockchain explorer for a specific network, e.g. Etherscan for Ethereum" - }, - "addEthereumChainConfirmationDescription": { - "message": "这将允许在 MetaMask 中使用此网络。" - }, - "addEthereumChainConfirmationRisks": { - "message": "MetaMask 不验证自定义网络。" - }, - "addEthereumChainConfirmationRisksLearnMore": { - "message": "了解 $1。", - "description": "$1 is a link with text that is provided by the 'addEthereumChainConfirmationRisksLearnMoreLink' key" - }, - "addEthereumChainConfirmationRisksLearnMoreLink": { - "message": "诈骗和网络安全风险", - "description": "Link text for the 'addEthereumChainConfirmationRisksLearnMore' translation key" - }, - "addEthereumChainConfirmationTitle": { - "message": "允许此网站增加一个网络?" - }, - "addFriendsAndAddresses": { - "message": "添加您信任的朋友和地址" - }, - "addFromAListOfPopularNetworks": { - "message": "从热门网络列表中选择网络来添加,或手动添加网络。仅可与您信任的实体互动。" - }, - "addMemo": { - "message": "添加备忘录" - }, - "addMoreNetworks": { - "message": "手动添加更多网络" - }, - "addNetwork": { - "message": "添加网络" - }, - "addNetworkTooltipWarning": { - "message": "此网络连接依赖于第三方。此连接可能不太可靠,或使第三方可进行活动跟踪。$1", - "description": "$1 is Learn more link" - }, - "addSuggestedTokens": { - "message": "添加推荐代币" - }, - "addToken": { - "message": "添加代币" - }, - "address": { - "message": "地址" - }, - "addressBookIcon": { - "message": "地址簿图标" - }, - "advanced": { - "message": "高级" - }, - "advancedBaseGasFeeToolTip": { - "message": "当您的交易被包含在区块中时,您的最大基本费用与实际基本费用之间的任何差额将被退还。总金额按最大基本费用(以GWEI为单位)*燃料上限计算。" - }, - "advancedGasFeeDefaultOptIn": { - "message": "将这些 $1 保存为“高级”默认值" - }, - "advancedGasFeeDefaultOptOut": { - "message": "始终使用这些值和高级设置作为默认值。" - }, - "advancedGasFeeModalTitle": { - "message": "高级燃料费" - }, - "advancedGasPriceTitle": { - "message": "燃料价格" - }, - "advancedOptions": { - "message": "高级选项" - }, - "advancedPriorityFeeToolTip": { - "message": "优先费(又称“矿工费”)直接向矿工支付,激励他们优先处理您的交易。" - }, - "affirmAgree": { - "message": "我同意" - }, - "airgapVault": { - "message": "AirGap Vault" - }, - "airgapVaultTutorial": { - "message": " (使用教程)" - }, - "alertDisableTooltip": { - "message": "这可以在“设置 > 提醒”中进行更改" - }, - "alertSettingsUnconnectedAccount": { - "message": "浏览网站时选择的账户未连接" - }, - "alertSettingsUnconnectedAccountDescription": { - "message": "当您浏览已连接的 web3 网站时,此警报会显示在弹出窗口中,但当前选择的账户未连接。" - }, - "alertSettingsWeb3ShimUsage": { - "message": "当网站尝试使用已经删除的 window.web3 API 时" - }, - "alertSettingsWeb3ShimUsageDescription": { - "message": "当您浏览尝试使用已删除的 window.web3 API 并因此可能出现故障的网站时,此警报会显示在弹出窗口中。" - }, - "alerts": { - "message": "提醒" - }, - "allOfYour": { - "message": "您的所有$1", - "description": "$1 is the symbol or name of the token that the user is approving spending" - }, - "allowExternalExtensionTo": { - "message": "允许此外部扩展程序:" - }, - "allowSpendToken": { - "message": "授予访问您的 $1 的权限?", - "description": "$1 is the symbol of the token that are requesting to spend" - }, - "allowThisSiteTo": { - "message": "允许此网站:" - }, - "allowWithdrawAndSpend": { - "message": "允许 $1 提取和消费最高以下金额:", - "description": "The url of the site that requested permission to 'withdraw and spend'" - }, - "amount": { - "message": "数额" - }, - "appDescription": { - "message": "浏览器中的以太坊钱包", - "description": "The description of the application" - }, - "appName": { - "message": "MetaMask", - "description": "The name of the application" - }, - "appNameBeta": { - "message": "MetaMask Beta", - "description": "The name of the application (Beta)" - }, - "appNameFlask": { - "message": "MetaMask Flask", - "description": "The name of the application (Flask)" - }, - "approve": { - "message": "批准消费限额" - }, - "approveAllTokensTitle": { - "message": "是否允许访问您的所有$1?", - "description": "$1 is the symbol of the token for which the user is granting approval" - }, - "approveAndInstall": { - "message": "批准并安装" - }, - "approveButtonText": { - "message": "批准" - }, - "approveSpendLimit": { - "message": "批准 $1 消费限额", - "description": "The token symbol that is being approved" - }, - "approved": { - "message": "已批准" - }, - "approvedAmountWithColon": { - "message": "已批准金额:" - }, - "approvedAsset": { - "message": "已获批准的资产" - }, - "areYouDeveloper": { - "message": "您是开发人员吗?" - }, - "areYouSure": { - "message": "您确定吗?" - }, - "asset": { - "message": "资产" - }, - "assetOptions": { - "message": "资产选项" - }, - "assets": { - "message": "资产" - }, - "attemptToCancel": { - "message": "尝试取消吗?" - }, - "attemptToCancelDescription": { - "message": "提交此尝试不能保证将会取消您的初始交易。如果取消尝试成功,将向您收取以上交易费。" - }, - "attemptingConnect": { - "message": "正在尝试连接到区块链。" - }, - "attributions": { - "message": "参与者" - }, - "authorizedPermissions": { - "message": "您已授权以下权限" - }, - "autoLockTimeLimit": { - "message": "自动锁定计时器(分钟)" - }, - "autoLockTimeLimitDescription": { - "message": "设置 MetaMask 将被锁定前的空闲时间(单位:分钟)。" - }, - "average": { - "message": "平均值" - }, - "back": { - "message": "返回" - }, - "backToAll": { - "message": "返回全部" - }, - "backupApprovalInfo": { - "message": "如果不慎丢失个人设备,忘记密码,需要重新安装 MetaMask,或者需在另一台设备上访问钱包,使用此助记词才能恢复您的钱包。" - }, - "backupApprovalNotice": { - "message": "请备份您的账户助记词,保证您的钱包和资金安全。" - }, - "backupNow": { - "message": "立即备份" - }, - "balance": { - "message": "余额" - }, - "balanceOutdated": { - "message": "余额可能已过期" - }, - "baseFee": { - "message": "基本费用" - }, - "basic": { - "message": "基本" - }, - "betaMetamaskDescription": { - "message": "MetaMask 深受数百万人信任,是一款可以让所有人进入 web3 世界的安全钱包。" - }, - "betaMetamaskDescriptionExplanation": { - "message": "使用此版本来测试即将发布的功能。您的使用和反馈有助于我们构建最好的 MetaMask 版本。您对 MetaMask 测试版的使用须遵守我们的标准 $1 以及我们的 $2。作为测试版,出现漏洞的风险可能会增加。继续即表示您接受并承认这些风险,以及我们条款和测试版条款中发现的风险。", - "description": "$1 represents localization item betaMetamaskDescriptionExplanationTermsLinkText. $2 represents localization item betaMetamaskDescriptionExplanationBetaTermsLinkText" - }, - "betaMetamaskDescriptionExplanationBetaTermsLinkText": { - "message": "补充测试版条款" - }, - "betaMetamaskDescriptionExplanationTermsLinkText": { - "message": "条款" - }, - "betaMetamaskVersion": { - "message": "MetaMask 测试版本" - }, - "betaWelcome": { - "message": "欢迎使用 MetaMask 测试版" - }, - "blockExplorerAccountAction": { - "message": "账户", - "description": "This is used with viewOnEtherscan and viewInExplorer e.g View Account in Explorer" - }, - "blockExplorerAssetAction": { - "message": "资产", - "description": "This is used with viewOnEtherscan and viewInExplorer e.g View Asset in Explorer" - }, - "blockExplorerSwapAction": { - "message": "交换", - "description": "This is used with viewOnEtherscan e.g View Swap on Etherscan" - }, - "blockExplorerUrl": { - "message": "区块浏览器 URL" - }, - "blockExplorerUrlDefinition": { - "message": "用作此网络的区块浏览器的 URL。" - }, - "blockExplorerView": { - "message": "在 $1 查看账户", - "description": "$1 replaced by URL for custom block explorer" - }, - "blockies": { - "message": "Blockies" - }, - "browserNotSupported": { - "message": "您的浏览器不受支持……" - }, - "buildContactList": { - "message": "建立您的联系人列表" - }, - "builtAroundTheWorld": { - "message": "MetaMask 是在世界各地设计和建造的。" - }, - "busy": { - "message": "忙碌中" - }, - "buy": { - "message": "购买" - }, - "buyAsset": { - "message": "购买$1", - "description": "$1 is the ticker symbol of a an asset the user is being prompted to purchase" - }, - "buyCryptoWithCoinbasePay": { - "message": "用Coinbase Pay购买$1", - "description": "$1 represents the crypto symbol to be purchased" - }, - "buyCryptoWithCoinbasePayDescription": { - "message": "您可以使用Coinbase账户轻松购买或转移加密货币。", - "description": "$1 represents the crypto symbol to be purchased" - }, - "buyCryptoWithMoonPay": { - "message": "用MoonPay购买$1", - "description": "$1 represents the cypto symbol to be purchased" - }, - "buyCryptoWithMoonPayDescription": { - "message": "MoonPay支持热门的支付方式,包括Visa、万事达卡、Apple / Google / Samsung Pay,以及超过145个国家/地区的银行转账。代币会被存入您的MetaMask账户。" - }, - "buyCryptoWithTransak": { - "message": "用Transak购买$1", - "description": "$1 represents the cypto symbol to be purchased" - }, - "buyCryptoWithTransakDescription": { - "message": "Transak在超过100个国家/地区支持信用卡和借记卡、Apple Pay、MobiKwik和银行转账(取决于地点)。$1会被直接存入您的MetaMask账户。", - "description": "$1 represents the crypto symbol to be purchased" - }, - "buyWithWyre": { - "message": "使用Wyre购买$1" - }, - "buyWithWyreDescription": { - "message": "购买不超过$1000可以轻松开通。快速交互式上限购买验证。支持借记卡/信用卡、Apple Pay、银行转账。适用于100多个国家。代币存入您的MetaMask账户" - }, - "bytes": { - "message": "字节" - }, - "canToggleInSettings": { - "message": "您可以在“设置 -> 提醒”中重新启用该通知。" - }, - "cancel": { - "message": "取消" - }, - "cancelEdit": { - "message": "取消编辑" - }, - "cancelPopoverTitle": { - "message": "取消交易" - }, - "cancelSpeedUp": { - "message": "取消或加快交易。" - }, - "cancelSpeedUpLabel": { - "message": "这笔燃料费将$1原来的费用。", - "description": "$1 is text 'replace' in bold" - }, - "cancelSpeedUpTransactionTooltip": { - "message": "若要$1交易,燃料费用必须增加至少10%才能被网络认可。", - "description": "$1 is string 'cancel' or 'speed up'" - }, - "cancelSwapForFee": { - "message": "以~$1取消兑换", - "description": "$1 could be e.g. $2.98, it is a cost for cancelling a Smart Transaction" - }, - "cancelSwapForFree": { - "message": "免费取消兑换" - }, - "cancellationGasFee": { - "message": "取消燃料费用" - }, - "cancelled": { - "message": "已取消" - }, - "chainId": { - "message": "链 ID" - }, - "chainIdDefinition": { - "message": "用于签署此网络的交易的链 ID。" - }, - "chainIdExistsErrorMsg": { - "message": "此链 ID 目前已被 $1 网络使用。" - }, - "chainListReturnedDifferentTickerSymbol": { - "message": "链ID为$1的网络使用的货币代码($2)可能与您输入的不同。请在继续之前进行验证。", - "description": "$1 is the chain id currently entered in the network form and $2 is the return value of nativeCurrency.symbol from chainlist.network" - }, - "chromeRequiredForHardwareWallets": { - "message": "您需要在 Google Chrome 上使用 MetaMask 以连接到您的硬件钱包。" - }, - "clickToConnectLedgerViaWebHID": { - "message": "点击这里以通过 WebHID 连接您的 Ledger", - "description": "Text that can be clicked to open a browser popup for connecting the ledger device via webhid" - }, - "clickToRevealSeed": { - "message": "点击此处以显示助记词" - }, - "close": { - "message": "关闭" - }, - "collectibleAddFailedMessage": { - "message": "由于所有权信息不匹配,无法添加NFT。请确保所输入的信息正确无误。" - }, - "collectibleAddressError": { - "message": "此代币是NFT。另加上$1", - "description": "$1 is a clickable link with text defined by the 'importNFTPage' key" - }, - "confirm": { - "message": "确认" - }, - "confirmPassword": { - "message": "确认密码" - }, - "confirmRecoveryPhrase": { - "message": "确认助记词" - }, - "confirmSecretBackupPhrase": { - "message": "请确认您的账户助记词" - }, - "confirmed": { - "message": "已确认" - }, - "confusableUnicode": { - "message": "'$1' 与 '$2' 相似。" - }, - "confusableZeroWidthUnicode": { - "message": "找到零宽字符。" - }, - "confusingEnsDomain": { - "message": "我们在 ENS 名称中检测到一个可令人混淆的字符。检查 ENS 名称以避免潜在的骗局。" - }, - "congratulations": { - "message": "恭喜" - }, - "connect": { - "message": "连接" - }, - "connectAccountOrCreate": { - "message": "连接账户或创建新账户" - }, - "connectHardwareWallet": { - "message": "连接硬件钱包" - }, - "connectManually": { - "message": "手动连接到当前站点" - }, - "connectTo": { - "message": "连接到 $1", - "description": "$1 is the name/origin of a web3 site/application that the user can connect to metamask" - }, - "connectToAll": { - "message": "连接到您的全部 $1", - "description": "$1 will be replaced by the translation of connectToAllAccounts" - }, - "connectToAllAccounts": { - "message": "账户", - "description": "will replace $1 in connectToAll, completing the sentence 'connect to all of your accounts', will be text that shows list of accounts on hover" - }, - "connectToMultiple": { - "message": "连接到 $1", - "description": "$1 will be replaced by the translation of connectToMultipleNumberOfAccounts" - }, - "connectToMultipleNumberOfAccounts": { - "message": "$1 个账户", - "description": "$1 is the number of accounts to which the web3 site/application is asking to connect; this will substitute $1 in connectToMultiple" - }, - "connectWithMetaMask": { - "message": "与 MetaMask 连接" - }, - "connectedAccountsDescriptionPlural": { - "message": "您有 $1 个账户连接到了该网站。", - "description": "$1 is the number of accounts" - }, - "connectedAccountsDescriptionSingular": { - "message": "您有1个账户连接到了该网站。" - }, - "connectedAccountsEmptyDescription": { - "message": "MetaMask 没有连接到该网站。要连接到 web3 网站,请找到并点击连接按钮。" - }, - "connectedSites": { - "message": "已连接的网站" - }, - "connectedSitesDescription": { - "message": "$1 已连接到这些网站。他们可以查看您的账户地址。", - "description": "$1 is the account name" - }, - "connectedSitesEmptyDescription": { - "message": "$1 还没连接到任何网站。", - "description": "$1 is the account name" - }, - "connectedSnapSites": { - "message": "$1的snap已连接到这些站点。它们有上述的访问权限。", - "description": "$1 represents the name of the snap" - }, - "connecting": { - "message": "连接中……" - }, - "connectingTo": { - "message": "正在连接 $1" - }, - "connectingToGoerli": { - "message": "正在连接 Goerli 测试网络" - }, - "connectingToMainnet": { - "message": "正在连接到以太坊主网" - }, - "contactUs": { - "message": "联系我们" - }, - "contacts": { - "message": "联系信息" - }, - "continue": { - "message": "继续" - }, - "continueToCoinbasePay": { - "message": "继续使用Coinbase Pay" - }, - "continueToMoonPay": { - "message": "继续使用MoonPay" - }, - "continueToTransak": { - "message": "继续前往 Transak" - }, - "continueToWyre": { - "message": "继续前往 Wyre" - }, - "contract": { - "message": "合约" - }, - "contractAddress": { - "message": "合约地址" - }, - "contractAddressError": { - "message": "您正在向代币的合约地址发送代币。这可能导致这些代币丢失。" - }, - "contractDeployment": { - "message": "合约部署" - }, - "contractInteraction": { - "message": "合约交互" - }, - "convertTokenToNFTDescription": { - "message": "我们检测到该资产是NFT。Metamask现在完全原生支持NFT。您想将它从您的代币列表中删除并将它添加为NFT吗?" - }, - "convertTokenToNFTExistDescription": { - "message": "我们检测到该资产已作为NFT添加。是否要将其从代币列表中删除?" - }, - "copiedExclamation": { - "message": "已复制!" - }, - "copyAddress": { - "message": "复制地址到剪贴板" - }, - "copyPrivateKey": { - "message": "这是您的私钥(点击以复制)" - }, - "copyRawTransactionData": { - "message": "复制原始交易数据" - }, - "copyToClipboard": { - "message": "复制到剪贴板" - }, - "copyTransactionId": { - "message": "复制交易 ID" - }, - "create": { - "message": "创建" - }, - "createAWallet": { - "message": "创建钱包" - }, - "createAccount": { - "message": "创建账户" - }, - "createNewWallet": { - "message": "创建新钱包" - }, - "createPassword": { - "message": "创建密码" - }, - "currencyConversion": { - "message": "货币转换" - }, - "currencySymbol": { - "message": "货币符号" - }, - "currencySymbolDefinition": { - "message": "此网络的货币显示的股票代码。" - }, - "currentAccountNotConnected": { - "message": "您的当前账户没有连接" - }, - "currentExtension": { - "message": "当前扩展程序页面" - }, - "currentLanguage": { - "message": "当前语言" - }, - "currentTitle": { - "message": "当前:" - }, - "currentlyUnavailable": { - "message": "在此网络上不可用" - }, - "curveHighGasEstimate": { - "message": "高价燃料估算图" - }, - "curveLowGasEstimate": { - "message": "低价燃料估算图" - }, - "curveMediumGasEstimate": { - "message": "市场价燃料估算图" - }, - "custom": { - "message": "高级" - }, - "customContentSearch": { - "message": "搜索以前添加的网络" - }, - "customGas": { - "message": "自定义燃料" - }, - "customGasSettingToolTipMessage": { - "message": "使用$1来定制燃料价格。如果您不熟悉这可能会引起混淆。操作风险自付。", - "description": "$1 is key 'advanced' (text: 'Advanced') separated here so that it can be passed in with bold fontweight" - }, - "customGasSubTitle": { - "message": "提升费用可能会缩短处理时间,但不能保证。" - }, - "customSpendLimit": { - "message": "自定义消费限额" - }, - "customToken": { - "message": "自定义代币" - }, - "customTokenWarningInNonTokenDetectionNetwork": { - "message": "代币检测在此网络上尚不可用。请手动导入代币并确保您信任它。了解 $1" - }, - "customTokenWarningInTokenDetectionNetwork": { - "message": "手动导入代币前,请确保您信任它。了解 $1。" - }, - "customerSupport": { - "message": "客户支持" - }, - "dappSuggested": { - "message": "建议的网站" - }, - "dappSuggestedGasSettingToolTipMessage": { - "message": "$1 建议了这个价格。", - "description": "$1 is url for the dapp that has suggested gas settings" - }, - "dappSuggestedShortLabel": { - "message": "网站" - }, - "dappSuggestedTooltip": { - "message": "$1 建议了这个价格。", - "description": "$1 represents the Dapp's origin" - }, - "darkTheme": { - "message": "深色" - }, - "data": { - "message": "数据" - }, - "dataBackupFoundInfo": { - "message": "您的部分账户数据已在之前安装 MetaMask 时备份。其中可能包括您的设置、联系人和代币。您现在想恢复这些数据吗?" - }, - "dataHex": { - "message": "十六进制" - }, - "decimal": { - "message": "代币小数" - }, - "decimalsMustZerotoTen": { - "message": "小数位至少为0,且不得超过36。" - }, - "decrypt": { - "message": "解密" - }, - "decryptCopy": { - "message": "复制加密消息" - }, - "decryptInlineError": { - "message": "由于错误:$1,无法解密此消息", - "description": "$1 is error message" - }, - "decryptMessageNotice": { - "message": "$1 希望阅读此消息来完成您的操作", - "description": "$1 is the web3 site name" - }, - "decryptMetamask": { - "message": "解密消息" - }, - "decryptRequest": { - "message": "解密请求" - }, - "delete": { - "message": "删除" - }, - "deleteAccount": { - "message": "删除账户" - }, - "deleteNetwork": { - "message": "删除网络?" - }, - "deleteNetworkDescription": { - "message": "您确定要删除该网络吗?" - }, - "depositCrypto": { - "message": "存入$1", - "description": "$1 represents the cypto symbol to be purchased" - }, - "description": { - "message": "描述" - }, - "details": { - "message": "详细信息" - }, - "directDepositCrypto": { - "message": "直接存入$1" - }, - "directDepositCryptoExplainer": { - "message": "如果您已经有了一些$1,那么在您的新钱包里获得$1的最快方式是直接存入。" - }, - "disabledGasOptionToolTipMessage": { - "message": "“$1”已被禁用,因为它不满足在原来的燃料费用基础上至少增加10%的要求。", - "description": "$1 is gas estimate type which can be market or aggressive" - }, - "disconnect": { - "message": "断开连接" - }, - "disconnectAllAccounts": { - "message": "断开所有账户的连接" - }, - "disconnectAllAccountsConfirmationDescription": { - "message": "您确定要断开连接吗?您可能会失去网站功能。" - }, - "disconnectPrompt": { - "message": "断开连接 $1" - }, - "disconnectThisAccount": { - "message": "断开此账户的连接" - }, - "dismiss": { - "message": "关闭" - }, - "dismissReminderDescriptionField": { - "message": "开启此选项以关闭账户助记词备份提醒消息。我们强烈建议您备份您的账户助记词,以避免资金损失" - }, - "dismissReminderField": { - "message": "关闭账户助记词备份提醒" - }, - "domain": { - "message": "域" - }, - "done": { - "message": "完成" - }, - "dontShowThisAgain": { - "message": "不再显示此内容" - }, - "downArrow": { - "message": "向下箭头" - }, - "downloadGoogleChrome": { - "message": "下载 Google Chrome 浏览器" - }, - "downloadSecretBackup": { - "message": "下载此账户助记词,并将其安全保存在外部加密硬盘或存储介质上。" - }, - "downloadStateLogs": { - "message": "下载状态日志" - }, - "dropped": { - "message": "已放弃" - }, - "edit": { - "message": "编辑" - }, - "editANickname": { - "message": "编辑昵称" - }, - "editAddressNickname": { - "message": "编辑地址昵称" - }, - "editCancellationGasFeeModalTitle": { - "message": "编辑取消燃料费用" - }, - "editContact": { - "message": "编辑联系信息" - }, - "editGasEducationButtonText": { - "message": "我应该如何选择?" - }, - "editGasEducationHighExplanation": { - "message": "这最适合对时间敏感的交易(如交换),因为它能增加交易成功的可能性。如果交换需要太长的时间来处理,它可能会失败,并导致您损失一些燃料费。" - }, - "editGasEducationLowExplanation": { - "message": "只有在处理时间不太重要时才能使用较低的燃料费用。较低的费用使我们难以预测您的交易何时(或会否)成功。" - }, - "editGasEducationMediumExplanation": { - "message": "中燃料费用适合用于发送、提取或其他非时间敏感交易。此设置最常导致交易成功。" - }, - "editGasEducationModalIntro": { - "message": "选择合适的燃料费取决于交易的类型和它对您的重要性。" - }, - "editGasEducationModalTitle": { - "message": "如何选择?" - }, - "editGasFeeModalTitle": { - "message": "编辑网络费" - }, - "editGasHigh": { - "message": "高" - }, - "editGasLimitOutOfBounds": { - "message": "燃料上限至少为 $1" - }, - "editGasLimitOutOfBoundsV2": { - "message": "燃料上限必须大于 $1 且小于 $2", - "description": "$1 is the minimum limit for gas and $2 is the maximum limit" - }, - "editGasLimitTooltip": { - "message": "燃料上限是您愿意使用的最大燃料单位。燃料单位是“最大优先费”和“最大费用”的乘数。" - }, - "editGasLow": { - "message": "低" - }, - "editGasMaxBaseFeeGWEIImbalance": { - "message": "最大基本费用不能低于优先费用" - }, - "editGasMaxBaseFeeHigh": { - "message": "最大基本费用高于必要水平" - }, - "editGasMaxBaseFeeLow": { - "message": "对于当前网络条件而言,最大基本费用较低" - }, - "editGasMaxFeeHigh": { - "message": "最大费用高于必要水平" - }, - "editGasMaxFeeLow": { - "message": "对于网络条件而言,最大费用过低" - }, - "editGasMaxFeePriorityImbalance": { - "message": "最大费用不能低于最大优先费用" - }, - "editGasMaxFeeTooltip": { - "message": "最大费用是您将支付的最大费用(基本费用+优先费用)。" - }, - "editGasMaxPriorityFeeBelowMinimum": { - "message": "最大优先费用必须大于0 GWEI。" - }, - "editGasMaxPriorityFeeBelowMinimumV2": { - "message": "优先费用必须大于0。" - }, - "editGasMaxPriorityFeeHigh": { - "message": "最大优先费用高于必要水平。您可以支付超过所需的费用。" - }, - "editGasMaxPriorityFeeHighV2": { - "message": "优先费用高于必要水平。您可以支付超过所需的费用" - }, - "editGasMaxPriorityFeeLow": { - "message": "对于当前网络条件而言,最大优先费用较低" - }, - "editGasMaxPriorityFeeLowV2": { - "message": "对于当前网络条件而言,优先费用较低" - }, - "editGasMaxPriorityFeeTooltip": { - "message": "最大优先费(又称“矿工费”)直接向矿工支付,激励他们优先处理您的交易。您通常会支付您的最大设置" - }, - "editGasMedium": { - "message": "中" - }, - "editGasPriceTooLow": { - "message": "燃料价格必须大于0" - }, - "editGasPriceTooltip": { - "message": "此网络在提交交易时需要一个“燃料价格”字段。燃料价格是您支付的每单位燃料金额。" - }, - "editGasSubTextAmountLabel": { - "message": "最大金额:", - "description": "This is meant to be used as the $1 substitution editGasSubTextAmount" - }, - "editGasSubTextFeeLabel": { - "message": "最大费用:" - }, - "editGasTitle": { - "message": "编辑优先级" - }, - "editGasTooLow": { - "message": "处理时间未知" - }, - "editGasTooLowTooltip": { - "message": "对于当前的市场条件而言,您的最大费用或最大优先费用可能较低。我们不知道您的交易将在何时(或会否)处理。" - }, - "editGasTooLowWarningTooltip": { - "message": "这降低了您的最大费用,但如果网络流量增加,您的交易可能会被延迟或失败。" - }, - "editNonceField": { - "message": "编辑 Nonce" - }, - "editNonceMessage": { - "message": "这是高级功能,请谨慎使用。" - }, - "editPermission": { - "message": "编辑权限" - }, - "editSpeedUpEditGasFeeModalTitle": { - "message": "编辑加速燃料费用" - }, - "enableAutoDetect": { - "message": " 启用自动检测" - }, - "enableEIP1559V2": { - "message": "启用增强型燃料费用户界面" - }, - "enableEIP1559V2AlertMessage": { - "message": "我们已经更新了燃料费用估算和定制的方式。" - }, - "enableEIP1559V2ButtonText": { - "message": "在设置中开启增强型燃料费用户界面" - }, - "enableEIP1559V2Description": { - "message": "我们已经更新了燃料估算和定制的方式。如果您想使用新的燃料体验,请开启。$1", - "description": "$1 here is Learn More link" - }, - "enableEIP1559V2Header": { - "message": "新燃料体验" - }, - "enableFromSettings": { - "message": " 从设置中启用它。" - }, - "enableOpenSeaAPI": { - "message": "启用 OpenSea API" - }, - "enableOpenSeaAPIDescription": { - "message": "使用 OpenSea 的 API 获取 NFT 数据。NFT 自动检测依赖于 OpenSea 的 API,在后者关闭时自动检测将不可用。" - }, - "enableSmartTransactions": { - "message": "启用智能交易" - }, - "enableToken": { - "message": "启用 $1", - "description": "$1 is a token symbol, e.g. ETH" - }, - "encryptionPublicKeyNotice": { - "message": "$1 想要您的加密公钥。同意后,该网站将可以向您发送加密消息。", - "description": "$1 is the web3 site name" - }, - "encryptionPublicKeyRequest": { - "message": "申请加密公钥" - }, - "endOfFlowMessage1": { - "message": "您通过了测试——保管好您的账户助记词,这是您的责任!" - }, - "endOfFlowMessage10": { - "message": "全部完成" - }, - "endOfFlowMessage2": { - "message": "安全保存技巧" - }, - "endOfFlowMessage3": { - "message": "在多处保存备份。" - }, - "endOfFlowMessage4": { - "message": "绝不向任何人分享该账户助记词。" - }, - "endOfFlowMessage5": { - "message": "谨防网络钓鱼!MetaMask 绝不会主动要求您提供个人账户助记词。" - }, - "endOfFlowMessage6": { - "message": "如果您需要再次备份账户助记词,请通过“设置 -> 安全”选项完成该操作。" - }, - "endOfFlowMessage7": { - "message": "如果您有任何疑问或发现可疑之处,请联系我们的支持部门 $1。", - "description": "$1 is a clickable link with text defined by the 'here' key. The link will open to a form where users can file support tickets." - }, - "endOfFlowMessage8": { - "message": "MetaMask 无法恢复您的账户助记词。" - }, - "endOfFlowMessage9": { - "message": "了解更多。" - }, - "endpointReturnedDifferentChainId": { - "message": "RPC 端点使用链不同的链 ID: $1", - "description": "$1 is the return value of eth_chainId from an RPC endpoint" - }, - "ensIllegalCharacter": { - "message": "ENS 的非法字符。" - }, - "ensNotFoundOnCurrentNetwork": { - "message": "未在当前网络找到 ENS 名称。请尝试切换至以太坊主网。" - }, - "ensNotSupportedOnNetwork": { - "message": "网络不支持 ENS" - }, - "ensRegistrationError": { - "message": "ENS 名称注册错误" - }, - "ensUnknownError": { - "message": "ENS 查找失败。" - }, - "enterMaxSpendLimit": { - "message": "输入最大消费限额" - }, - "enterPassword": { - "message": "输入密码" - }, - "enterPasswordContinue": { - "message": "输入密码继续" - }, - "errorCode": { - "message": "代码:$1", - "description": "Displayed error code for debugging purposes. $1 is the error code" - }, - "errorDetails": { - "message": "错误详情", - "description": "Title for collapsible section that displays error details for debugging purposes" - }, - "errorMessage": { - "message": "信息:$1", - "description": "Displayed error message for debugging purposes. $1 is the error message" - }, - "errorName": { - "message": "代码:$1", - "description": "Displayed error name for debugging purposes. $1 is the error name" - }, - "errorPageMessage": { - "message": "通过重新加载页面再试一次,或联系支持部门 $1。", - "description": "Message displayed on generic error page in the fullscreen or notification UI, $1 is a clickable link with text defined by the 'here' key. The link will open to a form where users can file support tickets." - }, - "errorPagePopupMessage": { - "message": "通过关闭并重新打开弹出窗口再试一次,或联系支持部门 $1。", - "description": "Message displayed on generic error page in the popup UI, $1 is a clickable link with text defined by the 'here' key. The link will open to a form where users can file support tickets." - }, - "errorPageTitle": { - "message": "MetaMask 遇到了一个错误", - "description": "Title of generic error page" - }, - "errorStack": { - "message": "栈:", - "description": "Title for error stack, which is displayed for debugging purposes" - }, - "estimatedProcessingTimes": { - "message": "预计处理时间" - }, - "ethGasPriceFetchWarning": { - "message": "由于目前主要的燃料估算服务不可用,因此提供了备用燃料价格。" - }, - "ethereumPublicAddress": { - "message": "以太坊公共地址" - }, - "etherscan": { - "message": "Etherscan" - }, - "etherscanView": { - "message": "在 Etherscan 上查看账户" - }, - "etherscanViewOn": { - "message": "在 Etherscan 上查看" - }, - "expandExperience": { - "message": "扩展您的web3体验" - }, - "expandView": { - "message": "展开视图" - }, - "experimental": { - "message": "试验" - }, - "exportPrivateKey": { - "message": "导出私钥" - }, - "externalExtension": { - "message": "外部扩展程序" - }, - "failed": { - "message": "失败" - }, - "failedToFetchChainId": { - "message": "无法获取链 ID。您的 RPC URL 正确吗?" - }, - "failedToFetchTickerSymbolData": { - "message": "股票代码验证数据当前未能提供,请确保您输入的代码正确无误。这会影响您在此网络看到的兑换率" - }, - "failureMessage": { - "message": "出了点问题,我们无法完成此操作" - }, - "fast": { - "message": "快" - }, - "fastest": { - "message": "最快" - }, - "feeAssociatedRequest": { - "message": "此请求需要支付一定的费用。" - }, - "fiat": { - "message": "法币", - "description": "Exchange type" - }, - "fileImportFail": { - "message": "文件导入失败?点击这里!", - "description": "Helps user import their account from a JSON file" - }, - "flaskSnapSettingsCardButtonCta": { - "message": "查看详细信息", - "description": "Call to action a user can take to see more information about the Snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "添加于", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "自", - "description": "Part of the sentence describing when and where snap was added" - }, - "flaskWelcomeUninstall": { - "message": "您应该卸载此扩展程序", - "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." - }, - "flaskWelcomeWarning1": { - "message": "Flask供开发人员试验不稳定的新API。除非您是开发人员或Beta测试人员,否则请$1。", - "description": "This is a warning shown on the Flask Welcome screen, intended to encourage non-developers not to proceed any further. $1 is the bolded message 'flaskWelcomeUninstall'" - }, - "flaskWelcomeWarning2": { - "message": "我们不保证此扩展程序的安全性或稳定性。Flask提供的新API并未针对网络钓鱼攻击进行强化,这意味着任何需要Flask的站点或快取都可能是窃取您资产的恶意企图。", - "description": "This explains the risks of using MetaMask Flask" - }, - "flaskWelcomeWarning3": { - "message": "所有Flask API都是实验性的。它们可能会在未事先通知的情况下被更改或删除,它们也可能会无限期地留在Flask上而不会迁移到稳定的MetaMask。您需要自行承担使用它们的风险。", - "description": "This message warns developers about unstable Flask APIs" - }, - "flaskWelcomeWarning4": { - "message": "确保在使用Flask时禁用常规MetaMask扩展程序。", - "description": "This message calls to pay attention about multiple versions of MetaMask running on the same site (Flask + Prod)" - }, - "flaskWelcomeWarningAcceptButton": { - "message": "我接受风险", - "description": "this text is shown on a button, which the user presses to confirm they understand the risks of using Flask" - }, - "followUsOnTwitter": { - "message": "在 Twitter 上关注我们" - }, - "forbiddenIpfsGateway": { - "message": "禁用的 IPFS 网关:请指定一个 CID 网关" - }, - "forgetDevice": { - "message": "忽略此设备" - }, - "forgotPassword": { - "message": "忘记密码了?" - }, - "from": { - "message": "自" - }, - "fromAddress": { - "message": "从:$1", - "description": "$1 is the address to include in the From label. It is typically shortened first using shortenAddress" - }, - "fromTokenLists": { - "message": "从代币列表:$1" - }, - "functionApprove": { - "message": "功能:批准" - }, - "functionSetApprovalForAll": { - "message": "功能:SetApprovalForAll" - }, - "functionType": { - "message": "功能类型" - }, - "gas": { - "message": "燃料" - }, - "gasDisplayAcknowledgeDappButtonText": { - "message": "编辑建议的燃料费" - }, - "gasDisplayDappWarning": { - "message": "这笔燃料费是由 $1 建议的。忽略它可能会导致您的交易出现问题。如果您有疑问,请联系 $1。", - "description": "$1 represents the Dapp's origin" - }, - "gasEstimatesUnavailableWarning": { - "message": "无法获取我们的低、中、高估计值。" - }, - "gasFee": { - "message": "燃料费" - }, - "gasLimit": { - "message": "燃料上限" - }, - "gasLimitInfoTooltipContent": { - "message": "燃料上限是指您愿意花费的最大燃料单位量。" - }, - "gasLimitRecommended": { - "message": "建议的燃料上限是$1。如果燃料上限低于此值,则可能会失败。" - }, - "gasLimitTooLow": { - "message": "燃料上限至少为21000" - }, - "gasLimitTooLowWithDynamicFee": { - "message": "燃料上限至少为 $1", - "description": "$1 is the custom gas limit, in decimal." - }, - "gasLimitV2": { - "message": "燃料限制" - }, - "gasOption": { - "message": "燃料选项" - }, - "gasPrice": { - "message": "Gas 价格 (GWEI)" - }, - "gasPriceExcessive": { - "message": "您的燃料费设置得过高。请考虑降低金额。" - }, - "gasPriceExcessiveInput": { - "message": "燃料价格过高" - }, - "gasPriceExtremelyLow": { - "message": "燃料价格极低" - }, - "gasPriceFetchFailed": { - "message": "由于网络错误,燃料价格估算失败。" - }, - "gasPriceInfoTooltipContent": { - "message": "燃料价格指明了您愿意为每单位燃料支付的以太币数量。" - }, - "gasTimingHoursShort": { - "message": "$1 小时", - "description": "$1 represents a number of hours" - }, - "gasTimingMinutes": { - "message": "$1 分钟", - "description": "$1 represents a number of minutes" - }, - "gasTimingMinutesShort": { - "message": "$1 分钟", - "description": "$1 represents a number of minutes" - }, - "gasTimingNegative": { - "message": "可能在 $1 内", - "description": "$1 represents an amount of time" - }, - "gasTimingPositive": { - "message": "有可能在 $1 以内", - "description": "$1 represents an amount of time" - }, - "gasTimingSeconds": { - "message": "$1 秒", - "description": "$1 represents a number of seconds" - }, - "gasTimingSecondsShort": { - "message": "$1 秒", - "description": "$1 represents a number of seconds" - }, - "gasTimingVeryPositive": { - "message": "很可能在 $1 以内", - "description": "$1 represents an amount of time" - }, - "gasUsed": { - "message": "使用的燃料" - }, - "gdprMessage": { - "message": "这些数据是汇总的,因此,根据《通用数据保护条例》(欧盟)2016/679,这些数据是匿名的。有关我们隐私惯例的更多信息,请参见我们的 $1。", - "description": "$1 refers to the gdprMessagePrivacyPolicy message, the translation of which is meant to be used exclusively in the context of gdprMessage" - }, - "gdprMessagePrivacyPolicy": { - "message": "隐私政策", - "description": "this translation is intended to be exclusively used as the replacement for the $1 in the gdprMessage translation" - }, - "general": { - "message": "常规" - }, - "getEther": { - "message": "获取以太币" - }, - "getEtherFromFaucet": { - "message": "从 $1 的水龙头获取以太币", - "description": "Displays network name for Ether faucet" - }, - "getStarted": { - "message": "开始使用" - }, - "goBack": { - "message": "返回" - }, - "goerli": { - "message": "Goerli 测试网络" - }, - "gotIt": { - "message": "知道了!" - }, - "grantedToWithColon": { - "message": "授予:" - }, - "gwei": { - "message": "GWEI" - }, - "happyToSeeYou": { - "message": "我们很高兴见到您。" - }, - "hardware": { - "message": "硬件" - }, - "hardwareWalletConnected": { - "message": "已连接的硬件钱包" - }, - "hardwareWalletLegacyDescription": { - "message": "(旧)", - "description": "Text representing the MEW path" - }, - "hardwareWalletSupportLinkConversion": { - "message": "点击这里" - }, - "hardwareWallets": { - "message": "连接硬件钱包" - }, - "hardwareWalletsMsg": { - "message": "选择希望用于 MetaMask 的硬件钱包。" - }, - "here": { - "message": "此处", - "description": "as in -click here- for more information (goes with troubleTokenBalances)" - }, - "hexData": { - "message": "十六进制数据" - }, - "hide": { - "message": "隐藏" - }, - "hideFullTransactionDetails": { - "message": "隐藏完整的交易细节" - }, - "hideSeedPhrase": { - "message": "隐藏助记词" - }, - "hideToken": { - "message": "隐藏代币" - }, - "hideTokenPrompt": { - "message": "隐藏代币?" - }, - "hideTokenSymbol": { - "message": "隐藏 $1", - "description": "$1 is the symbol for a token (e.g. 'DAI')" - }, - "hideZeroBalanceTokens": { - "message": "隐藏没有余额的代币" - }, - "high": { - "message": "过高" - }, - "highGasSettingToolTipMessage": { - "message": "使用$1来覆盖网络流量因像流行的 NFT 丢弃而出现的剧增。", - "description": "$1 is key 'high' (text: 'Aggressive') separated here so that it can be passed in with bold fontweight" - }, - "highLowercase": { - "message": "高" - }, - "history": { - "message": "历史记录" - }, - "ignoreAll": { - "message": "忽略所有" - }, - "ignoreTokenWarning": { - "message": "如果您隐藏代币,它们将不会在您的钱包中显示。但您仍然可以通过搜索代币来添加它们。" - }, - "import": { - "message": "导入", - "description": "Button to import an account from a selected file" - }, - "importAccount": { - "message": "导入账户" - }, - "importAccountError": { - "message": "导入账户时出错。" - }, - "importAccountMsg": { - "message": "导入的账户将不会与最初创建的 MetaMask 账户助记词相关联。了解更多有关导入账户的信息" - }, - "importAccountSeedPhrase": { - "message": "使用账户助记词导入钱包" - }, - "importMyWallet": { - "message": "导入我的钱包" - }, - "importNFT": { - "message": "导入 NFT" - }, - "importNFTAddressToolTip": { - "message": "例如,在OpenSea中,NFT页面的详情下,有一个蓝色的超链接值,标记为“合约地址”。如果您点击它,它将带您前往该合约在Etherscan上的地址;在该页面的左上角,应该有一个标记为“合约”的图标,在右侧,有一长串字母和数字。这是创建您的NFT的合约地址。点击地址右侧的“复制”图标,就可以将它复制到剪贴板上。" - }, - "importNFTPage": { - "message": "导入NFT页面" - }, - "importNFTTokenIdToolTip": { - "message": "收藏品的ID是唯一标识符,因为所有NFT都是独一无二的。同样,在OpenSea上,此数字位于“详情”下方。记下它,或将它复制到剪贴板上。" - }, - "importNFTs": { - "message": "添加收藏品" - }, - "importTokenQuestion": { - "message": "导入代币?" - }, - "importTokenWarning": { - "message": "任何人都可以用任何名称创建代币,包括现有代币的虚假版本。添加和交易风险自负!" - }, - "importTokens": { - "message": "添加资产" - }, - "importTokensCamelCase": { - "message": "添加代币" - }, - "importWallet": { - "message": "导入钱包" - }, - "importWithCount": { - "message": "导入$1", - "description": "$1 will the number of detected tokens that are selected for importing, if all of them are selected then $1 will be all" - }, - "importYourExisting": { - "message": "使用账户助记词导入您的现有钱包" - }, - "imported": { - "message": "已导入", - "description": "status showing that an account has been fully loaded into the keyring" - }, - "infuraBlockedNotification": { - "message": "MetaMask 无法连接到区块链主机。请检查可能的原因 $1。", - "description": "$1 is a clickable link with with text defined by the 'here' key" - }, - "initialTransactionConfirmed": { - "message": "您的初始交易已被网络确认。请点击“确定”返回。" - }, - "insufficientBalance": { - "message": "余额不足。" - }, - "insufficientCurrencyBuyOrDeposit": { - "message": "您的账户中没有足够的$1可以支付$2网络上的交易费用。$3或从另一个账户存入。", - "description": "$1 is the native currency of the network, $2 is the name of the current network, $3 is the key 'buy' + the ticker symbol of the native currency of the chain wrapped in a button" - }, - "insufficientCurrencyDeposit": { - "message": "您的账户中没有足够的$1可以支付$2网络上的交易费用。请从另一个账户存入$1。", - "description": "$1 is the native currency of the network, $2 is the name of the current network" - }, - "insufficientFunds": { - "message": "资金不足." - }, - "insufficientFundsForGas": { - "message": "燃料资金不足" - }, - "insufficientTokens": { - "message": "代币不足。" - }, - "invalidAddress": { - "message": "地址无效" - }, - "invalidAddressRecipient": { - "message": "接收方地址无效" - }, - "invalidAddressRecipientNotEthNetwork": { - "message": "非 ETH 网络,请使用小写" - }, - "invalidAssetType": { - "message": "该资产是NFT,需要在NFT选项卡下的“导入NFT”页面上重新添加" - }, - "invalidBlockExplorerURL": { - "message": "无效的区块浏览器 URL" - }, - "invalidChainIdTooBig": { - "message": "无效的链 ID,链 ID 过大。" - }, - "invalidCustomNetworkAlertContent1": { - "message": "需要重新输入自定义网络 '$1' 的链 ID。", - "description": "$1 is the name/identifier of the network." - }, - "invalidCustomNetworkAlertContent2": { - "message": "为了保护您免受恶意或有问题的网络供应商的影响,现在所有的自定义网络都需要有链 ID。" - }, - "invalidCustomNetworkAlertContent3": { - "message": "进入设置 > 网络并输入链 ID。您可以通过 $1 查找最热门网络的链 ID。", - "description": "$1 is a link to https://chainid.network" - }, - "invalidCustomNetworkAlertTitle": { - "message": "无效的自定义网络" - }, - "invalidHexNumber": { - "message": "无效的十六进制数字。" - }, - "invalidHexNumberLeadingZeros": { - "message": "无效的十六进制数字。删除所有前导零。" - }, - "invalidIpfsGateway": { - "message": "无效的 IPFS 网关。该值必须是一个有效的 URL" - }, - "invalidNumber": { - "message": "无效数字。输入一个十进制或带有“0x”前缀的十六进制数字。" - }, - "invalidNumberLeadingZeros": { - "message": "无效数字。删除所有前导零。" - }, - "invalidRPC": { - "message": "RPC URL 无效" - }, - "invalidSeedPhrase": { - "message": "助记词无效" - }, - "invalidSeedPhraseCaseSensitive": { - "message": "输入无效!助记词须区分大小写。" - }, - "ipfsGateway": { - "message": "IPFS 网关" - }, - "ipfsGatewayDescription": { - "message": "输入用于 ENS 内容解析的 IPFS CID 网关的 URL。" - }, - "jazzAndBlockies": { - "message": "哈希头像是帮助您一眼识别账户的独特图标,有 Jazzicons 和 Blockies 两种不同风格。" - }, - "jazzicons": { - "message": "Jazzicons" - }, - "jsDeliver": { - "message": "jsDeliver" - }, - "jsonFile": { - "message": "JSON 文件", - "description": "format for importing an account" - }, - "keystone": { - "message": "Keystone" - }, - "keystoneTutorial": { - "message": " (使用教程)" - }, - "knownAddressRecipient": { - "message": "已知合约地址。" - }, - "knownTokenWarning": { - "message": "此操作将编辑已经在您的钱包中列出的代币,有肯能被用来欺骗您。只有确定要更改这些代币的内容时,才通过此操作。了解更多关于 $1" - }, - "lastConnected": { - "message": "最后连接" - }, - "learnCancelSpeeedup": { - "message": "学习如何 $1", - "description": "$1 is link to cancel or speed up transactions" - }, - "learnMore": { - "message": "了解更多" - }, - "learnMoreAboutGas": { - "message": "想要 $1 有关燃料的相关信息吗?", - "description": "$1 will be replaced by the learnMore translation key" - }, - "learnMoreUpperCase": { - "message": "了解更多" - }, - "learnScamRisk": { - "message": "诈骗和安全风险的信息。" - }, - "ledgerAccountRestriction": { - "message": "您需要先使用最后一个账户,然后才能添加新账户。" - }, - "ledgerConnectionInstructionCloseOtherApps": { - "message": "关闭任何连接到您设备的其他软件,然后点击这里刷新。" - }, - "ledgerConnectionInstructionHeader": { - "message": "点击确认前:" - }, - "ledgerConnectionInstructionStepFour": { - "message": "在您的 Ledger 设备上启用“智能合约数据”或“盲签”" - }, - "ledgerConnectionInstructionStepOne": { - "message": "在“设置 > 高级”下启用使用 Ledger Live" - }, - "ledgerConnectionInstructionStepThree": { - "message": "在您的 Ledger 设备中插入并选择 Ethereum 应用程序" - }, - "ledgerConnectionInstructionStepTwo": { - "message": "打开和解锁 Ledger Live 应用程序" - }, - "ledgerConnectionPreferenceDescription": { - "message": "自定义连接您的 Ledger 到 Metamask 的方式。建议使用 $1,但也可使用其他选项。请在这里阅读更多信息:$2", - "description": "A description that appears above a dropdown where users can select between up to three options - Ledger Live, U2F or WebHID - depending on what is supported in their browser. $1 is the recommended browser option, it will be either WebHID or U2f. $2 is a link to an article where users can learn more, but will be the translation of the learnMore message." - }, - "ledgerDeviceOpenFailureMessage": { - "message": "Ledger 设备打开失败。您的 Ledger 可能已连接到其他软件。请关闭 Ledger Live 或其他连接到您的 Ledger 设备的应用程序,并尝试再次连接。" - }, - "ledgerLive": { - "message": "Ledger Live", - "description": "The name of a desktop app that can be used with your ledger device. We can also use it to connect a users Ledger device to MetaMask." - }, - "ledgerLiveApp": { - "message": "Ledger Live 应用程序" - }, - "ledgerLocked": { - "message": "无法连接到 Ledger 设备。请确保您的设备已解锁并打开 Etherum 应用程序。" - }, - "ledgerTimeout": { - "message": "Ledger Live 响应时间过长或连接超时。请确保 Ledger Live 应用程序已打开且您的设备已解锁。" - }, - "ledgerTransportChangeWarning": { - "message": "如果您的 Ledger Live 应用程序已打开,请断开任何打开的 Ledger Live 的连接并关闭 Ledger Live 应用程序。" - }, - "ledgerWebHIDNotConnectedErrorMessage": { - "message": "Ledger 设备未连接。如果您想要连接您的 Ledger,请再次点击“继续”并批准 HID 连接", - "description": "An error message shown to the user during the hardware connect flow." - }, - "letsGoSetUp": { - "message": "是的,让我们开始吧!" - }, - "levelArrow": { - "message": "水平箭头" - }, - "lightTheme": { - "message": "浅色" - }, - "likeToImportTokens": { - "message": "您想导入这些代币吗?" - }, - "link": { - "message": "链接" - }, - "links": { - "message": "链接" - }, - "loadMore": { - "message": "加载更多" - }, - "loading": { - "message": "正在加载..." - }, - "loadingNFTs": { - "message": "正在加载NFT......" - }, - "loadingTokens": { - "message": "加载代币中……" - }, - "localhost": { - "message": "Localhost 8545" - }, - "lock": { - "message": "注销" - }, - "lockTimeTooGreat": { - "message": "锁定时间过长" - }, - "logo": { - "message": "$1标志", - "description": "$1 is the name of the ticker" - }, - "low": { - "message": "低" - }, - "lowGasSettingToolTipMessage": { - "message": "使用$1等待较便宜的价格。时间估计远不准确,因为价格有些难以预测。", - "description": "$1 is key 'low' separated here so that it can be passed in with bold fontweight" - }, - "lowLowercase": { - "message": "低" - }, - "lowPriorityMessage": { - "message": "以后的交易将在这个时候之后排队。最后一次看到的价格是在一段时间之前。" - }, - "mainnet": { - "message": "以太坊主网" - }, - "mainnetToken": { - "message": "该地址与已知的以太坊主网代币地址匹配。重新检查您尝试添加的代币的合约地址和网络。" - }, - "makeAnotherSwap": { - "message": "创建新的交换" - }, - "makeSureNoOneWatching": { - "message": "请确保没有人在观看您的屏幕", - "description": "Warning to users to be care while creating and saving their new Secret Recovery Phrase" - }, - "malformedData": { - "message": "格式错误的数据" - }, - "manageSnaps": { - "message": "管理已安装的Snap" - }, - "max": { - "message": "最大" - }, - "maxBaseFee": { - "message": "最大基本费用" - }, - "maxFee": { - "message": "最大费用" - }, - "maxPriorityFee": { - "message": "最大优先费用" - }, - "medium": { - "message": "市场" - }, - "mediumGasSettingToolTipMessage": { - "message": "使用 $1 按当前市场价格快速处理。", - "description": "$1 is key 'medium' (text: 'Market') separated here so that it can be passed in with bold fontweight" - }, - "memo": { - "message": "备注" - }, - "memorizePhrase": { - "message": "记住该账户助记词。" - }, - "message": { - "message": "消息" - }, - "metaMaskConnectStatusParagraphOne": { - "message": "现在您可以更好地控制 MetaMask 中的账户连接。" - }, - "metaMaskConnectStatusParagraphThree": { - "message": "点击它以管理您的连接账户。" - }, - "metaMaskConnectStatusParagraphTwo": { - "message": "连接状态按钮显示所访问的网站是否与您当前选择的账户连接。" - }, - "metamaskDescription": { - "message": "将您连接到以太坊和去中心化网络。" - }, - "metamaskSwapsOfflineDescription": { - "message": "MetaMask Swaps 正在进行维护。请稍后再查看。" - }, - "metamaskVersion": { - "message": "MetaMask 版本" - }, - "metametricsCommitmentsAllowOptOut": { - "message": "始终允许您通过“设置”选择退出" - }, - "metametricsCommitmentsAllowOptOut2": { - "message": "始终可通过设置选择退出" - }, - "metametricsCommitmentsBoldNever": { - "message": "永不", - "description": "This string is localized separately from some of the commitments so that we can bold it" - }, - "metametricsCommitmentsIntro": { - "message": "MetaMask.." - }, - "metametricsCommitmentsNeverCollect": { - "message": "决不收集密钥、地址、交易、余额、哈希或任何个人信息" - }, - "metametricsCommitmentsNeverCollectIP": { - "message": "$1 收集您的完整 IP 地址", - "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" - }, - "metametricsCommitmentsNeverCollectKeysEtc": { - "message": "$1 收集密钥、地址、交易记录、余额、哈希或任何个人信息", - "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" - }, - "metametricsCommitmentsNeverIP": { - "message": "永不收集您的完整 IP 地址" - }, - "metametricsCommitmentsNeverSell": { - "message": "决不出售数据牟利。绝对不会!" - }, - "metametricsCommitmentsNeverSellDataForProfit": { - "message": "$1 为利益而出售您的数据,永远不会!", - "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" - }, - "metametricsCommitmentsSendAnonymizedEvents": { - "message": "发送匿名化点击和页面浏览事件" - }, - "metametricsHelpImproveMetaMask": { - "message": "帮助我们改进 MetaMask" - }, - "metametricsOptInDescription": { - "message": "MetaMask 希望收集使用数据,以更好地了解我们的用户如何与扩展程序交互。这些数据将被用于持续改进我们产品和以太坊生态系统的可用性和用户体验。" - }, - "metametricsOptInDescription2": { - "message": "我们想要收集基本使用数据以提高我们产品的可用性。这些数据将......" - }, - "metametricsTitle": { - "message": "和600多万用户一起改进 MetaMask" - }, - "mismatchedChainLinkText": { - "message": "验证网络信息", - "description": "Serves as link text for the 'mismatchedChain' key. This text will be embedded inside the translation for that key." - }, - "mismatchedChainRecommendation": { - "message": "我们建议您在继续之前$1。", - "description": "$1 is a clickable link with text defined by the 'mismatchedChainLinkText' key. The link will open to instructions for users to validate custom network details." - }, - "mismatchedNetworkName": { - "message": "根据我们的记录,该网络名称可能与此链ID不匹配。" - }, - "mismatchedNetworkSymbol": { - "message": "所提交的货币符号与我们对此链ID的预期不匹配。" - }, - "mismatchedRpcUrl": { - "message": "根据我们的记录,所提交的RPC URL值与此链ID的已知提供者不匹配。" - }, - "missingNFT": { - "message": "找不到您的 NFT?" - }, - "missingSetting": { - "message": "找不到设置吗?" - }, - "missingSettingRequest": { - "message": "在这里请求" - }, - "missingToken": { - "message": "没有看到您的代币?" - }, - "mobileSyncWarning": { - "message": "“与扩展程序同步”功能暂时被禁用。如果您想要在 MetaMask 移动设备上使用您的扩展程序钱包,那么在您的移动应用程序上:返回钱包设置选项并选择“使用账户助记词导入”选项。使用您的扩展程序钱包的助记词来将您的钱包导入移动设备。" - }, - "mustSelectOne": { - "message": "至少选择1种代币。" - }, - "myAccounts": { - "message": "我的账户" - }, - "name": { - "message": "名称" - }, - "needCryptoInWallet": { - "message": "要使用MetaMask与去中心化应用程序互动,您的钱包中需要有$1。", - "description": "$1 represents the cypto symbol to be purchased" - }, - "needHelp": { - "message": "需要帮助?请联系 $1", - "description": "$1 represents `needHelpLinkText`, the text which goes in the help link" - }, - "needHelpFeedback": { - "message": "分享您的反馈" - }, - "needHelpLinkText": { - "message": "MetaMask 支持" - }, - "needHelpSubmitTicket": { - "message": "提交工单" - }, - "needImportFile": { - "message": "您必须选择一个文件来导入。", - "description": "User is important an account and needs to add a file to continue" - }, - "negativeETH": { - "message": "不能发负值的 ETH。" - }, - "network": { - "message": "网络: " - }, - "networkAddedSuccessfully": { - "message": "网络添加成功!" - }, - "networkDetails": { - "message": "网络详情" - }, - "networkIsBusy": { - "message": "网络繁忙。燃料价格较高,估值较不准确。" - }, - "networkName": { - "message": "网络名称" - }, - "networkNameAvalanche": { - "message": "Avalanche" - }, - "networkNameBSC": { - "message": "BSC" - }, - "networkNameDefinition": { - "message": "与此网络关联的名称。" - }, - "networkNameEthereum": { - "message": "以太坊" - }, - "networkNamePolygon": { - "message": "Polygon" - }, - "networkNameTestnet": { - "message": "Testnet" - }, - "networkSettingsChainIdDescription": { - "message": "链 ID 用于签署交易。它必须与网络返回的链 ID 相匹配。您可以输入十进制或以'0x'开头的十六进制数字,但我们将以十进制显示该数字。" - }, - "networkStatus": { - "message": "网络状态" - }, - "networkStatusBaseFeeTooltip": { - "message": "基本费用由网络设定,每13-14秒更改一次。我们的 $1 和 $2 选项用于剧增。", - "description": "$1 and $2 are bold text for Medium and Aggressive respectively." - }, - "networkStatusPriorityFeeTooltip": { - "message": "优先费用(又称“矿工费”)。这笔费用直接向矿工支付,激励他们优先处理您的交易。" - }, - "networkStatusStabilityFeeTooltip": { - "message": "相对过去72小时,燃料费用为 $1。", - "description": "$1 is networks stability value - stable, low, high" - }, - "networkURL": { - "message": "网络 URL" - }, - "networkURLDefinition": { - "message": "用于访问此网络的 URL。" - }, - "networks": { - "message": "网络" - }, - "nevermind": { - "message": "没关系" - }, - "newAccount": { - "message": "新账户" - }, - "newAccountDetectedDialogMessage": { - "message": "检测到新地址!点击这里以添加到您的地址簿。" - }, - "newAccountNumberName": { - "message": "账户 $1", - "description": "Default name of next account to be created on create account screen" - }, - "newCollectibleAddedMessage": { - "message": "收藏品已成功添加!" - }, - "newContact": { - "message": "新联系人" - }, - "newContract": { - "message": "新合约" - }, - "newNFTDetectedMessage": { - "message": "允许 MetaMask 自动检测 Opensea 的 NFT 并在您的钱包中显示。" - }, - "newNFTsDetected": { - "message": "新功能!NFT 检测" - }, - "newNetworkAdded": { - "message": "成功添加了 “$1”!" - }, - "newPassword": { - "message": "新密码(至少 8 个字符)" - }, - "newToMetaMask": { - "message": "MetaMask 的新用户?" - }, - "newTokensImportedMessage": { - "message": "您已成功导入$1。", - "description": "$1 is the string of symbols of all the tokens imported" - }, - "newTokensImportedTitle": { - "message": "已导入代币" - }, - "newTotal": { - "message": "新总额" - }, - "newTransactionFee": { - "message": "新交易费用" - }, - "newValues": { - "message": "新的值" - }, - "next": { - "message": "下一步" - }, - "nextNonceWarning": { - "message": "Nonce 高于建议的 nouce 值 $1", - "description": "The next nonce according to MetaMask's internal logic" - }, - "nft": { - "message": "非同质化代币(NFT)" - }, - "nftTokenIdPlaceholder": { - "message": "输入代币ID" - }, - "nfts": { - "message": "收藏品" - }, - "nickname": { - "message": "昵称" - }, - "noAccountsFound": { - "message": "未找到符合给定查询条件的账户" - }, - "noAddressForName": { - "message": "此名称尚未设置地址。" - }, - "noAlreadyHaveSeed": { - "message": "不,我已经有一个账户助记词" - }, - "noConversionDateAvailable": { - "message": "没有可用的货币转换日期" - }, - "noConversionRateAvailable": { - "message": "无可用汇率" - }, - "noNFTs": { - "message": "尚无 NFT" - }, - "noSnaps": { - "message": "没有安装Snap" - }, - "noThanks": { - "message": "不,谢谢" - }, - "noThanksVariant2": { - "message": "不,谢谢." - }, - "noTransactions": { - "message": "您没有任何交易" - }, - "noWebcamFound": { - "message": "未找到您电脑的网络摄像头。请重试。" - }, - "noWebcamFoundTitle": { - "message": "未找到网络摄像头" - }, - "nonce": { - "message": "nonce" - }, - "nonceField": { - "message": "自定义交易 nonce" - }, - "nonceFieldDescription": { - "message": "打开这个功能可以改变确认屏幕上的 nonce(交易号码)。这是一个高级功能,请谨慎使用。" - }, - "nonceFieldHeading": { - "message": "自定义 Nonce" - }, - "notBusy": { - "message": "非忙碌中" - }, - "notCurrentAccount": { - "message": "这是正确的账户吗?这与您钱包中当前选择的账户不同" - }, - "notEnoughGas": { - "message": "燃料不足" - }, - "notifications": { - "message": "通知" - }, - "notifications10ActionText": { - "message": "在设置中访问", - "description": "The 'call to action' on the button, or link, of the 'Visit in settings' notification. Upon clicking, users will be taken to settings page." - }, - "notifications10DescriptionOne": { - "message": "Ethereum Mainnet、Polygon、BSC 和 Avalanche 网络目前提供经改进的代币检测。 即将推出更多!" - }, - "notifications10DescriptionThree": { - "message": "代币检测功能默认开启。但是您可从设置中禁用它。" - }, - "notifications10DescriptionTwo": { - "message": "我们从第三方代币列表中获取代币。将自动检测在两个以上代币列表中列出的代币。" - }, - "notifications10Title": { - "message": "经改进的代币检测现已推出" - }, - "notifications11Description": { - "message": "代币可由任何人创建,而且名称可以重复。如您看到一个您不信任或未与之交互的代币出现——那么,不信任它会更安全。" - }, - "notifications11Title": { - "message": "欺诈和安全风险" - }, - "notifications12ActionText": { - "message": "启用黑暗模式" - }, - "notifications12Description": { - "message": "扩展程序的深色模式终于来了!若要开启,请前往“设置 -> 实验项”,然后选择一个显示选项:浅色、深色、系统。" - }, - "notifications12Title": { - "message": "何时启用黑暗模式?现在启用黑暗模式! 🕶️🦊" - }, - "notifications13ActionText": { - "message": "显示自定义网络列表" - }, - "notifications13Description": { - "message": "您现在可以轻松添加以下热门自定义网络:Arbitrum、Avalanche、Binance Smart Chain、Fantom、Harmony、Optimism、Palm和Polygon!如需启用此功能,请转到“设置” -> “实验”,然后打开“显示自定义网络列表”!", - "description": "Description of a notification in the 'See What's New' popup. Describes popular network feature." - }, - "notifications13Title": { - "message": "添加热门网络" - }, - "notifications1Description": { - "message": "MetaMask Mobile 用户现在可以在他们的移动钱包中交换代币。扫描二维码以获取移动应用程序并开始交换。", - "description": "Description of a notification in the 'See What's New' popup. Describes the swapping on mobile feature." - }, - "notifications1Title": { - "message": "可以在移动设备上交换了!", - "description": "Title for a notification in the 'See What's New' popup. Tells users that they can now use MetaMask Swaps on Mobile." - }, - "notifications3ActionText": { - "message": "了解更多", - "description": "The 'call to action' on the button, or link, of the 'Stay secure' notification. Upon clicking, users will be taken to a page about security on the metamask support website." - }, - "notifications3Description": { - "message": "及时了解 MetaMask 安全最佳实践,并从 MetaMask 官方支持部门获取最新的安全提示。", - "description": "Description of a notification in the 'See What's New' popup. Describes the information they can get on security from the linked support page." - }, - "notifications3Title": { - "message": "保持安全", - "description": "Title for a notification in the 'See What's New' popup. Encourages users to consider security." - }, - "notifications4ActionText": { - "message": "开始交换", - "description": "The 'call to action' on the button, or link, of the 'Swap on Binance Smart Chain!' notification. Upon clicking, users will be taken to a page where then can swap tokens on Binance Smart Chain." - }, - "notifications4Description": { - "message": "在您的钱包内获取最优惠的代币交换价格。MetaMask 现在将您连接到币安智能链上的多个去中心化交易所聚合器和专业做市商。", - "description": "Description of a notification in the 'See What's New' popup." - }, - "notifications4Title": { - "message": "在币安智能链上交换", - "description": "Title for a notification in the 'See What's New' popup. Encourages users to do swaps on Binance Smart Chain." - }, - "notifications5Description": { - "message": "您的“Seed Phrase”现在被称为“账户助记词”(Secret Recovery Phrase)。", - "description": "Description of a notification in the 'See What's New' popup. Describes the seed phrase wording update." - }, - "notifications6DescriptionOne": { - "message": "从 Chrome 版本91开始,启用我们的 Ledger 支持 (U2F) 的 API 不再支持硬件钱包。MetaMask 实施了新的 Ledger Live 支持,允许您继续通过 Ledger Live 桌面应用程序连接到您的 Ledger 设备。", - "description": "Description of a notification in the 'See What's New' popup. Describes the Ledger support update." - }, - "notifications6DescriptionThree": { - "message": "在 Metamask 中与您的 Ledger 账户交互时,将打开一个新选项卡,并且将要求您打开 Ledger Live 应用程序。应用程序打开后,您将被要求允许 WebSocket 连接到您的 MetaMask 账户。就是这样!", - "description": "Description of a notification in the 'See What's New' popup. Describes the Ledger support update." - }, - "notifications6DescriptionTwo": { - "message": "您可以通过点击“设置 > 高级> 使用 Ledger Live”来启用 Ledger Live 支持。", - "description": "Description of a notification in the 'See What's New' popup. Describes the Ledger support update." - }, - "notifications6Title": { - "message": "Chrome 用户的 Ledger 支持更新", - "description": "Title for a notification in the 'See What's New' popup. Lets users know about the Ledger support update" - }, - "notifications7DescriptionOne": { - "message": "MetaMask v10.1.0 包括使用 Ledger 设备时对 EIP-1559 交易的新支持。", - "description": "Description of a notification in the 'See What's New' popup. Describes changes for ledger and EIP1559 in v10.1.0" - }, - "notifications7DescriptionTwo": { - "message": "要在以太坊主网上完成交易,请确保您的 Ledger 设备拥有最新的固件。", - "description": "Description of a notification in the 'See What's New' popup. Describes the need to update ledger firmware." - }, - "notifications7Title": { - "message": "Ledger 固件更新", - "description": "Title for a notification in the 'See What's New' popup. Notifies ledger users of the need to update firmware." - }, - "notifications8ActionText": { - "message": "转到高级设置", - "description": "Description on an action button that appears in the What's New popup. Tells the user that if they click it, they will go to our Advanced Settings page." - }, - "notifications8DescriptionOne": { - "message": "从 MetaMask v10.4.0 开始,您不再需要 Ledger Live 即可将您的 Ledger 设备连接到 Metamask。", - "description": "Description of a notification in the 'See What's New' popup. Describes changes for how Ledger Live is no longer needed to connect the device." - }, - "notifications8DescriptionTwo": { - "message": "为了更轻松和更稳定的 ledger 体验,请转到设置中的“高级”选项卡,将“首选 Ledger 连接类型”切换为“WebHID”。", - "description": "Description of a notification in the 'See What's New' popup. Describes how the user can turn off the Ledger Live setting." - }, - "notifications8Title": { - "message": "Ledger 连接改进", - "description": "Title for a notification in the 'See What's New' popup. Notifies ledger users that there is an improvement in how they can connect their device." - }, - "notifications9DescriptionOne": { - "message": "当确认智能合约交易时,我们现在为您提供更多关于“数据”选项卡的见解。" - }, - "notifications9DescriptionTwo": { - "message": "您现在可以在确认之前更好地了解您的交易详情,并且可以更轻松地添加交易地址到您的地址簿,帮助您做出安全和知情的决定。" - }, - "notifications9Title": { - "message": "👓 我们正在使交易更容易阅读。" - }, - "notificationsEmptyText": { - "message": "此处无内容。" - }, - "notificationsHeader": { - "message": "通知" - }, - "notificationsInfos": { - "message": "$1,来自$2", - "description": "$1 is the date at which the notification has been dispatched and $2 is the link to the snap that dispatched the notification." - }, - "notificationsMarkAllAsRead": { - "message": "将所有标记为已读" - }, - "numberOfNewTokensDetected": { - "message": "在此账户中发现 $1 新代币", - "description": "$1 is the number of new tokens detected" - }, - "ofTextNofM": { - "message": "/" - }, - "off": { - "message": "关" - }, - "offlineForMaintenance": { - "message": "离线维护" - }, - "ok": { - "message": "确定" - }, - "on": { - "message": "开" - }, - "onboardingCreateWallet": { - "message": "创建新钱包" - }, - "onboardingImportWallet": { - "message": "导入现有钱包" - }, - "onboardingPinExtensionBillboardAccess": { - "message": "完全访问权限" - }, - "onboardingPinExtensionBillboardDescription": { - "message": "这些扩展程序可以查看和更改信息" - }, - "onboardingPinExtensionBillboardDescription2": { - "message": "在此网站上。" - }, - "onboardingPinExtensionBillboardTitle": { - "message": "扩展程序" - }, - "onboardingPinExtensionChrome": { - "message": "点击浏览器扩展程序图标" - }, - "onboardingPinExtensionDescription": { - "message": "在您的浏览器上固定 MetaMask,以便访问并轻松查看交易确认。" - }, - "onboardingPinExtensionDescription2": { - "message": "您可以通过点击扩展程序打开 MetaMask,并一键访问您的钱包。" - }, - "onboardingPinExtensionDescription3": { - "message": "点击浏览器扩展程序图标即可即时访问它" - }, - "onboardingPinExtensionLabel": { - "message": "固定 MetaMask" - }, - "onboardingPinExtensionStep1": { - "message": "1" - }, - "onboardingPinExtensionStep2": { - "message": "2" - }, - "onboardingPinExtensionTitle": { - "message": "您的 MetaMask 安装完成!" - }, - "onboardingReturnNotice": { - "message": "“$1”将关闭此选项卡,并直接返回到 $2", - "description": "Return the user to the site that initiated onboarding" - }, - "onboardingShowIncomingTransactionsDescription": { - "message": "在您的钱包中显示传入的交易依赖于与 $1 的通信。Etherscan 将有权访问您的以太坊地址和 IP 地址。查看 $2。", - "description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key." - }, - "onboardingUsePhishingDetectionDescription": { - "message": "网络钓鱼检测警报依赖于与 $1 的通信。jsDeliver 将有权访问您的 IP 地址。查看 $2。", - "description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link" - }, - "onlyAddTrustedNetworks": { - "message": "恶意网络提供商可能会谎报区块链的状态并记录您的网络活动。只添加您信任的自定义网络。" - }, - "onlyConnectTrust": { - "message": "只连接您信任的网站。" - }, - "openFullScreenForLedgerWebHid": { - "message": "全屏打开 MetaMask 以通过 WebHID 连接您的 ledger。", - "description": "Shown to the user on the confirm screen when they are viewing MetaMask in a popup window but need to connect their ledger via webhid." - }, - "openSourceCode": { - "message": "检查源代码" - }, - "optional": { - "message": "可选" - }, - "optionalWithParanthesis": { - "message": "(可选)" - }, - "or": { - "message": "或" - }, - "origin": { - "message": "来源" - }, - "osTheme": { - "message": "系统" - }, - "padlock": { - "message": "挂锁" - }, - "parameters": { - "message": "参数" - }, - "participateInMetaMetrics": { - "message": "参加 MetaMetrics" - }, - "participateInMetaMetricsDescription": { - "message": "加入 MetaMetrics ,帮助我们改进 MetaMask" - }, - "password": { - "message": "密码" - }, - "passwordNotLongEnough": { - "message": "密码长度不足" - }, - "passwordSetupDetails": { - "message": "此密码只会在此设备上解锁您的 MetaMask 钱包。MetaMask 无法恢复此密码。" - }, - "passwordStrength": { - "message": "密码强度:$1", - "description": "Return password strength to the user when user wants to create password." - }, - "passwordStrengthDescription": { - "message": "强密码可以提高钱包的安全性,以防设备被盗或被入侵。" - }, - "passwordTermsWarning": { - "message": "我明白 MetaMask 无法为我恢复此密码。$1" - }, - "passwordsDontMatch": { - "message": "密码不匹配" - }, - "pastePrivateKey": { - "message": "请粘贴您的私钥:", - "description": "For importing an account from a private key" - }, - "pending": { - "message": "待处理" - }, - "pendingTransactionInfo": { - "message": "在那笔交易完成之前,这笔交易不会被处理。" - }, - "pendingTransactionMultiple": { - "message": "您有 ($1) 笔待处理的交易" - }, - "pendingTransactionSingle": { - "message": "您有 (1) 笔待处理的交易。", - "description": "$1 is count of pending transactions" - }, - "permissionRequest": { - "message": "权限请求" - }, - "permissionRequestCapitalized": { - "message": "权限请求" - }, - "permission_accessNetwork": { - "message": "访问互联网。", - "description": "The description of the `endowment:network-access` permission." - }, - "permission_accessSnap": { - "message": "连接$1的Snap。", - "description": "The description for the `wallet_snap_*` permission. $1 is the name of the Snap." - }, - "permission_customConfirmation": { - "message": "在MetaMask中显示确认。", - "description": "The description for the `snap_confirm` permission" - }, - "permission_ethereumAccounts": { - "message": "查看您允许的账户的地址(必填)", - "description": "The description for the `eth_accounts` permission" - }, - "permission_longRunning": { - "message": "无限期运行。", - "description": "The description for the `endowment:long-running` permission" - }, - "permission_manageBip44Keys": { - "message": "控制您的“$1”账户和资产。", - "description": "The description for the `snap_getBip44Entropy` permission. $1 is the name of a protocol, e.g. 'Filecoin'." - }, - "permission_manageState": { - "message": "在您的设备上存储和管理其数据。", - "description": "The description for the `snap_manageState` permission" - }, - "permission_notifications": { - "message": "显示通知。", - "description": "The description for the `snap_notify` permission" - }, - "permission_unknown": { - "message": "未知权限:$1", - "description": "$1 is the name of a requested permission that is not recognized." - }, - "permissions": { - "message": "权限" - }, - "personalAddressDetected": { - "message": "检测到个人地址。请输入代币合约地址。" - }, - "pleaseConfirm": { - "message": "请确认" - }, - "plusXMore": { - "message": "另外 $1 项", - "description": "$1 is a number of additional but unshown items in a list- this message will be shown in place of those items" - }, - "popularCustomNetworks": { - "message": "流行自定义网络" - }, - "preferredLedgerConnectionType": { - "message": "首选 Ledger 连接类型", - "description": "A header for a dropdown in the advanced section of settings. Appears above the ledgerConnectionPreferenceDescription message" - }, - "preparingSwap": { - "message": "正在准备交换......" - }, - "prev": { - "message": "上一个" - }, - "primaryCurrencySetting": { - "message": "主要货币" - }, - "primaryCurrencySettingDescription": { - "message": "选择原生以优先显示链的原生货币(例如 ETH)的值。选择法定货币以优先显示以您所选法定货币显示的值。" - }, - "priorityFee": { - "message": "优先费用" - }, - "priorityFeeProperCase": { - "message": "优先费用" - }, - "privacyMsg": { - "message": "隐私政策" - }, - "privateKey": { - "message": "私钥", - "description": "select this type of file to use to import an account" - }, - "privateKeyWarning": { - "message": "警告:切勿泄露此密钥。任何拥有您私钥的人都可以窃取您账户中持有的任何资产。" - }, - "privateNetwork": { - "message": "私有网络" - }, - "proceedWithTransaction": { - "message": "我仍然想继续" - }, - "proposedApprovalLimit": { - "message": "拟议的审批上限" - }, - "provide": { - "message": "提供" - }, - "publicAddress": { - "message": "公共地址" - }, - "queue": { - "message": "队列" - }, - "queued": { - "message": "队列中" - }, - "reAddAccounts": { - "message": "重新添加任何其他账户" - }, - "reAdded": { - "message": "重新添加" - }, - "readdToken": { - "message": "将来您还可以通过账户选项菜单中的“导入代币”来添加此代币。" - }, - "receive": { - "message": "接收" - }, - "recents": { - "message": "最近" - }, - "recipientAddressPlaceholder": { - "message": "搜索、公共地址 (0x) 或 ENS" - }, - "recommendedGasLabel": { - "message": "建议" - }, - "recoveryPhraseReminderBackupStart": { - "message": "从这里开始" - }, - "recoveryPhraseReminderConfirm": { - "message": "明白了" - }, - "recoveryPhraseReminderHasBackedUp": { - "message": "始终将您的账户助记词保存在安全和秘密的地方" - }, - "recoveryPhraseReminderHasNotBackedUp": { - "message": "需要再次备份您的账户助记词?" - }, - "recoveryPhraseReminderItemOne": { - "message": "切勿与任何人分享您的账户助记词" - }, - "recoveryPhraseReminderItemTwo": { - "message": "MetaMask 团队绝对不会索要您的账户助记词" - }, - "recoveryPhraseReminderSubText": { - "message": "您的账户助记词控制您的所有账户。" - }, - "recoveryPhraseReminderTitle": { - "message": "保护您的资金" - }, - "refreshList": { - "message": "刷新列表" - }, - "reject": { - "message": "拒绝" - }, - "rejectAll": { - "message": "拒绝全部" - }, - "rejectTxsDescription": { - "message": "您将批量拒绝 $1 笔交易。" - }, - "rejectTxsN": { - "message": "拒绝 $1 笔交易" - }, - "rejected": { - "message": "已拒绝" - }, - "remember": { - "message": "记住:" - }, - "remindMeLater": { - "message": "稍后提醒我" - }, - "remove": { - "message": "删除" - }, - "removeAccount": { - "message": "删除账户" - }, - "removeAccountDescription": { - "message": "该账户将从您的钱包中删除。在继续操作前,确认您已拥有该导入账户的原始账户助记词或私钥。您可以通过账户下拉菜单再次导入或创建账户。" - }, - "removeNFT": { - "message": "删除 NFT" - }, - "removeSnap": { - "message": "移除Snap" - }, - "removeSnapConfirmation": { - "message": "您确定要移除$1吗?", - "description": "$1 represents the name of the snap" - }, - "removeSnapDescription": { - "message": "此操作将会删除snap及其数据,并撤销您获授予的权限。" - }, - "replace": { - "message": "替换" - }, - "requestsAwaitingAcknowledgement": { - "message": "待确认的请求" - }, - "required": { - "message": "必需" - }, - "reset": { - "message": "重置" - }, - "resetAccount": { - "message": "重置账户" - }, - "resetAccountDescription": { - "message": "重置账户将清除您的交易历史记录。这不会改变您账户中的余额,也不会要求您重新输入账户助记词。" - }, - "resetWallet": { - "message": "重置钱包" - }, - "resetWalletSubHeader": { - "message": "MetaMask不会保留密码的副本。如果您在解锁账户时遇到问题,需要重置您的钱包。您可以提供设置钱包时使用的助记词,以进行重置。" - }, - "resetWalletUsingSRP": { - "message": "此操作将从此设备中删除您当前的钱包和助记词,以及您编制的账户列表。使用助记词进行重置后,您将会看到一个账户列表(基于用于重置的助记词)。这个新列表将自动包括有余额的账户。您还可以使用之前创建的$1。您导入的自定义账户需要是$2,添加到账户中的任何自定义代币也需要是$3。" - }, - "resetWalletWarning": { - "message": "在继续之前,请确保您所使用的助记词正确无误。您将无法撤消此操作。" - }, - "restartMetamask": { - "message": "重新启动MetaMask" - }, - "restore": { - "message": "恢复" - }, - "restoreWalletPreferences": { - "message": "已找到 $1 的数据备份。您想恢复您的钱包偏好设置吗?", - "description": "$1 is the date at which the data was backed up" - }, - "retryTransaction": { - "message": "重试交易" - }, - "reusedTokenNameWarning": { - "message": "此处的代币使用了与您关注的另一种代币相同的符号,这可能会让人感到困惑或具有欺骗性。" - }, - "revealSeedWords": { - "message": "显示助记词" - }, - "revealSeedWordsDescription": { - "message": "如果更改浏览器或移动计算机,您将需要此助记词才能访问账户。将它们保存在安全、秘密的地方。" - }, - "revealSeedWordsWarning": { - "message": "这些账户助记词可以用来窃取您的所有账户。" - }, - "revealSeedWordsWarningTitle": { - "message": "切勿与任何人分享此账户助记词!" - }, - "revealTheSeedPhrase": { - "message": "显示助记词" - }, - "revokeAllTokensTitle": { - "message": "撤销访问您的所有$1的权限?", - "description": "$1 is the symbol of the token for which the user is revoking approval" - }, - "revokeApproveForAllDescription": { - "message": "通过撤销权限,以下$1将无法再访问您的$2", - "description": "$1 is either key 'account' or 'contract', and $2 is either a string or link of a given token symbol or name" - }, - "rpcUrl": { - "message": "新的 RPC URL" - }, - "safeTransferFrom": { - "message": "安全转账来自" - }, - "save": { - "message": "保存" - }, - "saveAsCsvFile": { - "message": "保存为 CSV 文件" - }, - "scanInstructions": { - "message": "将二维码放在摄像头前" - }, - "scanQrCode": { - "message": "扫描二维码" - }, - "scrollDown": { - "message": "向下滚动" - }, - "search": { - "message": "搜索" - }, - "searchAccounts": { - "message": "搜索账户" - }, - "searchResults": { - "message": "搜索结果" - }, - "searchSettings": { - "message": "在设置中搜索" - }, - "searchTokens": { - "message": "搜索代币" - }, - "secretBackupPhraseDescription": { - "message": "您的账户助记词可以帮助您轻松备份和恢复个人账户。" - }, - "secretBackupPhraseWarning": { - "message": "警告:切勿向他人透露您的账户助记词。任何拥有该账户助记词的人都可以永远拿走您的以太币。" - }, - "secretPhrase": { - "message": "只有这个钱包上的第一个账户将自动加载。完成此流程后,若要添加额外的账户,点击下拉菜单,然后选择“创建账户”。" - }, - "secretRecoveryPhrase": { - "message": "助记词" - }, - "secureWallet": { - "message": "安全钱包" - }, - "securityAndPrivacy": { - "message": "安全和隐私" - }, - "seedPhraseConfirm": { - "message": "确认助记词" - }, - "seedPhraseEnterMissingWords": { - "message": "确认助记词" - }, - "seedPhraseIntroNotRecommendedButtonCopy": { - "message": "稍后提醒我(不推荐)" - }, - "seedPhraseIntroRecommendedButtonCopy": { - "message": "保护我的钱包(推荐)" - }, - "seedPhraseIntroSidebarBulletFour": { - "message": "写下并存储在多个秘密位置。" - }, - "seedPhraseIntroSidebarBulletOne": { - "message": "保存到密码管理器" - }, - "seedPhraseIntroSidebarBulletThree": { - "message": "存放在保险箱内。" - }, - "seedPhraseIntroSidebarBulletTwo": { - "message": "储存在银行保险库。" - }, - "seedPhraseIntroSidebarCopyOne": { - "message": "您的账户助记词是由12个单词组成的短语,它是您的钱包和资金的“主密钥”" - }, - "seedPhraseIntroSidebarCopyThree": { - "message": "如果有人要求您的恢复短语,他们可能会试图欺骗您并偷窃您的钱包资金" - }, - "seedPhraseIntroSidebarCopyTwo": { - "message": "切勿分享您的账户助记词,包括也不能与 MetaMask 分享!" - }, - "seedPhraseIntroSidebarTitleOne": { - "message": "什么是账户助记词?" - }, - "seedPhraseIntroSidebarTitleThree": { - "message": "我是否应该分享我的账户助记词?" - }, - "seedPhraseIntroSidebarTitleTwo": { - "message": "如何保存我的账户助记词?" - }, - "seedPhraseIntroTitle": { - "message": "保护您的钱包安全" - }, - "seedPhraseIntroTitleCopy": { - "message": "在开始之前,观看这个简短的视频来了解您的账户助记词以及如何保护您的钱包安全。" - }, - "seedPhraseReq": { - "message": "助记词包含 12、15、18、21 或 24 个字词" - }, - "seedPhraseWriteDownDetails": { - "message": "请写下这个由12个单词组成的账户助记词,然后将其保存到您信任并且只有您可以访问的地方。" - }, - "seedPhraseWriteDownHeader": { - "message": "写下您的助记词" - }, - "selectAHigherGasFee": { - "message": "选择更高的燃料费用,加快交易处理速度。*" - }, - "selectAccounts": { - "message": "选择要在此网站上使用的账户" - }, - "selectAll": { - "message": "全部选择" - }, - "selectAnAccount": { - "message": "选择一个账户" - }, - "selectAnAccountAlreadyConnected": { - "message": "此账户已连接到 MetaMask" - }, - "selectEachPhrase": { - "message": "请选择每个单词,以确保其正确性。" - }, - "selectHdPath": { - "message": "选择 HD 路径" - }, - "selectNFTPrivacyPreference": { - "message": "在设置中打开 NFT 检测" - }, - "selectPathHelp": { - "message": "如果您没有看到您期望的账户,请尝试切换 HD 路径。" - }, - "selectType": { - "message": "选择类型" - }, - "selectingAllWillAllow": { - "message": "选择全部将允许本网站查看您当前的所有账户。确保您信任这个网站。" - }, - "send": { - "message": "发送" - }, - "sendAmount": { - "message": "发送金额" - }, - "sendBugReport": { - "message": "向我们发送错误报告。" - }, - "sendSpecifiedTokens": { - "message": "发送 $1", - "description": "Symbol of the specified token" - }, - "sendTo": { - "message": "发送到" - }, - "sendTokens": { - "message": "发送代币" - }, - "sendingDisabled": { - "message": "尚不支持发送ERC-1155 NFT资产。" - }, - "sendingNativeAsset": { - "message": "正在发送 $1", - "description": "$1 represents the native currency symbol for the current network (e.g. ETH or BNB)" - }, - "sendingToTokenContractWarning": { - "message": "警告:您将要发送到代币合约,这可能会导致资金损失。$1", - "description": "$1 is a clickable link with text defined by the 'learnMoreUpperCase' key. The link will open to a support article regarding the known contract address warning" - }, - "setAdvancedPrivacySettings": { - "message": "设置高级隐私设置" - }, - "setAdvancedPrivacySettingsDetails": { - "message": "MetaMask 使用这些可信的第三方服务来提高产品可用性和安全性。" - }, - "setApprovalForAll": { - "message": "设置批准所有" - }, - "setApprovalForAllTitle": { - "message": "批准$1,且无消费限制", - "description": "The token symbol that is being approved" - }, - "settings": { - "message": "设置" - }, - "settingsSearchMatchingNotFound": { - "message": "没有找到匹配的结果." - }, - "shorthandVersion": { - "message": "v$1", - "description": "$1 is replaced by a version string (e.g. 1.2.3)" - }, - "show": { - "message": "显示" - }, - "showAdvancedGasInline": { - "message": "高级燃料控制" - }, - "showAdvancedGasInlineDescription": { - "message": "选择此项可直接在发送和确认界面显示燃料价格和上限控制。" - }, - "showCustomNetworkList": { - "message": "显示自定义网络列表" - }, - "showCustomNetworkListDescription": { - "message": "选择此项,在添加新网络时就会显示附有预填详细信息的网络列表。" - }, - "showFiatConversionInTestnets": { - "message": "在测试网络上显示转换" - }, - "showFiatConversionInTestnetsDescription": { - "message": "选择此项以在测试网络上显示法定货币转换" - }, - "showHexData": { - "message": "显示十六进制数据" - }, - "showHexDataDescription": { - "message": "选择此项以在发送屏幕上显示十六进制数据字段" - }, - "showHide": { - "message": "显示/隐藏" - }, - "showIncomingTransactions": { - "message": "显示传入的交易" - }, - "showIncomingTransactionsDescription": { - "message": "选择此项以使用 Etherscan 在交易列表中显示传入的交易" - }, - "showPermissions": { - "message": "显示权限" - }, - "showPrivateKeys": { - "message": "显示私钥" - }, - "showRecommendations": { - "message": "显示建议" - }, - "showTestnetNetworks": { - "message": "显示测试网络" - }, - "showTestnetNetworksDescription": { - "message": "选择此项以在网络列表中显示测试网络" - }, - "sigRequest": { - "message": "签名请求" - }, - "sign": { - "message": "签名" - }, - "signNotice": { - "message": "谨慎行事。此操作有可能用来从您的账户提取资产。确保您信任此站点。" - }, - "signatureRequest": { - "message": "签名请求" - }, - "signatureRequest1": { - "message": "消息" - }, - "signed": { - "message": "已签名" - }, - "simulationErrorMessageV2": { - "message": "我们无法估算燃料。合约中可能存在错误,这笔交易可能会失败。" - }, - "skip": { - "message": "跳过" - }, - "skipAccountSecurity": { - "message": "跳过账户安全?" - }, - "skipAccountSecurityDetails": { - "message": "我明白,在我备份我的账户助记词之前,我可能会丢失我的账户及其所有资产。" - }, - "slow": { - "message": "慢" - }, - "smartTransaction": { - "message": "智能交易" - }, - "snapAccess": { - "message": "$1的snap可以访问:", - "description": "$1 represents the name of the snap" - }, - "snapAdded": { - "message": "从 $2 添加到 $1", - "description": "$1 represents the date the snap was installed, $2 represents which origin installed the snap." - }, - "snapError": { - "message": "Snap错误:'$1'。错误代码:'$2'", - "description": "This is shown when a snap encounters an error. $1 is the error message from the snap, and $2 is the error code." - }, - "snapInstall": { - "message": "安装Snap" - }, - "snapInstallWarningCheck": { - "message": "请勾选全部以确认您理解。" - }, - "snapRequestsPermission": { - "message": "此Snap正在请求以下权限:" - }, - "snaps": { - "message": "Snap" - }, - "snapsSettingsDescription": { - "message": "管理您的Snap" - }, - "snapsStatus": { - "message": "Snap状态取决于活动。" - }, - "snapsToggle": { - "message": "Snap仅在启用后才会运行" - }, - "someNetworksMayPoseSecurity": { - "message": "某些网络可能会带来安全和/或隐私风险。在添加和使用网络之前,请先了解风险。" - }, - "somethingWentWrong": { - "message": "哎呀!出了点问题。" - }, - "source": { - "message": "来源" - }, - "speedUp": { - "message": "加速" - }, - "speedUpCancellation": { - "message": "加速该取消操作" - }, - "speedUpExplanation": { - "message": "我们根据当前网络条件更新了燃料费用,将其提高了至少10%(网络要求)。" - }, - "speedUpPopoverTitle": { - "message": "加快交易速度" - }, - "speedUpTooltipText": { - "message": "新燃料费" - }, - "speedUpTransaction": { - "message": "加速该交易" - }, - "spendLimitAmount": { - "message": "消费限额" - }, - "spendLimitInsufficient": { - "message": "消费限额不足" - }, - "spendLimitInvalid": { - "message": "消费限额无效;必须是正数" - }, - "spendLimitPermission": { - "message": "支付限额权限" - }, - "spendLimitRequestedBy": { - "message": "$1 请求的消费限额", - "description": "Origin of the site requesting the spend limit" - }, - "spendLimitTooLarge": { - "message": "消费限额过大" - }, - "srpInputNumberOfWords": { - "message": "我有一个包含$1个单词的助记词", - "description": "This is the text for each option in the dropdown where a user selects how many words their secret recovery phrase has during import. The $1 is the number of words (either 12, 15, 18, 21, or 24)." - }, - "srpPasteFailedTooManyWords": { - "message": "粘贴失败,因为它包含超过24个单词。一个助记词最多可包含24个单词。", - "description": "Description of SRP paste erorr when the pasted content has too many words" - }, - "srpPasteTip": { - "message": "您可以将整个助记词粘贴到任何字段中", - "description": "Our secret recovery phrase input is split into one field per word. This message explains to users that they can paste their entire secrete recovery phrase into any field, and we will handle it correctly." - }, - "srpToggleShow": { - "message": "显示/隐藏助记词中的这个单词", - "description": "Describes a toggle that is used to show or hide a single word of the secret recovery phrase" - }, - "srpWordHidden": { - "message": "这个单词已隐藏", - "description": "Explains that a word in the secret recovery phrase is hidden" - }, - "srpWordShown": { - "message": "这个单词处于显示状态", - "description": "Explains that a word in the secret recovery phrase is being shown" - }, - "stable": { - "message": "稳定" - }, - "stableLowercase": { - "message": "稳定" - }, - "stateLogError": { - "message": "检索状态日志时出错。" - }, - "stateLogFileName": { - "message": "MetaMask 状态日志" - }, - "stateLogs": { - "message": "状态日志" - }, - "stateLogsDescription": { - "message": "状态日志包含您的公共账户地址和已发送的交易。" - }, - "status": { - "message": "状态" - }, - "statusConnected": { - "message": "已连接" - }, - "statusNotConnected": { - "message": "未连接" - }, - "step1LatticeWallet": { - "message": "请确保您的 Lattice1 已准备好连接" - }, - "step1LatticeWalletMsg": { - "message": "当您的 Lattice1 设备设置好并在线时,您可以将 MetaMask 与它连接。解锁您的设备并准备好您的设备 ID。若要了解有关使用硬件钱包的更多信息,$1", - "description": "$1 represents the `hardwareWalletSupportLinkConversion` localization key" - }, - "step1LedgerWallet": { - "message": "下载 Ledger 应用程序" - }, - "step1LedgerWalletMsg": { - "message": "下载、设置并输入您的密码以解锁 $1。", - "description": "$1 represents the `ledgerLiveApp` localization value" - }, - "step1TrezorWallet": { - "message": "插入 Trezor 钱包" - }, - "step1TrezorWalletMsg": { - "message": "将您的钱包直接连接到电脑。若要了解有关使用硬件钱包设备的更多信息,$1", - "description": "$1 represents the `hardwareWalletSupportLinkConversion` localization key" - }, - "step2LedgerWallet": { - "message": "插入 Ledger 钱包" - }, - "step2LedgerWalletMsg": { - "message": "将您的钱包直接连接到电脑。解锁 Ledger 并打开 Ethereum 应用程序。若要了解有关使用您的硬件钱包设备的更多信息,$1。", - "description": "$1 represents the `hardwareWalletSupportLinkConversion` localization key" - }, - "stillGettingMessage": { - "message": "仍然收到此消息?" - }, - "storePhrase": { - "message": "通过如 1Password 等密码管理工具保存该账户助记词。" - }, - "strong": { - "message": "强" - }, - "stxAreHere": { - "message": "智能交易已推出!" - }, - "stxBenefit1": { - "message": "将交易成本减至最低" - }, - "stxBenefit2": { - "message": "减少交易失败" - }, - "stxBenefit3": { - "message": "消除卡住的交易" - }, - "stxBenefit4": { - "message": "防止抢先交易" - }, - "stxCancelled": { - "message": "交换就会失败" - }, - "stxCancelledDescription": { - "message": "您的交易就会失败,并被取消,以保护您免于支付不必要的燃料费。" - }, - "stxCancelledSubDescription": { - "message": "再次尝试进行交换。下次我们会在这里保护您免受类似风险。 " - }, - "stxDescription": { - "message": "MetaMask Swap变得更加智能!启用智能交易将允许MetaMask从编程上优化您的交换,以帮助:" - }, - "stxErrorNotEnoughFunds": { - "message": "没有足够的资金进行智能交易。" - }, - "stxErrorUnavailable": { - "message": "智能交易暂时不可用。" - }, - "stxFailure": { - "message": "交换失败" - }, - "stxFailureDescription": { - "message": "突然的市场变化可能导致失败。如果问题仍然存在,请联系$1。", - "description": "This message is shown to a user if their swap fails. The $1 will be replaced by support.metamask.io" - }, - "stxFallbackPendingTx": { - "message": "智能交易暂时不可用,因为您有一笔待处理的交易。" - }, - "stxFallbackUnavailable": { - "message": "即使智能交易不可用,您仍然可以交换代币。" - }, - "stxPendingPrivatelySubmittingSwap": { - "message": "正在秘密提交您的Swap..." - }, - "stxPendingPubliclySubmittingSwap": { - "message": "正在公开提交您的Swap..." - }, - "stxSubDescription": { - "message": "*智能交易将尝试多次隐秘提交您的交易。如果所有尝试都失败,交易将会公开广播,以确保您的交换能成功进行。" - }, - "stxSuccess": { - "message": "交换完成!" - }, - "stxSuccessDescription": { - "message": "您的$1现在可用。", - "description": "$1 is a token symbol, e.g. ETH" - }, - "stxSwapCompleteIn": { - "message": "Swap距离完成尚有<", - "description": "'<' means 'less than', e.g. Swap will complete in < 2:59" - }, - "stxTooltip": { - "message": "在提交前模拟交易,以降低交易成本并减少失败。" - }, - "stxTryRegular": { - "message": "尝试定期交换。" - }, - "stxTryingToCancel": { - "message": "正在尝试取消您的交易......" - }, - "stxUnavailable": { - "message": "智能交易被禁用" - }, - "stxUnknown": { - "message": "状态未知" - }, - "stxUnknownDescription": { - "message": "有一笔交易已经成功,但我们不确定是哪一笔。这可能是由于在处理此交换时提交了另一笔交易。" - }, - "stxUserCancelled": { - "message": "交换已取消" - }, - "stxUserCancelledDescription": { - "message": "您的交易已被取消,您并未支付任何不必要的燃料费。" - }, - "stxYouCanOptOut": { - "message": "您可以随时选择退出高级设置。" - }, - "submit": { - "message": "提交" - }, - "submitted": { - "message": "已提交" - }, - "support": { - "message": "获取帮助" - }, - "supportCenter": { - "message": "访问我们的支持中心" - }, - "swap": { - "message": "交换" - }, - "swapAggregator": { - "message": "聚合器" - }, - "swapAllowSwappingOf": { - "message": "允许交换 $1", - "description": "Shows a user that they need to allow a token for swapping on their hardware wallet" - }, - "swapAmountReceived": { - "message": "保证金额" - }, - "swapAmountReceivedInfo": { - "message": "这是您将收到的最低金额。根据滑点值,您可能会收到更多。" - }, - "swapApproval": { - "message": "批准 $1 进行交换", - "description": "Used in the transaction display list to describe a transaction that is an approve call on a token that is to be swapped.. $1 is the symbol of a token that has been approved." - }, - "swapApproveNeedMoreTokens": { - "message": "您还需要 $1 的 $2 来完成这笔交换", - "description": "Tells the user how many more of a given token they need for a specific swap. $1 is an amount of tokens and $2 is the token symbol." - }, - "swapApproveNeedMoreTokensSmartTransactions": { - "message": "您还需要更多$1才能使用智能交易完成此交换。", - "description": "Tells the user that they need more of a certain token ($1) before they can complete the swap via smart transactions." - }, - "swapBestOfNQuotes": { - "message": "$1 报价中最棒的。", - "description": "$1 is the number of quotes that the user can select from when opening the list of quotes on the 'view quote' screen" - }, - "swapBuildQuotePlaceHolderText": { - "message": "没有与 $1 匹配的代币", - "description": "Tells the user that a given search string does not match any tokens in our token lists. $1 can be any string of text" - }, - "swapConfirmWithHwWallet": { - "message": "使用您的硬件钱包确认" - }, - "swapContractDataDisabledErrorDescription": { - "message": "在您的 Ledger 的 Etherum 应用程序中,转到“设置”并允许合约数据。然后再次尝试交换。" - }, - "swapContractDataDisabledErrorTitle": { - "message": "您的 Ledger 上未启用合约数据" - }, - "swapCustom": { - "message": "自定义" - }, - "swapDecentralizedExchange": { - "message": "去中心化交易所" - }, - "swapDirectContract": { - "message": "直接合约" - }, - "swapEditLimit": { - "message": "编辑限制" - }, - "swapEnableDescription": { - "message": "这是必须的,并授予 MetaMask 权限交换您的 $1。", - "description": "Gives the user info about the required approval transaction for swaps. $1 will be the symbol of a token being approved for swaps." - }, - "swapEnableTokenForSwapping": { - "message": "这将 $1 进行交换", - "description": "$1 is for the 'enableToken' key, e.g. 'enable ETH'" - }, - "swapEstimatedNetworkFees": { - "message": "预估网络费用" - }, - "swapEstimatedNetworkFeesInfo": { - "message": "这是预估的网络费用,将用于完成您的交换。实际金额可能会根据网络条件而变化。" - }, - "swapFailedErrorDescriptionWithSupportLink": { - "message": "交易有时会失败,我们随时为您提供帮助。如果此问题仍然存在,您可以在 $1 联系我们的客服,以获得进一步的帮助。", - "description": "This message is shown to a user if their swap fails. The $1 will be replaced by support.metamask.io" - }, - "swapFailedErrorTitle": { - "message": "交换失败" - }, - "swapFetchingQuoteNofN": { - "message": "获取$2的$1报价", - "description": "A count of possible quotes shown to the user while they are waiting for quotes to be fetched. $1 is the number of quotes already loaded, and $2 is the total number of resources that we check for quotes. Keep in mind that not all resources will have a quote for a particular swap." - }, - "swapFetchingQuotes": { - "message": "取得报价中" - }, - "swapFetchingQuotesErrorDescription": { - "message": "呃……出错了。再试一次,如果错误仍存在,请联系客服。" - }, - "swapFetchingQuotesErrorTitle": { - "message": "获取报价出错" - }, - "swapFetchingTokens": { - "message": "获取代币中……" - }, - "swapFromTo": { - "message": "$1 到 $2 的交换", - "description": "Tells a user that they need to confirm on their hardware wallet a swap of 2 tokens. $1 is a source token and $2 is a destination token" - }, - "swapGasFeesDetails": { - "message": "燃料费用是估算的,并将根据网络流量和交易复杂性而波动。" - }, - "swapGasFeesLearnMore": { - "message": "了解更多关于燃料费的信息" - }, - "swapGasFeesSplit": { - "message": "上一个屏幕上的燃料费用在这两笔交易之间分摊。" - }, - "swapGasFeesSummary": { - "message": "燃料费用支付给在 $1 网络上处理交易的加密矿工。MetaMask 不会从燃料费用中获利。", - "description": "$1 is the selected network, e.g. Ethereum or BSC" - }, - "swapHighSlippageWarning": { - "message": "滑点金额非常高。" - }, - "swapIncludesMMFee": { - "message": "包括 $1% 的 MetaMask 费用。", - "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." - }, - "swapLowSlippageError": { - "message": "交易可能会失败,最大滑点过低。" - }, - "swapMaxSlippage": { - "message": "最大滑点" - }, - "swapMetaMaskFee": { - "message": "MetaMask 费用" - }, - "swapMetaMaskFeeDescription": { - "message": "我们每次都能从顶级流动性资源中找到最优惠的价格。$1% 的费用会自动计入此报价。", - "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." - }, - "swapNQuotesWithDot": { - "message": "$1 报价。", - "description": "$1 is the number of quotes that the user can select from when opening the list of quotes on the 'view quote' screen" - }, - "swapNewQuoteIn": { - "message": "$1 后更新报价", - "description": "Tells the user the amount of time until the currently displayed quotes are update. $1 is a time that is counting down from 1:00 to 0:00" - }, - "swapOnceTransactionHasProcess": { - "message": "处理完此交易后,您的 $1 将被添加到您的账户中。", - "description": "This message communicates the token that is being transferred. It is shown on the awaiting swap screen. The $1 will be a token symbol." - }, - "swapPriceDifference": { - "message": "您将用 $1 $2 (~$3) 交换 $4 $5 (~$6)。", - "description": "This message represents the price slippage for the swap. $1 and $4 are a number (ex: 2.89), $2 and $5 are symbols (ex: ETH), and $3 and $6 are fiat currency amounts." - }, - "swapPriceDifferenceTitle": { - "message": "~$1% 的价差", - "description": "$1 is a number (ex: 1.23) that represents the price difference." - }, - "swapPriceImpactTooltip": { - "message": "价格影响是当前市场价格与交易执行期间收到的金额之间的差异。价格影响是您的交易规模相对于流动资金池规模的一个函数。" - }, - "swapPriceUnavailableDescription": { - "message": "由于缺乏市场价格数据,无法确定价格影响。在交换之前,请确认您对即将收到的代币数量感到满意。" - }, - "swapPriceUnavailableTitle": { - "message": "在继续之前,请检查您的费率" - }, - "swapProcessing": { - "message": "处理中" - }, - "swapQuoteDetails": { - "message": "报价详情" - }, - "swapQuoteSource": { - "message": "报价来源" - }, - "swapQuotesExpiredErrorDescription": { - "message": "请请求新的报价,以获得最新的价格。" - }, - "swapQuotesExpiredErrorTitle": { - "message": "报价超时" - }, - "swapQuotesNotAvailableErrorDescription": { - "message": "尝试调整金额或滑点设置,然后重试。" - }, - "swapQuotesNotAvailableErrorTitle": { - "message": "无可用报价" - }, - "swapRate": { - "message": "费率" - }, - "swapReceiving": { - "message": "正在接收" - }, - "swapReceivingInfoTooltip": { - "message": "这是一个预估额。确切的金额取决于滑点。" - }, - "swapRequestForQuotation": { - "message": "请求报价" - }, - "swapReviewSwap": { - "message": "审查交换" - }, - "swapSelect": { - "message": "选择" - }, - "swapSelectAQuote": { - "message": "选择一个报价" - }, - "swapSelectAToken": { - "message": "选择代币" - }, - "swapSelectQuotePopoverDescription": { - "message": "以下是从多个流动性来源收集到的所有报价。" - }, - "swapSlippageNegative": { - "message": "滑点必须大于或等于0" - }, - "swapSlippagePercent": { - "message": "$1%", - "description": "$1 is the amount of % for slippage" - }, - "swapSource": { - "message": "流动性来源" - }, - "swapSourceInfo": { - "message": "我们搜索多个流动性来源(交易所、聚合器和专业做市商),以找到最优惠的价格和最低的网络费用。" - }, - "swapSuggested": { - "message": "建议的交换" - }, - "swapSuggestedGasSettingToolTipMessage": { - "message": "交换是复杂和时间敏感的交易。我们建议使用此燃料费用,以便在成本和成功交换的信心之间保持良好的平衡。" - }, - "swapSwapFrom": { - "message": "交换自" - }, - "swapSwapSwitch": { - "message": "在代币之间切换" - }, - "swapSwapTo": { - "message": "交换为" - }, - "swapToConfirmWithHwWallet": { - "message": "使用您的硬件钱包确认" - }, - "swapTokenAvailable": { - "message": "您的 $1 已添加到您的账户。", - "description": "This message is shown after a swap is successful and communicates the exact amount of tokens the user has received for a swap. The $1 is a decimal number of tokens followed by the token symbol." - }, - "swapTokenBalanceUnavailable": { - "message": "我们无法检索您的 $1 余额", - "description": "This message communicates to the user that their balance of a given token is currently unavailable. $1 will be replaced by a token symbol" - }, - "swapTokenToToken": { - "message": "用 $1 交换 $2", - "description": "Used in the transaction display list to describe a swap. $1 and $2 are the symbols of tokens in involved in a swap." - }, - "swapTokenVerificationAddedManually": { - "message": "此代币已手动添加。" - }, - "swapTokenVerificationMessage": { - "message": "始终在 $1 上确认代币地址。", - "description": "Points the user to Etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"Etherscan\" followed by an info icon that shows more info on hover." - }, - "swapTokenVerificationOnlyOneSource": { - "message": "仅在1个来源上进行了验证。" - }, - "swapTokenVerificationSources": { - "message": "在 $1 个来源上进行了验证。", - "description": "Indicates the number of token information sources that recognize the symbol + address. $1 is a decimal number." - }, - "swapTooManyDecimalsError": { - "message": "$1 允许最多 $2 个小数位", - "description": "$1 is a token symbol and $2 is the max. number of decimals allowed for the token" - }, - "swapTransactionComplete": { - "message": "交易完成" - }, - "swapTwoTransactions": { - "message": "2笔交易" - }, - "swapUnknown": { - "message": "未知" - }, - "swapVerifyTokenExplanation": { - "message": "多个代币可以使用相同的名称和符号。检查 $1 以确认这是您正在寻找的代币。", - "description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network." - }, - "swapYourTokenBalance": { - "message": "$1 $2 可用于交换", - "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" - }, - "swapZeroSlippage": { - "message": "0%滑点" - }, - "swapsAdvancedOptions": { - "message": "高级选项" - }, - "swapsExcessiveSlippageWarning": { - "message": "滑点金额太高,会导致不良率。请将最大滑点降低到低于15%的值。" - }, - "swapsMaxSlippage": { - "message": "最大滑点" - }, - "swapsNotEnoughForTx": { - "message": "没有足够的 $1 来完成此交易", - "description": "Tells the user that they don't have enough of a token for a proposed swap. $1 is a token symbol" - }, - "swapsViewInActivity": { - "message": "在活动中查看" - }, - "switchEthereumChainConfirmationDescription": { - "message": "这将切换 MetaMask 中选定的网络到以前添加的网络:" - }, - "switchEthereumChainConfirmationTitle": { - "message": "允许此网站切换网络?" - }, - "switchNetwork": { - "message": "切换网络" - }, - "switchNetworks": { - "message": "切换网络" - }, - "switchToNetwork": { - "message": "切换至$1", - "description": "$1 represents the custom network that has previously been added" - }, - "switchToThisAccount": { - "message": "切换到该账户" - }, - "switchingNetworksCancelsPendingConfirmations": { - "message": "切换网络将取消所有待处理的确认" - }, - "symbol": { - "message": "符号" - }, - "symbolBetweenZeroTwelve": { - "message": "符号不得超过11个字符。" - }, - "syncFailed": { - "message": "同步失败" - }, - "syncInProgress": { - "message": "同步进行中" - }, - "syncWithMobile": { - "message": "与移动设备同步" - }, - "syncWithMobileBeCareful": { - "message": "扫描此代码时,请确保附近没有其他人在看您的屏幕" - }, - "syncWithMobileComplete": { - "message": "您的数据已同步成功。尽情体验 MetaMask 移动应用程序吧!" - }, - "syncWithMobileDesc": { - "message": "您可以将您的账户和信息与您的移动设备同步。打开 MetaMask 移动应用程序,进入“设置”,点击“从浏览器扩展程序同步”" - }, - "syncWithMobileDescNewUsers": { - "message": "如果您是首次启用 MetaMask 移动应用程序,请通过个人手机完成如下操作。" - }, - "syncWithMobileScanThisCode": { - "message": "使用 MetaMask 移动应用程序扫描此代码" - }, - "syncWithMobileTitle": { - "message": "与移动设备同步" - }, - "syncWithThreeBox": { - "message": "与 3Box 同步数据(实验功能)" - }, - "syncWithThreeBoxDescription": { - "message": "开启以使用 3Box 备份您的设置。此功能目前是实验功能,使用时风险自负。" - }, - "syncWithThreeBoxDisabled": { - "message": "由于初始同步过程中出现错误,3Box 已被禁用" - }, - "tenPercentIncreased": { - "message": "增加10%" - }, - "terms": { - "message": "使用条款" - }, - "termsOfService": { - "message": "服务条款" - }, - "testFaucet": { - "message": "测试水龙头" - }, - "testNetworks": { - "message": "测试网络" - }, - "theme": { - "message": "主题" - }, - "themeDescription": { - "message": "选择您喜欢的MetaMask主题。" - }, - "thisWillCreate": { - "message": "这将创建新的钱包和账户助记词" - }, - "time": { - "message": "时间" - }, - "tips": { - "message": "小贴士" - }, - "to": { - "message": "至" - }, - "toAddress": { - "message": "至:$1", - "description": "$1 is the address to include in the To label. It is typically shortened first using shortenAddress" - }, - "toggleTestNetworks": { - "message": "$1 测试网络", - "description": "$1 is a clickable link with text defined by the 'showHide' key. The link will open to the advanced settings where users can enable the display of test networks in the network dropdown." - }, - "token": { - "message": "代币" - }, - "tokenAddress": { - "message": "代币地址" - }, - "tokenAlreadyAdded": { - "message": "代币已添加。" - }, - "tokenContractAddress": { - "message": "代币合约地址" - }, - "tokenDecimalFetchFailed": { - "message": "需要代币小数。" - }, - "tokenDecimalTitle": { - "message": "代币小数:" - }, - "tokenDetails": { - "message": "代币详情" - }, - "tokenDetection": { - "message": "代币检测" - }, - "tokenDetectionAlertMessage": { - "message": "代币检测目前适用于 $1. $2" - }, - "tokenDetectionToggleDescription": { - "message": "ConsenSys的代币API使用来自各种第三方的代币列表,汇总成一个代币列表。关闭它将会停止检测添加到您钱包中的新代币,但会保留搜索代币以导入的选项。" - }, - "tokenId": { - "message": "代币 ID" - }, - "tokenList": { - "message": "代币列表:" - }, - "tokenSymbol": { - "message": "代币符号" - }, - "tokensFoundTitle": { - "message": "发现$1新代币", - "description": "$1 is the number of new tokens detected" - }, - "tooltipApproveButton": { - "message": "我理解" - }, - "total": { - "message": "共计" - }, - "transaction": { - "message": "交易" - }, - "transactionCancelAttempted": { - "message": "已在 $2 尝试取消交易 ,燃料费用预计为 $1" - }, - "transactionCancelSuccess": { - "message": "交易已在 $2 成功取消。" - }, - "transactionConfirmed": { - "message": "交易已在 $2 确认。" - }, - "transactionCreated": { - "message": "在 $2 创建了值为 $1 的交易。" - }, - "transactionData": { - "message": "交易数据" - }, - "transactionDecodingAccreditationDecoded": { - "message": "由 Truffle 解码" - }, - "transactionDecodingAccreditationVerified": { - "message": "已在 $1 验证的合约" - }, - "transactionDecodingUnsupportedNetworkError": { - "message": "链 ID $1 不可使用交易解码" - }, - "transactionDetailDappGasMoreInfo": { - "message": "建议的网站" - }, - "transactionDetailDappGasTooltip": { - "message": "编辑以使用 MetaMask 建议的基于最新区块的燃料费用。" - }, - "transactionDetailGasHeading": { - "message": "估算的燃料费" - }, - "transactionDetailGasInfoV2": { - "message": "估算" - }, - "transactionDetailGasTooltipConversion": { - "message": "了解更多关于燃料费的信息" - }, - "transactionDetailGasTooltipExplanation": { - "message": "燃料费由网络设定,并根据网络流量和交易的复杂性而波动。" - }, - "transactionDetailGasTooltipIntro": { - "message": "燃料费用支付给在 $1 网络上处理交易的加密矿工。MetaMask 不会从燃料费用中获利。" - }, - "transactionDetailGasTotalSubtitle": { - "message": "金额 + 燃料费" - }, - "transactionDetailLayer2GasHeading": { - "message": "2层燃料费用" - }, - "transactionDetailMultiLayerTotalSubtitle": { - "message": "金额 + 费用" - }, - "transactionDropped": { - "message": "交易已在 $2 放弃。" - }, - "transactionError": { - "message": "交易出错。合约代码中抛出异常。" - }, - "transactionErrorNoContract": { - "message": "试图在非合约地址上调用函数。" - }, - "transactionErrored": { - "message": "交易出现错误。" - }, - "transactionFee": { - "message": "交易费" - }, - "transactionHistoryBaseFee": { - "message": "基本费用 (GWEI)" - }, - "transactionHistoryL1GasLabel": { - "message": "1层燃料费总计" - }, - "transactionHistoryL2GasLimitLabel": { - "message": "2层燃料上限" - }, - "transactionHistoryL2GasPriceLabel": { - "message": "2层燃料价格" - }, - "transactionHistoryMaxFeePerGas": { - "message": "每单位燃料的最大费用" - }, - "transactionHistoryPriorityFee": { - "message": "优先费用 (GWEI)" - }, - "transactionHistoryTotalGasFee": { - "message": "燃料费总额" - }, - "transactionResubmitted": { - "message": "已在 $2 重新提交交易,燃料费预计升至 $1" - }, - "transactionSubmitted": { - "message": "已在 $2 提交交易,燃料费预计为 $1。" - }, - "transactionUpdated": { - "message": "交易于 $2 更新。" - }, - "transfer": { - "message": "转移" - }, - "transferBetweenAccounts": { - "message": "在我的账户之间转移" - }, - "transferFrom": { - "message": "转移自" - }, - "troubleConnectingToWallet": { - "message": "我们在连接您的 $1 时遇到问题,尝试检查 $2 并重试。", - "description": "$1 is the wallet device name; $2 is a link to wallet connection guide" - }, - "troubleStarting": { - "message": "MetaMask无法启动。可能发生间歇性错误,因此请尝试重新启动扩展程序。" - }, - "troubleTokenBalances": { - "message": "我们在加载您的代币余额时遇到问题。您可以查看它们 ", - "description": "Followed by a link (here) to view token balances" - }, - "trustSiteApprovePermission": { - "message": "通过授予权限,您允许以下 $1 访问您的资金" - }, - "tryAgain": { - "message": "重试" - }, - "turnOnTokenDetection": { - "message": "开启增强型代币检测" - }, - "twelveHrTitle": { - "message": "12小时:" - }, - "txInsightsNotSupported": { - "message": "此合约目前不支持交易见解。" - }, - "typePassword": { - "message": "输入您的 MetaMask 密码" - }, - "typeYourSRP": { - "message": "输入助记词" - }, - "u2f": { - "message": "U2F", - "description": "A name on an API for the browser to interact with devices that support the U2F protocol. On some browsers we use it to connect MetaMask to Ledger devices." - }, - "unapproved": { - "message": "未批准" - }, - "units": { - "message": "单位" - }, - "unknown": { - "message": "未知" - }, - "unknownCameraError": { - "message": "尝试访问您的相机时出错。请重试……" - }, - "unknownCameraErrorTitle": { - "message": "糟糕!出问题了...." - }, - "unknownCollection": { - "message": "未命名的收藏" - }, - "unknownNetwork": { - "message": "未知的私有网络" - }, - "unknownQrCode": { - "message": "错误:我们无法识别该二维码" - }, - "unlimited": { - "message": "无限制" - }, - "unlock": { - "message": "登录" - }, - "unlockMessage": { - "message": "即将进入去中心化网络" - }, - "unrecognizedChain": { - "message": "这个自定义网络无法识别。我们建议您在继续操作之前 $1", - "description": "$1 is a clickable link with text defined by the 'unrecognizedChanLinkText' key. The link will open to instructions for users to validate custom network details." - }, - "unsendableAsset": { - "message": "当前不支持发送可收藏的 (ERC-721) 代币", - "description": "This is an error message we show the user if they attempt to send a collectible asset type, for which currently don't support sending" - }, - "unverifiedContractAddressMessage": { - "message": "我们无法验证此合约。请确保此地址是可靠的。" - }, - "upArrow": { - "message": "向上箭头" - }, - "updatedWithDate": { - "message": "已于 $1 更新" - }, - "urlErrorMsg": { - "message": "URL 需要相应的 HTTP/HTTPS 前缀。" - }, - "urlExistsErrorMsg": { - "message": "此 URL 目前已被 $1 网络使用。" - }, - "useCollectibleDetection": { - "message": "自动检测 NFT" - }, - "useCollectibleDetectionDescription": { - "message": "显示 NFT 媒体和数据可能会将您的 IP 地址暴露给集中式服务器。第三方 API(例如 OpenSea)用于在您的钱包中检测 NFT。这会通过这些服务暴露您的账户地址。如果您不希望该应用程序从这些服务中提取数据,请禁用此功能。" - }, - "usePhishingDetection": { - "message": "使用网络钓鱼检测" - }, - "usePhishingDetectionDescription": { - "message": "显示针对 Ethereum 用户的网络钓鱼域名警告" - }, - "useTokenDetectionPrivacyDesc": { - "message": "要自动显示发送到您账户的代币,需要与第三方服务器通信以获取代币的图像。这些服务器将拥有您的IP地址的访问权限。" - }, - "usedByClients": { - "message": "被各种不同的客户使用" - }, - "userName": { - "message": "用户名" - }, - "verifyThisTokenDecimalOn": { - "message": "代币小数可以在 $1 上找到", - "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" - }, - "verifyThisTokenOn": { - "message": "在 $1 上验证此代币", - "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" - }, - "verifyThisUnconfirmedTokenOn": { - "message": "在 $1 上验证此代币,并确保这是您想要交易的代币。", - "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" - }, - "viewAccount": { - "message": "查看账户" - }, - "viewAllDetails": { - "message": "查看所有详情" - }, - "viewContact": { - "message": "查看联系人" - }, - "viewFullTransactionDetails": { - "message": "查看全部交易详情" - }, - "viewMore": { - "message": "查看更多" - }, - "viewOnBlockExplorer": { - "message": "在区块浏览器上查看" - }, - "viewOnCustomBlockExplorer": { - "message": "在 $2 上查看 $1", - "description": "$1 is the action type. e.g (Account, Transaction, Swap) and $2 is the Custom Block Exporer URL" - }, - "viewOnEtherscan": { - "message": "在 Etherscan 上查看 $1", - "description": "$1 is the action type. e.g (Account, Transaction, Swap)" - }, - "viewOnOpensea": { - "message": "在 Opensea 上查看" - }, - "viewinExplorer": { - "message": "在 Explorer 中查看 $1", - "description": "$1 is the action type. e.g (Account, Transaction, Swap)" - }, - "visitWebSite": { - "message": "访问我们的网站" - }, - "walletConnectionGuide": { - "message": "我们的硬件钱包连接指南" - }, - "walletCreationSuccessDetail": { - "message": "您已经成功地保护了您的钱包。请确保您的账户助记词安全和秘密——这是您的责任!" - }, - "walletCreationSuccessReminder1": { - "message": "MetaMask 无法恢复您的账户助记词。" - }, - "walletCreationSuccessReminder2": { - "message": "MetaMask 绝对不会索要您的账户助记词。" - }, - "walletCreationSuccessReminder3": { - "message": "对任何人 $1,否则您的资金有被盗风险", - "description": "$1 is separated as walletCreationSuccessReminder3BoldSection so that we can bold it" - }, - "walletCreationSuccessReminder3BoldSection": { - "message": "切勿分享您的账户助记词", - "description": "This string is localized separately from walletCreationSuccessReminder3 so that we can bold it" - }, - "walletCreationSuccessTitle": { - "message": "钱包创建成功" - }, - "wantToAddThisNetwork": { - "message": "想要添加此网络吗?" - }, - "warning": { - "message": "警告" - }, - "weak": { - "message": "弱" - }, - "web3ShimUsageNotification": { - "message": "我们发现当前的网站尝试使用已经删除的 window.web3 API。如果这个网站出现故障,请点击 $1 以获取更多信息。", - "description": "$1 is a clickable link." - }, - "webhid": { - "message": "WebHID", - "description": "Refers to a interface for connecting external devices to the browser. Used for connecting ledger to the browser. Read more here https://developer.mozilla.org/en-US/docs/Web/API/WebHID_API" - }, - "welcome": { - "message": "欢迎使用 MetaMask" - }, - "welcomeBack": { - "message": "欢迎回来!" - }, - "welcomeExploreDescription": { - "message": "存储、发送和使用加密货币和资产。" - }, - "welcomeExploreTitle": { - "message": "探索去中心化应用" - }, - "welcomeLoginDescription": { - "message": "使用您的 MetaMask 登录去中心化应用 - 无需注册。" - }, - "welcomeLoginTitle": { - "message": "迎接您的钱包" - }, - "welcomeToMetaMask": { - "message": "让我们开始吧" - }, - "welcomeToMetaMaskIntro": { - "message": "MetaMask 深受数百万人信任,是一款可以让所有人进入 web3 世界的安全钱包。" - }, - "whatsNew": { - "message": "最新动态", - "description": "This is the title of a popup that gives users notifications about new features and updates to MetaMask." - }, - "whatsThis": { - "message": "这是什么?" - }, - "writePhrase": { - "message": "请将该账户助记词记录在纸上,并保存在安全的地方。如果希望提升安全性,请将它记录在多张纸上,并分别保存在2 - 3个不同的地方。" - }, - "xOfY": { - "message": "$1 / $2", - "description": "$1 and $2 are intended to be two numbers, where $2 is a total, and $1 is a count towards that total" - }, - "xOfYPending": { - "message": "$1 / $2 待处理", - "description": "$1 and $2 are intended to be two numbers, where $2 is a total number of pending confirmations, and $1 is a count towards that total" - }, - "yes": { - "message": "是" - }, - "yesLetsTry": { - "message": "是的,我们试一下" - }, - "youHaveAddedAll": { - "message": "您已经添加了所有热门网络。您可以探索更多网络$1,或者您可以$2", - "description": "$1 is a link with the text 'here' and $2 is a button with the text 'add more networks manually'" - }, - "youNeedToAllowCameraAccess": { - "message": "需要开启相机访问权限,才能使用该功能。" - }, - "youSign": { - "message": "您正在签名" - }, - "yourPrivateSeedPhrase": { - "message": "您的个人账户助记词" - }, - "zeroGasPriceOnSpeedUpError": { - "message": "加速时零燃料价格" - } -} diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index 377f74db1..d517d3b2e 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -47,10 +47,6 @@ "SIWEAddressInvalid": { "message": "登录请求中的地址与您用于登录的账户地址不匹配。" }, - "SIWEDomainInvalid": { - "message": "您尝试登录的网站($1)与登录请求中的域名不匹配。请谨慎行事。", - "description": "$1 represents the website domain" - }, "SIWEDomainWarningBody": { "message": "网站($1)要求您登录到错误的域名。这可能是网络钓鱼攻击。", "description": "$1 represents the website domain" @@ -882,9 +878,6 @@ "data": { "message": "数据" }, - "dataBackupFoundInfo": { - "message": "您的部分账户数据已在之前安装 MetaMask 时备份。其中可能包括您的设置、联系人和代币。您现在想恢复这些数据吗?" - }, "dataBackupSeemsCorrupt": { "message": "无法还原数据。文件似乎已损坏。" }, @@ -2869,10 +2862,6 @@ "restoreUserDataDescription": { "message": "您可以使用以前备份的JSON文件来恢复包含首选项和账户地址的用户设置。" }, - "restoreWalletPreferences": { - "message": "已找到 $1 的数据备份。您想恢复您的钱包偏好设置吗?", - "description": "$1 is the date at which the data was backed up" - }, "retryTransaction": { "message": "重试交易" }, @@ -3845,15 +3834,6 @@ "syncWithMobileTitle": { "message": "与移动设备同步" }, - "syncWithThreeBox": { - "message": "与 3Box 同步数据(实验功能)" - }, - "syncWithThreeBoxDescription": { - "message": "开启以使用 3Box 备份您的设置。此功能目前是实验功能,使用时风险自负。" - }, - "syncWithThreeBoxDisabled": { - "message": "由于初始同步过程中出现错误,3Box 已被禁用" - }, "tenPercentIncreased": { "message": "增加10%" }, diff --git a/app/images/aurora.png b/app/images/aurora.png new file mode 100644 index 0000000000000000000000000000000000000000..5c59ca5eb91bcc267f758fea78d0c451892efd13 GIT binary patch literal 48350 zcmeFac{r78^gsNdGBlxy5Gu2z6hiDqMMX*|v{h(OM5dDVDb0m4M`%zgX*UR^+9ws6 zPXj7RWvG-y15M|**1C7!@9+KZz23jxKaT4<=j`)5>sj|_eb&0yz3%lq``LRP7uXJz z8!5+e+`zeWW;$`4Y!LjjMW!DdIdk{UbNG*Jz#KO?sA-1(NSL^0Z00x(Ztl!!i^J01 zKb;`KX$%k@ioSn7%kx_$|9qA)4wCruxleN8 zpO2hmh5P?}mhdt9^I5=|jQI1JCrIi4=d*_BKlR*yPk^+$MUsAyN@L#0>B>a~YfQ0{&0+8@uQUDVEOA1KBe@OvI_%A5{ z3I8PpoDct13P8gDtE7-|<9gwT*QMR&?w%D#Ek1iR$lN)|+tlY&^}s9H0}2!dsQvX; zX5QqQwye=g6Srqg%?3~NTKwx>I5+K{YQMm|3hU3(FBJc`IXIN} zza2hDZo>a|0VVGIZ>O-Y{C^kxPn-2Wmi`Nk|DVr?CiPKtCqPTNHFA8`=XWaGPW~G4 zbHatL3l}`1pKtmw9+NMp)$_7EY5b@@_<7xgieDS-)|maf?Zv^19lyJuZC~*3BD=Sy z9oJL@zj~`znjQ837$XgWyj3gcu0i^T1v$ajPX&MbcC<-ni%O(N<1df*I7dW5d+ByV zL7nlp{EfBiv-2{xZF}8(vt7HyBY(fAeN*t{kcauXn{imdwjq>QI!}9b_@6lcTy=e( zP?)!7#PV65Nh{4flD^oY6kmmfXENBd?dVIZCzr(`+7Y|Nw#}x=g zp8((Rc8!03KMh)cyF@k2tphKXVfoSVj916Ud&?5@T@$ZYb=>iAsmzdpvpjDGEukPN z_|kDV;rWux5#^nR5(ggKIQ$rtMEnn%i3dK#(6e{~KV>2@f?J?WDnc~Rnkpj)X<7K#B2W3}E}1P>bn z(xQ+(M7!zgbovZ-dS-FM zEjvB6lkw4u>@FNt|5>@a<DJ$O@+hl z9|a$&yOygq0nUrmnO9Tx^f&GBk-aw40}gWA*rcx?quJ>+)s5rq-9K7w)jdqZuRcsht-fdc?LwFHhS5gZ#frgd zFfTj8@t)l{HqOhIJ?*;xKK*p(n8k?lZMR@LY~BQC#q&?&idVmp=_A1~TX+AdUNSA(%ab-w40)Jmi8`t^|I6)h8@{>$jM^Um(g%m{x3qE?RnGb)1<7=Paj74{Cf3n7M#fpq1eb= z3Vtk8sB=gk-Sq!BZdcqezD{q{bti?MT`^PM1(G_)VMLB&0&+L9ZkfZNf|5$b2w>q= zEa((0rC=4T1u%vie?1%`mEJV^!X^)kNjTspHeeXURmVAcxi1VNv6#&&C_O&RsOp?JWk^K1SBQl?VIR3-%X12yPJq{{kmA@(P?} zbp?%^^+o*}AT~=jSZu6^t9Y^$96W_xg*K&{b5R>5#wZc%VKLLFQdy2CMkxsAB&y(?1=NP*4Vw((HT6{uQ23O0Hl<`7y$J{>kQF0 zm7unzvouFIUTb-J_h04K-*@8hsOjB_$c0d$xIz6?d}QcT-cF;gy!~~fM&Z!~#47)M zSKhwzOO=*70~dqpjoaRzvLCDf=UqoI)$2@fsd(#N+P9C;{d&)>aBq1y%O6Lyh?W9v z8BR-w`!$+-X~e$RU1;-#hr|R2RALkf1H%hjLv{N1`Kq`4de{d|wCNl(*!4`2>zHQA zge?lZPz9Q*nJpe)D>Ns7w5X+;*+kmTu-}MvgcgOwI|(P9m}U6flX%&X~l3bt@s6AI2tF_lbag< z;CKD}q-b0g!VD?cI#-9UX`NZxw^MgJrpczc?w9ebmEEAis-5m!%+r05}{mpGg0?Gqyi}OdlHI1)CH$vW1+fT@78klk!22ndS)55*f;eHf$+|10k|> zfGzL5*Pwou{3c|bLTq(PZ2wHg$?7!HGE%EqQulBsrl^tH$b_ID*kS+&Yr&9koG&$_ zh|@_vu)gVKnP`sS{S&Fy`nzTfN?#>-nVM6Ymkuv%4C~wBrjnF0zX@k;wT zp3i`J+}#8Jt6^P^8=RWxA)qQ@!ET7SH*}Z{1B>Lt_y?BNBQxzR%P$=#Xs@VR;RV3# z>0ij5&5s*#%`-e6E|RYsy!>Xwr!cTkBO4O)BD-5#ZgO4`c6uLTpxinH5P4RKxIW|Q zZ{YivMRWCzhUMV3am0Wmr0nron_8bpMtw#{#0-aXuQt-8=>szkvWd6d+dSX?@=t$U zOr;e`eh+zXPa90dny44u3CKB5o+y?XyZri>dnSEX-*daU6hl^A$4na#v@PCgb6dFN zByXLpO-C+JVWF=>oO4~1m)+W&$jx6mT-jmjX1FRlgTU#VRs8A*tW0c^skxE?d2hon zobs6=HW9sDcW1yf5!kh?%d6_v@6Y|T3W*cpfck9ey$c!LEZG$O5X@G^;D0oiVk==} z>u=qx&sE)0P0>eHH{A%-g>#PT#QkF33%NhvJ(1`f=-(AM29GPVxzJY;FxDRLbz|C_L$#)K>B>673&N=c+ zLDP8a)A6}CzrSd-7~S)*z35F?(;T=uGlI-oiE(wi#W}&g&Oq_e`q<#3|E8b*`6Kvu zTl>XSqvhW(SX0IPt?J(^8QYfs{&DTbz6CO~7k`BK`huaJ=|_&p78!r@&2>2$m=Ty3 zoL+psrLLuZex26ub&&5>Hh*a2{LG}6TQ2*3;_sm6hTAe+6lTM?T>BVu$ZZfxcKZH2 z==kUn;co2{rI&fVI%L`I`D04Q)62=Wv#bw3ztZ*>48|*@4B#kKjdouub)28k{j@gx zN!deztT)C91RqgokRVSe`p;Df33VQ_WGyV-un42qpDuCtQ-05 zuE)@KB^OhxrmBLlZVW|$94u%X?cQdj5ANHO{QA7fr`m3aq}bwIsk(_y05#6s019n7P&qs%ERwT_4fHV{C+n4>&>%FOC?>V!I{6iO!#%d`{AVHAc~8jcfRcN zE4_P3lrY9f!S=7N>g~lp*PZ^-%|Gv+kKxdls#D%H_Y0*XpEnEISG_-FAng%@TaMiP z^BH~Dy}pKJjBXSg>gDEHwatqL6)aE-c-}SnKuNFu>~$VFhuepvQ`zj&6|@g?+cCIY zv95l8+aR+Qxs8if6r zJFe<3Pr7QT`yp(Q)s8*;Zz*9N8@%^gSnl$B8!SR_<_gs){OXT;byPdq*@XAADjq-D z=%z2${@)8D54H6;xa2{oiT4eB`>yR(x6*7JK6|-&DlY9*>ivFq<-!pTnyjz2PM_*hh!}im;ouj;vOizXV`=G22{ZdJlaPlO zcdSUjz0<7_Tg$H4{z zgdarHLO2c9%hU0{TPk{^tEarO2;%uohpKlmzig_}y$w%8c_1oO{`X}Xc$j};fvVYy zPs{AqIF#PiKKOjo)R2eM?B15B4!K>|*eb6KqV=pz=2vR`ZMR;QSyk!vuVlCIwFg%8?JTc+1`9jg<%YFKu4;C2`#doAA|!6JUpa zeGu@^)!LG~*2UXwz7=$@@<*D}_X`(O7c8}rc?Vwb9(2t*ETVGR?dI34bgE@JyuIaw z8I(*nRPXQ-po-j`>#<5U{yY{&qVJRh`18Se`DKrbAS$1Ro*%ui0ZP@&yPr-vHW3ER z*-P`SwxpyZWL)_yo0#X#AGw#!357R`ENoK~gL9`=V}e-Xz_7)-6gFBs(;l~fR{6*} zw|41i?!8a%wzM@!#}vBhoL2`)E{E-yYl}xOO0@>T@Isl}ke7_JJ~zf~c<@Zs2unf( zs`>@PE|)#d861A7{o0ound6|p0rhZ2-Tnu|UlO)@T+lb30(s%|;)aa-+ zajEs%{FbdZR}AVI^XA&pT$N#)Cbz5~lmeUyhSBy*w9mC=ZP~%t{x>0utefT%6jg!x zN7HO}Ra3wGOc>?(GGhCuLoGaGn#+(J@|YZXtO*U6R@!&G#+$Xfgcxm}bBO-&ZLfp< zrW?6R{LcmbY0ftFWfz{ z^JG1h>QxB_MOw`k>wn4fANTQ?FK>a@nlQb+5joNAw|2SC9}0w%41i$|w6v!`1nb^1^}OaU+*Bi=P1u z%n$}v7Qp1$ggkU^-_1RXzhHi&Q~tIB53L!(m{=1LAKeCJeA0P!$)T?_vOYg4mbq(z zWs()!R*$-`?=nZd>&ph7M3?hv>E3sXUdc~K1!LF zAGM@#x?AnmLCb9VWLLsg1+$gAlH?k=zF;@0?`S&_q*?+Tf+rl$Xx;hw{^d?Sg+hlW zx#}YrPq`Ow^D0~q%aEMMGQkzjB@v*yIlqcP{+mNwI}r+L>Un? zb6-Hg0O`BW>iL7r$8|lfCSO`GeuYbKp@_mb(#+z1AZ_wsFTlNV&P0q9AzUF5Y#Ov-&xqPmgmN%6Fy ztRy~h8D_^uV1nBwtQxjU7oJ@gumyj0O3d9aKaAPD`MERW!vms^B7rtdlGV}9xyE-!ip<>FN|0SFhiSe@dc;Y1-ozr zWzh*&9APVtK=GTYW!;ZPSRDDaPE0ms^O`f8_*9jBoL9WaLKC+OB~<*<&mifdhPl zDBz9}7kjE~Uwn6Kkz8`u@>nDVtqk*$>ypCT^2<2`ucHP7K4L1oO{B`F#N7CDxvX!_ zk@@riYTuHg8>`+3KeP#Z+A9=yv6_;_fSvrGMjVmqEq3akC+F%7@>b- z6v^>VAfdm2Af613d%RO2KXOT-VEv~-XEK7Zt1_KD<~S7z)f1e@Sp9};`(p}z`M+ZF zks!a+(7B8t$Eh^1^JOq#k7T_*8ju0HPLMiYpk z#U&U*vYB&`p>(h~(}FBs+x*%OLnx~|S8VZFHa+w)B<6CnE~CW*VE|{E1&%7}-ss}& zouLcF7PGYY7&6E%bII)O=;Bb2&)!8YJJO?sF5s;%+9Gz@T5>`5cARDkJZEwNBpco^ z0{ZB-Z9T^5+7`9NET$K;$?*weZWniU6~?G046u)4J+q(nO^hK&%a6xd%w@94vCju$ zLZOf2WORW#SnN27T#(iMPae8Jw<@`RNv)0G&qYhAex8Tu#8 zOq??B(&TU)i!K`_a3lkulfXMf2E>=y)}jH&yQ0ss7-B8uOmk$^lGDUQv<3Eff>%U@ z?xC1-=;E1e9?s0*p=@$2M1upl>EwZ7VDK#FfsyLY=z-NcLzjp>Fq90tiykPDSWOBPeCnoMvEtK^T`4%pqA0rm;Wqc5(cTjChWABQt^p( zXtE~7ui8_qFGuhLB<(GtunSGa)P7<4b-f_gck;@PV)YtUyA zsiE$SBjGS|rfC&UgT4ZPn#kD7P@yQ|t3;^M5I@4}#E`@%P9P*Fs9A7`k2r)b4UyV< zVl@t76&>m+9%3OI;vNj~s*k{yhQQ5=3bP_EVgL+FM(_Zy}H ze+)UoZ(mF%MnaikXpi=VTaCG%n7HFGhkZtwU~MP zVv^ArLbb+YVrSTqGr}gIGi14|B6P+H7@{bdGM{tjr%ULJtL4|PFlU5KAhhG5v>c!y zAsUXE;KxvK#t53(ole$E(HT7DqD5l6#V7pG?!nwp8sZ!bVUML08!+0lhGIcKzW!VS?ADlVio%0(chN&Vzb$a7);0;IbL6M_YEi` zL?_7IVRGtY(A}9vjZkf1t@r1|P-Iq;(_eupAIpGI)D{%2?3JO23ho+|%bX`Zu>&#n zbZD?2+;I9=BVX_=vDXs(l!5Xf5WGt zS9R3ZP&H+VP%Sw(0Tgmgqn&d{CjRDTJt|z=V-4B@4z0whBlqH}iqmC%Ywnv_WKgX= zVhZkvnns}bFK#D_FTla~lep1EcM`A67mMFACvg=N|H<7&aZeOKNaB%~7NfZF4*w8q zDspaa#PU<5gW^9psqCP~ozG#@(iBJHH!sa2@%{dxOx&7**`e<;(0;368fuS3?SGU1 z|GhYq#N+(K#Nq^omvC;kx3!4(&V6!32@oAXLrRwyN1S!%F83z3Ey8FNp$gHav+k1( zKS}gk)OPme7P!S_oJK$l2X>zcl;|umyRjWf5d}mS0$2SOwVd?|A1ttN8T=v`=F;D) zIR7hr+>#v<`U@^ZJnKG#2L`mFWBIyh<5w=i2~__;)$yoWP-rNNx&!w5M-XViG14;N zWSMjErBQ zDB}h6G^w=0H`uHGpP)+rN@d$mH@sMV6kZv0)&rAm2mxpqVr>dNb zQHf&(Lgbm1-$Y*g?)$|OFPX_?s1qW8E>V8~kavSGczOiohGB0PkS>%qna)UeB8SSI z0T%tF`9TmW71%J}Np^0!)KCslD@w1B>wScdm!mM$JpsTEs|lV%)EZ+U98bYqQ{qIx zZH-ODz+V&aJqSFQ3powI8xS~g%NtQ%guqqrzZV1FL%;vYeVFv!i6lL@Vic3!&ZLilw3Dhp36ZFSG>h?OVH6_ajW(IX zaLY5?NcaG0jcBkk2zF&W7UIf=FVM=^3d6&U69GB%E?U_~S|brT0cp`IvNEUo!8jy* zV8vL5WH=Gd_d*J9N$erQAvFn&iNbZ4{RqmC%X1l&okWUjJZ3|GZY_E<1ArTr(WJd* z_yn=klpbJM_zMa7a7rvH0t>WL55)Ti;&c;gm*=57Cz+gM&UcMv(9zK5ewhSaj(fNE zFSv`(o(14UE0`H2PGrWAWH*)u4DS(u>6m0TNI5z{8YqMz_?iTuc121e=Eu1eMq;a9 zQPxmEtMeq3W`KAviYqX2ue~I`x58K~&XSA-ieHvcvc)6=O9o$piSxrr{C>qmv3L_| zZ(4=o7bTSJK|CB+m{lZR<+}#Oxr#{xX=X2=T-`Jir7uV*5p-$?G>vaC4S|Ub}9`d@X28`HT5gm8}L6=-1g& zqBw-J1K}`=l@gZ|oM4}0EWbHVC9bGuqhxT3iTA7%^Rmf(N&ev*K$y1LS|jNl8$(6q2b_-_YrDhmO=HB6WK zy~Nrt*Fb{*A>|N*|DM4ggz!zJME4MW9Ka7D_A_?`U-{&**V zzh(fp-x1*71o&ZWO4PYI5&SR77a9DbQc4Q_5&m!~(F%lr8Q^=e;F+Abh}ie=InUsa zXYj`&{5zab7vYZs_&N-Jde&lu@0yWfz~ILbd@F))%o#2~_Hp9N68!X)$^<_!`38ey zMJ1zX2f~q);>nH^SG1d<}IZCouo(}#W7)SBiegP6q)$SU1ISh z6o-0JJFyUIS6pmWp@?l%r$I9eV-UK?-KUUZMijP;MJbW-HFCpcJvK&eID3j$(xhg5wMdiK{f>c!g1C%dh$X)x9@=@Mj#mH$XQksFt z4Y^Kv40IdFN&`sC*hC%%uD~}%f^Ak-lHX=iocHIfW&xHd(6mvakTc%d;y_rOeg0;Q z%V5X}HX{}<2|*H;AcG+Zd?74DT)#IXi;dpe6*P+;QJuLMw@tlrToEcS1m)R8?rPsB zahTuh_dPMDN#t0G_B#^i2Aoh9k)_cGvtf&oahwN zGDHHN1S5n?5-rKj8_C0%oe6|6crnD`B}wi&W-m`@xx6FuN4mWu;9q@w#K5U?T#Tu@ zP>y?VhrprC&L(bGuS_A}=KG#ZV8HJZaH3qF3!vNrU8&4n1bna70^)GBPbmXFkbw6^ z;Ac1yMeP^>E=RzJCz=uP%gI^{_%H(g34tG%p zj8Bo{3~?)2I0S$b<8xLj6Yx1+UzzkwlD>mct0%|JL{ff(?iHl_uR95Q@1Lkf@UMEAR#8;GC-_3@5Jtl-3W|BCM?wgGeVmpp!C#+ph{3;3@ZS^sF`Q@@ z!jA*^9t8jEib8_VSNCaQ@Qr9nr6TAuS--W_|aY=489+OuZ-;P<2Y%A9|`bH8T`XqvkCsnlw%BjD#7<7 z_@g<|UkLvMz@Ja>udWDZ?5p~`W$?8LzCXg>E5ij4`)eSE*Ax74u1g8Nc~S~%xOSQn z{ACD#lq8o%@Zknl81-kHJQ9Zy{96812ET~brp}27e-~{25&lhp?@22{*lw*^1V1nN zB7;Ak@>$VL3?5BRG#%kz2KY$?-_v^vV}HKS2L|7s;5#7vxxl^#vJdrO(;9;B;%Z0m zT~kvmiT%z=1b-32he!VmY1aYYHVC7n)8v+@K=3Cf-(YYYh)t_`04Ga><8i1S>c=K8 zQt#_Joz$1E=*QZfR@AEMlt*j-;<#yuz8KK&CiJ7cdt)*5HR9Z?7#ev(gnNE&c;PZtMKZ_Vx zjzo4za6@r<^@P2DBoXGm;tWC0Oih`}EM?(AlW+@1efs2Q0NtP5XXB<#(3AgupHBI* zhdMf)a}oL|PQ<-~vi&1exH<&gB~gZ;`%EZiZDZD^x5j)~A;l>XbhsVaLtBWRn3ib- zJ*A?HCGWuq9g6%>iDA$bM$)T+bh2k~Vn3$ZY0jSFSWCcuBAm`;u(W z%BvSLvDr=eR`54c@>GJ$ta@A=0cABcNd!*}WpVGobtWj=5F@NhzYFPhlLpJsI}uR$ z(sZxzo?^(#W*wLbn}}5AYX|>y4>lphOu4 zc1MHp-US2-NBLba<>$|8+zyHiiu%&lS4165KJYymfN5Hpllp!8jn_d^!?MnmUp>EhfbS{7$1@+@IlQMn~kM%q9S)X2)>LO~> zuabh44slonSTm_t`KI}FBnB4uwYie@(y31`n26BpAfq2d=#cAlDOG>(Nny~(gjq7^ z6A3!@>Fp=OdW7xQAF%V?M+6u}z9Q&Na~kCtbfR4s>z|1Ly%?dxdL~dLExR+m5p?q% z`K(i~OGSYk&Ix!Jk~;PHJW?igh~G4w-b&D`n&-1_x*QD}fY7U<6d>r(jbSbMu3k3= zeOTBs2AxU>>eSntK>LxPgOj!s>wb|B80%V%N(7y?>Sc)a0i3`ap;rNPM})4Cl+jJl zT@U56UcC&lPObW}z&iHoi@>)U#CmD-=?H?pq_vVkr(V6l7@?Oyfrp*rkAna@vEJ3A z%%JyaWbJnix+5iny?Q6Wg3bEQ-+)Dfu3zb)`!#B_9Iz1~vTpqiz(S-0mf^IN*0$io#FWNK!LnLSmJtY7bX z0Kr3_Y%PM{fZ&OlFFh#?yljyN%L3H97g3LXtprC+`fsr3Fr+SH&RvJk*yiEpy&4!t zE5LBtcnzm$2Q(94tqTM1ibhjHw)knqlFZCT)^=yjdp58D1#Pj0d5dNAz`ah`Jq}}-AVcbGV;apbgPW|^!6w}1NEak z;a4qpVDg>j{+X2FS))FH7KDXxyBn*j#%a*Pqk1Jk)#eu7Lgqx>MLU^urx9(`sGknU zu~Q#57(PhQ@d-aaSK*StUFgbF%Jy#&mjX?yS|g2 z`j`c{u_@K)2C+064d}G6In4~%T$INQ*iS&IU9SkZSD*o~M;1|gShVhEJTsuZtCbnR z`t=TIz!WfGKZekAFu;KfsO~ml2IN#fV-0&NGJyK^S+xSRwWK^$bi^l z71mN0AIG~Z_yzAM*ton@gT;I>>5u8|o}3Iu7vhfr{M4Bjt^B!( z;V&$@&+KK#)o@{fT3#a_v-3olo5k2eX=w8eqGVp$wx0F9JE*Bn9sAFaWwB*n1PgT& z-4zK)&8VPcp1IqMb=6tR-W}8DC8)~nsLqk%1O~)%aHJ6>bAff^T3T9~n0rVg@zIb|?{4~3e7z?(wiA})Wn`UVpCH*Fsn_()Pi zJ^M!h9-H>~3}aJ&iiM*Yr39Wo$iINa4)r;Dur25fS#SU?y71vQQU7mGI78F=DUngn zn)%Mqv^U2mPLRnd9Cz;r6#&+~YsBJRr$}7fwHN5SD3rs_PYHXJp-{iR#^sW;*{_lf zsf}w4A!3xO(H+#azXHf#qE}x?aK_YLJJlU$PC?MA?q5X6sckQ~xEN+(Efk^ZDBcF* z)X>!K4ibyU<+Hy1Jv4~5?bkpFf_?k2k05>+yGWn? zo_RNpMse*f6R~(qJ`=x(TQL#!?Y%)98~0)Vf;eq;PkkC92BYgQV%TxT6--zR*zW=M z!I%-$WH^x$uK&q*s$bCj5M3_nOPdB`>bp_nUKVyw)Vcqr!Es}7{pZWsY^C|lUFc%H zcoB6wv$4O{1+z44FM4S@G{BK{zNF0-mJa@{zn=8kJlC&(W{ZTeD6Nz0Dcf+^Q5Lpz$C zI(GHqGm3ad{S=jsy&QKX3mE13-hLhdPuOvSGld4N_!J*+SsBcpE2|RD4IB?C zPB7Q4ZEf*Z1x}C{4`OfZvQyzvM~KW3q4y$c;mGQ_@Ky#vNKRnh%ND4yjr+H|uP-o@ zgzw@bOf}h{Zg}dH<62uglIcO!54vard|AV^XfcGQkN44Y1Hah<%!LS3MRS8SJiiAG z@dnLqe9$p-7+UpISoU~Vk{*^!IYD_ZN6B(L6@ zP7p@wHFCu2Q?GlI`a4Lb#t}q63Dhhh^!D(&6+N&jcEKD*j^j>C9}=HQ;_!sJX^|m_ z+X<^4@7kixaTjsaIofGVd-gpK6LQrG)FKaGl~M78-XxcWV73l{n*s>tq+%KK?BbTH z6r%DFVPA>Zfk44wq^1$5QANrWWmhuh&jx*CrkbOcnHQ1C(Qvb84aUvCeK?JM=%_VO zLdJ|P< zN6g1l#LH5|L+(-{^uB1ve;LSQ{t!KlI?43^ysKtL=Cb2!DR5v03W9SNG=Mu?4`P_D zQ;cT5>U8M1M(IpA63t!Wg}#Le&fQ#rcs$?`+9g^Vb)4x}ZLLZr=bpnz<8MTJ10k_A z!6Uuv3%*HmLUUA9t1*D_(-hoslMO(}hkN4yS}=g87Y?u-wwh$XgQ!gL03~YXWB@z9 zf((G-N2EXw7yxA)F>$!lghF5Nu%Le%W=!$%C}b!K1~C5%<7YRR9EB#^D{N*a2aF1R zMe)XtUxqI&?@EG=3+GGmIf3IYW4hqW-mW4Sa7M2;q>;(&_!2bv0Yp%fB*lL}j=uy$ zqGEn&3gu+cq=rKjLgM4_5WR{gR5IK=cmQ3c<35Pa#z>zcYsThRa^m$siXnE~4Zf{h zY!79jK$eoeGW5$ZTN{r!=0h>cbqDxX(fnn{r(jG&G;zjKl=Y=J<0PC$Qrq$O$m%IRkP6w5~>w6Xb4} zF(=fvY&c3zpyN%W$q69OpM_4i)ejb6bb`Cx9OeYxz>az{IY0rasG_6=D-CQsj#=OsXBkRPOPhtxjKe|z z8t0r~JLMsu=sr?pzS~$#(bI+-6ctUY5NO&Rj0#w(xuGnX@j5>>=(pN_5#E>l+ri%>0wvf{x14_UET472Q zEtmnZ_m5hUkE3baP%vOd56lDkQjF3Tcx6!%8eAf8DweN&&g5@Wo_0a`Hz;3$@@=qf zvqL-|6(%zInjMy#i6C}-1j^Tgd<~=`(}sr<@RSwmzo1|wmfwF}EI$YJz?Tv7G@BtL zR^LJW?O^Xo5#?j`BT;@)KA{Pbes6A#H>FcbWnJGTq?detb+^(B=Pq z3h~rM?Phom-1V>~KH2dM#D53yD-r)~5?oIl4XiauJSpdOd}e@jFhX+zzi1YrIL(-L zSU52}9d6%d;d!rhLk4*lgXaWJmm1hq@%a?}(wtHn>YgqZt}l3HYskvJRq3wcl&Rqy64FCNOF`E298oZ68RaVe^w&#KzWz*!2-(=?i^ef*O;!?g0R>;oLn5_NcHl zOD3*~;yx(87{yIdTph$upm>bDSUgc<1`}6C@!2Ro55+@Jd<=+VqNv&5X~axT9Ba?S zF~bV9QG6zfPe5@U5XZ`)W_OKPyjEio6PHEtekg8*;u}%i0K_vBeP=0WhhKPHZe zvah>niwt`V-s)l#T&uq&#-U8?p4>Rf;4Xg`qBk8SkYT zNN+^xB#=hNW2e=NrSGpA!gQmwE_~HfWx78|uRsc|As=Ci;ccCMm67s>H~SEgvJtbu zPRj1k-QiiGf1rYt!(@^@zd)?~XsLb|ZX|Wl5t+J}Oba2It}cdIhu!ky$l*K1vtoDJ zPTWtd?8DTfTZ%bgJz#ly5q543upOlob0lgFo6|KZ??+S0*p6EEA&HJK8w6L;&|A=Z z!VHr+N^>bIpAPVLG3XNrI(jG>p>IJCt%MaBId|OOX~^Py_ULjJiIiYQW8mI_>Wr_1 z;=Uk`q&x1e`6E8|ArqIuAd*D!A`~}A@pT}MtUK-y{t?%H#>6SVBp{Eg0gOn9*k3>e zm4fN(d(@^79M}yNM$KG5_`_Gu1F~kfzj>(i> ziV=q8eK_1BwnN5h#|&lB$fd`H)5H)eBKToQjX9vqI3g4nu=>qwkIBg7V--zYY7HBj1>1fw*3VFDh2zOObKeSK! zlKhPNKk^QyOkNV@eXvSAM)IT|F^N8Z7Q$ZXT^p(1TDW`5DP#`3l<* zCO-h>wFy7USCD>?--~$WIqdl(@34!>-ywOzPx7Q68U?Z>ZyzR>H?&P;@=+vD_)*@F z^n?6f#52!!^&feMQ%rs)$rFCqQE`T(e;DW|`5CTa`5fD;Oui4w8zG)!D4#?6LB2oY zabGa!kG#V@Ccl&9QNI_-lm6i#kNVwbn~UWiX|AJqYm&q`^u>6KRRaC{Fg}a=a!vE_ zc-s&=aeRI$b*D6CjD60gi4JhNluI7=rNAX7|Li@NbU2 zOVcZWrq>uu4l-~DlG8*ua3{e0Fv9s1wLlDKRLVSBdTcRmnqwO%3eq1Ze-G8eK5`7I zSGBGGqyBIuQ{M+?FT5}as!CW|x#^VhrMONtWaov>sxn%uxUT!FiJhK7DDQ&Vp&s{C zFA)xG^1^l^oc1VtF&yv|y={nt`Z37}e{cdRV${(y(drdMuB>ao80{ zxx@@(2i{Nwu|w*8LH(3LoX7=_|DGErX6L|+L?%zi)6v>JXzdP+9VlIz_M)}_${ZBK z`Bb`z*a^es1Hcb?IS!-;5cg^vKTHKlyCu6{EWYu62#N2?$F&@|-%~Rja%*!dJ?M@?gX z<;EZSMR79#J9A3#iXhXdOCTq-WBd1rcKJ)*0J}^(i4|y`e)pUviSA%Y-Ir{bsE0F|ebR}DU zBmuFRCgA(b^YEnm^7H^JO#`^bm?pt~C{hr0Rg{Go-J&?rGRa&&InAxOdDvw>*8iS|C-QT$ZdTEui` zxQsu%ws2{|(+~MJq}K*dS~_Tg@8InSa9&W@8*7;1E5lvEJ;5e;ja-HXRIOZcLU8Wz z#`j;J<)2W8y9w9>sVQ3&7SwiTHWl8S;azF(-iUfx?h1zertZr+BOUf2{f2OdqrXkZ z*JscE87#rQnSo@#*1OW1q%*P-Z(VT0N$QE@2)bFY30~`v(FxCz(9MG3&D+_%1)k3I zR58N59+Ba*#~W@X43y-?VTKq7urf?jD^(m!j?~bVI{_@xN&hm6n*4dr|vn-BjJl?5Y;&O&5$mcN1R2%WSLmL)KZjynfeUAiwTK{q0J($kOl zO?QF|GT{}0pK?K=1F{l}jhH42?0@e|_Ejc?QP?;zIDY;#Auuyj#RAZjrj;XU+BH=pMvH7$M2AwQR@%t)Y0< z4qh+efMemVaO~x>gmNO%@#x@x0-t{nGhK>H&P?!hU20{kt;6_4W28nGHuFUgGSCmg zr7gBh-^GZ*lv6+1au}?@+ZckyH*?Ch`rugbE~R~6eez#4QoM|UFw>~oaO=i%Khw~3 zcX)XZi10?LpKAFYjx(kU{jqo6$u>p&`X2`~bygg_MS3IZoOv_5d==gu;^wqS<;{!C zli}`Qf;irDcg3V*I&fSbs;x=tyWo2aC_l-6>cu%MC^uOzE^l_(&+)JsuW_(bD^55B zUA8-?ZHK6X8ni!Z$N9= z!+k5rqBmvIe&G?i_x+V-tNSK(zR<*%+1Lu;FH)zIbouO;_n zxOnUw#KX83%u*|l>I|EeEDIOHeF=lZXj=LF9+aw6NV?LX+K<3 z8^nzv5;u0F|AsLg6A?Kt#b7ty65{xito_PgjRzCf;1z3trO3-qiay1!__+mL26wX| z5~By(N(dex?eC%trbKR&8xJceH+$t#gWW|6oGwOo_JV@LGgc$E0dL<*`pBS1;@sj=zWYtcGi+%il-iZD=Dsgy$y3MBuS~rVBMBq#_--fZZf*Z z*{$^~TZBYj)`I@RXa3%?>;@Fi`R0LhI9Fj|5rFa-P;TbCDE$`bZo#l@dH;2prrlQc zQ5#0Rz$pfQ7lc*L8LIG77+Yk0&K@ULw+QOC>IMCJdB84i21Es3J4|-ryKZmTWWy7& zaJ@~rW7&0;Ux05jQnoL?aP5z-{dZ$9H-U&keBr)lAMzo(rMS%D$lGY|+^0WRD8R`k znZaf;k$J8!K49{Dgeg4!(lh^CQ93T^c580xVkR(8H_S3sPn6`caO}rDin*q@T#*j* zgA-lWV{GZ+zb5-nJ@i1Vb<)Q)7m7M|Cb4ks5cpaJEXhqTTR(OCT<)z*NeIsS<4de2 zGe>&oUbBYaxT#JrLg%WQqza$njdpJu^=H%GcrAM4xOw%qv}L3m@5J$xum7smcUeE( z7Ssz&tQxE$e_q<$@xJV^y(GIdL1zBi%U~Bgi(>u6&La^Rnus*nHEtg1y)~>L{HN7- zO*qSKzc?P+nCw{qchS3W59^72xiXyB`h{O7m36h~f{@6&*&z6aGLmgUS}IcNwEU2b z0@1^Fz0$s}4>#QUQin?fTBTU-9*ltkJH!R|BstMJx~9YG;9+a4t?;EVRM=>F>yjbJ zXrZB6u%<0@IBvN70P;0&MwL?%+}vR2oOOd9x9ndC#|5%zXoH{WHuLhs9k!6wGyCCi zazG-C0Dq@e;%)U26r{RA!@dM`XA=j;YHs%PZ4SVk;SEIkhSjCdoO>&V&7mR4lW0F; z)bE(O_izM!5e-tz`IxH9r=CX|oan>uPKwsCF|?*0pS5a=A3t|ry^k2cFqye)zgyuH zg>CT5m#qt71i=m*U#=pl?(+tg`;z~W-o31fqCSUBQxH$|9d;w#3;_tOflhAF=7R7m zjJAw#Rj|ACM+=7~kB7Me`4vKm3&Yk@HZSE|`d~3|=nTlg>ig|Ph6E=xA~g!yNJmAv z|L}F!Mq%iPV*(C}`#~bjk7*PQIo1}QusOj6esRD@oZ|54&hAuO)RT^@rhY*euIJEM ziU^bAa_FARj0k1Acu(%sV2(c@{K~1~REBGBy*LW{_bNO9{hhwJw=6N_A5oL=YX zkbEo(8OKA!DgV!nqUQ69FlLey$T}1j|53wEq*=#CTk~ z@qNTRmzv_r6QDwz#z5 z+m00JhqdX&V-W$TtV64=rmi5bO^QX_kE5dvB!j3cvm#=L=yj<;yCU&ZMxtln^ItL1lPQYM<{ zGXEnc8U9wdgf~pPVqI4PCBx6K)UdfmfSV?7ry*pa79Fo%?J?!y;fMeT(gmdTsLn!c zSAgADn#auoOc*}r(9ovIHs)%GZLVI>HjA9zP5xw5z~rY zWB5pVqy>_E)0*C&Rm!!H7*~VM^z29WojU(NYe1_`n@jEKe+I+Xu5mv^r=CyUI+bQ` zc!Z%#UCIBP{GD;b()``)vf<_tRaowY$Zzfw6@pq?zmnHp?=9@I zShp3HfKl-FHI0K8QxkoM`yZXN)Y=?_)#^69!(QQ2+4~3A*8Go<%Co|*O8^;4hK=rr z%PY<1avB5SImXz^gdua+oog74ls9?7DSRjHNqmLxrB5%%=I^M*TnXRVFK+O+y_0?{ zD|l*1obPZ6!6bO29?x_|ZiAI92^e1uY-!Dc^%q}=8hbF=Apa=*1Vp|yIYL@Ks3oNK zJGjIhFVpwV>djj;w^DizTq@Y2>tJ|u!nsF&Fs2i}3Q)OMaQNA@cB*j;bdp|mb;F)5 z7T8469lOQ#=-b8lrSg zMZya&rmjaW>19{9nj$v`-!gg<-sJB*v%wOxjz3N|W<|B%|8+KE&i(2|c#_NTHE@Z{Uuo9cPnJ80Z&|!_DaGK{d9RMG z$w)!Zm>2W9hQR$vJ$UP%ASYtpnH_`U@H+f4Hb0YX-r8>q=gDy=@lC=`Bd@>J9&L1V z!R9US^I;pdqPbjX!Otc5+j+70YgeTe(g_x-dDeJB(Bo}T7x?zWL9fMsmqSe0VN95) zFMihxU8QgLy)qiYo=W_*a4*o{P zNq7ym^GtWkWBLWb7}!@j))#)B9f_BXLjXqy8w7_fo}3%)W}@CXBEU5e(Rpf=5e6yik@9d`6X(zJj)@Y0~SWFhc zFCfjlV^FeeSkf#Bfj&akk6#v4x8R(u*+w3+Xx+|=*Y1{AXpiZ=k; z)AQtv^V`S9-_n<1*q@zP@$2e&cjurfL%D36!P$of8-KA-ZT%hG4%<%!l4saEtFI=_G#zXN>RjQV4r(w)>3%bZNnae@)?s# zYUHlq*Y14GK))AuNz`suHP-0uTljPK-NC20#2)%^m2OXUI;6`K2md=g$1&h8>okf0 zI_NKOR&DtKsRUZ^pFqm+y72g?cgEoKB(an0jE5R^UpAQh`J^`nb4sR;W)yVSwG}o+ zlLHaz*_P*d6{q(B^~RAMi@>s+jsP8s)B0$8)-Qtjf8A_~rK(SX`t?1hHRf8@@pcm# z(KjT6zMdBK#ihq1Z%kS(KMW_Q)Yt6f*tX~OLiu3N;LK%Nw~We?{x@Wu#TOKIO%(gdw3ys~5;SKP<3vi4W0sZ@ zyk|=?4;2_;jz@Pvr7lmWel+5fc&-fNK-!g2!4kZClVisg;N?tuGl|E#@;twn4NHny zsm;+Nn#X|V*+BFPozy_w)nt|R#9XVSBaQgoNvK=|`O$W{E$_73rMAU~O;=GUwNnd7 zD*Q5wd(H+fpg9W~>g#P$zh@FGE?ZfU*$lp2AzC^S6j%<4uvTY4QumI%9~S4kVA}-m zY-5$Run@OJW{`7mGWD&iUq1;*cOW)hzM#!y5h6*lNS|5cC;1MBOybuqvda3dundjp zPIafu>xluJy9&1k-+r|FR={3zg%3@198Cl6BMeO-fyf*1xT0YDFqmL*I}f2;G+VwX zLEvf_H0AxkWWPDBhc*V>b$ABo5y+M3=m$j!UMiMM4oPO}G#k63IR|OWvMn+;eYsXe z+j=aT97np3h2yT3)7<1T>Fyq;4)+Old2|~cc6|`EU4?O?d*vT~sI{jdSJrJpc{g|} z9{p6OUT{jE6QUWo(GO?i6G%1^+$|h$#HDslY8i{XsG;Nt>J(+jPvQ*RER#zy8-q-* zEy|;CXcI;%@Sa~EXX}Mk^1z%T@`j^XIONz(z&q%rWfFn&GqWmhobXvgRyA>>;Rb`m_D_;cO{uMde8whB{A%-h!;z*>P z=2$cq9(IkWmeYZ-m?t6%**6j^^t@!b#hpI!U?L6)zWVd&klJmD87Bmu&13TL$$ zd)Jy1VSKP=v@UmNXqHoed3UMoUF%wHQZXY0AUg&1fbs6AJcd6sn zmOxkmW*o4iK5g(V{J8i@VOMXyiu}a!*F8Xc>VK{U>uQ6)D@W(0vi6JnzuX7Bm`snU%)8|@>lMO)Q$D$Vo#u-H z{*2TW(_4GAXuk``(4|ngqd=*z;i!NS8PUF=>2&+-uNe*dI1&Fc%o-KQFLGnsXRm#UetarxY>+<`<^Ry-k}@UhR$col z_5FbJstUsQfwb3=9H=<{tJk`|i=Go$Hipxr9U&eg|>6m_T z*()3GYTKsZ;6?rYUm>TYeJVGob1+HhJJRD=9a-`2$$b+vAWCt+E>a3_oBgT&&hSOO zqYnZJWDtpy9H@6s{KRi1`wd&vL!uK^hk@zytD-U^c}^T_NsSPW70k&MqgW z-h{8~80Vpm`}r{3Fl1%_}pg$Nx5G^M&yU=`)rMAP2|zrH*} zP61eVWMcf9R~4NCi}CHoUx5E&+*v>$4M0z=|JGo?Z$6b|)E)ywk)|QQ|H6=1l0?zg z@Q=~>5%P#RCZvYun_!8^>>-_=7-e~mJOrbk>vy3gG!@^u66#a$VZbj%N2WZWb21{; z;lOh2=VI>3GD3BdxGM$R0^#;*YPYEy2v{?YeZchYCOX+?G;QL3vP_N0n7W39rS&C} zmUW?8miv}^BF_ank|t$Pg{xJVtD>elBYwXuaIqF zcvkyWv3cfN)*uQjJzt;{w0#_pnFRwxOo=zi!RB&wUHQ`eX^tyF)DR>G@XuS9#oeHC$+QUQf>p$dFAp5; zuaaGF{z&nHs2$M9%okRmbSz)KIASTeCdqPnOhB2GWC4K1xAP-p6BEf zvoFdqHh~0dFP~hihBl^jRfH$0Qzq-&K7dxK%AQ#IIu?kS5z4}g@vMo_s!9|<0m#e> z#T5}leJ^Z$rZXGPd33j|DN_#dUv5EDSxHb_a?__W8`Nm0OnjN8mJ!#%ctbI7vH4RfG$E7K-MripWuhmOBsA3g?C)YY z6@JU+npqXAdNU@>ZaIvhnrK}+`GyHj$*!`VpK z#i#oI%BQBu5B#GF?V>SzkcheS{Fya1@_F$s{@q84E!Gl-(CZt?f5tvivPu3%mXR1z z)fB+uhVVb_9BVl{3&rAJn&SLjudG3eyN4YG=&Lj1UDEPd8H~6wpe%5k1Jj&BIWr0F zJ!>&=DGvFP_$2vid%&!uD1`-;xiOu0;m(KEY1o-x=kHEh zQ>K5K3Ww9QfH`c!L7Pq^gfXJT+f9a?5vp~ra@F!szm^g9;$`N_z+ z8_B2-8#NX}by>Wm761abO>GN5O$F-telN^Fad{wvnGu)#5DJxe+tw#Xk%3kyiix~% zJ@MpRb2yQ8L?AF~e_@0;I?~|uG*octF7nqm*fhjM`ltzL# z>uLup*p%*nB0gy>4A6wbu3@Kh0zxTYtT^AZaxL02Mz6UXMFf;M^^1UtSYQN@?k?rs zw?gSeFu-;=S)fPtzqGL1ptPoT49V9OwU*_ipprSR@sXWnImplPuvngX8YT|676saW zLF4h9*(dJz_?X#6%8+QU_zI%{$Ag}*IW*p9Eb6y-Dz#$sOQJs`i&00ET^JqdrG)Bv zWRy1`4_h$5HRoOa`2{Fl+EeP+iVQkt&SG!#1`!!A*8Z~nC;=O0oM|t54Aqx$Z zk+6tff4G0P@{ED2&qPNk{CBZ^uMt*5R`x(EX1H`NFu^%GscxGvODBJZVqsQmC(A0k%Kcr`xQ(`smM z0@c`Xy3(Sr?i@5*bcL*h$j2dhYg1kkZBQ<*^lvs-2}F|tw&4u@#FFmmo7EjV`tTBU z(^~$jP2trvM<0RP-OLlpfnjFQmd)%Ul#6fN>U?Z3fpUrqoRe)!M?VTM*pK~?*H6%m zW6)7XudhU5b7kPj+mi!elO#02HYd1madW>bObeTTWq#0iDb24`iD?YA%67y%W_X_J z`K_<)ZU%cd;;&j3Vo*P1(VNjX?VbIN`A^WRcAkA>UK%&*h>JFrqK - + diff --git a/app/scripts/background.js b/app/scripts/background.js index cbacd952f..f3ed3dc3a 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -7,9 +7,8 @@ import pump from 'pump'; import debounce from 'debounce-stream'; import log from 'loglevel'; import browser from 'webextension-polyfill'; -import { storeAsStream, storeTransformStream } from '@metamask/obs-store'; +import { storeAsStream } from '@metamask/obs-store'; import PortStream from 'extension-port-stream'; -import { captureException } from '@sentry/browser'; import { ethErrors } from 'eth-rpc-errors'; import { @@ -289,16 +288,11 @@ async function loadStateFromPersistence() { if (!versionedData) { throw new Error('MetaMask - migrator returned undefined'); } + // this initializes the meta/version data as a class variable to be used for future writes + localStore.setMetadata(versionedData.meta); // write to disk - if (localStore.isSupported) { - localStore.set(versionedData); - } else { - // throw in setTimeout so as to not block boot - setTimeout(() => { - throw new Error('MetaMask - Localstore not supported'); - }); - } + localStore.set(versionedData.data); // return just the data return versionedData.data; @@ -338,6 +332,7 @@ function setupController(initState, initLangCode, remoteSourcePort) { getOpenMetamaskTabsIds: () => { return openMetamaskTabsIDs; }, + localStore, }); setupEnsIpfsResolver({ @@ -354,8 +349,7 @@ function setupController(initState, initLangCode, remoteSourcePort) { pump( storeAsStream(controller.store), debounce(1000), - storeTransformStream(versionifyData), - createStreamSink(persistData), + createStreamSink((state) => localStore.set(state)), (error) => { log.error('MetaMask - Persistence pipeline failed', error); }, @@ -363,43 +357,6 @@ function setupController(initState, initLangCode, remoteSourcePort) { setupSentryGetStateGlobal(controller); - /** - * Assigns the given state to the versioned object (with metadata), and returns that. - * - * @param {object} state - The state object as emitted by the MetaMaskController. - * @returns {VersionedData} The state object wrapped in an object that includes a metadata key. - */ - function versionifyData(state) { - versionedData.data = state; - return versionedData; - } - - let dataPersistenceFailing = false; - - async function persistData(state) { - if (!state) { - throw new Error('MetaMask - updated state is missing'); - } - if (!state.data) { - throw new Error('MetaMask - updated state does not have data'); - } - if (localStore.isSupported) { - try { - await localStore.set(state); - if (dataPersistenceFailing) { - dataPersistenceFailing = false; - } - } catch (err) { - // log error so we dont break the pipeline - if (!dataPersistenceFailing) { - dataPersistenceFailing = true; - captureException(err); - } - log.error('error setting state in local store:', err); - } - } - } - // // connect to other contexts // diff --git a/app/scripts/controllers/metametrics.js b/app/scripts/controllers/metametrics.js index d771c5319..212b9a908 100644 --- a/app/scripts/controllers/metametrics.js +++ b/app/scripts/controllers/metametrics.js @@ -18,6 +18,9 @@ import { TRAITS, } from '../../../shared/constants/metametrics'; import { SECOND } from '../../../shared/constants/time'; +import { isManifestV3 } from '../../../shared/modules/mv3.utils'; +import { METAMETRICS_FINALIZE_EVENT_FRAGMENT_ALARM } from '../../../shared/constants/alarms'; +import { checkAlarmExists } from '../lib/util'; const EXTENSION_UNINSTALL_URL = 'https://metamask.io/uninstalled'; @@ -62,7 +65,7 @@ const exceptionsToFilter = { export default class MetaMetricsController { /** * @param {object} options - * @param {object} options.segment - an instance of analytics-node for tracking + * @param {object} options.segment - an instance of analytics for tracking * events that conform to the new MetaMetrics tracking plan. * @param {object} options.preferencesStore - The preferences controller store, used * to access and subscribe to preferences that will be attached to events @@ -144,16 +147,49 @@ export default class MetaMetricsController { // within the fragment's timeout window. When creating a new event fragment // a timeout can be specified that will cause an abandoned event to be // tracked if the event isn't progressed within that amount of time. - setInterval(() => { - Object.values(this.store.getState().fragments).forEach((fragment) => { - if ( - fragment.timeout && - Date.now() - fragment.lastUpdated / 1000 > fragment.timeout - ) { - this.finalizeEventFragment(fragment.id, { abandoned: true }); + if (isManifestV3) { + /* eslint-disable no-undef */ + chrome.alarms.getAll((alarms) => { + const hasAlarm = checkAlarmExists( + alarms, + METAMETRICS_FINALIZE_EVENT_FRAGMENT_ALARM, + ); + + if (!hasAlarm) { + chrome.alarms.create(METAMETRICS_FINALIZE_EVENT_FRAGMENT_ALARM, { + delayInMinutes: 1, + periodInMinutes: 1, + }); } }); - }, SECOND * 30); + chrome.alarms.onAlarm.addListener(() => { + chrome.alarms.getAll((alarms) => { + const hasAlarm = checkAlarmExists( + alarms, + METAMETRICS_FINALIZE_EVENT_FRAGMENT_ALARM, + ); + + if (hasAlarm) { + this.finalizeAbandonedFragments(); + } + }); + }); + } else { + setInterval(() => { + this.finalizeAbandonedFragments(); + }, SECOND * 30); + } + } + + finalizeAbandonedFragments() { + Object.values(this.store.getState().fragments).forEach((fragment) => { + if ( + fragment.timeout && + Date.now() - fragment.lastUpdated / 1000 > fragment.timeout + ) { + this.finalizeEventFragment(fragment.id, { abandoned: true }); + } + }); } generateMetaMetricsId() { @@ -678,7 +714,7 @@ export default class MetaMetricsController { ).length, [TRAITS.NUMBER_OF_TOKENS]: this._getNumberOfTokens(metamaskState), [TRAITS.OPENSEA_API_ENABLED]: metamaskState.openSeaEnabled, - [TRAITS.THREE_BOX_ENABLED]: metamaskState.threeBoxSyncingAllowed, + [TRAITS.THREE_BOX_ENABLED]: false, // deprecated, hard-coded as false [TRAITS.THEME]: metamaskState.theme || 'default', [TRAITS.TOKEN_DETECTION_ENABLED]: metamaskState.useTokenDetection, }; diff --git a/app/scripts/controllers/metametrics.test.js b/app/scripts/controllers/metametrics.test.js index 77fa34e54..1925da7a9 100644 --- a/app/scripts/controllers/metametrics.test.js +++ b/app/scripts/controllers/metametrics.test.js @@ -675,7 +675,6 @@ describe('MetaMetricsController', function () { identities: [{}, {}], ledgerTransportType: 'web-hid', openSeaEnabled: true, - threeBoxSyncingAllowed: false, useCollectibleDetection: false, theme: 'default', useTokenDetection: true, @@ -714,7 +713,6 @@ describe('MetaMetricsController', function () { ledgerTransportType: 'web-hid', openSeaEnabled: true, identities: [{}, {}], - threeBoxSyncingAllowed: false, useCollectibleDetection: false, theme: 'default', useTokenDetection: true, @@ -735,7 +733,6 @@ describe('MetaMetricsController', function () { ledgerTransportType: 'web-hid', openSeaEnabled: false, identities: [{}, {}, {}], - threeBoxSyncingAllowed: false, useCollectibleDetection: false, theme: 'default', useTokenDetection: true, @@ -764,7 +761,6 @@ describe('MetaMetricsController', function () { ledgerTransportType: 'web-hid', openSeaEnabled: true, identities: [{}, {}], - threeBoxSyncingAllowed: false, useCollectibleDetection: true, theme: 'default', useTokenDetection: true, @@ -783,7 +779,6 @@ describe('MetaMetricsController', function () { ledgerTransportType: 'web-hid', openSeaEnabled: true, identities: [{}, {}], - threeBoxSyncingAllowed: false, useCollectibleDetection: true, theme: 'default', useTokenDetection: true, diff --git a/app/scripts/controllers/threebox.js b/app/scripts/controllers/threebox.js deleted file mode 100644 index 6af4b9711..000000000 --- a/app/scripts/controllers/threebox.js +++ /dev/null @@ -1,305 +0,0 @@ -import { ObservableStore } from '@metamask/obs-store'; - -/* eslint-disable import/first,import/order */ -const Box = process.env.IN_TEST - ? require('../../../development/mock-3box') - : require('3box'); -/* eslint-enable import/order */ - -import log from 'loglevel'; -import { JsonRpcEngine } from 'json-rpc-engine'; -import { providerFromEngine } from 'eth-json-rpc-middleware'; -import Migrator from '../lib/migrator'; -import migrations from '../migrations'; -import createOriginMiddleware from '../lib/createOriginMiddleware'; -import createMetamaskMiddleware from './network/createMetamaskMiddleware'; -/* eslint-enable import/first */ - -const SYNC_TIMEOUT = 60 * 1000; // one minute - -export default class ThreeBoxController { - constructor(opts = {}) { - const { - preferencesController, - keyringController, - addressBookController, - version, - getKeyringControllerState, - trackMetaMetricsEvent, - } = opts; - - this.preferencesController = preferencesController; - this.addressBookController = addressBookController; - this.keyringController = keyringController; - this.provider = this._createProvider({ - version, - getAccounts: async ({ origin }) => { - if (origin !== '3Box') { - return []; - } - const { isUnlocked } = getKeyringControllerState(); - - const accounts = await this.keyringController.getAccounts(); - - if (isUnlocked && accounts[0]) { - const appKeyAddress = await this.keyringController.getAppKeyAddress( - accounts[0], - 'wallet://3box.metamask.io', - ); - return [appKeyAddress]; - } - return []; - }, - processPersonalMessage: async (msgParams) => { - const accounts = await this.keyringController.getAccounts(); - return keyringController.signPersonalMessage( - { ...msgParams, from: accounts[0] }, - { - withAppKeyOrigin: 'wallet://3box.metamask.io', - }, - ); - }, - }); - this._trackMetaMetricsEvent = trackMetaMetricsEvent; - - const initState = { - threeBoxSyncingAllowed: false, - showRestorePrompt: true, - threeBoxLastUpdated: 0, - ...opts.initState, - threeBoxAddress: null, - threeBoxSynced: false, - threeBoxDisabled: false, - }; - this.store = new ObservableStore(initState); - this.registeringUpdates = false; - this.lastMigration = migrations - .sort((a, b) => a.version - b.version) - .slice(-1)[0]; - - if (initState.threeBoxSyncingAllowed) { - this.init(); - } - } - - async init() { - const accounts = await this.keyringController.getAccounts(); - this.address = accounts[0]; - - this._trackMetaMetricsEvent({ - event: '3Box Initiated', - category: '3Box', - }); - - if (this.address && !(this.box && this.store.getState().threeBoxSynced)) { - await this.new3Box(); - } - } - - async _update3Box() { - try { - const { threeBoxSyncingAllowed, threeBoxSynced } = this.store.getState(); - if (threeBoxSyncingAllowed && threeBoxSynced) { - const newState = { - preferences: this.preferencesController.store.getState(), - addressBook: this.addressBookController.state, - lastUpdated: Date.now(), - lastMigration: this.lastMigration, - }; - - await this.space.private.set( - 'metamaskBackup', - JSON.stringify(newState), - ); - await this.setShowRestorePromptToFalse(); - } - } catch (error) { - console.error(error); - } - } - - _createProvider(providerOpts) { - const metamaskMiddleware = createMetamaskMiddleware(providerOpts); - const engine = new JsonRpcEngine(); - engine.push(createOriginMiddleware({ origin: '3Box' })); - engine.push(metamaskMiddleware); - const provider = providerFromEngine(engine); - return provider; - } - - _waitForOnSyncDone() { - return new Promise((resolve) => { - this.box.onSyncDone(() => { - log.debug('3Box box sync done'); - return resolve(); - }); - }); - } - - async new3Box() { - const accounts = await this.keyringController.getAccounts(); - this.address = await this.keyringController.getAppKeyAddress( - accounts[0], - 'wallet://3box.metamask.io', - ); - let backupExists; - try { - const threeBoxConfig = await Box.getConfig(this.address); - backupExists = threeBoxConfig.spaces && threeBoxConfig.spaces.metamask; - } catch (e) { - if (e.message.match(/^Error: Invalid response \(404\)/u)) { - this._trackMetaMetricsEvent({ - event: '3Box Backup does not exist', - category: '3Box', - }); - - backupExists = false; - } else { - this._trackMetaMetricsEvent({ - event: '3Box Config Error', - category: '3Box', - }); - - throw e; - } - } - if (this.getThreeBoxSyncingState() || backupExists) { - this.store.updateState({ threeBoxSynced: false }); - - let timedOut = false; - const syncTimeout = setTimeout(() => { - log.error(`3Box sync timed out after ${SYNC_TIMEOUT} ms`); - timedOut = true; - this.store.updateState({ - threeBoxDisabled: true, - threeBoxSyncingAllowed: false, - }); - }, SYNC_TIMEOUT); - try { - this.box = await Box.openBox(this.address, this.provider); - await this._waitForOnSyncDone(); - this.space = await this.box.openSpace('metamask', { - onSyncDone: async () => { - const stateUpdate = { - threeBoxSynced: true, - threeBoxAddress: this.address, - }; - if (timedOut) { - log.info(`3Box sync completed after timeout; no longer disabled`); - stateUpdate.threeBoxDisabled = false; - } - - clearTimeout(syncTimeout); - this.store.updateState(stateUpdate); - - log.debug('3Box space sync done'); - - this._trackMetaMetricsEvent({ - event: '3Box Synced', - category: '3Box', - }); - }, - }); - } catch (e) { - this._trackMetaMetricsEvent({ - event: '3Box Initiation Error', - category: '3Box', - }); - - console.error(e); - throw e; - } - } - } - - async getLastUpdated() { - const res = await this.space.private.get('metamaskBackup'); - const parsedRes = JSON.parse(res || '{}'); - return parsedRes.lastUpdated; - } - - async migrateBackedUpState(backedUpState) { - const migrator = new Migrator({ migrations }); - const { preferences, addressBook } = JSON.parse(backedUpState); - const formattedStateBackup = { - PreferencesController: preferences, - AddressBookController: addressBook, - }; - const initialMigrationState = - migrator.generateInitialState(formattedStateBackup); - const migratedState = await migrator.migrateData(initialMigrationState); - return { - preferences: migratedState.data.PreferencesController, - addressBook: migratedState.data.AddressBookController, - }; - } - - async restoreFromThreeBox() { - const backedUpState = await this.space.private.get('metamaskBackup'); - const { preferences, addressBook } = await this.migrateBackedUpState( - backedUpState, - ); - this.store.updateState({ threeBoxLastUpdated: backedUpState.lastUpdated }); - preferences && this.preferencesController.store.updateState(preferences); - addressBook && this.addressBookController.update(addressBook, true); - this.setShowRestorePromptToFalse(); - - this._trackMetaMetricsEvent({ - event: '3Box Restored Data', - category: '3Box', - }); - } - - turnThreeBoxSyncingOn() { - this._trackMetaMetricsEvent({ - event: '3Box Sync Turned On', - category: '3Box', - }); - - this._registerUpdates(); - } - - turnThreeBoxSyncingOff() { - this._trackMetaMetricsEvent({ - event: '3Box Sync Turned Off', - category: '3Box', - }); - - this.box.logout(); - } - - setShowRestorePromptToFalse() { - this.store.updateState({ showRestorePrompt: false }); - } - - setThreeBoxSyncingPermission(newThreeboxSyncingState) { - if (this.store.getState().threeBoxDisabled) { - return; - } - this.store.updateState({ - threeBoxSyncingAllowed: newThreeboxSyncingState, - }); - - if (newThreeboxSyncingState && this.box) { - this.turnThreeBoxSyncingOn(); - } - - if (!newThreeboxSyncingState && this.box) { - this.turnThreeBoxSyncingOff(); - } - } - - getThreeBoxSyncingState() { - return this.store.getState().threeBoxSyncingAllowed; - } - - _registerUpdates() { - if (!this.registeringUpdates) { - const updatePreferences = this._update3Box.bind(this); - this.preferencesController.store.subscribe(updatePreferences); - const updateAddressBook = this._update3Box.bind(this); - this.addressBookController.subscribe(updateAddressBook); - this.registeringUpdates = true; - } - } -} diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index cd4c8c1a0..5becce48b 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -161,7 +161,6 @@ export default class TransactionController extends EventEmitter { getNetwork: this.getNetwork.bind(this), getCurrentChainId: opts.getCurrentChainId, }); - this._onBootCleanUp(); this.store = this.txStateManager.store; this.nonceTracker = new NonceTracker({ @@ -208,6 +207,7 @@ export default class TransactionController extends EventEmitter { // request state update to finalize initialization this._updatePendingTxsAfterFirstBlock(); + this._onBootCleanUp(); } /** diff --git a/app/scripts/lib/createMetaRPCHandler.js b/app/scripts/lib/createMetaRPCHandler.js index d89156f86..f55319783 100644 --- a/app/scripts/lib/createMetaRPCHandler.js +++ b/app/scripts/lib/createMetaRPCHandler.js @@ -1,6 +1,7 @@ import { ethErrors, serializeError } from 'eth-rpc-errors'; +import { isManifestV3 } from '../../../shared/modules/mv3.utils'; -const createMetaRPCHandler = (api, outStream) => { +const createMetaRPCHandler = (api, outStream, store, localStoreApiWrapper) => { return async (data) => { if (outStream._writableState.ended) { return; @@ -22,6 +23,10 @@ const createMetaRPCHandler = (api, outStream) => { result = await api[data.method](...data.params); } catch (err) { error = err; + } finally { + if (isManifestV3 && store && data.method !== 'getState') { + localStoreApiWrapper.set(store.getState()); + } } if (outStream._writableState.ended) { diff --git a/app/scripts/lib/get-first-preferred-lang-code.js b/app/scripts/lib/get-first-preferred-lang-code.js index a47cdc2ac..040697136 100644 --- a/app/scripts/lib/get-first-preferred-lang-code.js +++ b/app/scripts/lib/get-first-preferred-lang-code.js @@ -1,8 +1,10 @@ import browser from 'webextension-polyfill'; import allLocales from '../../_locales/index.json'; +// ensure that we default users with browser language code 'zh' to the supported 'zh_CN' language code +const existingLocaleCodes = { zh: 'zh_CN' }; + // mapping some browsers return hyphen instead underscore in locale codes (e.g. zh_TW -> zh-tw) -const existingLocaleCodes = {}; allLocales.forEach((locale) => { if (locale && locale.code) { existingLocaleCodes[locale.code.toLowerCase().replace('_', '-')] = diff --git a/app/scripts/lib/local-store.js b/app/scripts/lib/local-store.js index 069853e12..707fb1122 100644 --- a/app/scripts/lib/local-store.js +++ b/app/scripts/lib/local-store.js @@ -1,5 +1,6 @@ import browser from 'webextension-polyfill'; import log from 'loglevel'; +import { captureException } from '@sentry/browser'; import { checkForError } from './util'; /** @@ -11,6 +12,45 @@ export default class ExtensionStore { if (!this.isSupported) { log.error('Storage local API not available.'); } + // we use this flag to avoid flooding sentry with a ton of errors: + // once data persistence fails once and it flips true we don't send further + // data persistence errors to sentry + this.dataPersistenceFailing = false; + } + + setMetadata(initMetaData) { + this.metadata = initMetaData; + } + + async set(state) { + if (!this.isSupported) { + throw new Error( + 'Metamask- cannot persist state to local store as this browser does not support this action', + ); + } + if (!state) { + throw new Error('MetaMask - updated state is missing'); + } + if (!this.metadata) { + throw new Error( + 'MetaMask - metadata must be set on instance of ExtensionStore before calling "set"', + ); + } + try { + // we format the data for storage as an object with the "data" key for the controller state object + // and the "meta" key for a metadata object containing a version number that tracks how the data shape + // has changed using migrations to adapt to backwards incompatible changes + await this._set({ data: state, meta: this.metadata }); + if (this.dataPersistenceFailing) { + this.dataPersistenceFailing = false; + } + } catch (err) { + if (!this.dataPersistenceFailing) { + this.dataPersistenceFailing = true; + captureException(err); + } + log.error('error setting state in local store:', err); + } } /** @@ -31,16 +71,6 @@ export default class ExtensionStore { return result; } - /** - * Sets the key in local state - * - * @param {object} state - The state to set - * @returns {Promise} - */ - async set(state) { - return this._set(state); - } - /** * Returns all of the keys currently saved * diff --git a/app/scripts/lib/local-store.test.js b/app/scripts/lib/local-store.test.js new file mode 100644 index 000000000..2c3cea405 --- /dev/null +++ b/app/scripts/lib/local-store.test.js @@ -0,0 +1,79 @@ +import browser from 'webextension-polyfill'; +import LocalStore from './local-store'; + +jest.mock('webextension-polyfill', () => ({ + storage: { local: true }, +})); + +const setup = ({ isSupported }) => { + browser.storage.local = isSupported; + return new LocalStore(); +}; +describe('LocalStore', () => { + afterEach(() => { + jest.resetModules(); + }); + describe('contructor', () => { + it('should set isSupported property to false when browser does not support local storage', () => { + const localStore = setup({ isSupported: false }); + + expect(localStore.isSupported).toBe(false); + }); + + it('should set isSupported property to true when browser supports local storage', () => { + const localStore = setup({ isSupported: true }); + expect(localStore.isSupported).toBe(true); + }); + }); + + describe('setMetadata', () => { + it('should set the metadata property on LocalStore', () => { + const metadata = { version: 74 }; + const localStore = setup({ isSupported: true }); + localStore.setMetadata(metadata); + + expect(localStore.metadata).toStrictEqual(metadata); + }); + }); + + describe('set', () => { + it('should throw an error if called in a browser that does not support local storage', async () => { + const localStore = setup({ isSupported: false }); + await expect(() => localStore.set()).rejects.toThrow( + 'Metamask- cannot persist state to local store as this browser does not support this action', + ); + }); + + it('should throw an error if not passed a truthy value as an argument', async () => { + const localStore = setup({ isSupported: true }); + await expect(() => localStore.set()).rejects.toThrow( + 'MetaMask - updated state is missing', + ); + }); + + it('should throw an error if passed a valid argument but metadata has not yet been set', async () => { + const localStore = setup({ isSupported: true }); + await expect(() => + localStore.set({ appState: { test: true } }), + ).rejects.toThrow( + 'MetaMask - metadata must be set on instance of ExtensionStore before calling "set"', + ); + }); + + it('should not throw if passed a valid argument and metadata has been set', async () => { + const localStore = setup({ isSupported: true }); + localStore.setMetadata({ version: 74 }); + await expect(async function () { + localStore.set({ appState: { test: true } }); + }).not.toThrow(); + }); + }); + + describe('get', () => { + it('should return undefined if called in a browser that does not support local storage', async () => { + const localStore = setup({ isSupported: false }); + const result = await localStore.get(); + expect(result).toStrictEqual(undefined); + }); + }); +}); diff --git a/app/scripts/lib/network-store.js b/app/scripts/lib/network-store.js index abee778c1..ea6ba5876 100644 --- a/app/scripts/lib/network-store.js +++ b/app/scripts/lib/network-store.js @@ -50,16 +50,37 @@ export default class ReadOnlyNetworkStore { return this._state; } + /** + * Set metadata/version state + * + * @param {object} metadata - The metadata/version data to set + */ + setMetadata(metadata) { + this.metadata = metadata; + } + /** * Set state * * @param {object} state - The state to set - * @returns {Promise} */ async set(state) { + if (!this.isSupported) { + throw new Error( + 'Metamask- cannot persist state to local store as this browser does not support this action', + ); + } + if (!state) { + throw new Error('MetaMask - updated state is missing'); + } + if (!this.metadata) { + throw new Error( + 'MetaMask - metadata must be set on instance of ExtensionStore before calling "set"', + ); + } if (!this._initialized) { await this._initializing; } - this._state = state; + this._state = { data: state, meta: this._metadata }; } } diff --git a/app/scripts/lib/segment/analytics.js b/app/scripts/lib/segment/analytics.js new file mode 100644 index 000000000..c93275f94 --- /dev/null +++ b/app/scripts/lib/segment/analytics.js @@ -0,0 +1,275 @@ +import removeSlash from 'remove-trailing-slash'; +import looselyValidate from '@segment/loosely-validate-event'; +import { isString } from 'lodash'; +import isRetryAllowed from 'is-retry-allowed'; + +const noop = () => ({}); + +// Taken from https://stackoverflow.com/a/1349426/3696652 +const characters = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; +const generateRandomId = () => { + let result = ''; + const charactersLength = characters.length; + for (let i = 0; i < 20; i++) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + return result; +}; + +// Method below is inspired from axios-retry https://github.com/softonic/axios-retry +function isNetworkError(error) { + return ( + !error.response && + Boolean(error.code) && // Prevents retrying cancelled requests + error.code !== 'ECONNABORTED' && // Prevents retrying timed out requests + isRetryAllowed(error) + ); // Prevents retrying unsafe errors +} + +export default class Analytics { + /** + * Initialize a new `Analytics` with Segment project's `writeKey` and an + * optional dictionary of `options`. + * + * @param {string} writeKey + * @param {object} [options] - (optional) + * @property {number} [flushAt] (default: 20) + * @property {number} [flushInterval] (default: 10000) + * @property {string} [host] (default: 'https://api.segment.io') + */ + constructor(writeKey, options = {}) { + this.writeKey = writeKey; + + this.host = removeSlash(options.host || 'https://api.segment.io'); + this.flushInterval = options.flushInterval || 10000; + this.flushAt = options.flushAt || Math.max(options.flushAt, 1) || 20; + + this.queue = []; + this.path = '/v1/batch'; + this.maxQueueSize = 1024 * 450; + this.flushed = false; + this.retryCount = 3; + + Object.defineProperty(this, 'enable', { + configurable: false, + writable: false, + enumerable: true, + value: true, + }); + } + + _validate(message, type) { + looselyValidate(message, type); + } + + _message(type, message, callback) { + this._validate(message, type); + this.enqueue(type, message, callback); + return this; + } + + /** + * Send an identify `message`. + * + * @param {object} message + * @param {Function} [callback] - (optional) + * @returns {Analytics} + */ + identify(message, callback) { + return this._message('identify', message, callback); + } + + /** + * Send a track `message`. + * + * @param {object} message + * @param {Function} [callback] - (optional) + * @returns {Analytics} + */ + track(message, callback) { + return this._message('track', message, callback); + } + + /** + * Send a page `message`. + * + * @param {object} message + * @param {Function} [callback] - (optional) + * @returns {Analytics} + */ + page(message, callback) { + return this._message('page', message, callback); + } + + /** + * Add a `message` of type `type` to the queue and + * check whether it should be flushed. + * + * @param {string} type + * @param {object} msg + * @param {Function} [callback] - (optional) + */ + enqueue(type, msg, callback = noop) { + if (!this.enable) { + setImmediate(callback); + return; + } + + const message = { ...msg, type }; + + // Specifying library here helps segment to understand structure of request. + // Currently segment seems to support these source libraries only. + message.context = { + ...message.context, + library: { + name: 'analytics-node', + }, + }; + + if (!message.timestamp) { + message.timestamp = new Date(); + } + + if (!message.messageId) { + message.messageId = generateRandomId(); + } + + if (message.anonymousId && !isString(message.anonymousId)) { + message.anonymousId = JSON.stringify(message.anonymousId); + } + if (message.userId && !isString(message.userId)) { + message.userId = JSON.stringify(message.userId); + } + this.queue.push({ message, callback }); + + if (!this.flushed) { + this.flushed = true; + this.flush(); + return; + } + + const hasReachedFlushAt = this.queue.length >= this.flushAt; + const hasReachedQueueSize = + this.queue.reduce((acc, item) => acc + JSON.stringify(item).length, 0) >= + this.maxQueueSize; + if (hasReachedFlushAt || hasReachedQueueSize) { + this.flush(); + } + + if (this.flushInterval && !this.timer) { + this.timer = setTimeout(this.flush.bind(this), this.flushInterval); + } + } + + /** + * Flush the current queue + * + * @param {Function} [callback] - (optional) + */ + flush(callback = noop) { + if (!this.enable) { + setImmediate(callback); + return Promise.resolve(); + } + + if (this.timer) { + clearTimeout(this.timer); + this.timer = null; + } + + if (!this.queue.length) { + setImmediate(callback); + return Promise.resolve(); + } + + const items = this.queue.splice(0, this.flushAt); + const callbacks = items.map((item) => item.callback); + const messages = items.map((item) => item.message); + + const data = { + batch: messages, + timestamp: new Date(), + sentAt: new Date(), + }; + + const done = (err) => { + setImmediate(() => { + callbacks.forEach((fn) => fn(err, data)); + callback(err, data); + }); + }; + + const headers = { + Authorization: `Basic ${Buffer.from(this.writeKey, 'utf8').toString( + 'base64', + )}`, + }; + + return this._sendRequest( + `${this.host}${this.path}`, + { + method: 'POST', + body: JSON.stringify(data), + headers, + }, + done, + 0, + ); + } + + _retryRequest(url, body, done, retryNo) { + const delay = Math.pow(2, retryNo) * 100; + setTimeout(() => { + this._sendRequest(url, body, done, retryNo + 1); + }, delay); + } + + async _sendRequest(url, body, done, retryNo) { + return fetch(url, body) + .then(async (response) => { + if (response.ok) { + done(); + } else if ( + this._isErrorRetryable({ response }) && + retryNo <= this.retryCount + ) { + this._retryRequest(url, body, done, retryNo); + } else { + const error = new Error(response.statusText); + done(error); + } + }) + .catch((error) => { + if (this._isErrorRetryable(error) && retryNo <= this.retryCount) { + this._retryRequest(url, body, done, retryNo); + } else { + done(error); + } + }); + } + + _isErrorRetryable(error) { + // Retry Network Errors. + if (isNetworkError(error)) { + return true; + } + + if (!error.response) { + // Cannot determine if the request can be retried + return false; + } + + // Retry Server Errors (5xx). + if (error.response.status >= 500 && error.response.status <= 599) { + return true; + } + + // Retry if rate limited. + if (error.response.status === 429) { + return true; + } + + return false; + } +} diff --git a/app/scripts/lib/segment/analytics.test.js b/app/scripts/lib/segment/analytics.test.js new file mode 100644 index 000000000..33844bb9f --- /dev/null +++ b/app/scripts/lib/segment/analytics.test.js @@ -0,0 +1,116 @@ +import Analytics from './analytics'; + +const DUMMY_KEY = 'DUMMY_KEY'; +const DUMMY_MESSAGE = { + userId: 'userId', + idValue: 'idValue', + event: 'event', +}; +const FLUSH_INTERVAL = 10000; + +global.setImmediate = (arg) => { + arg(); +}; + +global.fetch = () => + Promise.resolve({ + ok: true, + json: () => Promise.resolve({ success: true }), + }); + +describe('Analytics', function () { + let analytics; + + beforeEach(() => { + analytics = new Analytics(DUMMY_KEY); + }); + + describe('#flush', function () { + it('first message is immediately flushed', function () { + const mock = jest.fn(analytics.flush); + analytics.flush = mock; + analytics.track(DUMMY_MESSAGE); + expect(analytics.queue).toHaveLength(0); + expect(mock).toHaveBeenCalledTimes(1); + }); + + it('after first message it is called when queue size equals flushAt value', function () { + analytics = new Analytics(DUMMY_KEY, { flushAt: 3 }); + const mock = jest.fn(analytics.flush); + analytics.flush = mock; + analytics.track(DUMMY_MESSAGE); + analytics.track(DUMMY_MESSAGE); + analytics.track(DUMMY_MESSAGE); + analytics.track(DUMMY_MESSAGE); + expect(analytics.queue).toHaveLength(0); + expect(mock).toHaveBeenCalledTimes(2); + }); + + it('except for first message it is called until queue size is less than flushAt value', function () { + analytics = new Analytics(DUMMY_KEY, { flushAt: 3 }); + const mock = jest.fn(analytics.flush); + analytics.flush = mock; + analytics.track(DUMMY_MESSAGE); + analytics.track(DUMMY_MESSAGE); + analytics.track(DUMMY_MESSAGE); + expect(analytics.queue).toHaveLength(2); + expect(mock).toHaveBeenCalledTimes(1); + }); + + it('after first message it is called after flushInterval is elapsed', function () { + jest.useFakeTimers(); + analytics = new Analytics(DUMMY_KEY, { flushInterval: FLUSH_INTERVAL }); + const mock = jest.fn(analytics.flush); + analytics.flush = mock; + analytics.track(DUMMY_MESSAGE); + analytics.track(DUMMY_MESSAGE); + jest.advanceTimersByTime(FLUSH_INTERVAL); + expect(analytics.queue).toHaveLength(0); + expect(mock).toHaveBeenCalledTimes(2); + }); + + it('after first message it is not called until flushInterval is elapsed', function () { + jest.useFakeTimers(); + analytics = new Analytics(DUMMY_KEY, { flushInterval: FLUSH_INTERVAL }); + const mock = jest.fn(analytics.flush); + analytics.flush = mock; + analytics.track(DUMMY_MESSAGE); + analytics.track(DUMMY_MESSAGE); + jest.advanceTimersByTime(FLUSH_INTERVAL - 100); + expect(analytics.queue).toHaveLength(1); + expect(mock).toHaveBeenCalledTimes(1); + }); + + it('invokes callbacks', async function () { + const callback = jest.fn(); + analytics.track(DUMMY_MESSAGE); + analytics.track(DUMMY_MESSAGE, callback); + await analytics.flush(); + expect(callback).toHaveBeenCalledTimes(1); + }); + }); + + describe('#track', function () { + it('adds messages to ququq', function () { + analytics.track(DUMMY_MESSAGE); + analytics.track(DUMMY_MESSAGE); + expect(analytics.queue).toHaveLength(1); + }); + }); + + describe('#page', function () { + it('adds messages to ququq', function () { + analytics.page(DUMMY_MESSAGE); + analytics.page(DUMMY_MESSAGE); + expect(analytics.queue).toHaveLength(1); + }); + }); + + describe('#identify', function () { + it('adds messages to ququq', function () { + analytics.identify(DUMMY_MESSAGE); + analytics.identify(DUMMY_MESSAGE); + expect(analytics.queue).toHaveLength(1); + }); + }); +}); diff --git a/app/scripts/lib/segment.js b/app/scripts/lib/segment/index.js similarity index 96% rename from app/scripts/lib/segment.js rename to app/scripts/lib/segment/index.js index 1b054333b..99062b820 100644 --- a/app/scripts/lib/segment.js +++ b/app/scripts/lib/segment/index.js @@ -1,5 +1,5 @@ -import Analytics from 'analytics-node'; -import { SECOND } from '../../../shared/constants/time'; +import { SECOND } from '../../../../shared/constants/time'; +import Analytics from './analytics'; const SEGMENT_WRITE_KEY = process.env.SEGMENT_WRITE_KEY ?? null; const SEGMENT_HOST = process.env.SEGMENT_HOST ?? null; diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index 5ef0e68b4..73bad861c 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -53,11 +53,6 @@ export const SENTRY_STATE = { type: true, }, seedPhraseBackedUp: true, - showRestorePrompt: true, - threeBoxDisabled: true, - threeBoxLastUpdated: true, - threeBoxSynced: true, - threeBoxSyncingAllowed: true, unapprovedDecryptMsgCount: true, unapprovedEncryptionPublicKeyMsgCount: true, unapprovedMsgCount: true, @@ -226,7 +221,7 @@ function rewriteReportUrls(report) { } function toMetamaskUrl(origUrl) { - const filePath = origUrl.split(window.location.origin)[1]; + const filePath = origUrl.split(globalThis.location.origin)[1]; if (!filePath) { return origUrl; } diff --git a/app/scripts/lib/util.js b/app/scripts/lib/util.js index 2d454d4b5..6539e1f23 100644 --- a/app/scripts/lib/util.js +++ b/app/scripts/lib/util.js @@ -152,6 +152,17 @@ function getChainType(chainId) { return 'custom'; } +/** + * Checks if the alarmname exists in the list + * + * @param {Array} alarmList + * @param alarmName + * @returns + */ +function checkAlarmExists(alarmList, alarmName) { + return alarmList.some((alarm) => alarm.name === alarmName); +} + export { getPlatform, getEnvironmentType, @@ -161,4 +172,5 @@ export { addHexPrefix, bnToHex, getChainType, + checkAlarmExists, }; diff --git a/app/scripts/metamask-controller.actions.test.js b/app/scripts/metamask-controller.actions.test.js index c0e438c66..b3eff23d7 100644 --- a/app/scripts/metamask-controller.actions.test.js +++ b/app/scripts/metamask-controller.actions.test.js @@ -1,6 +1,11 @@ import { strict as assert } from 'assert'; import sinon from 'sinon'; import proxyquire from 'proxyquire'; + +import { + ApprovalRequestNotFoundError, + PermissionsRequestNotFoundError, +} from '@metamask/controllers'; import { ORIGIN_METAMASK } from '../../shared/constants/app'; const Ganache = require('../../test/e2e/ganache'); @@ -238,4 +243,137 @@ describe('MetaMaskController', function () { assert.deepEqual(transaction1, transaction2); }); }); + + describe('#removePermissionsFor', function () { + it('should not propagate PermissionsRequestNotFoundError', function () { + const error = new PermissionsRequestNotFoundError('123'); + metamaskController.permissionController = { + revokePermissions: () => { + throw error; + }, + }; + // Line below will not throw error, in case it throws this test case will fail. + metamaskController.removePermissionsFor({ subject: 'test_subject' }); + }); + + it('should propagate Error other than PermissionsRequestNotFoundError', function () { + const error = new Error(); + metamaskController.permissionController = { + revokePermissions: () => { + throw error; + }, + }; + assert.throws(() => { + metamaskController.removePermissionsFor({ subject: 'test_subject' }); + }, error); + }); + }); + + describe('#rejectPermissionsRequest', function () { + it('should not propagate PermissionsRequestNotFoundError', function () { + const error = new PermissionsRequestNotFoundError('123'); + metamaskController.permissionController = { + rejectPermissionsRequest: () => { + throw error; + }, + }; + // Line below will not throw error, in case it throws this test case will fail. + metamaskController.rejectPermissionsRequest('DUMMY_ID'); + }); + + it('should propagate Error other than PermissionsRequestNotFoundError', function () { + const error = new Error(); + metamaskController.permissionController = { + rejectPermissionsRequest: () => { + throw error; + }, + }; + assert.throws(() => { + metamaskController.rejectPermissionsRequest('DUMMY_ID'); + }, error); + }); + }); + + describe('#acceptPermissionsRequest', function () { + it('should not propagate PermissionsRequestNotFoundError', function () { + const error = new PermissionsRequestNotFoundError('123'); + metamaskController.permissionController = { + acceptPermissionsRequest: () => { + throw error; + }, + }; + // Line below will not throw error, in case it throws this test case will fail. + metamaskController.acceptPermissionsRequest('DUMMY_ID'); + }); + + it('should propagate Error other than PermissionsRequestNotFoundError', function () { + const error = new Error(); + metamaskController.permissionController = { + acceptPermissionsRequest: () => { + throw error; + }, + }; + assert.throws(() => { + metamaskController.acceptPermissionsRequest('DUMMY_ID'); + }, error); + }); + }); + + describe('#resolvePendingApproval', function () { + it('should not propagate ApprovalRequestNotFoundError', function () { + const error = new ApprovalRequestNotFoundError('123'); + metamaskController.approvalController = { + accept: () => { + throw error; + }, + }; + // Line below will not throw error, in case it throws this test case will fail. + metamaskController.resolvePendingApproval('DUMMY_ID', 'DUMMY_VALUE'); + }); + + it('should propagate Error other than ApprovalRequestNotFoundError', function () { + const error = new Error(); + metamaskController.approvalController = { + accept: () => { + throw error; + }, + }; + assert.throws(() => { + metamaskController.resolvePendingApproval('DUMMY_ID', 'DUMMY_VALUE'); + }, error); + }); + }); + + describe('#rejectPendingApproval', function () { + it('should not propagate ApprovalRequestNotFoundError', function () { + const error = new ApprovalRequestNotFoundError('123'); + metamaskController.approvalController = { + reject: () => { + throw error; + }, + }; + // Line below will not throw error, in case it throws this test case will fail. + metamaskController.rejectPendingApproval('DUMMY_ID', { + code: 1, + message: 'DUMMY_MESSAGE', + data: 'DUMMY_DATA', + }); + }); + + it('should propagate Error other than ApprovalRequestNotFoundError', function () { + const error = new Error(); + metamaskController.approvalController = { + reject: () => { + throw error; + }, + }; + assert.throws(() => { + metamaskController.rejectPendingApproval('DUMMY_ID', { + code: 1, + message: 'DUMMY_MESSAGE', + data: 'DUMMY_DATA', + }); + }, error); + }); + }); }); diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 904914fb5..546246d73 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -39,6 +39,8 @@ import { CollectibleDetectionController, PermissionController, SubjectMetadataController, + PermissionsRequestNotFoundError, + ApprovalRequestNotFoundError, ///: BEGIN:ONLY_INCLUDE_IN(flask) RateLimitController, NotificationController, @@ -123,7 +125,6 @@ import AppStateController from './controllers/app-state'; import CachedBalancesController from './controllers/cached-balances'; import AlertController from './controllers/alert'; import OnboardingController from './controllers/onboarding'; -import ThreeBoxController from './controllers/threebox'; import BackupController from './controllers/backup'; import IncomingTransactionsController from './controllers/incoming-transactions'; import MessageManager, { normalizeMsgData } from './lib/message-manager'; @@ -201,6 +202,9 @@ export default class MetamaskController extends EventEmitter { this.controllerMessenger = new ControllerMessenger(); + // instance of a class that wraps the extension's storage local API. + this.localStoreApiWrapper = opts.localStore; + // observable state store this.store = new ComposableObservableStore({ state: initState, @@ -247,7 +251,9 @@ export default class MetamaskController extends EventEmitter { this.tokenListController = new TokenListController({ chainId: hexToDecimal(this.networkController.getCurrentChainId()), - preventPollingOnNetworkRestart: true, + preventPollingOnNetworkRestart: initState.TokenListController + ? initState.TokenListController.preventPollingOnNetworkRestart + : true, onNetworkStateChange: (cb) => { this.networkController.store.subscribe((networkState) => { const modifiedNetworkState = { @@ -767,20 +773,6 @@ export default class MetamaskController extends EventEmitter { preferencesStore: this.preferencesController.store, }); - this.threeBoxController = new ThreeBoxController({ - preferencesController: this.preferencesController, - addressBookController: this.addressBookController, - keyringController: this.keyringController, - initState: initState.ThreeBoxController, - getKeyringControllerState: this.keyringController.memStore.getState.bind( - this.keyringController.memStore, - ), - version, - trackMetaMetricsEvent: this.metaMetricsController.trackEvent.bind( - this.metaMetricsController, - ), - }); - this.backupController = new BackupController({ preferencesController: this.preferencesController, addressBookController: this.addressBookController, @@ -1038,7 +1030,6 @@ export default class MetamaskController extends EventEmitter { PermissionController: this.permissionController, PermissionLogController: this.permissionLogController.store, SubjectMetadataController: this.subjectMetadataController, - ThreeBoxController: this.threeBoxController.store, BackupController: this.backupController, AnnouncementController: this.announcementController, GasFeeController: this.gasFeeController, @@ -1077,7 +1068,6 @@ export default class MetamaskController extends EventEmitter { PermissionController: this.permissionController, PermissionLogController: this.permissionLogController.store, SubjectMetadataController: this.subjectMetadataController, - ThreeBoxController: this.threeBoxController.store, BackupController: this.backupController, SwapsController: this.swapsController.store, EnsController: this.ensController.store, @@ -1493,7 +1483,6 @@ export default class MetamaskController extends EventEmitter { const { addressBookController, alertController, - approvalController, appStateController, collectiblesController, collectibleDetectionController, @@ -1510,7 +1499,6 @@ export default class MetamaskController extends EventEmitter { preferencesController, qrHardwareKeyring, swapsController, - threeBoxController, tokensController, smartTransactionsController, txController, @@ -1799,32 +1787,10 @@ export default class MetamaskController extends EventEmitter { setWeb3ShimUsageAlertDismissed: alertController.setWeb3ShimUsageAlertDismissed.bind(alertController), - // 3Box - setThreeBoxSyncingPermission: - threeBoxController.setThreeBoxSyncingPermission.bind( - threeBoxController, - ), - restoreFromThreeBox: - threeBoxController.restoreFromThreeBox.bind(threeBoxController), - setShowRestorePromptToFalse: - threeBoxController.setShowRestorePromptToFalse.bind(threeBoxController), - getThreeBoxLastUpdated: - threeBoxController.getLastUpdated.bind(threeBoxController), - turnThreeBoxSyncingOn: - threeBoxController.turnThreeBoxSyncingOn.bind(threeBoxController), - initializeThreeBox: this.initializeThreeBox.bind(this), - // permissions - removePermissionsFor: - permissionController.revokePermissions.bind(permissionController), - approvePermissionsRequest: - permissionController.acceptPermissionsRequest.bind( - permissionController, - ), - rejectPermissionsRequest: - permissionController.rejectPermissionsRequest.bind( - permissionController, - ), + removePermissionsFor: this.removePermissionsFor, + approvePermissionsRequest: this.acceptPermissionsRequest, + rejectPermissionsRequest: this.rejectPermissionsRequest, ...getPermissionBackgroundApiMethods(permissionController), ///: BEGIN:ONLY_INCLUDE_IN(flask) @@ -1942,14 +1908,8 @@ export default class MetamaskController extends EventEmitter { ), // approval controller - resolvePendingApproval: - approvalController.accept.bind(approvalController), - rejectPendingApproval: async (id, error) => { - approvalController.reject( - id, - new EthereumRpcError(error.code, error.message, error.data), - ); - }, + resolvePendingApproval: this.resolvePendingApproval, + rejectPendingApproval: this.rejectPendingApproval, // Notifications updateViewedNotifications: announcementController.updateViewed.bind( @@ -2139,6 +2099,11 @@ export default class MetamaskController extends EventEmitter { // clear permissions this.permissionController.clearState(); + ///: BEGIN:ONLY_INCLUDE_IN(flask) + // Clear snap state + this.snapController.clearState(); + ///: END:ONLY_INCLUDE_IN + // clear accounts in accountTracker this.accountTracker.clearAccounts(); @@ -2345,20 +2310,6 @@ export default class MetamaskController extends EventEmitter { log.error('Error while unlocking extension.', error); } - try { - const threeBoxSyncingAllowed = - this.threeBoxController.getThreeBoxSyncingState(); - if (threeBoxSyncingAllowed && !this.threeBoxController.box) { - // 'await' intentionally omitted to avoid waiting for initialization - this.threeBoxController.init(); - this.threeBoxController.turnThreeBoxSyncingOn(); - } else if (threeBoxSyncingAllowed && this.threeBoxController.box) { - this.threeBoxController.turnThreeBoxSyncingOn(); - } - } catch (error) { - log.error('Error while unlocking extension.', error); - } - // This must be set as soon as possible to communicate to the // keyring's iframe and have the setting initialized properly // Optimistically called to not block MetaMask login due to @@ -3484,7 +3435,15 @@ export default class MetamaskController extends EventEmitter { this.emit('controllerConnectionChanged', this.activeControllerConnections); // set up postStream transport - outStream.on('data', createMetaRPCHandler(api, outStream)); + outStream.on( + 'data', + createMetaRPCHandler( + api, + outStream, + this.store, + this.localStoreApiWrapper, + ), + ); const handleUpdate = (update) => { if (outStream._writableState.ended) { return; @@ -4226,10 +4185,6 @@ export default class MetamaskController extends EventEmitter { return null; } - async initializeThreeBox() { - await this.threeBoxController.init(); - } - /** * Sets the Ledger Live preference to use for Ledger hardware wallet support * @@ -4343,4 +4298,57 @@ export default class MetamaskController extends EventEmitter { return this.keyringController.setLocked(); } + + removePermissionsFor = (subjects) => { + try { + this.permissionController.revokePermissions(subjects); + } catch (exp) { + if (!(exp instanceof PermissionsRequestNotFoundError)) { + throw exp; + } + } + }; + + rejectPermissionsRequest = (requestId) => { + try { + this.permissionController.rejectPermissionsRequest(requestId); + } catch (exp) { + if (!(exp instanceof PermissionsRequestNotFoundError)) { + throw exp; + } + } + }; + + acceptPermissionsRequest = (request) => { + try { + this.permissionController.acceptPermissionsRequest(request); + } catch (exp) { + if (!(exp instanceof PermissionsRequestNotFoundError)) { + throw exp; + } + } + }; + + resolvePendingApproval = (id, value) => { + try { + this.approvalController.accept(id, value); + } catch (exp) { + if (!(exp instanceof ApprovalRequestNotFoundError)) { + throw exp; + } + } + }; + + rejectPendingApproval = (id, error) => { + try { + this.approvalController.reject( + id, + new EthereumRpcError(error.code, error.message, error.data), + ); + } catch (exp) { + if (!(exp instanceof ApprovalRequestNotFoundError)) { + throw exp; + } + } + }; } diff --git a/app/scripts/metamask-controller.test.js b/app/scripts/metamask-controller.test.js index 1baa0a39b..313d345ea 100644 --- a/app/scripts/metamask-controller.test.js +++ b/app/scripts/metamask-controller.test.js @@ -49,36 +49,6 @@ const firstTimeState = { const ganacheServer = new Ganache(); -const threeBoxSpies = { - _registerUpdates: sinon.spy(), - init: sinon.stub(), - getLastUpdated: sinon.stub(), - getThreeBoxSyncingState: sinon.stub().returns(true), - restoreFromThreeBox: sinon.stub(), - setShowRestorePromptToFalse: sinon.stub(), - setThreeBoxSyncingPermission: sinon.stub(), - turnThreeBoxSyncingOn: sinon.stub(), -}; - -class ThreeBoxControllerMock { - constructor() { - this._registerUpdates = threeBoxSpies._registerUpdates; - this.init = threeBoxSpies.init; - this.getLastUpdated = threeBoxSpies.getLastUpdated; - this.getThreeBoxSyncingState = threeBoxSpies.getThreeBoxSyncingState; - this.restoreFromThreeBox = threeBoxSpies.restoreFromThreeBox; - this.setShowRestorePromptToFalse = - threeBoxSpies.setShowRestorePromptToFalse; - this.setThreeBoxSyncingPermission = - threeBoxSpies.setThreeBoxSyncingPermission; - this.store = { - subscribe: () => undefined, - getState: () => ({}), - }; - this.turnThreeBoxSyncingOn = threeBoxSpies.turnThreeBoxSyncingOn; - } -} - const browserPolyfillMock = { runtime: { id: 'fake-extension-id', @@ -116,7 +86,6 @@ const createLoggerMiddlewareMock = () => (req, res, next) => { }; const MetaMaskController = proxyquire('./metamask-controller', { - './controllers/threebox': { default: ThreeBoxControllerMock }, './lib/createLoggerMiddleware': { default: createLoggerMiddlewareMock }, }).default; @@ -245,15 +214,10 @@ describe('MetaMaskController', function () { }); describe('submitPassword', function () { - const password = 'password'; - - beforeEach(async function () { + it('removes any identities that do not correspond to known accounts.', async function () { + const password = 'password'; await metamaskController.createNewVaultAndKeychain(password); - threeBoxSpies.init.reset(); - threeBoxSpies.turnThreeBoxSyncingOn.reset(); - }); - it('removes any identities that do not correspond to known accounts.', async function () { const fakeAddress = '0xbad0'; metamaskController.preferencesController.addAddresses([fakeAddress]); await metamaskController.submitPassword(password); @@ -278,23 +242,6 @@ describe('MetaMaskController', function () { ); }); }); - - it('gets the address from threebox and creates a new 3box instance', async function () { - await metamaskController.submitPassword(password); - assert(threeBoxSpies.init.calledOnce); - assert(threeBoxSpies.turnThreeBoxSyncingOn.calledOnce); - }); - - it('succeeds even if blockTracker or threeBoxController throw', async function () { - const throwErr = sinon.fake.throws('foo'); - metamaskController.blockTracker.checkForLatestBlock = throwErr; - metamaskController.threeBoxController.getThreeBoxSyncingState = throwErr; - await metamaskController.submitPassword(password); - assert.ok( - throwErr.calledTwice, - 'should have called checkForLatestBlock and getThreeBoxSyncingState', - ); - }); }); describe('#createNewVaultAndKeychain', function () { diff --git a/app/scripts/migrations/075.js b/app/scripts/migrations/075.js new file mode 100644 index 000000000..4ae6bb585 --- /dev/null +++ b/app/scripts/migrations/075.js @@ -0,0 +1,23 @@ +import { cloneDeep } from 'lodash'; + +const version = 75; + +/** + * Delete the ThreeBoxController. + */ +export default { + version, + async migrate(originalVersionedData) { + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; + return versionedData; + }, +}; + +function transformState(state) { + delete state.ThreeBoxController; + return state; +} diff --git a/app/scripts/migrations/075.test.js b/app/scripts/migrations/075.test.js new file mode 100644 index 000000000..fd270b8da --- /dev/null +++ b/app/scripts/migrations/075.test.js @@ -0,0 +1,63 @@ +import migration75 from './075'; + +describe('migration #75', () => { + it('should update the version metadata', async () => { + const oldStorage = { + meta: { + version: 74, + }, + data: {}, + }; + + const newStorage = await migration75.migrate(oldStorage); + expect(newStorage.meta).toStrictEqual({ + version: 75, + }); + }); + + it('should delete the ThreeBoxController', async () => { + const oldStorage = { + meta: { + version: 74, + }, + data: { + FooController: { a: 'b' }, + ThreeBoxController: { + stuff: 'stuff!', + moreStuff: { moreStuff: ['stuff', 'stuff', 'stuff'] }, + }, + }, + }; + + const newStorage = await migration75.migrate(oldStorage); + expect(newStorage).toStrictEqual({ + meta: { + version: 75, + }, + data: { + FooController: { a: 'b' }, + }, + }); + }); + + it('should handle missing ThreeBoxController', async () => { + const oldStorage = { + meta: { + version: 74, + }, + data: { + FooController: { a: 'b' }, + }, + }; + + const newStorage = await migration75.migrate(oldStorage); + expect(newStorage).toStrictEqual({ + meta: { + version: 75, + }, + data: { + FooController: { a: 'b' }, + }, + }); + }); +}); diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index 1fafb65bd..ab7c6b3d5 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -78,6 +78,7 @@ import m071 from './071'; import m072 from './072'; import m073 from './073'; import m074 from './074'; +import m075 from './075'; const migrations = [ m002, @@ -153,6 +154,7 @@ const migrations = [ m072, m073, m074, + m075, ]; export default migrations; diff --git a/app/scripts/ui.js b/app/scripts/ui.js index deb12f6c1..d9569f043 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -15,20 +15,28 @@ import launchMetaMaskUi, { updateBackgroundConnection } from '../../ui'; import { ENVIRONMENT_TYPE_FULLSCREEN, ENVIRONMENT_TYPE_POPUP, + PLATFORM_FIREFOX, } from '../../shared/constants/app'; import { isManifestV3 } from '../../shared/modules/mv3.utils'; import { SUPPORT_LINK } from '../../shared/lib/ui-utils'; import { getErrorHtml } from '../../shared/lib/error-utils'; import ExtensionPlatform from './platforms/extension'; import { setupMultiplex } from './lib/stream-utils'; -import { getEnvironmentType } from './lib/util'; +import { getEnvironmentType, getPlatform } from './lib/util'; import metaRPCClientFactory from './lib/metaRPCClientFactory'; const container = document.getElementById('app-content'); -const WORKER_KEEP_ALIVE_INTERVAL = 1000; +const ONE_SECOND_IN_MILLISECONDS = 1_000; + +const WORKER_KEEP_ALIVE_INTERVAL = ONE_SECOND_IN_MILLISECONDS; const WORKER_KEEP_ALIVE_MESSAGE = 'WORKER_KEEP_ALIVE_MESSAGE'; +// Timeout for initializing phishing warning page. +const PHISHING_WARNING_PAGE_TIMEOUT = ONE_SECOND_IN_MILLISECONDS; + +const PHISHING_WARNING_SW_STORAGE_KEY = 'phishing-warning-sw-registered'; + /* * As long as UI is open it will keep sending messages to service worker * In service worker as this message is received @@ -58,6 +66,7 @@ async function start() { const activeTab = await queryCurrentActiveTab(windowType); + let loadPhishingWarningPage; /** * In case of MV3 the issue of blank screen was very frequent, it is caused by UI initialising before background is ready to send state. * Code below ensures that UI is rendered only after background is ready. @@ -68,7 +77,7 @@ async function start() { * Code below ensures that UI is rendered only after CONNECTION_READY message is received thus background is ready. * In case the UI is already rendered, only update the streams. */ - const messageListener = (message) => { + const messageListener = async (message) => { if (message?.name === 'CONNECTION_READY') { if (isUIInitialised) { // Currently when service worker is revived we create new streams @@ -77,6 +86,98 @@ async function start() { } else { initializeUiWithTab(activeTab); } + await loadPhishingWarningPage(); + } + }; + + /** + * An error thrown if the phishing warning page takes too long to load. + */ + class PhishingWarningPageTimeoutError extends Error { + constructor() { + super('Timeout failed'); + } + } + + /** + * Load the phishing warning page temporarily to ensure the service + * worker has been registered, so that the warning page works offline. + */ + loadPhishingWarningPage = async function () { + const currentPlatform = getPlatform(); + + // Check session storage for whether we've already initalized the phishing warning + // service worker this browser session and do not attempt to re-initialize if so. + const phishingSWMemoryFetch = await browser.storage.session.get( + PHISHING_WARNING_SW_STORAGE_KEY, + ); + + if (phishingSWMemoryFetch[PHISHING_WARNING_SW_STORAGE_KEY]) { + return; + } + + let iframe; + try { + const extensionStartupPhishingPageUrl = new URL( + process.env.PHISHING_WARNING_PAGE_URL, + ); + // The `extensionStartup` hash signals to the phishing warning page that it should not bother + // setting up streams for user interaction. Otherwise this page load would cause a console + // error. + extensionStartupPhishingPageUrl.hash = '#extensionStartup'; + + iframe = window.document.createElement('iframe'); + iframe.setAttribute('src', extensionStartupPhishingPageUrl.href); + iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin'); + + // Create "deferred Promise" to allow passing resolve/reject to event handlers + let deferredResolve; + let deferredReject; + const loadComplete = new Promise((resolve, reject) => { + deferredResolve = resolve; + deferredReject = reject; + }); + + // The load event is emitted once loading has completed, even if the loading failed. + // If loading failed we can't do anything about it, so we don't need to check. + iframe.addEventListener('load', deferredResolve); + + // This step initiates the page loading. + window.document.body.appendChild(iframe); + + // This timeout ensures that this iframe gets cleaned up in a reasonable + // timeframe, and ensures that the "initialization complete" message + // doesn't get delayed too long. + setTimeout( + () => deferredReject(new PhishingWarningPageTimeoutError()), + PHISHING_WARNING_PAGE_TIMEOUT, + ); + await loadComplete; + // store a flag in sessions storage that we've already loaded the service worker + // and don't need to try again + if (currentPlatform === PLATFORM_FIREFOX) { + // Firefox does not yet support the storage.session API introduced in MV3 + // Tracked here: https://bugzilla.mozilla.org/show_bug.cgi?id=1687778 + console.error( + 'Firefox does not support required MV3 APIs: Phishing warning page iframe and service worker will reload each page refresh', + ); + } else { + browser.storage.session.set({ + [PHISHING_WARNING_SW_STORAGE_KEY]: true, + }); + } + } catch (error) { + if (error instanceof PhishingWarningPageTimeoutError) { + console.warn( + 'Phishing warning page timeout; page not guaranteed to work offline.', + ); + } else { + console.error('Failed to initialize phishing warning page', error); + } + } finally { + if (iframe) { + iframe.remove(); + } } }; diff --git a/development/generate-lavamoat-policies.js b/development/generate-lavamoat-policies.js index 4ac600636..a4004e0b8 100755 --- a/development/generate-lavamoat-policies.js +++ b/development/generate-lavamoat-policies.js @@ -11,7 +11,7 @@ start().catch((error) => { async function start() { const { - argv: { buildTypes, parallel }, + argv: { buildTypes, parallel, devMode }, } = yargs(hideBin(process.argv)).usage( '$0 [options]', 'Generate the LavaMoat policy file for one more more build types.', @@ -31,13 +31,22 @@ async function start() { description: 'Whether to generate policies in parallel.', type: 'boolean', }) + .option('devMode', { + alias: ['d'], + default: false, + demandOption: true, + description: + 'Whether to run the process under lavamoat (devMode=false) or node (devMode=true)', + type: 'boolean', + }) .strict(), ); + const buildCommand = devMode ? 'build:dev' : 'build'; await concurrently( (Array.isArray(buildTypes) ? buildTypes : [buildTypes]).map( (buildType) => ({ - command: `yarn build scripts:dist --policy-only --build-type=${buildType}`, + command: `yarn ${buildCommand} scripts:dist --policy-only --lint-fence-files=false --build-type=${buildType}`, env: { WRITE_AUTO_POLICY: 1, }, diff --git a/development/mock-3box.js b/development/mock-3box.js deleted file mode 100644 index ebbbe325d..000000000 --- a/development/mock-3box.js +++ /dev/null @@ -1,68 +0,0 @@ -function delay(time) { - return new Promise((resolve) => setTimeout(resolve, time)); -} - -async function loadFromMock3Box(key) { - const res = await window.fetch(`http://localhost:8889?key=${key}`); - const text = await res.text(); - return text.length ? JSON.parse(text) : null; -} - -async function saveToMock3Box(key, newDataAtKey) { - const res = await window.fetch('http://localhost:8889', { - method: 'POST', - body: JSON.stringify({ - key, - data: newDataAtKey, - }), - }); - - return res.text(); -} - -class Mock3Box { - static openBox(address) { - this.address = address; - return Promise.resolve({ - onSyncDone: (cb) => { - setTimeout(cb, 200); - }, - openSpace: async (spaceName, config) => { - const { onSyncDone } = config; - this.spaceName = spaceName; - - setTimeout(onSyncDone, 150); - - await delay(50); - - return { - private: { - get: async (key) => { - await delay(50); - const res = await loadFromMock3Box( - `${this.address}-${this.spaceName}-${key}`, - ); - return res; - }, - set: async (key, data) => { - await saveToMock3Box( - `${this.address}-${this.spaceName}-${key}`, - data, - ); - await delay(50); - return null; - }, - }, - }; - }, - logout: () => undefined, - }); - } - - static async getConfig(address) { - const backup = await loadFromMock3Box(`${address}-metamask-metamaskBackup`); - return backup ? { spaces: { metamask: {} } } : {}; - } -} - -module.exports = Mock3Box; diff --git a/development/ts-migration-dashboard/files-to-convert.json b/development/ts-migration-dashboard/files-to-convert.json index 69636584a..6cce4cb55 100644 --- a/development/ts-migration-dashboard/files-to-convert.json +++ b/development/ts-migration-dashboard/files-to-convert.json @@ -48,7 +48,6 @@ "app/scripts/controllers/preferences.test.js", "app/scripts/controllers/swaps.js", "app/scripts/controllers/swaps.test.js", - "app/scripts/controllers/threebox.js", "app/scripts/controllers/transactions/index.js", "app/scripts/controllers/transactions/index.test.js", "app/scripts/controllers/transactions/lib/tx-state-history-helpers.js", diff --git a/test/e2e/fixtures/README.md b/docs/generating-fixture-data.md similarity index 63% rename from test/e2e/fixtures/README.md rename to docs/generating-fixture-data.md index e8bbe39ac..77b90f3c2 100644 --- a/test/e2e/fixtures/README.md +++ b/docs/generating-fixture-data.md @@ -1,10 +1,3 @@ -# End-to-end tests - -This directory contains the fixture data used to bootstrap the individual e2e tests. Each sub-directory contains -one thing: - -1. A `state.json` file that represents a the saved state for the extension (see _Generating fixture data_ below) - ## Generating fixture data Fixture data can be generated by following these steps: diff --git a/jest.config.js b/jest.config.js index 38f289e50..bfaddcfa8 100644 --- a/jest.config.js +++ b/jest.config.js @@ -11,7 +11,7 @@ module.exports = { coverageThreshold: { global: { branches: 44, - functions: 42, + functions: 46, lines: 52, statements: 52, }, diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index df9ad3a1d..71e1e50d1 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -1,2194 +1,5 @@ { "resources": { - "3box": { - "globals": { - "console.error": true, - "console.log": true, - "console.warn": true, - "fetch": true, - "setTimeout": true - }, - "packages": { - "3box>3box-orbitdb-plugins": true, - "3box>3box-orbitdb-plugins>ipfs-log": true, - "3box>3id-resolver": true, - "3box>did-jwt": true, - "3box>ethers": true, - "3box>ethers>elliptic": true, - "3box>graphql-request": true, - "3box>https-did-resolver": true, - "3box>ipfs": true, - "3box>ipfs-did-document": true, - "3box>ipfs-mini": true, - "3box>ipfs>is-ipfs": true, - "3box>ipfs>multihashes": true, - "3box>js-sha256": true, - "3box>muport-did-resolver": true, - "3box>orbit-db": true, - "3box>orbit-db>orbit-db-access-controllers": true, - "3box>orbit-db>orbit-db-identity-provider": true, - "3box>orbit-db>orbit-db-pubsub": true, - "3box>store": true, - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, - "@babel/runtime": true, - "browserify>buffer": true, - "browserify>process": true, - "node-fetch": true - } - }, - "3box>3box-orbitdb-plugins": { - "globals": { - "console.log": true - }, - "packages": { - "3box>3box-orbitdb-plugins>ipfs-log": true, - "3box>3id-resolver>did-jwt": true, - "3box>3id-resolver>did-jwt>base64url": true, - "3box>did-jwt>did-resolver": true, - "3box>ipfs>is-ipfs": true, - "3box>orbit-db>orbit-db-access-controllers": true, - "3box>orbit-db>orbit-db-io": true, - "browserify>events": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>3box-orbitdb-plugins>ipfs-log": { - "globals": { - "clearTimeout": true, - "console.warn": true, - "setTimeout": true - }, - "packages": { - "3box>3box-orbitdb-plugins>ipfs-log>json-stringify-deterministic": true, - "3box>3box-orbitdb-plugins>ipfs-log>p-each-series": true, - "3box>3box-orbitdb-plugins>ipfs-log>p-map": true, - "3box>3box-orbitdb-plugins>ipfs-log>p-whilst": true, - "3box>orbit-db>orbit-db-io": true, - "browserify>buffer": true - } - }, - "3box>3id-resolver": { - "packages": { - "3box>3id-resolver>did-jwt": true, - "3box>3id-resolver>did-jwt>base64url": true, - "3box>did-jwt>did-resolver": true, - "3box>ipfs-did-document": true, - "@babel/runtime": true - } - }, - "3box>3id-resolver>did-jwt": { - "packages": { - "3box>3id-resolver>did-jwt>base64url": true, - "3box>did-jwt>did-resolver": true, - "3box>ethers>elliptic": true, - "3box>js-sha256": true, - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, - "@babel/runtime": true, - "browserify>buffer": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>3id-resolver>did-jwt>base64url": { - "packages": { - "browserify>buffer": true - } - }, - "3box>did-jwt": { - "packages": { - "3box>did-jwt>@stablelib/utf8": true, - "3box>did-jwt>did-resolver": true, - "3box>did-jwt>js-sha3": true, - "3box>did-jwt>uport-base64url": true, - "3box>ethers>elliptic": true, - "3box>js-sha256": true, - "3box>tweetnacl": true, - "browserify>buffer": true - } - }, - "3box>did-jwt>js-sha3": { - "globals": { - "define": true - }, - "packages": { - "browserify>process": true - } - }, - "3box>did-jwt>uport-base64url": { - "packages": { - "browserify>buffer": true - } - }, - "3box>ethers": { - "globals": { - "MessageChannel": true, - "XMLHttpRequest": true, - "atob": true, - "btoa": true, - "clearInterval": true, - "clearTimeout": true, - "console": true, - "crypto.getRandomValues": true, - "define": true, - "setInterval": true, - "setTimeout": true - } - }, - "3box>ethers>elliptic": { - "packages": { - "3box>ethers>elliptic>brorand": true, - "3box>ethers>elliptic>hmac-drbg": true, - "3box>ethers>elliptic>minimalistic-crypto-utils": true, - "3box>ethers>hash.js>minimalistic-assert": true, - "bn.js": true, - "ethers>@ethersproject/sha2>hash.js": true, - "pumpify>inherits": true - } - }, - "3box>ethers>elliptic>brorand": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, - "3box>ethers>elliptic>hmac-drbg": { - "packages": { - "3box>ethers>elliptic>minimalistic-crypto-utils": true, - "3box>ethers>hash.js>minimalistic-assert": true, - "ethers>@ethersproject/sha2>hash.js": true - } - }, - "3box>events": { - "globals": { - "console": true - } - }, - "3box>graphql-request": { - "globals": { - "fetch": true - }, - "packages": { - "3box>graphql-request>cross-fetch": true - } - }, - "3box>graphql-request>cross-fetch": { - "globals": { - "Blob": true, - "FileReader": true, - "FormData": true, - "URLSearchParams.prototype.isPrototypeOf": true, - "XMLHttpRequest": true - } - }, - "3box>graphql-request>cross-fetch>node-fetch": { - "globals": { - "fetch": true - } - }, - "3box>https-did-resolver": { - "globals": { - "XMLHttpRequest": true - }, - "packages": { - "3box>did-jwt>did-resolver": true, - "browserify>browser-resolve": true - } - }, - "3box>ipfs": { - "globals": { - "AbortController": true, - "clearInterval": true, - "clearTimeout": true, - "console.log": true, - "fetch": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>async-iterator-all": true, - "3box>ipfs>async-iterator-to-pull-stream": true, - "3box>ipfs>async-iterator-to-stream": true, - "3box>ipfs>base32.js": true, - "3box>ipfs>bignumber.js": true, - "3box>ipfs>callbackify": true, - "3box>ipfs>cids": true, - "3box>ipfs>class-is": true, - "3box>ipfs>datastore-core": true, - "3box>ipfs>datastore-pubsub": true, - "3box>ipfs>dlv": true, - "3box>ipfs>err-code": true, - "3box>ipfs>fnv1a": true, - "3box>ipfs>fsm-event": true, - "3box>ipfs>human-to-milliseconds": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>ipfs-bitswap": true, - "3box>ipfs>ipfs-block": true, - "3box>ipfs>ipfs-block-service": true, - "3box>ipfs>ipfs-mfs": true, - "3box>ipfs>ipfs-repo": true, - "3box>ipfs>ipfs-unixfs": true, - "3box>ipfs>ipfs-unixfs-exporter": true, - "3box>ipfs>ipfs-unixfs-importer": true, - "3box>ipfs>ipfs-utils": true, - "3box>ipfs>ipld": true, - "3box>ipfs>ipld-dag-cbor": true, - "3box>ipfs>ipld-dag-pb": true, - "3box>ipfs>ipld-raw": true, - "3box>ipfs>ipns": true, - "3box>ipfs>is-ipfs": true, - "3box>ipfs>is-pull-stream": true, - "3box>ipfs>iso-url": true, - "3box>ipfs>just-flatten-it": true, - "3box>ipfs>kind-of": true, - "3box>ipfs>libp2p": true, - "3box>ipfs>libp2p-bootstrap": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-kad-dht": true, - "3box>ipfs>libp2p-keychain": true, - "3box>ipfs>libp2p-record": true, - "3box>ipfs>libp2p-secio": true, - "3box>ipfs>libp2p-webrtc-star": true, - "3box>ipfs>libp2p-websocket-star-multi": true, - "3box>ipfs>libp2p-websockets": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>merge-options": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>multiaddr-to-uri": true, - "3box>ipfs>multibase": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async": true, - "3box>ipfs>peer-book": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>promisify-es6": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-cat": true, - "3box>ipfs>pull-defer": true, - "3box>ipfs>pull-mplex": true, - "3box>ipfs>pull-pushable": true, - "3box>ipfs>pull-sort": true, - "3box>ipfs>pull-stream": true, - "3box>ipfs>pull-stream-to-async-iterator": true, - "3box>ipfs>pull-stream-to-stream": true, - "3box>ipfs>pull-traverse": true, - "3box>ipfs>readable-stream": true, - "3box>ipfs>receptacle": true, - "3box>ipfs>stream-to-pull-stream": true, - "3box>ipfs>superstruct": true, - "3box>ipfs>varint": true, - "@metamask/providers>is-stream": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>insert-module-globals>is-buffer": true, - "browserify>timers-browserify": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs-mini": { - "globals": { - "XMLHttpRequest": true - } - }, - "3box>ipfs-postmsg-proxy>shortid": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "nanoid": true - } - }, - "3box>ipfs>async-iterator-to-pull-stream": { - "packages": { - "3box>ipfs>async-iterator-to-pull-stream>get-iterator": true, - "3box>ipfs>pull-stream-to-async-iterator": true - } - }, - "3box>ipfs>async-iterator-to-stream": { - "packages": { - "3box>ipfs>async-iterator-to-stream>readable-stream": true, - "browserify>process": true - } - }, - "3box>ipfs>async-iterator-to-stream>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>bignumber.js": { - "globals": { - "crypto": true, - "define": true - } - }, - "3box>ipfs>bl": { - "packages": { - "3box>ipfs>bl>readable-stream": true, - "browserify>buffer": true, - "browserify>util": true - } - }, - "3box>ipfs>bl>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>bs58": { - "packages": { - "3box>ipfs>bs58>base-x": true - } - }, - "3box>ipfs>bs58>base-x": { - "packages": { - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>ipfs>cids": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>multibase": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>multihashes": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>datastore-core": { - "packages": { - "3box>ipfs>datastore-core>pull-many": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true, - "gh-pages>async": true - } - }, - "3box>ipfs>datastore-pubsub": { - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>multibase": true, - "browserify>assert": true, - "browserify>buffer": true, - "nock>debug": true - } - }, - "3box>ipfs>dlv": { - "globals": { - "define": true - } - }, - "3box>ipfs>fsm-event": { - "packages": { - "3box>ipfs>fsm-event>fsm": true, - "browserify>assert": true, - "browserify>events": true - } - }, - "3box>ipfs>human-to-milliseconds": { - "packages": { - "3box>ipfs>promisify-es6": true - } - }, - "3box>ipfs>interface-datastore": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>err-code": true, - "3box>ipfs>interface-datastore>uuid": true, - "3box>ipfs>pull-defer": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true, - "browserify>os-browserify": true, - "browserify>path-browserify": true, - "gh-pages>async": true - } - }, - "3box>ipfs>interface-datastore>uuid": { - "globals": { - "crypto": true, - "msCrypto": true - } - }, - "3box>ipfs>ipfs-bitswap": { - "globals": { - "clearInterval": true, - "clearTimeout": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>ipfs-bitswap>bignumber.js": true, - "3box>ipfs>ipfs-bitswap>just-debounce-it": true, - "3box>ipfs>ipfs-bitswap>lodash.isequalwith": true, - "3box>ipfs>ipfs-bitswap>moving-average": true, - "3box>ipfs>ipfs-bitswap>multihashing-async": true, - "3box>ipfs>ipfs-bitswap>varint-decoder": true, - "3box>ipfs>ipfs-block": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-stream": true, - "browserify>assert": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>ipfs-bitswap>bignumber.js": { - "globals": { - "crypto": true, - "define": true - } - }, - "3box>ipfs>ipfs-bitswap>just-debounce-it": { - "globals": { - "clearTimeout": true, - "setTimeout": true - } - }, - "3box>ipfs>ipfs-bitswap>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>ipfs-bitswap>varint-decoder": { - "packages": { - "3box>ipfs>varint": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipfs-block": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>class-is": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipfs-block-service": { - "packages": { - "gh-pages>async": true - } - }, - "3box>ipfs>ipfs-mfs": { - "globals": { - "Blob": true, - "FileReader": true - }, - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>err-code": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>ipfs-mfs>async-iterator-last": true, - "3box>ipfs>ipfs-mfs>hamt-sharding": true, - "3box>ipfs>ipfs-mfs>mortice": true, - "3box>ipfs>ipfs-unixfs": true, - "3box>ipfs>ipfs-unixfs-exporter": true, - "3box>ipfs>ipfs-unixfs-importer": true, - "3box>ipfs>ipld-dag-pb": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>multihashes": true, - "3box>ipfs>promisify-es6": true, - "browserify>assert": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "nock>debug": true - } - }, - "3box>ipfs>ipfs-mfs>hamt-sharding": { - "packages": { - "3box>ipfs>ipfs-mfs>hamt-sharding>sparse-array": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipfs-mfs>mortice": { - "globals": { - "Worker": true - }, - "packages": { - "3box>ipfs-postmsg-proxy>shortid": true, - "3box>ipfs>ipfs-mfs>mortice>observable-webworkers": true, - "3box>ipfs>ipfs-mfs>mortice>promise-timeout": true, - "3box>ipfs>libp2p-kad-dht>p-queue": true, - "browserify>browser-resolve": true, - "browserify>events": true, - "browserify>process": true - } - }, - "3box>ipfs>ipfs-mfs>mortice>promise-timeout": { - "globals": { - "clearTimeout": true, - "setTimeout": true - } - }, - "3box>ipfs>ipfs-repo": { - "packages": { - "3box>ipfs>base32.js": true, - "3box>ipfs>cids": true, - "3box>ipfs>datastore-core": true, - "3box>ipfs>dlv": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>ipfs-block": true, - "3box>ipfs>ipfs-repo>bignumber.js": true, - "3box>ipfs>ipfs-repo>datastore-level": true, - "3box>ipfs>ipfs-repo>sort-keys": true, - "3box>ipfs>just-safe-set": true, - "3box>ipfs>pull-stream": true, - "browserify>assert": true, - "browserify>buffer": true, - "browserify>path-browserify": true, - "browserify>timers-browserify": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>ipfs-repo>bignumber.js": { - "globals": { - "crypto": true, - "define": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level": { - "packages": { - "3box>ipfs>interface-datastore": true, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down": true, - "3box>ipfs>ipfs-repo>datastore-level>level-js": true, - "3box>ipfs>pull-stream": true, - "3box>orbit-db>orbit-db-keystore>levelup": true, - "browserify>buffer": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down": { - "packages": { - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>abstract-leveldown": true, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>level-codec": true, - "3box>orbit-db>orbit-db-keystore>levelup>level-errors": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>abstract-leveldown": { - "packages": { - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>abstract-leveldown>level-supports": true, - "3box>orbit-db>orbit-db-cache>level-js>immediate": true, - "browserify>buffer": true, - "watchify>xtend": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>abstract-leveldown>level-supports": { - "packages": { - "watchify>xtend": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>level-codec": { - "packages": { - "browserify>buffer": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>level-js": { - "globals": { - "IDBKeyRange.bound": true, - "IDBKeyRange.lowerBound": true, - "IDBKeyRange.only": true, - "IDBKeyRange.upperBound": true, - "indexedDB.deleteDatabase": true, - "indexedDB.open": true - }, - "packages": { - "3box>ipfs>ipfs-repo>datastore-level>level-js>abstract-leveldown": true, - "3box>ipfs>ipfs-repo>datastore-level>level-js>idb-readable-stream": true, - "3box>orbit-db>orbit-db-cache>level-js>ltgt": true, - "browserify>buffer": true, - "browserify>process": true, - "browserify>stream-browserify": true, - "browserify>util": true, - "watchify>xtend": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>level-js>abstract-leveldown": { - "packages": { - "browserify>insert-module-globals>is-buffer": true, - "browserify>process": true, - "watchify>xtend": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>level-js>idb-readable-stream": { - "globals": { - "IDBKeyRange.bound": true, - "IDBKeyRange.lowerBound": true, - "IDBKeyRange.upperBound": true - }, - "packages": { - "browserify>stream-browserify": true, - "watchify>xtend": true - } - }, - "3box>ipfs>ipfs-repo>sort-keys": { - "packages": { - "geckodriver>got>is-plain-obj": true - } - }, - "3box>ipfs>ipfs-unixfs": { - "packages": { - "3box>ipfs>protons": true - } - }, - "3box>ipfs>ipfs-unixfs-exporter": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>err-code": true, - "3box>ipfs>ipfs-mfs>async-iterator-last": true, - "3box>ipfs>ipfs-mfs>hamt-sharding": true, - "3box>ipfs>ipfs-unixfs": true, - "3box>ipfs>ipfs-unixfs-importer": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipfs-unixfs-importer": { - "packages": { - "3box>ipfs>async-iterator-all": true, - "3box>ipfs>bl": true, - "3box>ipfs>err-code": true, - "3box>ipfs>ipfs-mfs>hamt-sharding": true, - "3box>ipfs>ipfs-unixfs": true, - "3box>ipfs>ipfs-unixfs-importer>async-iterator-batch": true, - "3box>ipfs>ipfs-unixfs-importer>async-iterator-first": true, - "3box>ipfs>ipfs-unixfs-importer>rabin-wasm": true, - "3box>ipfs>ipfs-unixfs-importer>superstruct": true, - "3box>ipfs>ipld-dag-pb": true, - "3box>ipfs>ipld-raw>multihashing-async": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>multihashes": true, - "browserify>buffer": true, - "madge>rc>deep-extend": true - } - }, - "3box>ipfs>ipfs-unixfs-importer>rabin-wasm": { - "globals": { - "Blob": true, - "Response": true, - "WebAssembly": true - }, - "packages": { - "3box>ipfs>ipfs-unixfs-importer>rabin-wasm>assemblyscript": true - } - }, - "3box>ipfs>ipfs-unixfs-importer>rabin-wasm>assemblyscript": { - "globals": { - "WebAssembly.Instance": true, - "WebAssembly.Module": true, - "WebAssembly.instantiateStreaming": true, - "console.log": true - } - }, - "3box>ipfs>ipfs-utils": { - "globals": { - "FileReader": true - }, - "packages": { - "3box>ipfs>ipfs-utils>is-buffer": true, - "3box>ipfs>ipfs-utils>readable-stream": true, - "3box>ipfs>is-pull-stream": true, - "3box>ipfs>kind-of": true, - "@metamask/providers>is-stream": true - } - }, - "3box>ipfs>ipfs-utils>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>ipld": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>ipfs-block": true, - "3box>ipfs>ipld-dag-cbor": true, - "3box>ipfs>ipld-dag-pb": true, - "3box>ipfs>ipld-raw": true, - "3box>ipfs>ipld>typical": true, - "3box>ipfs>merge-options": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>promisify-es6": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipld-dag-cbor": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>ipld-dag-cbor>is-circular": true, - "3box>ipfs>ipld-raw>multihashing-async": true, - "3box>ipfs>multicodec": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true, - "eth-lattice-keyring>gridplus-sdk>borc": true - } - }, - "3box>ipfs>ipld-dag-pb": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>class-is": true, - "3box>ipfs>ipld-raw>multihashing-async": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>protons": true, - "@storybook/react>@storybook/store>stable": true, - "browserify>assert": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipld-raw": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>ipld-raw>multihashing-async": true, - "3box>ipfs>multicodec": true - } - }, - "3box>ipfs>ipld-raw>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>ipld-raw>multihashing-async>murmurhash3js-revisited": true, - "3box>ipfs>multihashes": true, - "browserify>buffer": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>ipld-raw>multihashing-async>murmurhash3js-revisited": { - "globals": { - "define": true - } - }, - "3box>ipfs>ipld>typical": { - "globals": { - "define": true - } - }, - "3box>ipfs>ipns": { - "packages": { - "3box>ipfs>interface-datastore": true, - "3box>ipfs>ipns>timestamp-nano": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>multihashes": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>protons": true, - "base32-encode": true, - "browserify>buffer": true, - "nock>debug": true - } - }, - "3box>ipfs>is-ipfs": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>cids": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>multibase": true, - "3box>ipfs>multihashes": true, - "browserify>buffer": true - } - }, - "3box>ipfs>iso-url": { - "globals": { - "URL": true, - "URLSearchParams": true, - "location": true - } - }, - "3box>ipfs>libp2p": { - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>fsm-event": true, - "3box>ipfs>libp2p-websockets": true, - "3box>ipfs>libp2p>libp2p-connection-manager": true, - "3box>ipfs>libp2p>libp2p-floodsub": true, - "3box>ipfs>libp2p>libp2p-ping": true, - "3box>ipfs>libp2p>libp2p-switch": true, - "3box>ipfs>libp2p>superstruct": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-book": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "browserify>events": true, - "browserify>insert-module-globals>is-buffer": true, - "browserify>process": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p-bootstrap": { - "globals": { - "clearInterval": true, - "setInterval": true - }, - "packages": { - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p-crypto": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>libp2p-crypto>asn1.js": true, - "3box>ipfs>libp2p-crypto>iso-random-stream": true, - "3box>ipfs>libp2p-crypto>libp2p-crypto-secp256k1": true, - "3box>ipfs>libp2p-crypto>multihashing-async": true, - "3box>ipfs>protons": true, - "3box>tweetnacl": true, - "browserify>buffer": true, - "ethereumjs-util>ethereum-cryptography>browserify-aes": true, - "gh-pages>async": true, - "mockttp>node-forge": true - } - }, - "3box>ipfs>libp2p-crypto>asn1.js": { - "packages": { - "3box>ethers>hash.js>minimalistic-assert": true, - "bn.js": true, - "browserify>buffer": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>libp2p-crypto>iso-random-stream": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p-crypto>libp2p-crypto-secp256k1": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>libp2p-crypto>libp2p-crypto-secp256k1>multihashing-async": true, - "eth-trezor-keyring>hdkey>secp256k1": true, - "gh-pages>async": true - } - }, - "3box>ipfs>libp2p-crypto>libp2p-crypto-secp256k1>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>libp2p-crypto>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>libp2p-kad-dht": { - "globals": { - "clearInterval": true, - "clearTimeout": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>base32.js": true, - "3box>ipfs>cids": true, - "3box>ipfs>err-code": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-kad-dht>hashlru": true, - "3box>ipfs>libp2p-kad-dht>heap": true, - "3box>ipfs>libp2p-kad-dht>k-bucket": true, - "3box>ipfs>libp2p-kad-dht>multihashing-async": true, - "3box>ipfs>libp2p-kad-dht>p-queue": true, - "3box>ipfs>libp2p-kad-dht>p-times": true, - "3box>ipfs>libp2p-kad-dht>xor-distance": true, - "3box>ipfs>libp2p-record": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>multihashes": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>promisify-es6": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-stream": true, - "3box>ipfs>pull-stream-to-async-iterator": true, - "3box>ipfs>varint": true, - "@metamask/controllers>abort-controller": true, - "browserify>assert": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>insert-module-globals>is-buffer": true, - "gh-pages>async": true, - "nock>debug": true, - "promise-to-callback": true - } - }, - "3box>ipfs>libp2p-kad-dht>heap": { - "globals": { - "define": true - } - }, - "3box>ipfs>libp2p-kad-dht>k-bucket": { - "packages": { - "browserify>events": true, - "ethereumjs-wallet>randombytes": true - } - }, - "3box>ipfs>libp2p-kad-dht>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>libp2p-kad-dht>p-queue": { - "globals": { - "clearInterval": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "mockttp>@httptoolkit/subscriptions-transport-ws>eventemitter3": true - } - }, - "3box>ipfs>libp2p-kad-dht>p-times": { - "packages": { - "3box>ipfs>libp2p-kad-dht>p-times>p-map": true - } - }, - "3box>ipfs>libp2p-kad-dht>xor-distance": { - "packages": { - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p-keychain": { - "globals": { - "setTimeout": true - }, - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-keychain>sanitize-filename": true, - "3box>ipfs>merge-options": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true, - "gh-pages>async": true, - "mockttp>node-forge": true - } - }, - "3box>ipfs>libp2p-keychain>sanitize-filename": { - "packages": { - "3box>ipfs>libp2p-keychain>sanitize-filename>truncate-utf8-bytes": true - } - }, - "3box>ipfs>libp2p-keychain>sanitize-filename>truncate-utf8-bytes": { - "packages": { - "3box>ipfs>libp2p-keychain>sanitize-filename>truncate-utf8-bytes>utf8-byte-length": true - } - }, - "3box>ipfs>libp2p-record": { - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>libp2p-record>buffer-split": true, - "3box>ipfs>libp2p-record>multihashing-async": true, - "3box>ipfs>protons": true, - "browserify>assert": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true, - "gh-pages>async": true - } - }, - "3box>ipfs>libp2p-record>buffer-split": { - "packages": { - "3box>ipfs>libp2p-record>buffer-split>buffer-indexof": true - } - }, - "3box>ipfs>libp2p-record>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>libp2p-secio": { - "packages": { - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-secio>multihashing-async": true, - "3box>ipfs>libp2p-secio>pull-handshake": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-defer": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-stream": true, - "browserify>assert": true, - "browserify>buffer": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p-secio>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>libp2p-secio>pull-handshake": { - "packages": { - "3box>ipfs>libp2p-secio>pull-handshake>pull-reader": true, - "3box>ipfs>pull-cat": true, - "3box>ipfs>pull-mplex>pull-pair": true, - "3box>ipfs>pull-pushable": true - } - }, - "3box>ipfs>libp2p-secio>pull-handshake>pull-reader": { - "globals": { - "cb": true, - "clearTimeout": true, - "setTimeout": true - }, - "packages": { - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p-secio>pull-length-prefixed": { - "packages": { - "3box>ipfs>libp2p-secio>pull-handshake>pull-reader": true, - "3box>ipfs>pull-pushable": true, - "3box>ipfs>varint": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>ipfs>libp2p-webrtc-star": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>libp2p-webrtc-star>simple-peer": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client": true, - "3box>ipfs>libp2p-webrtc-star>webrtcsupport": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>stream-to-pull-stream": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p-webrtc-star>simple-peer": { - "globals": { - "clearInterval": true, - "console.warn": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>simple-peer>get-browser-rtc": true, - "3box>ipfs>libp2p-webrtc-star>simple-peer>readable-stream": true, - "browserify>buffer": true, - "ethereumjs-wallet>randombytes": true, - "nock>debug": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>libp2p-webrtc-star>simple-peer>get-browser-rtc": { - "globals": { - "RTCIceCandidate": true, - "RTCPeerConnection": true, - "RTCSessionDescription": true, - "mozRTCIceCandidate": true, - "mozRTCPeerConnection": true, - "mozRTCSessionDescription": true, - "webkitRTCIceCandidate": true, - "webkitRTCPeerConnection": true, - "webkitRTCSessionDescription": true - } - }, - "3box>ipfs>libp2p-webrtc-star>simple-peer>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client": { - "globals": { - "clearTimeout": true, - "location": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>component-bind": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>debug": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>indexof": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>parseqs": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>parseuri": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>to-array": true, - "3box>ipfs>libp2p-webrtc-star>socket.io>has-binary2": true, - "mockttp>@httptoolkit/subscriptions-transport-ws>backo2": true, - "pubnub>superagent>component-emitter": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>debug": { - "globals": { - "chrome": true, - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>debug>ms": true, - "browserify>process": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client": { - "globals": { - "MozWebSocket": true, - "WebSocket": true, - "XDomainRequest": true, - "XMLHttpRequest": true, - "addEventListener": true, - "attachEvent": true, - "clearTimeout": true, - "document": true, - "location": true, - "navigator": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>component-inherit": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>debug": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>has-cors": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>yeast": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>indexof": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>parseqs": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>parseuri": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "pubnub>superagent>component-emitter": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>debug": { - "globals": { - "chrome": true, - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>debug>ms": true, - "browserify>process": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser": { - "globals": { - "FileReader": true, - "btoa": true, - "navigator": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser>after": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser>arraybuffer.slice": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser>blob": true, - "3box>ipfs>libp2p-webrtc-star>socket.io>engine.io>engine.io-parser>base64-arraybuffer": true, - "3box>ipfs>libp2p-webrtc-star>socket.io>has-binary2": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser>blob": { - "globals": { - "Blob": true, - "MSBlobBuilder": true, - "MozBlobBuilder": true, - "WebKitBlobBuilder": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>has-cors": { - "globals": { - "XMLHttpRequest": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser": { - "globals": { - "Blob": true, - "File": true, - "FileReader": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser>debug": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser>isarray": true, - "browserify>buffer": true, - "pubnub>superagent>component-emitter": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser>debug": { - "globals": { - "chrome": true, - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser>debug>ms": true, - "browserify>process": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io>has-binary2": { - "globals": { - "Blob": true, - "File": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io>has-binary2>isarray": true, - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p-webrtc-star>webrtcsupport": { - "globals": { - "AudioContext": true, - "MediaStream": true, - "RTCIceCandidate": true, - "RTCPeerConnection": true, - "RTCSessionDescription": true, - "document": true, - "location.protocol": true, - "mozRTCIceCandidate": true, - "mozRTCPeerConnection": true, - "mozRTCSessionDescription": true, - "navigator.getUserMedia": true, - "navigator.mozGetUserMedia": true, - "navigator.msGetUserMedia": true, - "navigator.userAgent.match": true, - "navigator.webkitGetUserMedia": true, - "webkitAudioContext": true, - "webkitMediaStream": true, - "webkitRTCPeerConnection": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi": { - "globals": { - "setTimeout": true - }, - "packages": { - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star": { - "globals": { - "console.error": true - }, - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client": true, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true, - "uuid": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream": { - "globals": { - "console.error": true - }, - "packages": { - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>data-queue": true, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>debug": true, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>uuid": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>data-queue": { - "packages": { - "browserify>events": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>debug": { - "globals": { - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "analytics-node>ms": true, - "browserify>process": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>uuid": { - "globals": { - "crypto": true, - "msCrypto": true - } - }, - "3box>ipfs>libp2p-websockets": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>libp2p-websockets>pull-ws": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>multiaddr-to-uri": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "browserify>os-browserify": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p-websockets>pull-ws": { - "globals": { - "WebSocket": true, - "location": true - }, - "packages": { - "3box>ipfs>libp2p-websockets>pull-ws>relative-url": true, - "browserify>browser-resolve": true, - "browserify>events": true, - "browserify>https-browserify": true, - "browserify>process": true, - "browserify>stream-http": true, - "browserify>timers-browserify": true, - "browserify>url": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>ipfs>libp2p-websockets>pull-ws>relative-url": { - "packages": { - "browserify>url": true - } - }, - "3box>ipfs>libp2p>libp2p-connection-manager": { - "packages": { - "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor": true, - "browserify>events": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor": { - "globals": { - "clearInterval": true, - "clearTimeout": true, - "document": true, - "performance": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor>debug": true, - "browserify>events": true, - "browserify>process": true, - "lodash": true - } - }, - "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor>debug": { - "globals": { - "chrome": true, - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor>debug>ms": true, - "browserify>process": true - } - }, - "3box>ipfs>libp2p>libp2p-floodsub": { - "packages": { - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub": true, - "3box>ipfs>pull-stream": true, - "browserify>assert": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>err-code": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub>time-cache": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-pushable": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>insert-module-globals>is-buffer": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub>time-cache": { - "packages": { - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub>time-cache>lodash.throttle": true - } - }, - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub>time-cache>lodash.throttle": { - "globals": { - "clearTimeout": true, - "setTimeout": true - } - }, - "3box>ipfs>libp2p>libp2p-ping": { - "packages": { - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-secio>pull-handshake": true, - "3box>ipfs>pull-stream": true, - "browserify>events": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p>libp2p-switch": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>err-code": true, - "3box>ipfs>fsm-event": true, - "3box>ipfs>ipfs-bitswap>moving-average": true, - "3box>ipfs>libp2p-kad-dht>hashlru": true, - "3box>ipfs>libp2p>libp2p-switch>bignumber.js": true, - "3box>ipfs>libp2p>libp2p-switch>libp2p-circuit": true, - "3box>ipfs>libp2p>libp2p-switch>libp2p-identify": true, - "3box>ipfs>libp2p>libp2p-switch>multistream-select": true, - "3box>ipfs>libp2p>libp2p-switch>retimer": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-stream": true, - "browserify>assert": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>bignumber.js": { - "globals": { - "crypto": true, - "define": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>libp2p-circuit": { - "packages": { - "3box>ipfs>libp2p-secio>pull-handshake": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-stream": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>libp2p-identify": { - "globals": { - "console.warn": true - }, - "packages": { - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>multistream-select": { - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>libp2p-secio>pull-handshake": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>libp2p>libp2p-switch>multistream-select>semver": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-stream": true, - "3box>ipfs>varint": true, - "browserify>assert": true, - "browserify>buffer": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>multistream-select>semver": { - "globals": { - "console": true - }, - "packages": { - "browserify>process": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>retimer": { - "globals": { - "clearTimeout": true, - "setTimeout": true - } - }, - "3box>ipfs>mafmt": { - "packages": { - "3box>ipfs>multiaddr": true - } - }, - "3box>ipfs>merge-options": { - "packages": { - "geckodriver>got>is-plain-obj": true - } - }, - "3box>ipfs>multiaddr": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>class-is": true, - "3box>ipfs>multiaddr>hi-base32": true, - "3box>ipfs>multiaddr>is-ip": true, - "3box>ipfs>varint": true, - "browserify>buffer": true, - "react-devtools>ip": true - } - }, - "3box>ipfs>multiaddr-to-uri": { - "packages": { - "3box>ipfs>multiaddr": true - } - }, - "3box>ipfs>multiaddr>hi-base32": { - "globals": { - "define": true - }, - "packages": { - "browserify>process": true - } - }, - "3box>ipfs>multiaddr>is-ip": { - "packages": { - "chromedriver>tcp-port-used>is2>ip-regex": true - } - }, - "3box>ipfs>multibase": { - "packages": { - "3box>ipfs>multibase>base-x": true, - "browserify>buffer": true - } - }, - "3box>ipfs>multibase>base-x": { - "packages": { - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>ipfs>multicodec": { - "packages": { - "3box>ipfs>varint": true, - "browserify>buffer": true - } - }, - "3box>ipfs>multihashes": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>varint": true, - "browserify>buffer": true - } - }, - "3box>ipfs>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>multihashing-async>murmurhash3js": { - "globals": { - "define": true - } - }, - "3box>ipfs>multihashing-async>nodeify": { - "globals": { - "setTimeout": true - }, - "packages": { - "3box>ipfs>multihashing-async>nodeify>is-promise": true, - "3box>ipfs>multihashing-async>nodeify>promise": true, - "browserify>process": true, - "browserify>timers-browserify": true - } - }, - "3box>ipfs>multihashing-async>nodeify>promise": { - "globals": { - "setImediate": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>multihashing-async>nodeify>is-promise": true, - "browserify>process": true - } - }, - "3box>ipfs>peer-book": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>peer-id": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>multihashes": true, - "browserify>assert": true, - "browserify>buffer": true, - "gh-pages>async": true - } - }, - "3box>ipfs>peer-info": { - "packages": { - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info>unique-by": true, - "browserify>assert": true - } - }, - "3box>ipfs>protons": { - "packages": { - "3box>ipfs>protons>protocol-buffers-schema": true, - "3box>ipfs>protons>signed-varint": true, - "3box>ipfs>varint": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>ipfs>protons>signed-varint": { - "packages": { - "3box>ipfs>varint": true - } - }, - "3box>ipfs>pull-mplex": { - "packages": { - "3box>ipfs>pull-abortable": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-mplex>looper": true, - "3box>ipfs>pull-mplex>pull-through": true, - "3box>ipfs>pull-pushable": true, - "3box>ipfs>pull-stream": true, - "3box>ipfs>varint": true, - "browserify>buffer": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>pull-mplex>interface-connection": { - "packages": { - "3box>ipfs>pull-defer": true - } - }, - "3box>ipfs>pull-mplex>pull-through": { - "packages": { - "3box>ipfs>stream-to-pull-stream>looper": true - } - }, - "3box>ipfs>pull-sort": { - "packages": { - "3box>ipfs>pull-defer": true, - "3box>ipfs>pull-stream": true - } - }, - "3box>ipfs>pull-stream": { - "globals": { - "console.log": true - } - }, - "3box>ipfs>pull-stream-to-async-iterator": { - "packages": { - "3box>ipfs>pull-stream": true - } - }, - "3box>ipfs>pull-stream-to-stream": { - "packages": { - "browserify>process": true, - "browserify>stream-browserify": true, - "browserify>timers-browserify": true - } - }, - "3box>ipfs>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>receptacle": { - "globals": { - "clearTimeout": true, - "setTimeout": true - }, - "packages": { - "analytics-node>ms": true - } - }, - "3box>ipfs>stream-to-pull-stream": { - "globals": { - "console.error": true - }, - "packages": { - "3box>ipfs>pull-stream": true, - "3box>ipfs>stream-to-pull-stream>looper": true, - "browserify>process": true - } - }, - "3box>js-sha256": { - "globals": { - "define": true - }, - "packages": { - "browserify>process": true - } - }, - "3box>muport-did-resolver": { - "packages": { - "3box>did-jwt>did-resolver": true, - "@babel/runtime": true, - "node-fetch": true - } - }, - "3box>orbit-db": { - "globals": { - "console.log": true - }, - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>multihashes": true, - "3box>orbit-db>ipfs-pubsub-1on1": true, - "3box>orbit-db>logplease": true, - "3box>orbit-db>orbit-db-access-controllers": true, - "3box>orbit-db>orbit-db-cache": true, - "3box>orbit-db>orbit-db-counterstore": true, - "3box>orbit-db>orbit-db-docstore": true, - "3box>orbit-db>orbit-db-eventstore": true, - "3box>orbit-db>orbit-db-feedstore": true, - "3box>orbit-db>orbit-db-identity-provider": true, - "3box>orbit-db>orbit-db-io": true, - "3box>orbit-db>orbit-db-keystore": true, - "3box>orbit-db>orbit-db-kvstore": true, - "3box>orbit-db>orbit-db-pubsub": true, - "browserify>path-browserify": true - } - }, - "3box>orbit-db>ipfs-pubsub-1on1": { - "globals": { - "clearInterval": true, - "setInterval": true - }, - "packages": { - "3box>orbit-db>ipfs-pubsub-1on1>safe-buffer": true, - "browserify>events": true, - "browserify>path-browserify": true - } - }, - "3box>orbit-db>ipfs-pubsub-1on1>safe-buffer": { - "packages": { - "browserify>buffer": true - } - }, - "3box>orbit-db>logplease": { - "globals": { - "LOG": true, - "console.error": true, - "console.log": true - }, - "packages": { - "browserify>browser-resolve": true, - "browserify>events": true, - "browserify>process": true, - "browserify>util": true - } - }, - "3box>orbit-db>orbit-db-access-controllers": { - "globals": { - "console.log": true - }, - "packages": { - "3box>orbit-db>orbit-db-access-controllers>p-map-series": true, - "3box>orbit-db>orbit-db-io": true, - "browserify>events": true, - "browserify>path-browserify": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>orbit-db>orbit-db-access-controllers>p-map-series": { - "packages": { - "3box>orbit-db>orbit-db-store>p-each-series>p-reduce": true - } - }, - "3box>orbit-db>orbit-db-cache": { - "packages": { - "3box>orbit-db>logplease": true, - "3box>orbit-db>orbit-db-cache>level-js": true, - "browserify>path-browserify": true - } - }, - "3box>orbit-db>orbit-db-cache>level-js": { - "globals": { - "IDBKeyRange.bound": true, - "IDBKeyRange.lowerBound": true, - "IDBKeyRange.upperBound": true, - "indexedDB": true - }, - "packages": { - "3box>orbit-db>orbit-db-cache>level-js>abstract-leveldown": true, - "3box>orbit-db>orbit-db-cache>level-js>immediate": true, - "3box>orbit-db>orbit-db-cache>level-js>ltgt": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true, - "pumpify>inherits": true, - "stylelint>write-file-atomic>typedarray-to-buffer": true - } - }, - "3box>orbit-db>orbit-db-cache>level-js>abstract-leveldown": { - "packages": { - "browserify>insert-module-globals>is-buffer": true, - "browserify>process": true, - "watchify>xtend": true - } - }, - "3box>orbit-db>orbit-db-cache>level-js>immediate": { - "globals": { - "MessageChannel": true, - "MutationObserver": true, - "WebKitMutationObserver": true, - "clearTimeout": true, - "document.createElement": true, - "document.createTextNode": true, - "document.documentElement.appendChild": true, - "setImmediate": true, - "setTimeout": true - }, - "packages": { - "browserify>process": true - } - }, - "3box>orbit-db>orbit-db-cache>level-js>ltgt": { - "packages": { - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>orbit-db>orbit-db-counterstore": { - "packages": { - "3box>orbit-db>orbit-db-counterstore>crdts": true, - "3box>orbit-db>orbit-db-store": true - } - }, - "3box>orbit-db>orbit-db-docstore": { - "packages": { - "3box>orbit-db>orbit-db-docstore>p-map": true, - "3box>orbit-db>orbit-db-store": true, - "readable-stream": true - } - }, - "3box>orbit-db>orbit-db-eventstore": { - "packages": { - "3box>orbit-db>orbit-db-store": true - } - }, - "3box>orbit-db>orbit-db-feedstore": { - "packages": { - "3box>orbit-db>orbit-db-eventstore": true - } - }, - "3box>orbit-db>orbit-db-identity-provider": { - "packages": { - "3box>orbit-db>orbit-db-keystore": true - } - }, - "3box>orbit-db>orbit-db-io": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>ipld-dag-pb": true, - "browserify>buffer": true - } - }, - "3box>orbit-db>orbit-db-keystore": { - "globals": { - "console.error": true, - "console.log": true - }, - "packages": { - "3box>ethers>elliptic": true, - "3box>ipfs>libp2p-crypto": true, - "3box>orbit-db>orbit-db-cache>level-js": true, - "3box>orbit-db>orbit-db-keystore>levelup": true, - "3box>orbit-db>orbit-db-keystore>lru": true, - "eth-trezor-keyring>hdkey>secp256k1": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>orbit-db>orbit-db-keystore>levelup": { - "packages": { - "3box>orbit-db>orbit-db-keystore>levelup>deferred-leveldown": true, - "3box>orbit-db>orbit-db-keystore>levelup>level-errors": true, - "3box>orbit-db>orbit-db-keystore>levelup>level-iterator-stream": true, - "browserify>assert": true, - "browserify>events": true, - "browserify>process": true, - "browserify>util": true, - "watchify>xtend": true - } - }, - "3box>orbit-db>orbit-db-keystore>levelup>deferred-leveldown": { - "packages": { - "3box>orbit-db>orbit-db-cache>level-js>abstract-leveldown": true, - "pumpify>inherits": true - } - }, - "3box>orbit-db>orbit-db-keystore>levelup>level-errors": { - "packages": { - "webpack>memory-fs>errno": true - } - }, - "3box>orbit-db>orbit-db-keystore>levelup>level-iterator-stream": { - "packages": { - "3box>orbit-db>orbit-db-keystore>levelup>level-iterator-stream>readable-stream": true, - "pumpify>inherits": true, - "watchify>xtend": true - } - }, - "3box>orbit-db>orbit-db-keystore>levelup>level-iterator-stream>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>orbit-db>orbit-db-keystore>lru": { - "packages": { - "browserify>events": true, - "pumpify>inherits": true - } - }, - "3box>orbit-db>orbit-db-kvstore": { - "packages": { - "3box>orbit-db>orbit-db-store": true - } - }, - "3box>orbit-db>orbit-db-pubsub": { - "packages": { - "3box>orbit-db>logplease": true, - "3box>orbit-db>orbit-db-pubsub>ipfs-pubsub-peer-monitor": true, - "3box>orbit-db>orbit-db-pubsub>p-series": true, - "browserify>buffer": true - } - }, - "3box>orbit-db>orbit-db-pubsub>ipfs-pubsub-peer-monitor": { - "globals": { - "clearInterval": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "browserify>events": true - } - }, - "3box>orbit-db>orbit-db-pubsub>p-series": { - "packages": { - "3box>orbit-db>orbit-db-pubsub>p-series>@sindresorhus/is": true, - "3box>orbit-db>orbit-db-store>p-each-series>p-reduce": true - } - }, - "3box>orbit-db>orbit-db-pubsub>p-series>@sindresorhus/is": { - "packages": { - "browserify>insert-module-globals>is-buffer": true, - "browserify>util": true - } - }, - "3box>orbit-db>orbit-db-store": { - "globals": { - "clearInterval": true, - "console.error": true, - "console.warn": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>3box-orbitdb-plugins>ipfs-log": true, - "3box>ipfs>libp2p-kad-dht>p-times>p-map": true, - "3box>orbit-db>logplease": true, - "3box>orbit-db>orbit-db-io": true, - "3box>orbit-db>orbit-db-store>p-each-series": true, - "browserify>buffer": true, - "browserify>events": true, - "readable-stream": true - } - }, - "3box>orbit-db>orbit-db-store>p-each-series": { - "packages": { - "3box>orbit-db>orbit-db-store>p-each-series>p-reduce": true - } - }, - "3box>store": { - "globals": { - "ActiveXObject": true, - "console": true - } - }, - "3box>tweetnacl": { - "globals": { - "crypto": true, - "msCrypto": true, - "nacl": "write" - }, - "packages": { - "browserify>browser-resolve": true - } - }, - "3box>tweetnacl-util": { - "globals": { - "atob": true, - "btoa": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, "@babel/runtime": { "globals": { "regeneratorRuntime": "write" @@ -2236,9 +47,9 @@ }, "@ensdomains/content-hash>cids>multihashes": { "packages": { - "3box>ipfs>varint": true, "@ensdomains/content-hash>cids>multibase": true, - "@ensdomains/content-hash>cids>uint8arrays": true + "@ensdomains/content-hash>cids>uint8arrays": true, + "@ensdomains/content-hash>multihashes>varint": true } }, "@ensdomains/content-hash>cids>uint8arrays": { @@ -2283,17 +94,17 @@ }, "@ensdomains/content-hash>multihashes": { "packages": { - "3box>ipfs>varint": true, "@ensdomains/content-hash>multihashes>multibase": true, + "@ensdomains/content-hash>multihashes>varint": true, "@ensdomains/content-hash>multihashes>web-encoding": true, "browserify>buffer": true } }, "@ensdomains/content-hash>multihashes>multibase": { "packages": { - "3box>ipfs>bs58>base-x": true, "@ensdomains/content-hash>multihashes>web-encoding": true, - "browserify>buffer": true + "browserify>buffer": true, + "ethereumjs-wallet>bs58check>bs58>base-x": true } }, "@ensdomains/content-hash>multihashes>web-encoding": { @@ -2386,42 +197,13 @@ }, "@keystonehq/bc-ur-registry-eth": { "packages": { - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util": true, "@keystonehq/bc-ur-registry-eth>@keystonehq/bc-ur-registry": true, "@keystonehq/bc-ur-registry-eth>hdkey": true, "browserify>buffer": true, + "eth-lattice-keyring>@ethereumjs/util": true, "uuid": true } }, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util": { - "packages": { - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>@ethereumjs/rlp": true, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>ethereum-cryptography": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>@ethereumjs/rlp": { - "globals": { - "TextEncoder": true - } - }, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>ethereum-cryptography": { - "globals": { - "TextDecoder": true, - "crypto": true - }, - "packages": { - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>ethereum-cryptography>@noble/hashes": true, - "eth-json-rpc-middleware>@metamask/eth-sig-util>ethereum-cryptography>@noble/secp256k1": true - } - }, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>ethereum-cryptography>@noble/hashes": { - "globals": { - "TextEncoder": true, - "crypto": true - } - }, "@keystonehq/bc-ur-registry-eth>@keystonehq/bc-ur-registry": { "globals": { "define": true @@ -2449,7 +231,7 @@ }, "@keystonehq/bc-ur-registry-eth>hdkey>secp256k1": { "packages": { - "3box>ethers>elliptic": true + "ethers>@ethersproject/signing-key>elliptic": true } }, "@keystonehq/metamask-airgapped-keyring": { @@ -2468,10 +250,10 @@ "packages": { "@ethereumjs/tx": true, "@keystonehq/bc-ur-registry-eth": true, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util": true, "@keystonehq/bc-ur-registry-eth>hdkey": true, "@keystonehq/metamask-airgapped-keyring>@keystonehq/base-eth-keyring>rlp": true, "browserify>buffer": true, + "eth-lattice-keyring>@ethereumjs/util": true, "uuid": true } }, @@ -2879,38 +661,38 @@ "@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": true, "@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": true, "@metamask/controllers>eth-method-registry>ethjs>ethjs-query": true, - "@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-provider-http": true, "ethjs>ethjs-unit": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": { "packages": { "@metamask/controllers>eth-method-registry>ethjs>bn.js": true, - "@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": { "packages": { "@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": true, - "@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "promise-to-callback": true } }, "@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": { "packages": { "@metamask/controllers>eth-method-registry>ethjs>bn.js": true, - "@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, @@ -2925,11 +707,6 @@ "promise-to-callback": true } }, - "@metamask/controllers>eth-method-registry>ethjs>js-sha3": { - "packages": { - "browserify>process": true - } - }, "@metamask/controllers>eth-phishing-detect": { "packages": { "eslint>optionator>fast-levenshtein": true @@ -3094,7 +871,6 @@ }, "@metamask/controllers>web3-provider-engine>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "@metamask/controllers>web3-provider-engine>ethereumjs-util>ethjs-util": true, "bn.js": true, "browserify>assert": true, @@ -3102,7 +878,8 @@ "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>safe-buffer": true + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "@metamask/controllers>web3-provider-engine>ethereumjs-util>ethjs-util": { @@ -3192,7 +969,6 @@ }, "@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>eth-sig-util>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>eth-sig-util>ethereumjs-util>ethjs-util": true, "bn.js": true, "browserify>assert": true, @@ -3200,7 +976,8 @@ "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>safe-buffer": true + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>eth-sig-util>ethereumjs-util>ethjs-util": { @@ -3230,16 +1007,15 @@ }, "@metamask/eth-ledger-bridge-keyring>eth-sig-util": { "packages": { - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util": true, "browserify>buffer": true, + "eth-sig-util>tweetnacl": true, + "eth-sig-util>tweetnacl-util": true, "ethereumjs-abi": true } }, "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethjs-util": true, "bn.js": true, "browserify>assert": true, @@ -3247,7 +1023,8 @@ "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>safe-buffer": true + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethjs-util": { @@ -3259,13 +1036,23 @@ }, "@metamask/eth-ledger-bridge-keyring>hdkey": { "packages": { + "@metamask/eth-ledger-bridge-keyring>hdkey>secp256k1": true, "browserify>assert": true, "browserify>crypto-browserify": true, "eth-trezor-keyring>hdkey>coinstring": true, - "eth-trezor-keyring>hdkey>secp256k1": true, "ethereumjs-wallet>safe-buffer": true } }, + "@metamask/eth-ledger-bridge-keyring>hdkey>secp256k1": { + "packages": { + "bn.js": true, + "browserify>insert-module-globals>is-buffer": true, + "eth-trezor-keyring>hdkey>secp256k1>bip66": true, + "ethereumjs-util>create-hash": true, + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true + } + }, "@metamask/eth-token-tracker": { "globals": { "console.warn": true @@ -3324,38 +1111,38 @@ "@metamask/eth-token-tracker>ethjs>ethjs-abi": true, "@metamask/eth-token-tracker>ethjs>ethjs-contract": true, "@metamask/eth-token-tracker>ethjs>ethjs-query": true, - "@metamask/eth-token-tracker>ethjs>js-sha3": true, "browserify>buffer": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-provider-http": true, "ethjs>ethjs-unit": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/eth-token-tracker>ethjs>ethjs-abi": { "packages": { "@metamask/eth-token-tracker>ethjs>bn.js": true, - "@metamask/eth-token-tracker>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/eth-token-tracker>ethjs>ethjs-contract": { "packages": { "@metamask/eth-token-tracker>ethjs>ethjs-contract>ethjs-abi": true, - "@metamask/eth-token-tracker>ethjs>js-sha3": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "promise-to-callback": true } }, "@metamask/eth-token-tracker>ethjs>ethjs-contract>ethjs-abi": { "packages": { "@metamask/eth-token-tracker>ethjs>bn.js": true, - "@metamask/eth-token-tracker>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, @@ -3370,11 +1157,6 @@ "promise-to-callback": true } }, - "@metamask/eth-token-tracker>ethjs>js-sha3": { - "packages": { - "browserify>process": true - } - }, "@metamask/etherscan-link": { "globals": { "URL": true @@ -3532,38 +1314,38 @@ "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": true, "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": true, "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": true, - "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-provider-http": true, "ethjs>ethjs-unit": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": { "packages": { "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>bn.js": true, - "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": { "packages": { "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": true, - "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "promise-to-callback": true } }, "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": { "packages": { "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>bn.js": true, - "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, @@ -3578,11 +1360,6 @@ "promise-to-callback": true } }, - "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": { - "packages": { - "browserify>process": true - } - }, "@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet": { "packages": { "@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet>uuid": true, @@ -3682,6 +1459,14 @@ "redux-thunk": true } }, + "@segment/loosely-validate-event": { + "packages": { + "@segment/loosely-validate-event>component-type": true, + "@segment/loosely-validate-event>join-component": true, + "browserify>assert": true, + "browserify>buffer": true + } + }, "@sentry/browser": { "globals": { "XMLHttpRequest": true, @@ -3795,16 +1580,6 @@ "localStorage": true } }, - "@storybook/components>qs": { - "packages": { - "string.prototype.matchall>side-channel": true - } - }, - "@storybook/react>@storybook/store>stable": { - "globals": { - "define": true - } - }, "@truffle/codec": { "packages": { "@truffle/codec>@truffle/abi-utils": true, @@ -4032,7 +1807,15 @@ }, "@truffle/codec>web3-utils>ethereum-bloom-filters": { "packages": { - "ethers>@ethersproject/keccak256>js-sha3": true + "@truffle/codec>web3-utils>ethereum-bloom-filters>js-sha3": true + } + }, + "@truffle/codec>web3-utils>ethereum-bloom-filters>js-sha3": { + "globals": { + "define": true + }, + "packages": { + "browserify>process": true } }, "@truffle/decoder": { @@ -4081,106 +1864,41 @@ } }, "@zxing/browser": { - "globals": { - "HTMLElement": true, - "HTMLImageElement": true, - "HTMLVideoElement": true, - "URL.createObjectURL": true, - "clearTimeout": true, - "console.error": true, - "console.warn": true, - "document": true, - "navigator": true, - "setTimeout": true - }, - "packages": { - "@zxing/library": true - } - }, - "@zxing/library": { - "globals": { - "TextDecoder": true, - "TextEncoder": true, - "btoa": true, - "clearTimeout": true, - "define": true, - "document.createElement": true, - "document.createElementNS": true, - "document.getElementById": true, - "navigator.mediaDevices.enumerateDevices": true, - "navigator.mediaDevices.getUserMedia": true, - "setTimeout": true - } - }, - "addons-linter>sha.js": { - "packages": { - "ethereumjs-wallet>safe-buffer": true, - "pumpify>inherits": true - } - }, - "analytics-node": { - "globals": { - "clearTimeout": true, - "console.log": true, - "setImmediate": true, - "setTimeout": true - }, - "packages": { - "analytics-node>@segment/loosely-validate-event": true, - "analytics-node>axios": true, - "analytics-node>axios-retry": true, - "analytics-node>lodash.isstring": true, - "analytics-node>md5": true, - "analytics-node>ms": true, - "analytics-node>remove-trailing-slash": true, - "analytics-node>uuid": true, - "browserify>assert": true, - "browserify>process": true - } - }, - "analytics-node>@segment/loosely-validate-event": { - "packages": { - "analytics-node>@segment/loosely-validate-event>component-type": true, - "analytics-node>@segment/loosely-validate-event>join-component": true, - "browserify>assert": true, - "browserify>buffer": true - } - }, - "analytics-node>axios": { - "globals": { - "FormData": true, - "URLSearchParams": true, - "XMLHttpRequest": true, - "btoa": true, + "globals": { + "HTMLElement": true, + "HTMLImageElement": true, + "HTMLVideoElement": true, + "URL.createObjectURL": true, + "clearTimeout": true, + "console.error": true, "console.warn": true, "document": true, - "location.href": true, "navigator": true, "setTimeout": true }, "packages": { - "browserify>process": true + "@zxing/library": true } }, - "analytics-node>axios-retry": { + "@zxing/library": { "globals": { + "TextDecoder": true, + "TextEncoder": true, + "btoa": true, + "clearTimeout": true, + "define": true, + "document.createElement": true, + "document.createElementNS": true, + "document.getElementById": true, + "navigator.mediaDevices.enumerateDevices": true, + "navigator.mediaDevices.getUserMedia": true, "setTimeout": true - }, - "packages": { - "geckodriver>got>is-retry-allowed": true } }, - "analytics-node>md5": { + "addons-linter>sha.js": { "packages": { - "analytics-node>md5>charenc": true, - "analytics-node>md5>crypt": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "analytics-node>uuid": { - "globals": { - "crypto": true, - "msCrypto": true + "ethereumjs-wallet>safe-buffer": true, + "pumpify>inherits": true } }, "await-semaphore": { @@ -4274,7 +1992,7 @@ }, "browserify>crypto-browserify>browserify-cipher>browserify-des>des.js": { "packages": { - "3box>ethers>hash.js>minimalistic-assert": true, + "ethers>@ethersproject/sha2>hash.js>minimalistic-assert": true, "pumpify>inherits": true } }, @@ -4286,7 +2004,6 @@ }, "browserify>crypto-browserify>browserify-sign": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>buffer": true, "browserify>crypto-browserify>create-hmac": true, @@ -4294,14 +2011,15 @@ "browserify>crypto-browserify>public-encrypt>parse-asn1": true, "browserify>stream-browserify": true, "ethereumjs-util>create-hash": true, + "ethers>@ethersproject/signing-key>elliptic": true, "pumpify>inherits": true } }, "browserify>crypto-browserify>create-ecdh": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, - "browserify>buffer": true + "browserify>buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "browserify>crypto-browserify>create-hmac": { @@ -4324,8 +2042,8 @@ }, "browserify>crypto-browserify>diffie-hellman>miller-rabin": { "packages": { - "3box>ethers>elliptic>brorand": true, - "bn.js": true + "bn.js": true, + "ethers>@ethersproject/signing-key>elliptic>brorand": true } }, "browserify>crypto-browserify>pbkdf2": { @@ -4372,10 +2090,10 @@ }, "browserify>crypto-browserify>public-encrypt>parse-asn1>asn1.js": { "packages": { - "3box>ethers>hash.js>minimalistic-assert": true, "bn.js": true, "browserify>buffer": true, "browserify>vm-browserify": true, + "ethers>@ethersproject/sha2>hash.js>minimalistic-assert": true, "pumpify>inherits": true } }, @@ -4604,15 +2322,6 @@ "string.prototype.matchall>call-bind": true } }, - "enzyme>object-inspect": { - "globals": { - "HTMLElement": true, - "WeakRef": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, "enzyme>object-is": { "packages": { "globalthis>define-properties": true, @@ -4718,13 +2427,13 @@ }, "eth-json-rpc-middleware>@metamask/eth-sig-util": { "packages": { - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util": true, "browserify>buffer": true, "eth-json-rpc-middleware>@metamask/eth-sig-util>bn.js": true, "eth-json-rpc-middleware>@metamask/eth-sig-util>ethereum-cryptography": true, - "eth-json-rpc-middleware>@metamask/eth-sig-util>ethjs-util": true + "eth-json-rpc-middleware>@metamask/eth-sig-util>ethjs-util": true, + "eth-lattice-keyring>@ethereumjs/util": true, + "eth-sig-util>tweetnacl": true, + "eth-sig-util>tweetnacl-util": true } }, "eth-json-rpc-middleware>@metamask/eth-sig-util>bn.js": { @@ -4747,14 +2456,6 @@ "crypto": true } }, - "eth-json-rpc-middleware>@metamask/eth-sig-util>ethereum-cryptography>@noble/secp256k1": { - "globals": { - "crypto": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, "eth-json-rpc-middleware>@metamask/eth-sig-util>ethjs-util": { "packages": { "browserify>buffer": true, @@ -4868,44 +2569,62 @@ "clearInterval": true, "fetch": true, "open": true, - "setInterval": true, - "txData.type": true + "setInterval": true }, "packages": { "browserify>buffer": true, "browserify>crypto-browserify": true, "browserify>events": true, - "eth-lattice-keyring>@ethereumjs/common": true, "eth-lattice-keyring>@ethereumjs/tx": true, + "eth-lattice-keyring>@ethereumjs/util": true, "eth-lattice-keyring>bn.js": true, "eth-lattice-keyring>gridplus-sdk": true, - "eth-lattice-keyring>rlp": true, - "eth-lattice-keyring>secp256k1": true, - "ethereumjs-util": true + "eth-lattice-keyring>rlp": true } }, - "eth-lattice-keyring>@ethereumjs/common": { + "eth-lattice-keyring>@ethereumjs/tx": { "packages": { - "@ethereumjs/common>crc-32": true, + "@ethereumjs/common": true, "browserify>buffer": true, - "browserify>events": true, + "browserify>insert-module-globals>is-buffer": true, "ethereumjs-util": true } }, - "eth-lattice-keyring>@ethereumjs/tx": { + "eth-lattice-keyring>@ethereumjs/util": { "packages": { "browserify>buffer": true, "browserify>insert-module-globals>is-buffer": true, - "eth-lattice-keyring>@ethereumjs/tx>@ethereumjs/common": true, - "ethereumjs-util": true + "eth-lattice-keyring>@ethereumjs/util>@ethereumjs/rlp": true, + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography": true + } + }, + "eth-lattice-keyring>@ethereumjs/util>@ethereumjs/rlp": { + "globals": { + "TextEncoder": true + } + }, + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography": { + "globals": { + "TextDecoder": true, + "crypto": true + }, + "packages": { + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@noble/hashes": true, + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@noble/secp256k1": true + } + }, + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true } }, - "eth-lattice-keyring>@ethereumjs/tx>@ethereumjs/common": { + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@noble/secp256k1": { + "globals": { + "crypto": true + }, "packages": { - "@ethereumjs/common>crc-32": true, - "browserify>buffer": true, - "browserify>events": true, - "ethereumjs-util": true + "browserify>browser-resolve": true } }, "eth-lattice-keyring>bn.js": { @@ -4918,13 +2637,18 @@ }, "eth-lattice-keyring>gridplus-sdk": { "globals": { + "AbortController": true, + "Request": true, "__values": true, + "caches": true, + "clearTimeout": true, + "console.error": true, "console.log": true, "console.warn": true, + "fetch": true, "setTimeout": true }, "packages": { - "3box>ethers>elliptic": true, "@ethereumjs/common>crc-32": true, "@metamask/controllers>@ethersproject/abi": true, "bn.js": true, @@ -4937,13 +2661,13 @@ "eth-lattice-keyring>gridplus-sdk>bitwise": true, "eth-lattice-keyring>gridplus-sdk>borc": true, "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser": true, + "eth-lattice-keyring>gridplus-sdk>js-sha3": true, "eth-lattice-keyring>gridplus-sdk>rlp": true, - "eth-lattice-keyring>gridplus-sdk>secp256k1": true, - "eth-lattice-keyring>gridplus-sdk>superagent": true, "ethereumjs-wallet>aes-js": true, "ethereumjs-wallet>bs58check": true, - "ethers>@ethersproject/keccak256>js-sha3": true, "ethers>@ethersproject/sha2>hash.js": true, + "ethers>@ethersproject/signing-key>elliptic": true, + "ganache>secp256k1": true, "lodash": true } }, @@ -4987,10 +2711,10 @@ "console": true }, "packages": { - "3box>ipfs>iso-url": true, "browserify>buffer": true, "browserify>buffer>ieee754": true, - "eth-lattice-keyring>gridplus-sdk>borc>bignumber.js": true + "eth-lattice-keyring>gridplus-sdk>borc>bignumber.js": true, + "eth-lattice-keyring>gridplus-sdk>borc>iso-url": true } }, "eth-lattice-keyring>gridplus-sdk>borc>bignumber.js": { @@ -4999,6 +2723,13 @@ "define": true } }, + "eth-lattice-keyring>gridplus-sdk>borc>iso-url": { + "globals": { + "URL": true, + "URLSearchParams": true, + "location": true + } + }, "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser": { "globals": { "intToBuffer": true @@ -5006,7 +2737,7 @@ "packages": { "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser>bn.js": true, "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser>buffer": true, - "ethers>@ethersproject/keccak256>js-sha3": true + "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser>js-sha3": true } }, "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser>bn.js": { @@ -5026,41 +2757,30 @@ "browserify>buffer>ieee754": true } }, - "eth-lattice-keyring>gridplus-sdk>rlp": { + "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser>js-sha3": { "globals": { - "TextEncoder": true - } - }, - "eth-lattice-keyring>gridplus-sdk>secp256k1": { + "define": true + }, "packages": { - "3box>ethers>elliptic": true + "browserify>process": true } }, - "eth-lattice-keyring>gridplus-sdk>superagent": { + "eth-lattice-keyring>gridplus-sdk>js-sha3": { "globals": { - "XMLHttpRequest": true, - "btoa": true, - "clearTimeout": true, - "console.error": true, - "console.warn": true, - "setTimeout": true + "define": true }, "packages": { - "@storybook/components>qs": true, - "browserify>browser-resolve": true, - "browserify>process": true, - "eth-rpc-errors>fast-safe-stringify": true, - "pubnub>superagent>component-emitter": true + "browserify>process": true } }, - "eth-lattice-keyring>rlp": { + "eth-lattice-keyring>gridplus-sdk>rlp": { "globals": { "TextEncoder": true } }, - "eth-lattice-keyring>secp256k1": { - "packages": { - "3box>ethers>elliptic": true + "eth-lattice-keyring>rlp": { + "globals": { + "TextEncoder": true } }, "eth-method-registry": { @@ -5082,16 +2802,15 @@ }, "eth-sig-util": { "packages": { - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, "browserify>buffer": true, "eth-sig-util>ethereumjs-util": true, + "eth-sig-util>tweetnacl": true, + "eth-sig-util>tweetnacl-util": true, "ethereumjs-abi": true } }, "eth-sig-util>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>assert": true, "browserify>buffer": true, @@ -5099,7 +2818,8 @@ "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>safe-buffer": true + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "eth-sig-util>ethereumjs-util>ethjs-util": { @@ -5109,6 +2829,25 @@ "ethjs>ethjs-util>strip-hex-prefix": true } }, + "eth-sig-util>tweetnacl": { + "globals": { + "crypto": true, + "msCrypto": true, + "nacl": "write" + }, + "packages": { + "browserify>browser-resolve": true + } + }, + "eth-sig-util>tweetnacl-util": { + "globals": { + "atob": true, + "btoa": true + }, + "packages": { + "browserify>browser-resolve": true + } + }, "eth-trezor-keyring": { "globals": { "setTimeout": true @@ -5124,9 +2863,9 @@ }, "eth-trezor-keyring>@metamask/eth-sig-util": { "packages": { - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, "browserify>buffer": true, + "eth-sig-util>tweetnacl": true, + "eth-sig-util>tweetnacl-util": true, "eth-trezor-keyring>@metamask/eth-sig-util>ethereumjs-util": true, "eth-trezor-keyring>@metamask/eth-sig-util>ethjs-util": true, "ethereumjs-abi": true @@ -5134,14 +2873,14 @@ }, "eth-trezor-keyring>@metamask/eth-sig-util>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>assert": true, "browserify>buffer": true, "eth-trezor-keyring>@metamask/eth-sig-util>ethjs-util": true, "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, - "ethereumjs-util>rlp": true + "ethereumjs-util>rlp": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "eth-trezor-keyring>@metamask/eth-sig-util>ethjs-util": { @@ -5169,13 +2908,12 @@ }, "eth-trezor-keyring>hdkey>secp256k1": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>insert-module-globals>is-buffer": true, "eth-trezor-keyring>hdkey>secp256k1>bip66": true, - "eth-trezor-keyring>hdkey>secp256k1>drbg.js": true, "ethereumjs-util>create-hash": true, - "ethereumjs-wallet>safe-buffer": true + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "eth-trezor-keyring>hdkey>secp256k1>bip66": { @@ -5183,12 +2921,6 @@ "ethereumjs-wallet>safe-buffer": true } }, - "eth-trezor-keyring>hdkey>secp256k1>drbg.js": { - "packages": { - "browserify>buffer": true, - "browserify>crypto-browserify>create-hmac": true - } - }, "eth-trezor-keyring>trezor-connect": { "globals": { "__TREZOR_CONNECT_SRC": true, @@ -5211,10 +2943,19 @@ "setTimeout": true }, "packages": { - "3box>graphql-request>cross-fetch": true, "@babel/runtime": true, "browserify>events": true, - "eth-trezor-keyring>@metamask/eth-sig-util": true + "eth-trezor-keyring>@metamask/eth-sig-util": true, + "eth-trezor-keyring>trezor-connect>cross-fetch": true + } + }, + "eth-trezor-keyring>trezor-connect>cross-fetch": { + "globals": { + "Blob": true, + "FileReader": true, + "FormData": true, + "URLSearchParams.prototype.isPrototypeOf": true, + "XMLHttpRequest": true } }, "ethereumjs-abi": { @@ -5226,14 +2967,14 @@ }, "ethereumjs-abi>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>assert": true, "browserify>buffer": true, "ethereumjs-abi>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, - "ethereumjs-util>rlp": true + "ethereumjs-util>rlp": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethereumjs-abi>ethereumjs-util>ethjs-util": { @@ -5324,12 +3065,6 @@ "ethers>@ethersproject/sha2>hash.js": true } }, - "ethereumjs-util>ethereum-cryptography>blakejs": { - "globals": { - "TextEncoder": true, - "console.log": true - } - }, "ethereumjs-util>ethereum-cryptography>browserify-aes": { "packages": { "browserify>buffer": true, @@ -5364,7 +3099,7 @@ }, "ethereumjs-util>ethereum-cryptography>secp256k1": { "packages": { - "3box>ethers>elliptic": true + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethereumjs-util>rlp": { @@ -5401,21 +3136,31 @@ }, "ethereumjs-wallet>bs58check": { "packages": { - "3box>ipfs>bs58": true, "ethereumjs-util>create-hash": true, + "ethereumjs-wallet>bs58check>bs58": true, + "ethereumjs-wallet>safe-buffer": true + } + }, + "ethereumjs-wallet>bs58check>bs58": { + "packages": { + "ethereumjs-wallet>bs58check>bs58>base-x": true + } + }, + "ethereumjs-wallet>bs58check>bs58>base-x": { + "packages": { "ethereumjs-wallet>safe-buffer": true } }, "ethereumjs-wallet>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>assert": true, "browserify>buffer": true, "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>ethereumjs-util>ethjs-util": true + "ethereumjs-wallet>ethereumjs-util>ethjs-util": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethereumjs-wallet>ethereumjs-util>ethjs-util": { @@ -5887,10 +3632,10 @@ }, "ethers>@ethersproject/contracts>@ethersproject/transactions>@ethersproject/signing-key": { "packages": { - "3box>ethers>elliptic": true, "ethers>@ethersproject/contracts>@ethersproject/bytes": true, "ethers>@ethersproject/contracts>@ethersproject/logger": true, - "ethers>@ethersproject/contracts>@ethersproject/properties": true + "ethers>@ethersproject/contracts>@ethersproject/properties": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethers>@ethersproject/hash": { @@ -6236,10 +3981,10 @@ }, "ethers>@ethersproject/providers>@ethersproject/transactions>@ethersproject/signing-key": { "packages": { - "3box>ethers>elliptic": true, "ethers>@ethersproject/providers>@ethersproject/bytes": true, "ethers>@ethersproject/providers>@ethersproject/logger": true, - "ethers>@ethersproject/providers>@ethersproject/properties": true + "ethers>@ethersproject/providers>@ethersproject/properties": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethers>@ethersproject/providers>@ethersproject/web": { @@ -6319,16 +4064,16 @@ }, "ethers>@ethersproject/sha2>hash.js": { "packages": { - "3box>ethers>hash.js>minimalistic-assert": true, + "ethers>@ethersproject/sha2>hash.js>minimalistic-assert": true, "pumpify>inherits": true } }, "ethers>@ethersproject/signing-key": { "packages": { - "3box>ethers>elliptic": true, "ethers>@ethersproject/signing-key>@ethersproject/bytes": true, "ethers>@ethersproject/signing-key>@ethersproject/logger": true, - "ethers>@ethersproject/signing-key>@ethersproject/properties": true + "ethers>@ethersproject/signing-key>@ethersproject/properties": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethers>@ethersproject/signing-key>@ethersproject/bytes": { @@ -6346,6 +4091,33 @@ "ethers>@ethersproject/signing-key>@ethersproject/logger": true } }, + "ethers>@ethersproject/signing-key>elliptic": { + "packages": { + "bn.js": true, + "ethers>@ethersproject/sha2>hash.js": true, + "ethers>@ethersproject/sha2>hash.js>minimalistic-assert": true, + "ethers>@ethersproject/signing-key>elliptic>brorand": true, + "ethers>@ethersproject/signing-key>elliptic>hmac-drbg": true, + "ethers>@ethersproject/signing-key>elliptic>minimalistic-crypto-utils": true, + "pumpify>inherits": true + } + }, + "ethers>@ethersproject/signing-key>elliptic>brorand": { + "globals": { + "crypto": true, + "msCrypto": true + }, + "packages": { + "browserify>browser-resolve": true + } + }, + "ethers>@ethersproject/signing-key>elliptic>hmac-drbg": { + "packages": { + "ethers>@ethersproject/sha2>hash.js": true, + "ethers>@ethersproject/sha2>hash.js>minimalistic-assert": true, + "ethers>@ethersproject/signing-key>elliptic>minimalistic-crypto-utils": true + } + }, "ethers>@ethersproject/solidity": { "packages": { "@ethersproject/bignumber": true, @@ -6467,7 +4239,7 @@ }, "ethers>@ethersproject/transactions>@ethersproject/signing-key": { "packages": { - "3box>ethers>elliptic": true, + "ethers>@ethersproject/signing-key>elliptic": true, "ethers>@ethersproject/transactions>@ethersproject/bytes": true, "ethers>@ethersproject/transactions>@ethersproject/logger": true, "ethers>@ethersproject/transactions>@ethersproject/properties": true @@ -6525,7 +4297,15 @@ "ethers>@ethersproject/wallet>@ethersproject/keccak256": { "packages": { "@ethersproject/bignumber>@ethersproject/bytes": true, - "ethers>@ethersproject/keccak256>js-sha3": true + "ethers>@ethersproject/wallet>@ethersproject/keccak256>js-sha3": true + } + }, + "ethers>@ethersproject/wallet>@ethersproject/keccak256>js-sha3": { + "globals": { + "define": true + }, + "packages": { + "browserify>process": true } }, "ethers>@ethersproject/wallet>@ethersproject/properties": { @@ -6541,9 +4321,9 @@ }, "ethers>@ethersproject/wallet>@ethersproject/signing-key": { "packages": { - "3box>ethers>elliptic": true, "@ethersproject/bignumber>@ethersproject/bytes": true, "@ethersproject/bignumber>@ethersproject/logger": true, + "ethers>@ethersproject/signing-key>elliptic": true, "ethers>@ethersproject/wallet>@ethersproject/properties": true } }, @@ -6656,10 +4436,10 @@ "ethjs-contract": { "packages": { "ethjs-contract>ethjs-abi": true, - "ethjs-contract>js-sha3": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "promise-to-callback": true } }, @@ -6667,20 +4447,10 @@ "packages": { "browserify>buffer": true, "ethjs-contract>ethjs-abi>bn.js": true, - "ethjs-contract>ethjs-abi>js-sha3": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, - "ethjs-contract>ethjs-abi>js-sha3": { - "packages": { - "browserify>process": true - } - }, - "ethjs-contract>js-sha3": { - "packages": { - "browserify>process": true - } - }, "ethjs-query": { "globals": { "console": true @@ -6797,9 +4567,13 @@ "define": true } }, + "ganache>secp256k1": { + "packages": { + "ethers>@ethersproject/signing-key>elliptic": true + } + }, "gh-pages>async": { "globals": { - "clearTimeout": true, "setTimeout": true }, "packages": { @@ -6902,34 +4676,6 @@ "Intl": true } }, - "madge>rc>deep-extend": { - "packages": { - "browserify>buffer": true - } - }, - "mockttp>node-forge": { - "globals": { - "Blob": true, - "MutationObserver": true, - "QuotaExceededError": true, - "URL.createObjectURL": true, - "URL.revokeObjectURL": true, - "Worker": true, - "addEventListener": true, - "document": true, - "jQuery": true, - "localStorage": true, - "navigator": true, - "postMessage": true, - "removeEventListener": true, - "setTimeout": true - }, - "packages": { - "browserify>browser-resolve": true, - "browserify>process": true, - "browserify>timers-browserify": true - } - }, "nanoid": { "globals": { "crypto": true, @@ -7077,12 +4823,6 @@ "react-devtools>react-devtools-core": true } }, - "react-devtools>ip": { - "packages": { - "browserify>buffer": true, - "browserify>os-browserify": true - } - }, "react-devtools>react-devtools-core": { "globals": { "WebSocket": true, @@ -7498,8 +5238,13 @@ "setTimeout": true }, "packages": { - "3box>events": true, - "browserify>util": true + "browserify>util": true, + "safe-event-emitter>events": true + } + }, + "safe-event-emitter>events": { + "globals": { + "console": true } }, "semver": { @@ -7551,19 +5296,6 @@ "string.prototype.matchall>call-bind": true } }, - "string.prototype.matchall>side-channel": { - "packages": { - "enzyme>object-inspect": true, - "string.prototype.matchall>call-bind": true, - "string.prototype.matchall>get-intrinsic": true - } - }, - "stylelint>write-file-atomic>typedarray-to-buffer": { - "packages": { - "browserify>buffer": true, - "jsdom>request>is-typedarray": true - } - }, "textarea-caret": { "globals": { "document.body.appendChild": true, @@ -7615,11 +5347,6 @@ "console.warn": true, "define": true } - }, - "webpack>memory-fs>errno": { - "packages": { - "webpack>memory-fs>errno>prr": true - } } } } \ No newline at end of file diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index 70ae84749..613739559 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -1,2194 +1,5 @@ { "resources": { - "3box": { - "globals": { - "console.error": true, - "console.log": true, - "console.warn": true, - "fetch": true, - "setTimeout": true - }, - "packages": { - "3box>3box-orbitdb-plugins": true, - "3box>3box-orbitdb-plugins>ipfs-log": true, - "3box>3id-resolver": true, - "3box>did-jwt": true, - "3box>ethers": true, - "3box>ethers>elliptic": true, - "3box>graphql-request": true, - "3box>https-did-resolver": true, - "3box>ipfs": true, - "3box>ipfs-did-document": true, - "3box>ipfs-mini": true, - "3box>ipfs>is-ipfs": true, - "3box>ipfs>multihashes": true, - "3box>js-sha256": true, - "3box>muport-did-resolver": true, - "3box>orbit-db": true, - "3box>orbit-db>orbit-db-access-controllers": true, - "3box>orbit-db>orbit-db-identity-provider": true, - "3box>orbit-db>orbit-db-pubsub": true, - "3box>store": true, - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, - "@babel/runtime": true, - "browserify>buffer": true, - "browserify>process": true, - "node-fetch": true - } - }, - "3box>3box-orbitdb-plugins": { - "globals": { - "console.log": true - }, - "packages": { - "3box>3box-orbitdb-plugins>ipfs-log": true, - "3box>3id-resolver>did-jwt": true, - "3box>3id-resolver>did-jwt>base64url": true, - "3box>did-jwt>did-resolver": true, - "3box>ipfs>is-ipfs": true, - "3box>orbit-db>orbit-db-access-controllers": true, - "3box>orbit-db>orbit-db-io": true, - "browserify>events": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>3box-orbitdb-plugins>ipfs-log": { - "globals": { - "clearTimeout": true, - "console.warn": true, - "setTimeout": true - }, - "packages": { - "3box>3box-orbitdb-plugins>ipfs-log>json-stringify-deterministic": true, - "3box>3box-orbitdb-plugins>ipfs-log>p-each-series": true, - "3box>3box-orbitdb-plugins>ipfs-log>p-map": true, - "3box>3box-orbitdb-plugins>ipfs-log>p-whilst": true, - "3box>orbit-db>orbit-db-io": true, - "browserify>buffer": true - } - }, - "3box>3id-resolver": { - "packages": { - "3box>3id-resolver>did-jwt": true, - "3box>3id-resolver>did-jwt>base64url": true, - "3box>did-jwt>did-resolver": true, - "3box>ipfs-did-document": true, - "@babel/runtime": true - } - }, - "3box>3id-resolver>did-jwt": { - "packages": { - "3box>3id-resolver>did-jwt>base64url": true, - "3box>did-jwt>did-resolver": true, - "3box>ethers>elliptic": true, - "3box>js-sha256": true, - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, - "@babel/runtime": true, - "browserify>buffer": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>3id-resolver>did-jwt>base64url": { - "packages": { - "browserify>buffer": true - } - }, - "3box>did-jwt": { - "packages": { - "3box>did-jwt>@stablelib/utf8": true, - "3box>did-jwt>did-resolver": true, - "3box>did-jwt>js-sha3": true, - "3box>did-jwt>uport-base64url": true, - "3box>ethers>elliptic": true, - "3box>js-sha256": true, - "3box>tweetnacl": true, - "browserify>buffer": true - } - }, - "3box>did-jwt>js-sha3": { - "globals": { - "define": true - }, - "packages": { - "browserify>process": true - } - }, - "3box>did-jwt>uport-base64url": { - "packages": { - "browserify>buffer": true - } - }, - "3box>ethers": { - "globals": { - "MessageChannel": true, - "XMLHttpRequest": true, - "atob": true, - "btoa": true, - "clearInterval": true, - "clearTimeout": true, - "console": true, - "crypto.getRandomValues": true, - "define": true, - "setInterval": true, - "setTimeout": true - } - }, - "3box>ethers>elliptic": { - "packages": { - "3box>ethers>elliptic>brorand": true, - "3box>ethers>elliptic>hmac-drbg": true, - "3box>ethers>elliptic>minimalistic-crypto-utils": true, - "3box>ethers>hash.js>minimalistic-assert": true, - "bn.js": true, - "ethers>@ethersproject/sha2>hash.js": true, - "pumpify>inherits": true - } - }, - "3box>ethers>elliptic>brorand": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, - "3box>ethers>elliptic>hmac-drbg": { - "packages": { - "3box>ethers>elliptic>minimalistic-crypto-utils": true, - "3box>ethers>hash.js>minimalistic-assert": true, - "ethers>@ethersproject/sha2>hash.js": true - } - }, - "3box>events": { - "globals": { - "console": true - } - }, - "3box>graphql-request": { - "globals": { - "fetch": true - }, - "packages": { - "3box>graphql-request>cross-fetch": true - } - }, - "3box>graphql-request>cross-fetch": { - "globals": { - "Blob": true, - "FileReader": true, - "FormData": true, - "URLSearchParams.prototype.isPrototypeOf": true, - "XMLHttpRequest": true - } - }, - "3box>graphql-request>cross-fetch>node-fetch": { - "globals": { - "fetch": true - } - }, - "3box>https-did-resolver": { - "globals": { - "XMLHttpRequest": true - }, - "packages": { - "3box>did-jwt>did-resolver": true, - "browserify>browser-resolve": true - } - }, - "3box>ipfs": { - "globals": { - "AbortController": true, - "clearInterval": true, - "clearTimeout": true, - "console.log": true, - "fetch": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>async-iterator-all": true, - "3box>ipfs>async-iterator-to-pull-stream": true, - "3box>ipfs>async-iterator-to-stream": true, - "3box>ipfs>base32.js": true, - "3box>ipfs>bignumber.js": true, - "3box>ipfs>callbackify": true, - "3box>ipfs>cids": true, - "3box>ipfs>class-is": true, - "3box>ipfs>datastore-core": true, - "3box>ipfs>datastore-pubsub": true, - "3box>ipfs>dlv": true, - "3box>ipfs>err-code": true, - "3box>ipfs>fnv1a": true, - "3box>ipfs>fsm-event": true, - "3box>ipfs>human-to-milliseconds": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>ipfs-bitswap": true, - "3box>ipfs>ipfs-block": true, - "3box>ipfs>ipfs-block-service": true, - "3box>ipfs>ipfs-mfs": true, - "3box>ipfs>ipfs-repo": true, - "3box>ipfs>ipfs-unixfs": true, - "3box>ipfs>ipfs-unixfs-exporter": true, - "3box>ipfs>ipfs-unixfs-importer": true, - "3box>ipfs>ipfs-utils": true, - "3box>ipfs>ipld": true, - "3box>ipfs>ipld-dag-cbor": true, - "3box>ipfs>ipld-dag-pb": true, - "3box>ipfs>ipld-raw": true, - "3box>ipfs>ipns": true, - "3box>ipfs>is-ipfs": true, - "3box>ipfs>is-pull-stream": true, - "3box>ipfs>iso-url": true, - "3box>ipfs>just-flatten-it": true, - "3box>ipfs>kind-of": true, - "3box>ipfs>libp2p": true, - "3box>ipfs>libp2p-bootstrap": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-kad-dht": true, - "3box>ipfs>libp2p-keychain": true, - "3box>ipfs>libp2p-record": true, - "3box>ipfs>libp2p-secio": true, - "3box>ipfs>libp2p-webrtc-star": true, - "3box>ipfs>libp2p-websocket-star-multi": true, - "3box>ipfs>libp2p-websockets": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>merge-options": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>multiaddr-to-uri": true, - "3box>ipfs>multibase": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async": true, - "3box>ipfs>peer-book": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>promisify-es6": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-cat": true, - "3box>ipfs>pull-defer": true, - "3box>ipfs>pull-mplex": true, - "3box>ipfs>pull-pushable": true, - "3box>ipfs>pull-sort": true, - "3box>ipfs>pull-stream": true, - "3box>ipfs>pull-stream-to-async-iterator": true, - "3box>ipfs>pull-stream-to-stream": true, - "3box>ipfs>pull-traverse": true, - "3box>ipfs>readable-stream": true, - "3box>ipfs>receptacle": true, - "3box>ipfs>stream-to-pull-stream": true, - "3box>ipfs>superstruct": true, - "3box>ipfs>varint": true, - "@metamask/providers>is-stream": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>insert-module-globals>is-buffer": true, - "browserify>timers-browserify": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs-mini": { - "globals": { - "XMLHttpRequest": true - } - }, - "3box>ipfs-postmsg-proxy>shortid": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "nanoid": true - } - }, - "3box>ipfs>async-iterator-to-pull-stream": { - "packages": { - "3box>ipfs>async-iterator-to-pull-stream>get-iterator": true, - "3box>ipfs>pull-stream-to-async-iterator": true - } - }, - "3box>ipfs>async-iterator-to-stream": { - "packages": { - "3box>ipfs>async-iterator-to-stream>readable-stream": true, - "browserify>process": true - } - }, - "3box>ipfs>async-iterator-to-stream>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>bignumber.js": { - "globals": { - "crypto": true, - "define": true - } - }, - "3box>ipfs>bl": { - "packages": { - "3box>ipfs>bl>readable-stream": true, - "browserify>buffer": true, - "browserify>util": true - } - }, - "3box>ipfs>bl>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>bs58": { - "packages": { - "3box>ipfs>bs58>base-x": true - } - }, - "3box>ipfs>bs58>base-x": { - "packages": { - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>ipfs>cids": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>multibase": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>multihashes": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>datastore-core": { - "packages": { - "3box>ipfs>datastore-core>pull-many": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true, - "gh-pages>async": true - } - }, - "3box>ipfs>datastore-pubsub": { - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>multibase": true, - "browserify>assert": true, - "browserify>buffer": true, - "nock>debug": true - } - }, - "3box>ipfs>dlv": { - "globals": { - "define": true - } - }, - "3box>ipfs>fsm-event": { - "packages": { - "3box>ipfs>fsm-event>fsm": true, - "browserify>assert": true, - "browserify>events": true - } - }, - "3box>ipfs>human-to-milliseconds": { - "packages": { - "3box>ipfs>promisify-es6": true - } - }, - "3box>ipfs>interface-datastore": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>err-code": true, - "3box>ipfs>interface-datastore>uuid": true, - "3box>ipfs>pull-defer": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true, - "browserify>os-browserify": true, - "browserify>path-browserify": true, - "gh-pages>async": true - } - }, - "3box>ipfs>interface-datastore>uuid": { - "globals": { - "crypto": true, - "msCrypto": true - } - }, - "3box>ipfs>ipfs-bitswap": { - "globals": { - "clearInterval": true, - "clearTimeout": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>ipfs-bitswap>bignumber.js": true, - "3box>ipfs>ipfs-bitswap>just-debounce-it": true, - "3box>ipfs>ipfs-bitswap>lodash.isequalwith": true, - "3box>ipfs>ipfs-bitswap>moving-average": true, - "3box>ipfs>ipfs-bitswap>multihashing-async": true, - "3box>ipfs>ipfs-bitswap>varint-decoder": true, - "3box>ipfs>ipfs-block": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-stream": true, - "browserify>assert": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>ipfs-bitswap>bignumber.js": { - "globals": { - "crypto": true, - "define": true - } - }, - "3box>ipfs>ipfs-bitswap>just-debounce-it": { - "globals": { - "clearTimeout": true, - "setTimeout": true - } - }, - "3box>ipfs>ipfs-bitswap>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>ipfs-bitswap>varint-decoder": { - "packages": { - "3box>ipfs>varint": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipfs-block": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>class-is": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipfs-block-service": { - "packages": { - "gh-pages>async": true - } - }, - "3box>ipfs>ipfs-mfs": { - "globals": { - "Blob": true, - "FileReader": true - }, - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>err-code": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>ipfs-mfs>async-iterator-last": true, - "3box>ipfs>ipfs-mfs>hamt-sharding": true, - "3box>ipfs>ipfs-mfs>mortice": true, - "3box>ipfs>ipfs-unixfs": true, - "3box>ipfs>ipfs-unixfs-exporter": true, - "3box>ipfs>ipfs-unixfs-importer": true, - "3box>ipfs>ipld-dag-pb": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>multihashes": true, - "3box>ipfs>promisify-es6": true, - "browserify>assert": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "nock>debug": true - } - }, - "3box>ipfs>ipfs-mfs>hamt-sharding": { - "packages": { - "3box>ipfs>ipfs-mfs>hamt-sharding>sparse-array": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipfs-mfs>mortice": { - "globals": { - "Worker": true - }, - "packages": { - "3box>ipfs-postmsg-proxy>shortid": true, - "3box>ipfs>ipfs-mfs>mortice>observable-webworkers": true, - "3box>ipfs>ipfs-mfs>mortice>promise-timeout": true, - "3box>ipfs>libp2p-kad-dht>p-queue": true, - "browserify>browser-resolve": true, - "browserify>events": true, - "browserify>process": true - } - }, - "3box>ipfs>ipfs-mfs>mortice>promise-timeout": { - "globals": { - "clearTimeout": true, - "setTimeout": true - } - }, - "3box>ipfs>ipfs-repo": { - "packages": { - "3box>ipfs>base32.js": true, - "3box>ipfs>cids": true, - "3box>ipfs>datastore-core": true, - "3box>ipfs>dlv": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>ipfs-block": true, - "3box>ipfs>ipfs-repo>bignumber.js": true, - "3box>ipfs>ipfs-repo>datastore-level": true, - "3box>ipfs>ipfs-repo>sort-keys": true, - "3box>ipfs>just-safe-set": true, - "3box>ipfs>pull-stream": true, - "browserify>assert": true, - "browserify>buffer": true, - "browserify>path-browserify": true, - "browserify>timers-browserify": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>ipfs-repo>bignumber.js": { - "globals": { - "crypto": true, - "define": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level": { - "packages": { - "3box>ipfs>interface-datastore": true, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down": true, - "3box>ipfs>ipfs-repo>datastore-level>level-js": true, - "3box>ipfs>pull-stream": true, - "3box>orbit-db>orbit-db-keystore>levelup": true, - "browserify>buffer": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down": { - "packages": { - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>abstract-leveldown": true, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>level-codec": true, - "3box>orbit-db>orbit-db-keystore>levelup>level-errors": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>abstract-leveldown": { - "packages": { - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>abstract-leveldown>level-supports": true, - "3box>orbit-db>orbit-db-cache>level-js>immediate": true, - "browserify>buffer": true, - "watchify>xtend": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>abstract-leveldown>level-supports": { - "packages": { - "watchify>xtend": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>level-codec": { - "packages": { - "browserify>buffer": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>level-js": { - "globals": { - "IDBKeyRange.bound": true, - "IDBKeyRange.lowerBound": true, - "IDBKeyRange.only": true, - "IDBKeyRange.upperBound": true, - "indexedDB.deleteDatabase": true, - "indexedDB.open": true - }, - "packages": { - "3box>ipfs>ipfs-repo>datastore-level>level-js>abstract-leveldown": true, - "3box>ipfs>ipfs-repo>datastore-level>level-js>idb-readable-stream": true, - "3box>orbit-db>orbit-db-cache>level-js>ltgt": true, - "browserify>buffer": true, - "browserify>process": true, - "browserify>stream-browserify": true, - "browserify>util": true, - "watchify>xtend": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>level-js>abstract-leveldown": { - "packages": { - "browserify>insert-module-globals>is-buffer": true, - "browserify>process": true, - "watchify>xtend": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>level-js>idb-readable-stream": { - "globals": { - "IDBKeyRange.bound": true, - "IDBKeyRange.lowerBound": true, - "IDBKeyRange.upperBound": true - }, - "packages": { - "browserify>stream-browserify": true, - "watchify>xtend": true - } - }, - "3box>ipfs>ipfs-repo>sort-keys": { - "packages": { - "geckodriver>got>is-plain-obj": true - } - }, - "3box>ipfs>ipfs-unixfs": { - "packages": { - "3box>ipfs>protons": true - } - }, - "3box>ipfs>ipfs-unixfs-exporter": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>err-code": true, - "3box>ipfs>ipfs-mfs>async-iterator-last": true, - "3box>ipfs>ipfs-mfs>hamt-sharding": true, - "3box>ipfs>ipfs-unixfs": true, - "3box>ipfs>ipfs-unixfs-importer": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipfs-unixfs-importer": { - "packages": { - "3box>ipfs>async-iterator-all": true, - "3box>ipfs>bl": true, - "3box>ipfs>err-code": true, - "3box>ipfs>ipfs-mfs>hamt-sharding": true, - "3box>ipfs>ipfs-unixfs": true, - "3box>ipfs>ipfs-unixfs-importer>async-iterator-batch": true, - "3box>ipfs>ipfs-unixfs-importer>async-iterator-first": true, - "3box>ipfs>ipfs-unixfs-importer>rabin-wasm": true, - "3box>ipfs>ipfs-unixfs-importer>superstruct": true, - "3box>ipfs>ipld-dag-pb": true, - "3box>ipfs>ipld-raw>multihashing-async": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>multihashes": true, - "browserify>buffer": true, - "madge>rc>deep-extend": true - } - }, - "3box>ipfs>ipfs-unixfs-importer>rabin-wasm": { - "globals": { - "Blob": true, - "Response": true, - "WebAssembly": true - }, - "packages": { - "3box>ipfs>ipfs-unixfs-importer>rabin-wasm>assemblyscript": true - } - }, - "3box>ipfs>ipfs-unixfs-importer>rabin-wasm>assemblyscript": { - "globals": { - "WebAssembly.Instance": true, - "WebAssembly.Module": true, - "WebAssembly.instantiateStreaming": true, - "console.log": true - } - }, - "3box>ipfs>ipfs-utils": { - "globals": { - "FileReader": true - }, - "packages": { - "3box>ipfs>ipfs-utils>is-buffer": true, - "3box>ipfs>ipfs-utils>readable-stream": true, - "3box>ipfs>is-pull-stream": true, - "3box>ipfs>kind-of": true, - "@metamask/providers>is-stream": true - } - }, - "3box>ipfs>ipfs-utils>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>ipld": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>ipfs-block": true, - "3box>ipfs>ipld-dag-cbor": true, - "3box>ipfs>ipld-dag-pb": true, - "3box>ipfs>ipld-raw": true, - "3box>ipfs>ipld>typical": true, - "3box>ipfs>merge-options": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>promisify-es6": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipld-dag-cbor": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>ipld-dag-cbor>is-circular": true, - "3box>ipfs>ipld-raw>multihashing-async": true, - "3box>ipfs>multicodec": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true, - "eth-lattice-keyring>gridplus-sdk>borc": true - } - }, - "3box>ipfs>ipld-dag-pb": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>class-is": true, - "3box>ipfs>ipld-raw>multihashing-async": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>protons": true, - "@storybook/react>@storybook/store>stable": true, - "browserify>assert": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipld-raw": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>ipld-raw>multihashing-async": true, - "3box>ipfs>multicodec": true - } - }, - "3box>ipfs>ipld-raw>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>ipld-raw>multihashing-async>murmurhash3js-revisited": true, - "3box>ipfs>multihashes": true, - "browserify>buffer": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>ipld-raw>multihashing-async>murmurhash3js-revisited": { - "globals": { - "define": true - } - }, - "3box>ipfs>ipld>typical": { - "globals": { - "define": true - } - }, - "3box>ipfs>ipns": { - "packages": { - "3box>ipfs>interface-datastore": true, - "3box>ipfs>ipns>timestamp-nano": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>multihashes": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>protons": true, - "base32-encode": true, - "browserify>buffer": true, - "nock>debug": true - } - }, - "3box>ipfs>is-ipfs": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>cids": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>multibase": true, - "3box>ipfs>multihashes": true, - "browserify>buffer": true - } - }, - "3box>ipfs>iso-url": { - "globals": { - "URL": true, - "URLSearchParams": true, - "location": true - } - }, - "3box>ipfs>libp2p": { - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>fsm-event": true, - "3box>ipfs>libp2p-websockets": true, - "3box>ipfs>libp2p>libp2p-connection-manager": true, - "3box>ipfs>libp2p>libp2p-floodsub": true, - "3box>ipfs>libp2p>libp2p-ping": true, - "3box>ipfs>libp2p>libp2p-switch": true, - "3box>ipfs>libp2p>superstruct": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-book": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "browserify>events": true, - "browserify>insert-module-globals>is-buffer": true, - "browserify>process": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p-bootstrap": { - "globals": { - "clearInterval": true, - "setInterval": true - }, - "packages": { - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p-crypto": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>libp2p-crypto>asn1.js": true, - "3box>ipfs>libp2p-crypto>iso-random-stream": true, - "3box>ipfs>libp2p-crypto>libp2p-crypto-secp256k1": true, - "3box>ipfs>libp2p-crypto>multihashing-async": true, - "3box>ipfs>protons": true, - "3box>tweetnacl": true, - "browserify>buffer": true, - "ethereumjs-util>ethereum-cryptography>browserify-aes": true, - "gh-pages>async": true, - "mockttp>node-forge": true - } - }, - "3box>ipfs>libp2p-crypto>asn1.js": { - "packages": { - "3box>ethers>hash.js>minimalistic-assert": true, - "bn.js": true, - "browserify>buffer": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>libp2p-crypto>iso-random-stream": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p-crypto>libp2p-crypto-secp256k1": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>libp2p-crypto>libp2p-crypto-secp256k1>multihashing-async": true, - "eth-trezor-keyring>hdkey>secp256k1": true, - "gh-pages>async": true - } - }, - "3box>ipfs>libp2p-crypto>libp2p-crypto-secp256k1>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>libp2p-crypto>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>libp2p-kad-dht": { - "globals": { - "clearInterval": true, - "clearTimeout": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>base32.js": true, - "3box>ipfs>cids": true, - "3box>ipfs>err-code": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-kad-dht>hashlru": true, - "3box>ipfs>libp2p-kad-dht>heap": true, - "3box>ipfs>libp2p-kad-dht>k-bucket": true, - "3box>ipfs>libp2p-kad-dht>multihashing-async": true, - "3box>ipfs>libp2p-kad-dht>p-queue": true, - "3box>ipfs>libp2p-kad-dht>p-times": true, - "3box>ipfs>libp2p-kad-dht>xor-distance": true, - "3box>ipfs>libp2p-record": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>multihashes": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>promisify-es6": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-stream": true, - "3box>ipfs>pull-stream-to-async-iterator": true, - "3box>ipfs>varint": true, - "@metamask/controllers>abort-controller": true, - "browserify>assert": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>insert-module-globals>is-buffer": true, - "gh-pages>async": true, - "nock>debug": true, - "promise-to-callback": true - } - }, - "3box>ipfs>libp2p-kad-dht>heap": { - "globals": { - "define": true - } - }, - "3box>ipfs>libp2p-kad-dht>k-bucket": { - "packages": { - "browserify>events": true, - "ethereumjs-wallet>randombytes": true - } - }, - "3box>ipfs>libp2p-kad-dht>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>libp2p-kad-dht>p-queue": { - "globals": { - "clearInterval": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "mockttp>@httptoolkit/subscriptions-transport-ws>eventemitter3": true - } - }, - "3box>ipfs>libp2p-kad-dht>p-times": { - "packages": { - "3box>ipfs>libp2p-kad-dht>p-times>p-map": true - } - }, - "3box>ipfs>libp2p-kad-dht>xor-distance": { - "packages": { - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p-keychain": { - "globals": { - "setTimeout": true - }, - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-keychain>sanitize-filename": true, - "3box>ipfs>merge-options": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true, - "gh-pages>async": true, - "mockttp>node-forge": true - } - }, - "3box>ipfs>libp2p-keychain>sanitize-filename": { - "packages": { - "3box>ipfs>libp2p-keychain>sanitize-filename>truncate-utf8-bytes": true - } - }, - "3box>ipfs>libp2p-keychain>sanitize-filename>truncate-utf8-bytes": { - "packages": { - "3box>ipfs>libp2p-keychain>sanitize-filename>truncate-utf8-bytes>utf8-byte-length": true - } - }, - "3box>ipfs>libp2p-record": { - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>libp2p-record>buffer-split": true, - "3box>ipfs>libp2p-record>multihashing-async": true, - "3box>ipfs>protons": true, - "browserify>assert": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true, - "gh-pages>async": true - } - }, - "3box>ipfs>libp2p-record>buffer-split": { - "packages": { - "3box>ipfs>libp2p-record>buffer-split>buffer-indexof": true - } - }, - "3box>ipfs>libp2p-record>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>libp2p-secio": { - "packages": { - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-secio>multihashing-async": true, - "3box>ipfs>libp2p-secio>pull-handshake": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-defer": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-stream": true, - "browserify>assert": true, - "browserify>buffer": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p-secio>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>libp2p-secio>pull-handshake": { - "packages": { - "3box>ipfs>libp2p-secio>pull-handshake>pull-reader": true, - "3box>ipfs>pull-cat": true, - "3box>ipfs>pull-mplex>pull-pair": true, - "3box>ipfs>pull-pushable": true - } - }, - "3box>ipfs>libp2p-secio>pull-handshake>pull-reader": { - "globals": { - "cb": true, - "clearTimeout": true, - "setTimeout": true - }, - "packages": { - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p-secio>pull-length-prefixed": { - "packages": { - "3box>ipfs>libp2p-secio>pull-handshake>pull-reader": true, - "3box>ipfs>pull-pushable": true, - "3box>ipfs>varint": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>ipfs>libp2p-webrtc-star": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>libp2p-webrtc-star>simple-peer": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client": true, - "3box>ipfs>libp2p-webrtc-star>webrtcsupport": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>stream-to-pull-stream": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p-webrtc-star>simple-peer": { - "globals": { - "clearInterval": true, - "console.warn": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>simple-peer>get-browser-rtc": true, - "3box>ipfs>libp2p-webrtc-star>simple-peer>readable-stream": true, - "browserify>buffer": true, - "ethereumjs-wallet>randombytes": true, - "nock>debug": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>libp2p-webrtc-star>simple-peer>get-browser-rtc": { - "globals": { - "RTCIceCandidate": true, - "RTCPeerConnection": true, - "RTCSessionDescription": true, - "mozRTCIceCandidate": true, - "mozRTCPeerConnection": true, - "mozRTCSessionDescription": true, - "webkitRTCIceCandidate": true, - "webkitRTCPeerConnection": true, - "webkitRTCSessionDescription": true - } - }, - "3box>ipfs>libp2p-webrtc-star>simple-peer>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client": { - "globals": { - "clearTimeout": true, - "location": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>component-bind": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>debug": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>indexof": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>parseqs": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>parseuri": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>to-array": true, - "3box>ipfs>libp2p-webrtc-star>socket.io>has-binary2": true, - "mockttp>@httptoolkit/subscriptions-transport-ws>backo2": true, - "pubnub>superagent>component-emitter": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>debug": { - "globals": { - "chrome": true, - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>debug>ms": true, - "browserify>process": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client": { - "globals": { - "MozWebSocket": true, - "WebSocket": true, - "XDomainRequest": true, - "XMLHttpRequest": true, - "addEventListener": true, - "attachEvent": true, - "clearTimeout": true, - "document": true, - "location": true, - "navigator": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>component-inherit": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>debug": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>has-cors": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>yeast": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>indexof": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>parseqs": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>parseuri": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "pubnub>superagent>component-emitter": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>debug": { - "globals": { - "chrome": true, - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>debug>ms": true, - "browserify>process": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser": { - "globals": { - "FileReader": true, - "btoa": true, - "navigator": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser>after": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser>arraybuffer.slice": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser>blob": true, - "3box>ipfs>libp2p-webrtc-star>socket.io>engine.io>engine.io-parser>base64-arraybuffer": true, - "3box>ipfs>libp2p-webrtc-star>socket.io>has-binary2": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser>blob": { - "globals": { - "Blob": true, - "MSBlobBuilder": true, - "MozBlobBuilder": true, - "WebKitBlobBuilder": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>has-cors": { - "globals": { - "XMLHttpRequest": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser": { - "globals": { - "Blob": true, - "File": true, - "FileReader": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser>debug": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser>isarray": true, - "browserify>buffer": true, - "pubnub>superagent>component-emitter": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser>debug": { - "globals": { - "chrome": true, - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser>debug>ms": true, - "browserify>process": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io>has-binary2": { - "globals": { - "Blob": true, - "File": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io>has-binary2>isarray": true, - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p-webrtc-star>webrtcsupport": { - "globals": { - "AudioContext": true, - "MediaStream": true, - "RTCIceCandidate": true, - "RTCPeerConnection": true, - "RTCSessionDescription": true, - "document": true, - "location.protocol": true, - "mozRTCIceCandidate": true, - "mozRTCPeerConnection": true, - "mozRTCSessionDescription": true, - "navigator.getUserMedia": true, - "navigator.mozGetUserMedia": true, - "navigator.msGetUserMedia": true, - "navigator.userAgent.match": true, - "navigator.webkitGetUserMedia": true, - "webkitAudioContext": true, - "webkitMediaStream": true, - "webkitRTCPeerConnection": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi": { - "globals": { - "setTimeout": true - }, - "packages": { - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star": { - "globals": { - "console.error": true - }, - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client": true, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true, - "uuid": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream": { - "globals": { - "console.error": true - }, - "packages": { - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>data-queue": true, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>debug": true, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>uuid": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>data-queue": { - "packages": { - "browserify>events": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>debug": { - "globals": { - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "analytics-node>ms": true, - "browserify>process": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>uuid": { - "globals": { - "crypto": true, - "msCrypto": true - } - }, - "3box>ipfs>libp2p-websockets": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>libp2p-websockets>pull-ws": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>multiaddr-to-uri": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "browserify>os-browserify": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p-websockets>pull-ws": { - "globals": { - "WebSocket": true, - "location": true - }, - "packages": { - "3box>ipfs>libp2p-websockets>pull-ws>relative-url": true, - "browserify>browser-resolve": true, - "browserify>events": true, - "browserify>https-browserify": true, - "browserify>process": true, - "browserify>stream-http": true, - "browserify>timers-browserify": true, - "browserify>url": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>ipfs>libp2p-websockets>pull-ws>relative-url": { - "packages": { - "browserify>url": true - } - }, - "3box>ipfs>libp2p>libp2p-connection-manager": { - "packages": { - "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor": true, - "browserify>events": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor": { - "globals": { - "clearInterval": true, - "clearTimeout": true, - "document": true, - "performance": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor>debug": true, - "browserify>events": true, - "browserify>process": true, - "lodash": true - } - }, - "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor>debug": { - "globals": { - "chrome": true, - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor>debug>ms": true, - "browserify>process": true - } - }, - "3box>ipfs>libp2p>libp2p-floodsub": { - "packages": { - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub": true, - "3box>ipfs>pull-stream": true, - "browserify>assert": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>err-code": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub>time-cache": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-pushable": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>insert-module-globals>is-buffer": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub>time-cache": { - "packages": { - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub>time-cache>lodash.throttle": true - } - }, - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub>time-cache>lodash.throttle": { - "globals": { - "clearTimeout": true, - "setTimeout": true - } - }, - "3box>ipfs>libp2p>libp2p-ping": { - "packages": { - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-secio>pull-handshake": true, - "3box>ipfs>pull-stream": true, - "browserify>events": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p>libp2p-switch": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>err-code": true, - "3box>ipfs>fsm-event": true, - "3box>ipfs>ipfs-bitswap>moving-average": true, - "3box>ipfs>libp2p-kad-dht>hashlru": true, - "3box>ipfs>libp2p>libp2p-switch>bignumber.js": true, - "3box>ipfs>libp2p>libp2p-switch>libp2p-circuit": true, - "3box>ipfs>libp2p>libp2p-switch>libp2p-identify": true, - "3box>ipfs>libp2p>libp2p-switch>multistream-select": true, - "3box>ipfs>libp2p>libp2p-switch>retimer": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-stream": true, - "browserify>assert": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>bignumber.js": { - "globals": { - "crypto": true, - "define": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>libp2p-circuit": { - "packages": { - "3box>ipfs>libp2p-secio>pull-handshake": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-stream": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>libp2p-identify": { - "globals": { - "console.warn": true - }, - "packages": { - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>multistream-select": { - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>libp2p-secio>pull-handshake": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>libp2p>libp2p-switch>multistream-select>semver": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-stream": true, - "3box>ipfs>varint": true, - "browserify>assert": true, - "browserify>buffer": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>multistream-select>semver": { - "globals": { - "console": true - }, - "packages": { - "browserify>process": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>retimer": { - "globals": { - "clearTimeout": true, - "setTimeout": true - } - }, - "3box>ipfs>mafmt": { - "packages": { - "3box>ipfs>multiaddr": true - } - }, - "3box>ipfs>merge-options": { - "packages": { - "geckodriver>got>is-plain-obj": true - } - }, - "3box>ipfs>multiaddr": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>class-is": true, - "3box>ipfs>multiaddr>hi-base32": true, - "3box>ipfs>multiaddr>is-ip": true, - "3box>ipfs>varint": true, - "browserify>buffer": true, - "react-devtools>ip": true - } - }, - "3box>ipfs>multiaddr-to-uri": { - "packages": { - "3box>ipfs>multiaddr": true - } - }, - "3box>ipfs>multiaddr>hi-base32": { - "globals": { - "define": true - }, - "packages": { - "browserify>process": true - } - }, - "3box>ipfs>multiaddr>is-ip": { - "packages": { - "chromedriver>tcp-port-used>is2>ip-regex": true - } - }, - "3box>ipfs>multibase": { - "packages": { - "3box>ipfs>multibase>base-x": true, - "browserify>buffer": true - } - }, - "3box>ipfs>multibase>base-x": { - "packages": { - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>ipfs>multicodec": { - "packages": { - "3box>ipfs>varint": true, - "browserify>buffer": true - } - }, - "3box>ipfs>multihashes": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>varint": true, - "browserify>buffer": true - } - }, - "3box>ipfs>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>multihashing-async>murmurhash3js": { - "globals": { - "define": true - } - }, - "3box>ipfs>multihashing-async>nodeify": { - "globals": { - "setTimeout": true - }, - "packages": { - "3box>ipfs>multihashing-async>nodeify>is-promise": true, - "3box>ipfs>multihashing-async>nodeify>promise": true, - "browserify>process": true, - "browserify>timers-browserify": true - } - }, - "3box>ipfs>multihashing-async>nodeify>promise": { - "globals": { - "setImediate": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>multihashing-async>nodeify>is-promise": true, - "browserify>process": true - } - }, - "3box>ipfs>peer-book": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>peer-id": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>multihashes": true, - "browserify>assert": true, - "browserify>buffer": true, - "gh-pages>async": true - } - }, - "3box>ipfs>peer-info": { - "packages": { - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info>unique-by": true, - "browserify>assert": true - } - }, - "3box>ipfs>protons": { - "packages": { - "3box>ipfs>protons>protocol-buffers-schema": true, - "3box>ipfs>protons>signed-varint": true, - "3box>ipfs>varint": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>ipfs>protons>signed-varint": { - "packages": { - "3box>ipfs>varint": true - } - }, - "3box>ipfs>pull-mplex": { - "packages": { - "3box>ipfs>pull-abortable": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-mplex>looper": true, - "3box>ipfs>pull-mplex>pull-through": true, - "3box>ipfs>pull-pushable": true, - "3box>ipfs>pull-stream": true, - "3box>ipfs>varint": true, - "browserify>buffer": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>pull-mplex>interface-connection": { - "packages": { - "3box>ipfs>pull-defer": true - } - }, - "3box>ipfs>pull-mplex>pull-through": { - "packages": { - "3box>ipfs>stream-to-pull-stream>looper": true - } - }, - "3box>ipfs>pull-sort": { - "packages": { - "3box>ipfs>pull-defer": true, - "3box>ipfs>pull-stream": true - } - }, - "3box>ipfs>pull-stream": { - "globals": { - "console.log": true - } - }, - "3box>ipfs>pull-stream-to-async-iterator": { - "packages": { - "3box>ipfs>pull-stream": true - } - }, - "3box>ipfs>pull-stream-to-stream": { - "packages": { - "browserify>process": true, - "browserify>stream-browserify": true, - "browserify>timers-browserify": true - } - }, - "3box>ipfs>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>receptacle": { - "globals": { - "clearTimeout": true, - "setTimeout": true - }, - "packages": { - "analytics-node>ms": true - } - }, - "3box>ipfs>stream-to-pull-stream": { - "globals": { - "console.error": true - }, - "packages": { - "3box>ipfs>pull-stream": true, - "3box>ipfs>stream-to-pull-stream>looper": true, - "browserify>process": true - } - }, - "3box>js-sha256": { - "globals": { - "define": true - }, - "packages": { - "browserify>process": true - } - }, - "3box>muport-did-resolver": { - "packages": { - "3box>did-jwt>did-resolver": true, - "@babel/runtime": true, - "node-fetch": true - } - }, - "3box>orbit-db": { - "globals": { - "console.log": true - }, - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>multihashes": true, - "3box>orbit-db>ipfs-pubsub-1on1": true, - "3box>orbit-db>logplease": true, - "3box>orbit-db>orbit-db-access-controllers": true, - "3box>orbit-db>orbit-db-cache": true, - "3box>orbit-db>orbit-db-counterstore": true, - "3box>orbit-db>orbit-db-docstore": true, - "3box>orbit-db>orbit-db-eventstore": true, - "3box>orbit-db>orbit-db-feedstore": true, - "3box>orbit-db>orbit-db-identity-provider": true, - "3box>orbit-db>orbit-db-io": true, - "3box>orbit-db>orbit-db-keystore": true, - "3box>orbit-db>orbit-db-kvstore": true, - "3box>orbit-db>orbit-db-pubsub": true, - "browserify>path-browserify": true - } - }, - "3box>orbit-db>ipfs-pubsub-1on1": { - "globals": { - "clearInterval": true, - "setInterval": true - }, - "packages": { - "3box>orbit-db>ipfs-pubsub-1on1>safe-buffer": true, - "browserify>events": true, - "browserify>path-browserify": true - } - }, - "3box>orbit-db>ipfs-pubsub-1on1>safe-buffer": { - "packages": { - "browserify>buffer": true - } - }, - "3box>orbit-db>logplease": { - "globals": { - "LOG": true, - "console.error": true, - "console.log": true - }, - "packages": { - "browserify>browser-resolve": true, - "browserify>events": true, - "browserify>process": true, - "browserify>util": true - } - }, - "3box>orbit-db>orbit-db-access-controllers": { - "globals": { - "console.log": true - }, - "packages": { - "3box>orbit-db>orbit-db-access-controllers>p-map-series": true, - "3box>orbit-db>orbit-db-io": true, - "browserify>events": true, - "browserify>path-browserify": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>orbit-db>orbit-db-access-controllers>p-map-series": { - "packages": { - "3box>orbit-db>orbit-db-store>p-each-series>p-reduce": true - } - }, - "3box>orbit-db>orbit-db-cache": { - "packages": { - "3box>orbit-db>logplease": true, - "3box>orbit-db>orbit-db-cache>level-js": true, - "browserify>path-browserify": true - } - }, - "3box>orbit-db>orbit-db-cache>level-js": { - "globals": { - "IDBKeyRange.bound": true, - "IDBKeyRange.lowerBound": true, - "IDBKeyRange.upperBound": true, - "indexedDB": true - }, - "packages": { - "3box>orbit-db>orbit-db-cache>level-js>abstract-leveldown": true, - "3box>orbit-db>orbit-db-cache>level-js>immediate": true, - "3box>orbit-db>orbit-db-cache>level-js>ltgt": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true, - "pumpify>inherits": true, - "stylelint>write-file-atomic>typedarray-to-buffer": true - } - }, - "3box>orbit-db>orbit-db-cache>level-js>abstract-leveldown": { - "packages": { - "browserify>insert-module-globals>is-buffer": true, - "browserify>process": true, - "watchify>xtend": true - } - }, - "3box>orbit-db>orbit-db-cache>level-js>immediate": { - "globals": { - "MessageChannel": true, - "MutationObserver": true, - "WebKitMutationObserver": true, - "clearTimeout": true, - "document.createElement": true, - "document.createTextNode": true, - "document.documentElement.appendChild": true, - "setImmediate": true, - "setTimeout": true - }, - "packages": { - "browserify>process": true - } - }, - "3box>orbit-db>orbit-db-cache>level-js>ltgt": { - "packages": { - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>orbit-db>orbit-db-counterstore": { - "packages": { - "3box>orbit-db>orbit-db-counterstore>crdts": true, - "3box>orbit-db>orbit-db-store": true - } - }, - "3box>orbit-db>orbit-db-docstore": { - "packages": { - "3box>orbit-db>orbit-db-docstore>p-map": true, - "3box>orbit-db>orbit-db-store": true, - "readable-stream": true - } - }, - "3box>orbit-db>orbit-db-eventstore": { - "packages": { - "3box>orbit-db>orbit-db-store": true - } - }, - "3box>orbit-db>orbit-db-feedstore": { - "packages": { - "3box>orbit-db>orbit-db-eventstore": true - } - }, - "3box>orbit-db>orbit-db-identity-provider": { - "packages": { - "3box>orbit-db>orbit-db-keystore": true - } - }, - "3box>orbit-db>orbit-db-io": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>ipld-dag-pb": true, - "browserify>buffer": true - } - }, - "3box>orbit-db>orbit-db-keystore": { - "globals": { - "console.error": true, - "console.log": true - }, - "packages": { - "3box>ethers>elliptic": true, - "3box>ipfs>libp2p-crypto": true, - "3box>orbit-db>orbit-db-cache>level-js": true, - "3box>orbit-db>orbit-db-keystore>levelup": true, - "3box>orbit-db>orbit-db-keystore>lru": true, - "eth-trezor-keyring>hdkey>secp256k1": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>orbit-db>orbit-db-keystore>levelup": { - "packages": { - "3box>orbit-db>orbit-db-keystore>levelup>deferred-leveldown": true, - "3box>orbit-db>orbit-db-keystore>levelup>level-errors": true, - "3box>orbit-db>orbit-db-keystore>levelup>level-iterator-stream": true, - "browserify>assert": true, - "browserify>events": true, - "browserify>process": true, - "browserify>util": true, - "watchify>xtend": true - } - }, - "3box>orbit-db>orbit-db-keystore>levelup>deferred-leveldown": { - "packages": { - "3box>orbit-db>orbit-db-cache>level-js>abstract-leveldown": true, - "pumpify>inherits": true - } - }, - "3box>orbit-db>orbit-db-keystore>levelup>level-errors": { - "packages": { - "webpack>memory-fs>errno": true - } - }, - "3box>orbit-db>orbit-db-keystore>levelup>level-iterator-stream": { - "packages": { - "3box>orbit-db>orbit-db-keystore>levelup>level-iterator-stream>readable-stream": true, - "pumpify>inherits": true, - "watchify>xtend": true - } - }, - "3box>orbit-db>orbit-db-keystore>levelup>level-iterator-stream>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>orbit-db>orbit-db-keystore>lru": { - "packages": { - "browserify>events": true, - "pumpify>inherits": true - } - }, - "3box>orbit-db>orbit-db-kvstore": { - "packages": { - "3box>orbit-db>orbit-db-store": true - } - }, - "3box>orbit-db>orbit-db-pubsub": { - "packages": { - "3box>orbit-db>logplease": true, - "3box>orbit-db>orbit-db-pubsub>ipfs-pubsub-peer-monitor": true, - "3box>orbit-db>orbit-db-pubsub>p-series": true, - "browserify>buffer": true - } - }, - "3box>orbit-db>orbit-db-pubsub>ipfs-pubsub-peer-monitor": { - "globals": { - "clearInterval": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "browserify>events": true - } - }, - "3box>orbit-db>orbit-db-pubsub>p-series": { - "packages": { - "3box>orbit-db>orbit-db-pubsub>p-series>@sindresorhus/is": true, - "3box>orbit-db>orbit-db-store>p-each-series>p-reduce": true - } - }, - "3box>orbit-db>orbit-db-pubsub>p-series>@sindresorhus/is": { - "packages": { - "browserify>insert-module-globals>is-buffer": true, - "browserify>util": true - } - }, - "3box>orbit-db>orbit-db-store": { - "globals": { - "clearInterval": true, - "console.error": true, - "console.warn": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>3box-orbitdb-plugins>ipfs-log": true, - "3box>ipfs>libp2p-kad-dht>p-times>p-map": true, - "3box>orbit-db>logplease": true, - "3box>orbit-db>orbit-db-io": true, - "3box>orbit-db>orbit-db-store>p-each-series": true, - "browserify>buffer": true, - "browserify>events": true, - "readable-stream": true - } - }, - "3box>orbit-db>orbit-db-store>p-each-series": { - "packages": { - "3box>orbit-db>orbit-db-store>p-each-series>p-reduce": true - } - }, - "3box>store": { - "globals": { - "ActiveXObject": true, - "console": true - } - }, - "3box>tweetnacl": { - "globals": { - "crypto": true, - "msCrypto": true, - "nacl": "write" - }, - "packages": { - "browserify>browser-resolve": true - } - }, - "3box>tweetnacl-util": { - "globals": { - "atob": true, - "btoa": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, "@babel/code-frame": { "globals": { "console.warn": true @@ -2381,9 +192,9 @@ }, "@ensdomains/content-hash>cids>multihashes": { "packages": { - "3box>ipfs>varint": true, "@ensdomains/content-hash>cids>multibase": true, - "@ensdomains/content-hash>cids>uint8arrays": true + "@ensdomains/content-hash>cids>uint8arrays": true, + "@ensdomains/content-hash>multihashes>varint": true } }, "@ensdomains/content-hash>cids>uint8arrays": { @@ -2428,17 +239,17 @@ }, "@ensdomains/content-hash>multihashes": { "packages": { - "3box>ipfs>varint": true, "@ensdomains/content-hash>multihashes>multibase": true, + "@ensdomains/content-hash>multihashes>varint": true, "@ensdomains/content-hash>multihashes>web-encoding": true, "browserify>buffer": true } }, "@ensdomains/content-hash>multihashes>multibase": { "packages": { - "3box>ipfs>bs58>base-x": true, "@ensdomains/content-hash>multihashes>web-encoding": true, - "browserify>buffer": true + "browserify>buffer": true, + "ethereumjs-wallet>bs58check>bs58>base-x": true } }, "@ensdomains/content-hash>multihashes>web-encoding": { @@ -2531,42 +342,13 @@ }, "@keystonehq/bc-ur-registry-eth": { "packages": { - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util": true, "@keystonehq/bc-ur-registry-eth>@keystonehq/bc-ur-registry": true, "@keystonehq/bc-ur-registry-eth>hdkey": true, "browserify>buffer": true, + "eth-lattice-keyring>@ethereumjs/util": true, "uuid": true } }, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util": { - "packages": { - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>@ethereumjs/rlp": true, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>ethereum-cryptography": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>@ethereumjs/rlp": { - "globals": { - "TextEncoder": true - } - }, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>ethereum-cryptography": { - "globals": { - "TextDecoder": true, - "crypto": true - }, - "packages": { - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>ethereum-cryptography>@noble/hashes": true, - "eth-json-rpc-middleware>@metamask/eth-sig-util>ethereum-cryptography>@noble/secp256k1": true - } - }, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>ethereum-cryptography>@noble/hashes": { - "globals": { - "TextEncoder": true, - "crypto": true - } - }, "@keystonehq/bc-ur-registry-eth>@keystonehq/bc-ur-registry": { "globals": { "define": true @@ -2594,7 +376,7 @@ }, "@keystonehq/bc-ur-registry-eth>hdkey>secp256k1": { "packages": { - "3box>ethers>elliptic": true + "ethers>@ethersproject/signing-key>elliptic": true } }, "@keystonehq/metamask-airgapped-keyring": { @@ -2613,10 +395,10 @@ "packages": { "@ethereumjs/tx": true, "@keystonehq/bc-ur-registry-eth": true, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util": true, "@keystonehq/bc-ur-registry-eth>hdkey": true, "@keystonehq/metamask-airgapped-keyring>@keystonehq/base-eth-keyring>rlp": true, "browserify>buffer": true, + "eth-lattice-keyring>@ethereumjs/util": true, "uuid": true } }, @@ -3024,38 +806,38 @@ "@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": true, "@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": true, "@metamask/controllers>eth-method-registry>ethjs>ethjs-query": true, - "@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-provider-http": true, "ethjs>ethjs-unit": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": { "packages": { "@metamask/controllers>eth-method-registry>ethjs>bn.js": true, - "@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": { "packages": { "@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": true, - "@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "promise-to-callback": true } }, "@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": { "packages": { "@metamask/controllers>eth-method-registry>ethjs>bn.js": true, - "@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, @@ -3070,11 +852,6 @@ "promise-to-callback": true } }, - "@metamask/controllers>eth-method-registry>ethjs>js-sha3": { - "packages": { - "browserify>process": true - } - }, "@metamask/controllers>eth-phishing-detect": { "packages": { "eslint>optionator>fast-levenshtein": true @@ -3239,7 +1016,6 @@ }, "@metamask/controllers>web3-provider-engine>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "@metamask/controllers>web3-provider-engine>ethereumjs-util>ethjs-util": true, "bn.js": true, "browserify>assert": true, @@ -3247,7 +1023,8 @@ "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>safe-buffer": true + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "@metamask/controllers>web3-provider-engine>ethereumjs-util>ethjs-util": { @@ -3337,7 +1114,6 @@ }, "@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>eth-sig-util>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>eth-sig-util>ethereumjs-util>ethjs-util": true, "bn.js": true, "browserify>assert": true, @@ -3345,7 +1121,8 @@ "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>safe-buffer": true + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>eth-sig-util>ethereumjs-util>ethjs-util": { @@ -3375,16 +1152,15 @@ }, "@metamask/eth-ledger-bridge-keyring>eth-sig-util": { "packages": { - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util": true, "browserify>buffer": true, + "eth-sig-util>tweetnacl": true, + "eth-sig-util>tweetnacl-util": true, "ethereumjs-abi": true } }, "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethjs-util": true, "bn.js": true, "browserify>assert": true, @@ -3392,7 +1168,8 @@ "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>safe-buffer": true + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethjs-util": { @@ -3404,13 +1181,23 @@ }, "@metamask/eth-ledger-bridge-keyring>hdkey": { "packages": { + "@metamask/eth-ledger-bridge-keyring>hdkey>secp256k1": true, "browserify>assert": true, "browserify>crypto-browserify": true, "eth-trezor-keyring>hdkey>coinstring": true, - "eth-trezor-keyring>hdkey>secp256k1": true, "ethereumjs-wallet>safe-buffer": true } }, + "@metamask/eth-ledger-bridge-keyring>hdkey>secp256k1": { + "packages": { + "bn.js": true, + "browserify>insert-module-globals>is-buffer": true, + "eth-trezor-keyring>hdkey>secp256k1>bip66": true, + "ethereumjs-util>create-hash": true, + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true + } + }, "@metamask/eth-token-tracker": { "globals": { "console.warn": true @@ -3469,38 +1256,38 @@ "@metamask/eth-token-tracker>ethjs>ethjs-abi": true, "@metamask/eth-token-tracker>ethjs>ethjs-contract": true, "@metamask/eth-token-tracker>ethjs>ethjs-query": true, - "@metamask/eth-token-tracker>ethjs>js-sha3": true, "browserify>buffer": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-provider-http": true, "ethjs>ethjs-unit": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/eth-token-tracker>ethjs>ethjs-abi": { "packages": { "@metamask/eth-token-tracker>ethjs>bn.js": true, - "@metamask/eth-token-tracker>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/eth-token-tracker>ethjs>ethjs-contract": { "packages": { "@metamask/eth-token-tracker>ethjs>ethjs-contract>ethjs-abi": true, - "@metamask/eth-token-tracker>ethjs>js-sha3": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "promise-to-callback": true } }, "@metamask/eth-token-tracker>ethjs>ethjs-contract>ethjs-abi": { "packages": { "@metamask/eth-token-tracker>ethjs>bn.js": true, - "@metamask/eth-token-tracker>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, @@ -3515,11 +1302,6 @@ "promise-to-callback": true } }, - "@metamask/eth-token-tracker>ethjs>js-sha3": { - "packages": { - "browserify>process": true - } - }, "@metamask/etherscan-link": { "globals": { "URL": true @@ -3678,38 +1460,38 @@ "@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": true, "@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": true, "@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": true, - "@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-provider-http": true, "ethjs>ethjs-unit": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": { "packages": { "@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>bn.js": true, - "@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": { "packages": { "@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": true, - "@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "promise-to-callback": true } }, "@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": { "packages": { "@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>bn.js": true, - "@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, @@ -3724,11 +1506,6 @@ "promise-to-callback": true } }, - "@metamask/rpc-methods>@metamask/controllers>eth-method-registry>ethjs>js-sha3": { - "packages": { - "browserify>process": true - } - }, "@metamask/rpc-methods>@metamask/controllers>ethereumjs-wallet": { "packages": { "@metamask/rpc-methods>@metamask/controllers>ethereumjs-wallet>uuid": true, @@ -3869,38 +1646,38 @@ "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": true, "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": true, "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": true, - "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-provider-http": true, "ethjs>ethjs-unit": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": { "packages": { "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>bn.js": true, - "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": { "packages": { "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": true, - "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "promise-to-callback": true } }, "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": { "packages": { "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>bn.js": true, - "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, @@ -3915,11 +1692,6 @@ "promise-to-callback": true } }, - "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": { - "packages": { - "browserify>process": true - } - }, "@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet": { "packages": { "@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet>uuid": true, @@ -4071,38 +1843,38 @@ "@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": true, "@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": true, "@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": true, - "@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-provider-http": true, "ethjs>ethjs-unit": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": { "packages": { "@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>bn.js": true, - "@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": { "packages": { "@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": true, - "@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "promise-to-callback": true } }, "@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": { "packages": { "@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>bn.js": true, - "@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, @@ -4117,11 +1889,6 @@ "promise-to-callback": true } }, - "@metamask/snap-controllers>@metamask/controllers>eth-method-registry>ethjs>js-sha3": { - "packages": { - "browserify>process": true - } - }, "@metamask/snap-controllers>@metamask/controllers>ethereumjs-wallet": { "packages": { "@metamask/snap-controllers>@metamask/controllers>ethereumjs-wallet>uuid": true, @@ -4339,7 +2106,6 @@ }, "@metamask/snap-controllers>tar-stream": { "packages": { - "@metamask/snap-controllers>tar-stream>bl": true, "@metamask/snap-controllers>tar-stream>fs-constants": true, "@metamask/snap-controllers>tar-stream>readable-stream": true, "browserify>buffer": true, @@ -4347,13 +2113,7 @@ "browserify>string_decoder": true, "browserify>util": true, "end-of-stream": true, - "pumpify>inherits": true - } - }, - "@metamask/snap-controllers>tar-stream>bl": { - "packages": { - "@metamask/snap-controllers>tar-stream>readable-stream": true, - "browserify>buffer": true, + "madge>ora>bl": true, "pumpify>inherits": true } }, @@ -4467,6 +2227,14 @@ "redux-thunk": true } }, + "@segment/loosely-validate-event": { + "packages": { + "@segment/loosely-validate-event>component-type": true, + "@segment/loosely-validate-event>join-component": true, + "browserify>assert": true, + "browserify>buffer": true + } + }, "@sentry/browser": { "globals": { "XMLHttpRequest": true, @@ -4580,16 +2348,6 @@ "localStorage": true } }, - "@storybook/components>qs": { - "packages": { - "string.prototype.matchall>side-channel": true - } - }, - "@storybook/react>@storybook/store>stable": { - "globals": { - "define": true - } - }, "@truffle/codec": { "packages": { "@truffle/codec>@truffle/abi-utils": true, @@ -4817,7 +2575,15 @@ }, "@truffle/codec>web3-utils>ethereum-bloom-filters": { "packages": { - "ethers>@ethersproject/keccak256>js-sha3": true + "@truffle/codec>web3-utils>ethereum-bloom-filters>js-sha3": true + } + }, + "@truffle/codec>web3-utils>ethereum-bloom-filters>js-sha3": { + "globals": { + "define": true + }, + "packages": { + "browserify>process": true } }, "@truffle/decoder": { @@ -4865,107 +2631,42 @@ "browserify>browser-resolve": true } }, - "@zxing/browser": { - "globals": { - "HTMLElement": true, - "HTMLImageElement": true, - "HTMLVideoElement": true, - "URL.createObjectURL": true, - "clearTimeout": true, - "console.error": true, - "console.warn": true, - "document": true, - "navigator": true, - "setTimeout": true - }, - "packages": { - "@zxing/library": true - } - }, - "@zxing/library": { - "globals": { - "TextDecoder": true, - "TextEncoder": true, - "btoa": true, - "clearTimeout": true, - "define": true, - "document.createElement": true, - "document.createElementNS": true, - "document.getElementById": true, - "navigator.mediaDevices.enumerateDevices": true, - "navigator.mediaDevices.getUserMedia": true, - "setTimeout": true - } - }, - "addons-linter>sha.js": { - "packages": { - "ethereumjs-wallet>safe-buffer": true, - "pumpify>inherits": true - } - }, - "analytics-node": { - "globals": { - "clearTimeout": true, - "console.log": true, - "setImmediate": true, - "setTimeout": true - }, - "packages": { - "analytics-node>@segment/loosely-validate-event": true, - "analytics-node>axios": true, - "analytics-node>axios-retry": true, - "analytics-node>lodash.isstring": true, - "analytics-node>md5": true, - "analytics-node>ms": true, - "analytics-node>remove-trailing-slash": true, - "analytics-node>uuid": true, - "browserify>assert": true, - "browserify>process": true - } - }, - "analytics-node>@segment/loosely-validate-event": { - "packages": { - "analytics-node>@segment/loosely-validate-event>component-type": true, - "analytics-node>@segment/loosely-validate-event>join-component": true, - "browserify>assert": true, - "browserify>buffer": true - } - }, - "analytics-node>axios": { - "globals": { - "FormData": true, - "URLSearchParams": true, - "XMLHttpRequest": true, - "btoa": true, + "@zxing/browser": { + "globals": { + "HTMLElement": true, + "HTMLImageElement": true, + "HTMLVideoElement": true, + "URL.createObjectURL": true, + "clearTimeout": true, + "console.error": true, "console.warn": true, "document": true, - "location.href": true, "navigator": true, "setTimeout": true }, "packages": { - "browserify>process": true + "@zxing/library": true } }, - "analytics-node>axios-retry": { + "@zxing/library": { "globals": { + "TextDecoder": true, + "TextEncoder": true, + "btoa": true, + "clearTimeout": true, + "define": true, + "document.createElement": true, + "document.createElementNS": true, + "document.getElementById": true, + "navigator.mediaDevices.enumerateDevices": true, + "navigator.mediaDevices.getUserMedia": true, "setTimeout": true - }, - "packages": { - "geckodriver>got>is-retry-allowed": true } }, - "analytics-node>md5": { + "addons-linter>sha.js": { "packages": { - "analytics-node>md5>charenc": true, - "analytics-node>md5>crypt": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "analytics-node>uuid": { - "globals": { - "crypto": true, - "msCrypto": true + "ethereumjs-wallet>safe-buffer": true, + "pumpify>inherits": true } }, "await-semaphore": { @@ -5059,7 +2760,7 @@ }, "browserify>crypto-browserify>browserify-cipher>browserify-des>des.js": { "packages": { - "3box>ethers>hash.js>minimalistic-assert": true, + "ethers>@ethersproject/sha2>hash.js>minimalistic-assert": true, "pumpify>inherits": true } }, @@ -5071,7 +2772,6 @@ }, "browserify>crypto-browserify>browserify-sign": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>buffer": true, "browserify>crypto-browserify>create-hmac": true, @@ -5079,14 +2779,15 @@ "browserify>crypto-browserify>public-encrypt>parse-asn1": true, "browserify>stream-browserify": true, "ethereumjs-util>create-hash": true, + "ethers>@ethersproject/signing-key>elliptic": true, "pumpify>inherits": true } }, "browserify>crypto-browserify>create-ecdh": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, - "browserify>buffer": true + "browserify>buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "browserify>crypto-browserify>create-hmac": { @@ -5109,8 +2810,8 @@ }, "browserify>crypto-browserify>diffie-hellman>miller-rabin": { "packages": { - "3box>ethers>elliptic>brorand": true, - "bn.js": true + "bn.js": true, + "ethers>@ethersproject/signing-key>elliptic>brorand": true } }, "browserify>crypto-browserify>pbkdf2": { @@ -5157,10 +2858,10 @@ }, "browserify>crypto-browserify>public-encrypt>parse-asn1>asn1.js": { "packages": { - "3box>ethers>hash.js>minimalistic-assert": true, "bn.js": true, "browserify>buffer": true, "browserify>vm-browserify": true, + "ethers>@ethersproject/sha2>hash.js>minimalistic-assert": true, "pumpify>inherits": true } }, @@ -5423,15 +3124,6 @@ "string.prototype.matchall>call-bind": true } }, - "enzyme>object-inspect": { - "globals": { - "HTMLElement": true, - "WeakRef": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, "enzyme>object-is": { "packages": { "globalthis>define-properties": true, @@ -5537,13 +3229,13 @@ }, "eth-json-rpc-middleware>@metamask/eth-sig-util": { "packages": { - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util": true, "browserify>buffer": true, "eth-json-rpc-middleware>@metamask/eth-sig-util>bn.js": true, "eth-json-rpc-middleware>@metamask/eth-sig-util>ethereum-cryptography": true, - "eth-json-rpc-middleware>@metamask/eth-sig-util>ethjs-util": true + "eth-json-rpc-middleware>@metamask/eth-sig-util>ethjs-util": true, + "eth-lattice-keyring>@ethereumjs/util": true, + "eth-sig-util>tweetnacl": true, + "eth-sig-util>tweetnacl-util": true } }, "eth-json-rpc-middleware>@metamask/eth-sig-util>bn.js": { @@ -5566,14 +3258,6 @@ "crypto": true } }, - "eth-json-rpc-middleware>@metamask/eth-sig-util>ethereum-cryptography>@noble/secp256k1": { - "globals": { - "crypto": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, "eth-json-rpc-middleware>@metamask/eth-sig-util>ethjs-util": { "packages": { "browserify>buffer": true, @@ -5687,44 +3371,62 @@ "clearInterval": true, "fetch": true, "open": true, - "setInterval": true, - "txData.type": true + "setInterval": true }, "packages": { "browserify>buffer": true, "browserify>crypto-browserify": true, "browserify>events": true, - "eth-lattice-keyring>@ethereumjs/common": true, "eth-lattice-keyring>@ethereumjs/tx": true, + "eth-lattice-keyring>@ethereumjs/util": true, "eth-lattice-keyring>bn.js": true, "eth-lattice-keyring>gridplus-sdk": true, - "eth-lattice-keyring>rlp": true, - "eth-lattice-keyring>secp256k1": true, - "ethereumjs-util": true + "eth-lattice-keyring>rlp": true } }, - "eth-lattice-keyring>@ethereumjs/common": { + "eth-lattice-keyring>@ethereumjs/tx": { "packages": { - "@ethereumjs/common>crc-32": true, + "@ethereumjs/common": true, "browserify>buffer": true, - "browserify>events": true, + "browserify>insert-module-globals>is-buffer": true, "ethereumjs-util": true } }, - "eth-lattice-keyring>@ethereumjs/tx": { + "eth-lattice-keyring>@ethereumjs/util": { "packages": { "browserify>buffer": true, "browserify>insert-module-globals>is-buffer": true, - "eth-lattice-keyring>@ethereumjs/tx>@ethereumjs/common": true, - "ethereumjs-util": true + "eth-lattice-keyring>@ethereumjs/util>@ethereumjs/rlp": true, + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography": true + } + }, + "eth-lattice-keyring>@ethereumjs/util>@ethereumjs/rlp": { + "globals": { + "TextEncoder": true } }, - "eth-lattice-keyring>@ethereumjs/tx>@ethereumjs/common": { + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography": { + "globals": { + "TextDecoder": true, + "crypto": true + }, "packages": { - "@ethereumjs/common>crc-32": true, - "browserify>buffer": true, - "browserify>events": true, - "ethereumjs-util": true + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@noble/hashes": true, + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@noble/secp256k1": true + } + }, + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true + } + }, + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@noble/secp256k1": { + "globals": { + "crypto": true + }, + "packages": { + "browserify>browser-resolve": true } }, "eth-lattice-keyring>bn.js": { @@ -5737,13 +3439,18 @@ }, "eth-lattice-keyring>gridplus-sdk": { "globals": { + "AbortController": true, + "Request": true, "__values": true, + "caches": true, + "clearTimeout": true, + "console.error": true, "console.log": true, "console.warn": true, + "fetch": true, "setTimeout": true }, "packages": { - "3box>ethers>elliptic": true, "@ethereumjs/common>crc-32": true, "@metamask/controllers>@ethersproject/abi": true, "bn.js": true, @@ -5756,13 +3463,13 @@ "eth-lattice-keyring>gridplus-sdk>bitwise": true, "eth-lattice-keyring>gridplus-sdk>borc": true, "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser": true, + "eth-lattice-keyring>gridplus-sdk>js-sha3": true, "eth-lattice-keyring>gridplus-sdk>rlp": true, - "eth-lattice-keyring>gridplus-sdk>secp256k1": true, - "eth-lattice-keyring>gridplus-sdk>superagent": true, "ethereumjs-wallet>aes-js": true, "ethereumjs-wallet>bs58check": true, - "ethers>@ethersproject/keccak256>js-sha3": true, "ethers>@ethersproject/sha2>hash.js": true, + "ethers>@ethersproject/signing-key>elliptic": true, + "ganache>secp256k1": true, "lodash": true } }, @@ -5806,10 +3513,10 @@ "console": true }, "packages": { - "3box>ipfs>iso-url": true, "browserify>buffer": true, "browserify>buffer>ieee754": true, - "eth-lattice-keyring>gridplus-sdk>borc>bignumber.js": true + "eth-lattice-keyring>gridplus-sdk>borc>bignumber.js": true, + "eth-lattice-keyring>gridplus-sdk>borc>iso-url": true } }, "eth-lattice-keyring>gridplus-sdk>borc>bignumber.js": { @@ -5818,6 +3525,13 @@ "define": true } }, + "eth-lattice-keyring>gridplus-sdk>borc>iso-url": { + "globals": { + "URL": true, + "URLSearchParams": true, + "location": true + } + }, "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser": { "globals": { "intToBuffer": true @@ -5825,7 +3539,7 @@ "packages": { "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser>bn.js": true, "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser>buffer": true, - "ethers>@ethersproject/keccak256>js-sha3": true + "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser>js-sha3": true } }, "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser>bn.js": { @@ -5845,41 +3559,30 @@ "browserify>buffer>ieee754": true } }, - "eth-lattice-keyring>gridplus-sdk>rlp": { + "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser>js-sha3": { "globals": { - "TextEncoder": true - } - }, - "eth-lattice-keyring>gridplus-sdk>secp256k1": { + "define": true + }, "packages": { - "3box>ethers>elliptic": true + "browserify>process": true } }, - "eth-lattice-keyring>gridplus-sdk>superagent": { + "eth-lattice-keyring>gridplus-sdk>js-sha3": { "globals": { - "XMLHttpRequest": true, - "btoa": true, - "clearTimeout": true, - "console.error": true, - "console.warn": true, - "setTimeout": true + "define": true }, "packages": { - "@storybook/components>qs": true, - "browserify>browser-resolve": true, - "browserify>process": true, - "eth-rpc-errors>fast-safe-stringify": true, - "pubnub>superagent>component-emitter": true + "browserify>process": true } }, - "eth-lattice-keyring>rlp": { + "eth-lattice-keyring>gridplus-sdk>rlp": { "globals": { "TextEncoder": true } }, - "eth-lattice-keyring>secp256k1": { - "packages": { - "3box>ethers>elliptic": true + "eth-lattice-keyring>rlp": { + "globals": { + "TextEncoder": true } }, "eth-method-registry": { @@ -5901,16 +3604,15 @@ }, "eth-sig-util": { "packages": { - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, "browserify>buffer": true, "eth-sig-util>ethereumjs-util": true, + "eth-sig-util>tweetnacl": true, + "eth-sig-util>tweetnacl-util": true, "ethereumjs-abi": true } }, "eth-sig-util>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>assert": true, "browserify>buffer": true, @@ -5918,7 +3620,8 @@ "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>safe-buffer": true + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "eth-sig-util>ethereumjs-util>ethjs-util": { @@ -5928,6 +3631,25 @@ "ethjs>ethjs-util>strip-hex-prefix": true } }, + "eth-sig-util>tweetnacl": { + "globals": { + "crypto": true, + "msCrypto": true, + "nacl": "write" + }, + "packages": { + "browserify>browser-resolve": true + } + }, + "eth-sig-util>tweetnacl-util": { + "globals": { + "atob": true, + "btoa": true + }, + "packages": { + "browserify>browser-resolve": true + } + }, "eth-trezor-keyring": { "globals": { "setTimeout": true @@ -5943,9 +3665,9 @@ }, "eth-trezor-keyring>@metamask/eth-sig-util": { "packages": { - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, "browserify>buffer": true, + "eth-sig-util>tweetnacl": true, + "eth-sig-util>tweetnacl-util": true, "eth-trezor-keyring>@metamask/eth-sig-util>ethereumjs-util": true, "eth-trezor-keyring>@metamask/eth-sig-util>ethjs-util": true, "ethereumjs-abi": true @@ -5953,14 +3675,14 @@ }, "eth-trezor-keyring>@metamask/eth-sig-util>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>assert": true, "browserify>buffer": true, "eth-trezor-keyring>@metamask/eth-sig-util>ethjs-util": true, "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, - "ethereumjs-util>rlp": true + "ethereumjs-util>rlp": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "eth-trezor-keyring>@metamask/eth-sig-util>ethjs-util": { @@ -5988,13 +3710,12 @@ }, "eth-trezor-keyring>hdkey>secp256k1": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>insert-module-globals>is-buffer": true, "eth-trezor-keyring>hdkey>secp256k1>bip66": true, - "eth-trezor-keyring>hdkey>secp256k1>drbg.js": true, "ethereumjs-util>create-hash": true, - "ethereumjs-wallet>safe-buffer": true + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "eth-trezor-keyring>hdkey>secp256k1>bip66": { @@ -6002,12 +3723,6 @@ "ethereumjs-wallet>safe-buffer": true } }, - "eth-trezor-keyring>hdkey>secp256k1>drbg.js": { - "packages": { - "browserify>buffer": true, - "browserify>crypto-browserify>create-hmac": true - } - }, "eth-trezor-keyring>trezor-connect": { "globals": { "__TREZOR_CONNECT_SRC": true, @@ -6030,10 +3745,19 @@ "setTimeout": true }, "packages": { - "3box>graphql-request>cross-fetch": true, "@babel/runtime": true, "browserify>events": true, - "eth-trezor-keyring>@metamask/eth-sig-util": true + "eth-trezor-keyring>@metamask/eth-sig-util": true, + "eth-trezor-keyring>trezor-connect>cross-fetch": true + } + }, + "eth-trezor-keyring>trezor-connect>cross-fetch": { + "globals": { + "Blob": true, + "FileReader": true, + "FormData": true, + "URLSearchParams.prototype.isPrototypeOf": true, + "XMLHttpRequest": true } }, "ethereumjs-abi": { @@ -6045,14 +3769,14 @@ }, "ethereumjs-abi>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>assert": true, "browserify>buffer": true, "ethereumjs-abi>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, - "ethereumjs-util>rlp": true + "ethereumjs-util>rlp": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethereumjs-abi>ethereumjs-util>ethjs-util": { @@ -6143,12 +3867,6 @@ "ethers>@ethersproject/sha2>hash.js": true } }, - "ethereumjs-util>ethereum-cryptography>blakejs": { - "globals": { - "TextEncoder": true, - "console.log": true - } - }, "ethereumjs-util>ethereum-cryptography>browserify-aes": { "packages": { "browserify>buffer": true, @@ -6183,7 +3901,7 @@ }, "ethereumjs-util>ethereum-cryptography>secp256k1": { "packages": { - "3box>ethers>elliptic": true + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethereumjs-util>rlp": { @@ -6220,21 +3938,31 @@ }, "ethereumjs-wallet>bs58check": { "packages": { - "3box>ipfs>bs58": true, "ethereumjs-util>create-hash": true, + "ethereumjs-wallet>bs58check>bs58": true, + "ethereumjs-wallet>safe-buffer": true + } + }, + "ethereumjs-wallet>bs58check>bs58": { + "packages": { + "ethereumjs-wallet>bs58check>bs58>base-x": true + } + }, + "ethereumjs-wallet>bs58check>bs58>base-x": { + "packages": { "ethereumjs-wallet>safe-buffer": true } }, "ethereumjs-wallet>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>assert": true, "browserify>buffer": true, "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>ethereumjs-util>ethjs-util": true + "ethereumjs-wallet>ethereumjs-util>ethjs-util": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethereumjs-wallet>ethereumjs-util>ethjs-util": { @@ -6706,10 +4434,10 @@ }, "ethers>@ethersproject/contracts>@ethersproject/transactions>@ethersproject/signing-key": { "packages": { - "3box>ethers>elliptic": true, "ethers>@ethersproject/contracts>@ethersproject/bytes": true, "ethers>@ethersproject/contracts>@ethersproject/logger": true, - "ethers>@ethersproject/contracts>@ethersproject/properties": true + "ethers>@ethersproject/contracts>@ethersproject/properties": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethers>@ethersproject/hash": { @@ -7055,10 +4783,10 @@ }, "ethers>@ethersproject/providers>@ethersproject/transactions>@ethersproject/signing-key": { "packages": { - "3box>ethers>elliptic": true, "ethers>@ethersproject/providers>@ethersproject/bytes": true, "ethers>@ethersproject/providers>@ethersproject/logger": true, - "ethers>@ethersproject/providers>@ethersproject/properties": true + "ethers>@ethersproject/providers>@ethersproject/properties": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethers>@ethersproject/providers>@ethersproject/web": { @@ -7138,16 +4866,16 @@ }, "ethers>@ethersproject/sha2>hash.js": { "packages": { - "3box>ethers>hash.js>minimalistic-assert": true, + "ethers>@ethersproject/sha2>hash.js>minimalistic-assert": true, "pumpify>inherits": true } }, "ethers>@ethersproject/signing-key": { "packages": { - "3box>ethers>elliptic": true, "ethers>@ethersproject/signing-key>@ethersproject/bytes": true, "ethers>@ethersproject/signing-key>@ethersproject/logger": true, - "ethers>@ethersproject/signing-key>@ethersproject/properties": true + "ethers>@ethersproject/signing-key>@ethersproject/properties": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethers>@ethersproject/signing-key>@ethersproject/bytes": { @@ -7165,6 +4893,33 @@ "ethers>@ethersproject/signing-key>@ethersproject/logger": true } }, + "ethers>@ethersproject/signing-key>elliptic": { + "packages": { + "bn.js": true, + "ethers>@ethersproject/sha2>hash.js": true, + "ethers>@ethersproject/sha2>hash.js>minimalistic-assert": true, + "ethers>@ethersproject/signing-key>elliptic>brorand": true, + "ethers>@ethersproject/signing-key>elliptic>hmac-drbg": true, + "ethers>@ethersproject/signing-key>elliptic>minimalistic-crypto-utils": true, + "pumpify>inherits": true + } + }, + "ethers>@ethersproject/signing-key>elliptic>brorand": { + "globals": { + "crypto": true, + "msCrypto": true + }, + "packages": { + "browserify>browser-resolve": true + } + }, + "ethers>@ethersproject/signing-key>elliptic>hmac-drbg": { + "packages": { + "ethers>@ethersproject/sha2>hash.js": true, + "ethers>@ethersproject/sha2>hash.js>minimalistic-assert": true, + "ethers>@ethersproject/signing-key>elliptic>minimalistic-crypto-utils": true + } + }, "ethers>@ethersproject/solidity": { "packages": { "@ethersproject/bignumber": true, @@ -7286,7 +5041,7 @@ }, "ethers>@ethersproject/transactions>@ethersproject/signing-key": { "packages": { - "3box>ethers>elliptic": true, + "ethers>@ethersproject/signing-key>elliptic": true, "ethers>@ethersproject/transactions>@ethersproject/bytes": true, "ethers>@ethersproject/transactions>@ethersproject/logger": true, "ethers>@ethersproject/transactions>@ethersproject/properties": true @@ -7344,7 +5099,15 @@ "ethers>@ethersproject/wallet>@ethersproject/keccak256": { "packages": { "@ethersproject/bignumber>@ethersproject/bytes": true, - "ethers>@ethersproject/keccak256>js-sha3": true + "ethers>@ethersproject/wallet>@ethersproject/keccak256>js-sha3": true + } + }, + "ethers>@ethersproject/wallet>@ethersproject/keccak256>js-sha3": { + "globals": { + "define": true + }, + "packages": { + "browserify>process": true } }, "ethers>@ethersproject/wallet>@ethersproject/properties": { @@ -7360,9 +5123,9 @@ }, "ethers>@ethersproject/wallet>@ethersproject/signing-key": { "packages": { - "3box>ethers>elliptic": true, "@ethersproject/bignumber>@ethersproject/bytes": true, "@ethersproject/bignumber>@ethersproject/logger": true, + "ethers>@ethersproject/signing-key>elliptic": true, "ethers>@ethersproject/wallet>@ethersproject/properties": true } }, @@ -7475,10 +5238,10 @@ "ethjs-contract": { "packages": { "ethjs-contract>ethjs-abi": true, - "ethjs-contract>js-sha3": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "promise-to-callback": true } }, @@ -7486,20 +5249,10 @@ "packages": { "browserify>buffer": true, "ethjs-contract>ethjs-abi>bn.js": true, - "ethjs-contract>ethjs-abi>js-sha3": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, - "ethjs-contract>ethjs-abi>js-sha3": { - "packages": { - "browserify>process": true - } - }, - "ethjs-contract>js-sha3": { - "packages": { - "browserify>process": true - } - }, "ethjs-query": { "globals": { "console": true @@ -7616,9 +5369,13 @@ "define": true } }, + "ganache>secp256k1": { + "packages": { + "ethers>@ethersproject/signing-key>elliptic": true + } + }, "gh-pages>async": { "globals": { - "clearTimeout": true, "setTimeout": true }, "packages": { @@ -7741,32 +5498,22 @@ "Intl": true } }, - "madge>rc>deep-extend": { + "madge>ora>bl": { "packages": { - "browserify>buffer": true + "browserify>buffer": true, + "madge>ora>bl>readable-stream": true, + "pumpify>inherits": true } }, - "mockttp>node-forge": { - "globals": { - "Blob": true, - "MutationObserver": true, - "QuotaExceededError": true, - "URL.createObjectURL": true, - "URL.revokeObjectURL": true, - "Worker": true, - "addEventListener": true, - "document": true, - "jQuery": true, - "localStorage": true, - "navigator": true, - "postMessage": true, - "removeEventListener": true, - "setTimeout": true - }, + "madge>ora>bl>readable-stream": { "packages": { + "@storybook/api>util-deprecate": true, "browserify>browser-resolve": true, + "browserify>buffer": true, + "browserify>events": true, "browserify>process": true, - "browserify>timers-browserify": true + "browserify>string_decoder": true, + "pumpify>inherits": true } }, "nanoid": { @@ -7928,12 +5675,6 @@ "react-devtools>react-devtools-core": true } }, - "react-devtools>ip": { - "packages": { - "browserify>buffer": true, - "browserify>os-browserify": true - } - }, "react-devtools>react-devtools-core": { "globals": { "WebSocket": true, @@ -8349,8 +6090,13 @@ "setTimeout": true }, "packages": { - "3box>events": true, - "browserify>util": true + "browserify>util": true, + "safe-event-emitter>events": true + } + }, + "safe-event-emitter>events": { + "globals": { + "console": true } }, "semver": { @@ -8402,13 +6148,6 @@ "string.prototype.matchall>call-bind": true } }, - "string.prototype.matchall>side-channel": { - "packages": { - "enzyme>object-inspect": true, - "string.prototype.matchall>call-bind": true, - "string.prototype.matchall>get-intrinsic": true - } - }, "stylelint>autoprefixer>browserslist": { "packages": { "browserify>browser-resolve": true, @@ -8418,12 +6157,6 @@ "stylelint>autoprefixer>caniuse-lite": true } }, - "stylelint>write-file-atomic>typedarray-to-buffer": { - "packages": { - "browserify>buffer": true, - "jsdom>request>is-typedarray": true - } - }, "terser>@jridgewell/source-map>@jridgewell/gen-mapping": { "globals": { "define": true @@ -8523,11 +6256,6 @@ "console.warn": true, "define": true } - }, - "webpack>memory-fs>errno": { - "packages": { - "webpack>memory-fs>errno>prr": true - } } } } \ No newline at end of file diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index df9ad3a1d..71e1e50d1 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -1,2194 +1,5 @@ { "resources": { - "3box": { - "globals": { - "console.error": true, - "console.log": true, - "console.warn": true, - "fetch": true, - "setTimeout": true - }, - "packages": { - "3box>3box-orbitdb-plugins": true, - "3box>3box-orbitdb-plugins>ipfs-log": true, - "3box>3id-resolver": true, - "3box>did-jwt": true, - "3box>ethers": true, - "3box>ethers>elliptic": true, - "3box>graphql-request": true, - "3box>https-did-resolver": true, - "3box>ipfs": true, - "3box>ipfs-did-document": true, - "3box>ipfs-mini": true, - "3box>ipfs>is-ipfs": true, - "3box>ipfs>multihashes": true, - "3box>js-sha256": true, - "3box>muport-did-resolver": true, - "3box>orbit-db": true, - "3box>orbit-db>orbit-db-access-controllers": true, - "3box>orbit-db>orbit-db-identity-provider": true, - "3box>orbit-db>orbit-db-pubsub": true, - "3box>store": true, - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, - "@babel/runtime": true, - "browserify>buffer": true, - "browserify>process": true, - "node-fetch": true - } - }, - "3box>3box-orbitdb-plugins": { - "globals": { - "console.log": true - }, - "packages": { - "3box>3box-orbitdb-plugins>ipfs-log": true, - "3box>3id-resolver>did-jwt": true, - "3box>3id-resolver>did-jwt>base64url": true, - "3box>did-jwt>did-resolver": true, - "3box>ipfs>is-ipfs": true, - "3box>orbit-db>orbit-db-access-controllers": true, - "3box>orbit-db>orbit-db-io": true, - "browserify>events": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>3box-orbitdb-plugins>ipfs-log": { - "globals": { - "clearTimeout": true, - "console.warn": true, - "setTimeout": true - }, - "packages": { - "3box>3box-orbitdb-plugins>ipfs-log>json-stringify-deterministic": true, - "3box>3box-orbitdb-plugins>ipfs-log>p-each-series": true, - "3box>3box-orbitdb-plugins>ipfs-log>p-map": true, - "3box>3box-orbitdb-plugins>ipfs-log>p-whilst": true, - "3box>orbit-db>orbit-db-io": true, - "browserify>buffer": true - } - }, - "3box>3id-resolver": { - "packages": { - "3box>3id-resolver>did-jwt": true, - "3box>3id-resolver>did-jwt>base64url": true, - "3box>did-jwt>did-resolver": true, - "3box>ipfs-did-document": true, - "@babel/runtime": true - } - }, - "3box>3id-resolver>did-jwt": { - "packages": { - "3box>3id-resolver>did-jwt>base64url": true, - "3box>did-jwt>did-resolver": true, - "3box>ethers>elliptic": true, - "3box>js-sha256": true, - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, - "@babel/runtime": true, - "browserify>buffer": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>3id-resolver>did-jwt>base64url": { - "packages": { - "browserify>buffer": true - } - }, - "3box>did-jwt": { - "packages": { - "3box>did-jwt>@stablelib/utf8": true, - "3box>did-jwt>did-resolver": true, - "3box>did-jwt>js-sha3": true, - "3box>did-jwt>uport-base64url": true, - "3box>ethers>elliptic": true, - "3box>js-sha256": true, - "3box>tweetnacl": true, - "browserify>buffer": true - } - }, - "3box>did-jwt>js-sha3": { - "globals": { - "define": true - }, - "packages": { - "browserify>process": true - } - }, - "3box>did-jwt>uport-base64url": { - "packages": { - "browserify>buffer": true - } - }, - "3box>ethers": { - "globals": { - "MessageChannel": true, - "XMLHttpRequest": true, - "atob": true, - "btoa": true, - "clearInterval": true, - "clearTimeout": true, - "console": true, - "crypto.getRandomValues": true, - "define": true, - "setInterval": true, - "setTimeout": true - } - }, - "3box>ethers>elliptic": { - "packages": { - "3box>ethers>elliptic>brorand": true, - "3box>ethers>elliptic>hmac-drbg": true, - "3box>ethers>elliptic>minimalistic-crypto-utils": true, - "3box>ethers>hash.js>minimalistic-assert": true, - "bn.js": true, - "ethers>@ethersproject/sha2>hash.js": true, - "pumpify>inherits": true - } - }, - "3box>ethers>elliptic>brorand": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, - "3box>ethers>elliptic>hmac-drbg": { - "packages": { - "3box>ethers>elliptic>minimalistic-crypto-utils": true, - "3box>ethers>hash.js>minimalistic-assert": true, - "ethers>@ethersproject/sha2>hash.js": true - } - }, - "3box>events": { - "globals": { - "console": true - } - }, - "3box>graphql-request": { - "globals": { - "fetch": true - }, - "packages": { - "3box>graphql-request>cross-fetch": true - } - }, - "3box>graphql-request>cross-fetch": { - "globals": { - "Blob": true, - "FileReader": true, - "FormData": true, - "URLSearchParams.prototype.isPrototypeOf": true, - "XMLHttpRequest": true - } - }, - "3box>graphql-request>cross-fetch>node-fetch": { - "globals": { - "fetch": true - } - }, - "3box>https-did-resolver": { - "globals": { - "XMLHttpRequest": true - }, - "packages": { - "3box>did-jwt>did-resolver": true, - "browserify>browser-resolve": true - } - }, - "3box>ipfs": { - "globals": { - "AbortController": true, - "clearInterval": true, - "clearTimeout": true, - "console.log": true, - "fetch": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>async-iterator-all": true, - "3box>ipfs>async-iterator-to-pull-stream": true, - "3box>ipfs>async-iterator-to-stream": true, - "3box>ipfs>base32.js": true, - "3box>ipfs>bignumber.js": true, - "3box>ipfs>callbackify": true, - "3box>ipfs>cids": true, - "3box>ipfs>class-is": true, - "3box>ipfs>datastore-core": true, - "3box>ipfs>datastore-pubsub": true, - "3box>ipfs>dlv": true, - "3box>ipfs>err-code": true, - "3box>ipfs>fnv1a": true, - "3box>ipfs>fsm-event": true, - "3box>ipfs>human-to-milliseconds": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>ipfs-bitswap": true, - "3box>ipfs>ipfs-block": true, - "3box>ipfs>ipfs-block-service": true, - "3box>ipfs>ipfs-mfs": true, - "3box>ipfs>ipfs-repo": true, - "3box>ipfs>ipfs-unixfs": true, - "3box>ipfs>ipfs-unixfs-exporter": true, - "3box>ipfs>ipfs-unixfs-importer": true, - "3box>ipfs>ipfs-utils": true, - "3box>ipfs>ipld": true, - "3box>ipfs>ipld-dag-cbor": true, - "3box>ipfs>ipld-dag-pb": true, - "3box>ipfs>ipld-raw": true, - "3box>ipfs>ipns": true, - "3box>ipfs>is-ipfs": true, - "3box>ipfs>is-pull-stream": true, - "3box>ipfs>iso-url": true, - "3box>ipfs>just-flatten-it": true, - "3box>ipfs>kind-of": true, - "3box>ipfs>libp2p": true, - "3box>ipfs>libp2p-bootstrap": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-kad-dht": true, - "3box>ipfs>libp2p-keychain": true, - "3box>ipfs>libp2p-record": true, - "3box>ipfs>libp2p-secio": true, - "3box>ipfs>libp2p-webrtc-star": true, - "3box>ipfs>libp2p-websocket-star-multi": true, - "3box>ipfs>libp2p-websockets": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>merge-options": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>multiaddr-to-uri": true, - "3box>ipfs>multibase": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async": true, - "3box>ipfs>peer-book": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>promisify-es6": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-cat": true, - "3box>ipfs>pull-defer": true, - "3box>ipfs>pull-mplex": true, - "3box>ipfs>pull-pushable": true, - "3box>ipfs>pull-sort": true, - "3box>ipfs>pull-stream": true, - "3box>ipfs>pull-stream-to-async-iterator": true, - "3box>ipfs>pull-stream-to-stream": true, - "3box>ipfs>pull-traverse": true, - "3box>ipfs>readable-stream": true, - "3box>ipfs>receptacle": true, - "3box>ipfs>stream-to-pull-stream": true, - "3box>ipfs>superstruct": true, - "3box>ipfs>varint": true, - "@metamask/providers>is-stream": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>insert-module-globals>is-buffer": true, - "browserify>timers-browserify": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs-mini": { - "globals": { - "XMLHttpRequest": true - } - }, - "3box>ipfs-postmsg-proxy>shortid": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "nanoid": true - } - }, - "3box>ipfs>async-iterator-to-pull-stream": { - "packages": { - "3box>ipfs>async-iterator-to-pull-stream>get-iterator": true, - "3box>ipfs>pull-stream-to-async-iterator": true - } - }, - "3box>ipfs>async-iterator-to-stream": { - "packages": { - "3box>ipfs>async-iterator-to-stream>readable-stream": true, - "browserify>process": true - } - }, - "3box>ipfs>async-iterator-to-stream>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>bignumber.js": { - "globals": { - "crypto": true, - "define": true - } - }, - "3box>ipfs>bl": { - "packages": { - "3box>ipfs>bl>readable-stream": true, - "browserify>buffer": true, - "browserify>util": true - } - }, - "3box>ipfs>bl>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>bs58": { - "packages": { - "3box>ipfs>bs58>base-x": true - } - }, - "3box>ipfs>bs58>base-x": { - "packages": { - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>ipfs>cids": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>multibase": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>multihashes": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>datastore-core": { - "packages": { - "3box>ipfs>datastore-core>pull-many": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true, - "gh-pages>async": true - } - }, - "3box>ipfs>datastore-pubsub": { - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>multibase": true, - "browserify>assert": true, - "browserify>buffer": true, - "nock>debug": true - } - }, - "3box>ipfs>dlv": { - "globals": { - "define": true - } - }, - "3box>ipfs>fsm-event": { - "packages": { - "3box>ipfs>fsm-event>fsm": true, - "browserify>assert": true, - "browserify>events": true - } - }, - "3box>ipfs>human-to-milliseconds": { - "packages": { - "3box>ipfs>promisify-es6": true - } - }, - "3box>ipfs>interface-datastore": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>err-code": true, - "3box>ipfs>interface-datastore>uuid": true, - "3box>ipfs>pull-defer": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true, - "browserify>os-browserify": true, - "browserify>path-browserify": true, - "gh-pages>async": true - } - }, - "3box>ipfs>interface-datastore>uuid": { - "globals": { - "crypto": true, - "msCrypto": true - } - }, - "3box>ipfs>ipfs-bitswap": { - "globals": { - "clearInterval": true, - "clearTimeout": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>ipfs-bitswap>bignumber.js": true, - "3box>ipfs>ipfs-bitswap>just-debounce-it": true, - "3box>ipfs>ipfs-bitswap>lodash.isequalwith": true, - "3box>ipfs>ipfs-bitswap>moving-average": true, - "3box>ipfs>ipfs-bitswap>multihashing-async": true, - "3box>ipfs>ipfs-bitswap>varint-decoder": true, - "3box>ipfs>ipfs-block": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-stream": true, - "browserify>assert": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>ipfs-bitswap>bignumber.js": { - "globals": { - "crypto": true, - "define": true - } - }, - "3box>ipfs>ipfs-bitswap>just-debounce-it": { - "globals": { - "clearTimeout": true, - "setTimeout": true - } - }, - "3box>ipfs>ipfs-bitswap>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>ipfs-bitswap>varint-decoder": { - "packages": { - "3box>ipfs>varint": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipfs-block": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>class-is": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipfs-block-service": { - "packages": { - "gh-pages>async": true - } - }, - "3box>ipfs>ipfs-mfs": { - "globals": { - "Blob": true, - "FileReader": true - }, - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>err-code": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>ipfs-mfs>async-iterator-last": true, - "3box>ipfs>ipfs-mfs>hamt-sharding": true, - "3box>ipfs>ipfs-mfs>mortice": true, - "3box>ipfs>ipfs-unixfs": true, - "3box>ipfs>ipfs-unixfs-exporter": true, - "3box>ipfs>ipfs-unixfs-importer": true, - "3box>ipfs>ipld-dag-pb": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>multihashes": true, - "3box>ipfs>promisify-es6": true, - "browserify>assert": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "nock>debug": true - } - }, - "3box>ipfs>ipfs-mfs>hamt-sharding": { - "packages": { - "3box>ipfs>ipfs-mfs>hamt-sharding>sparse-array": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipfs-mfs>mortice": { - "globals": { - "Worker": true - }, - "packages": { - "3box>ipfs-postmsg-proxy>shortid": true, - "3box>ipfs>ipfs-mfs>mortice>observable-webworkers": true, - "3box>ipfs>ipfs-mfs>mortice>promise-timeout": true, - "3box>ipfs>libp2p-kad-dht>p-queue": true, - "browserify>browser-resolve": true, - "browserify>events": true, - "browserify>process": true - } - }, - "3box>ipfs>ipfs-mfs>mortice>promise-timeout": { - "globals": { - "clearTimeout": true, - "setTimeout": true - } - }, - "3box>ipfs>ipfs-repo": { - "packages": { - "3box>ipfs>base32.js": true, - "3box>ipfs>cids": true, - "3box>ipfs>datastore-core": true, - "3box>ipfs>dlv": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>ipfs-block": true, - "3box>ipfs>ipfs-repo>bignumber.js": true, - "3box>ipfs>ipfs-repo>datastore-level": true, - "3box>ipfs>ipfs-repo>sort-keys": true, - "3box>ipfs>just-safe-set": true, - "3box>ipfs>pull-stream": true, - "browserify>assert": true, - "browserify>buffer": true, - "browserify>path-browserify": true, - "browserify>timers-browserify": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>ipfs-repo>bignumber.js": { - "globals": { - "crypto": true, - "define": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level": { - "packages": { - "3box>ipfs>interface-datastore": true, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down": true, - "3box>ipfs>ipfs-repo>datastore-level>level-js": true, - "3box>ipfs>pull-stream": true, - "3box>orbit-db>orbit-db-keystore>levelup": true, - "browserify>buffer": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down": { - "packages": { - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>abstract-leveldown": true, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>level-codec": true, - "3box>orbit-db>orbit-db-keystore>levelup>level-errors": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>abstract-leveldown": { - "packages": { - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>abstract-leveldown>level-supports": true, - "3box>orbit-db>orbit-db-cache>level-js>immediate": true, - "browserify>buffer": true, - "watchify>xtend": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>abstract-leveldown>level-supports": { - "packages": { - "watchify>xtend": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>encoding-down>level-codec": { - "packages": { - "browserify>buffer": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>level-js": { - "globals": { - "IDBKeyRange.bound": true, - "IDBKeyRange.lowerBound": true, - "IDBKeyRange.only": true, - "IDBKeyRange.upperBound": true, - "indexedDB.deleteDatabase": true, - "indexedDB.open": true - }, - "packages": { - "3box>ipfs>ipfs-repo>datastore-level>level-js>abstract-leveldown": true, - "3box>ipfs>ipfs-repo>datastore-level>level-js>idb-readable-stream": true, - "3box>orbit-db>orbit-db-cache>level-js>ltgt": true, - "browserify>buffer": true, - "browserify>process": true, - "browserify>stream-browserify": true, - "browserify>util": true, - "watchify>xtend": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>level-js>abstract-leveldown": { - "packages": { - "browserify>insert-module-globals>is-buffer": true, - "browserify>process": true, - "watchify>xtend": true - } - }, - "3box>ipfs>ipfs-repo>datastore-level>level-js>idb-readable-stream": { - "globals": { - "IDBKeyRange.bound": true, - "IDBKeyRange.lowerBound": true, - "IDBKeyRange.upperBound": true - }, - "packages": { - "browserify>stream-browserify": true, - "watchify>xtend": true - } - }, - "3box>ipfs>ipfs-repo>sort-keys": { - "packages": { - "geckodriver>got>is-plain-obj": true - } - }, - "3box>ipfs>ipfs-unixfs": { - "packages": { - "3box>ipfs>protons": true - } - }, - "3box>ipfs>ipfs-unixfs-exporter": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>err-code": true, - "3box>ipfs>ipfs-mfs>async-iterator-last": true, - "3box>ipfs>ipfs-mfs>hamt-sharding": true, - "3box>ipfs>ipfs-unixfs": true, - "3box>ipfs>ipfs-unixfs-importer": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipfs-unixfs-importer": { - "packages": { - "3box>ipfs>async-iterator-all": true, - "3box>ipfs>bl": true, - "3box>ipfs>err-code": true, - "3box>ipfs>ipfs-mfs>hamt-sharding": true, - "3box>ipfs>ipfs-unixfs": true, - "3box>ipfs>ipfs-unixfs-importer>async-iterator-batch": true, - "3box>ipfs>ipfs-unixfs-importer>async-iterator-first": true, - "3box>ipfs>ipfs-unixfs-importer>rabin-wasm": true, - "3box>ipfs>ipfs-unixfs-importer>superstruct": true, - "3box>ipfs>ipld-dag-pb": true, - "3box>ipfs>ipld-raw>multihashing-async": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>multihashes": true, - "browserify>buffer": true, - "madge>rc>deep-extend": true - } - }, - "3box>ipfs>ipfs-unixfs-importer>rabin-wasm": { - "globals": { - "Blob": true, - "Response": true, - "WebAssembly": true - }, - "packages": { - "3box>ipfs>ipfs-unixfs-importer>rabin-wasm>assemblyscript": true - } - }, - "3box>ipfs>ipfs-unixfs-importer>rabin-wasm>assemblyscript": { - "globals": { - "WebAssembly.Instance": true, - "WebAssembly.Module": true, - "WebAssembly.instantiateStreaming": true, - "console.log": true - } - }, - "3box>ipfs>ipfs-utils": { - "globals": { - "FileReader": true - }, - "packages": { - "3box>ipfs>ipfs-utils>is-buffer": true, - "3box>ipfs>ipfs-utils>readable-stream": true, - "3box>ipfs>is-pull-stream": true, - "3box>ipfs>kind-of": true, - "@metamask/providers>is-stream": true - } - }, - "3box>ipfs>ipfs-utils>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>ipld": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>ipfs-block": true, - "3box>ipfs>ipld-dag-cbor": true, - "3box>ipfs>ipld-dag-pb": true, - "3box>ipfs>ipld-raw": true, - "3box>ipfs>ipld>typical": true, - "3box>ipfs>merge-options": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>promisify-es6": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipld-dag-cbor": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>ipld-dag-cbor>is-circular": true, - "3box>ipfs>ipld-raw>multihashing-async": true, - "3box>ipfs>multicodec": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true, - "eth-lattice-keyring>gridplus-sdk>borc": true - } - }, - "3box>ipfs>ipld-dag-pb": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>class-is": true, - "3box>ipfs>ipld-raw>multihashing-async": true, - "3box>ipfs>multicodec": true, - "3box>ipfs>protons": true, - "@storybook/react>@storybook/store>stable": true, - "browserify>assert": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>ipld-raw": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>ipld-raw>multihashing-async": true, - "3box>ipfs>multicodec": true - } - }, - "3box>ipfs>ipld-raw>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>ipld-raw>multihashing-async>murmurhash3js-revisited": true, - "3box>ipfs>multihashes": true, - "browserify>buffer": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>ipld-raw>multihashing-async>murmurhash3js-revisited": { - "globals": { - "define": true - } - }, - "3box>ipfs>ipld>typical": { - "globals": { - "define": true - } - }, - "3box>ipfs>ipns": { - "packages": { - "3box>ipfs>interface-datastore": true, - "3box>ipfs>ipns>timestamp-nano": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>multihashes": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>protons": true, - "base32-encode": true, - "browserify>buffer": true, - "nock>debug": true - } - }, - "3box>ipfs>is-ipfs": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>cids": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>multibase": true, - "3box>ipfs>multihashes": true, - "browserify>buffer": true - } - }, - "3box>ipfs>iso-url": { - "globals": { - "URL": true, - "URLSearchParams": true, - "location": true - } - }, - "3box>ipfs>libp2p": { - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>fsm-event": true, - "3box>ipfs>libp2p-websockets": true, - "3box>ipfs>libp2p>libp2p-connection-manager": true, - "3box>ipfs>libp2p>libp2p-floodsub": true, - "3box>ipfs>libp2p>libp2p-ping": true, - "3box>ipfs>libp2p>libp2p-switch": true, - "3box>ipfs>libp2p>superstruct": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-book": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "browserify>events": true, - "browserify>insert-module-globals>is-buffer": true, - "browserify>process": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p-bootstrap": { - "globals": { - "clearInterval": true, - "setInterval": true - }, - "packages": { - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p-crypto": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>libp2p-crypto>asn1.js": true, - "3box>ipfs>libp2p-crypto>iso-random-stream": true, - "3box>ipfs>libp2p-crypto>libp2p-crypto-secp256k1": true, - "3box>ipfs>libp2p-crypto>multihashing-async": true, - "3box>ipfs>protons": true, - "3box>tweetnacl": true, - "browserify>buffer": true, - "ethereumjs-util>ethereum-cryptography>browserify-aes": true, - "gh-pages>async": true, - "mockttp>node-forge": true - } - }, - "3box>ipfs>libp2p-crypto>asn1.js": { - "packages": { - "3box>ethers>hash.js>minimalistic-assert": true, - "bn.js": true, - "browserify>buffer": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>libp2p-crypto>iso-random-stream": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p-crypto>libp2p-crypto-secp256k1": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>libp2p-crypto>libp2p-crypto-secp256k1>multihashing-async": true, - "eth-trezor-keyring>hdkey>secp256k1": true, - "gh-pages>async": true - } - }, - "3box>ipfs>libp2p-crypto>libp2p-crypto-secp256k1>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>libp2p-crypto>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>libp2p-kad-dht": { - "globals": { - "clearInterval": true, - "clearTimeout": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>base32.js": true, - "3box>ipfs>cids": true, - "3box>ipfs>err-code": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-kad-dht>hashlru": true, - "3box>ipfs>libp2p-kad-dht>heap": true, - "3box>ipfs>libp2p-kad-dht>k-bucket": true, - "3box>ipfs>libp2p-kad-dht>multihashing-async": true, - "3box>ipfs>libp2p-kad-dht>p-queue": true, - "3box>ipfs>libp2p-kad-dht>p-times": true, - "3box>ipfs>libp2p-kad-dht>xor-distance": true, - "3box>ipfs>libp2p-record": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>multihashes": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>promisify-es6": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-stream": true, - "3box>ipfs>pull-stream-to-async-iterator": true, - "3box>ipfs>varint": true, - "@metamask/controllers>abort-controller": true, - "browserify>assert": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>insert-module-globals>is-buffer": true, - "gh-pages>async": true, - "nock>debug": true, - "promise-to-callback": true - } - }, - "3box>ipfs>libp2p-kad-dht>heap": { - "globals": { - "define": true - } - }, - "3box>ipfs>libp2p-kad-dht>k-bucket": { - "packages": { - "browserify>events": true, - "ethereumjs-wallet>randombytes": true - } - }, - "3box>ipfs>libp2p-kad-dht>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>libp2p-kad-dht>p-queue": { - "globals": { - "clearInterval": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "mockttp>@httptoolkit/subscriptions-transport-ws>eventemitter3": true - } - }, - "3box>ipfs>libp2p-kad-dht>p-times": { - "packages": { - "3box>ipfs>libp2p-kad-dht>p-times>p-map": true - } - }, - "3box>ipfs>libp2p-kad-dht>xor-distance": { - "packages": { - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p-keychain": { - "globals": { - "setTimeout": true - }, - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>interface-datastore": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-keychain>sanitize-filename": true, - "3box>ipfs>merge-options": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true, - "gh-pages>async": true, - "mockttp>node-forge": true - } - }, - "3box>ipfs>libp2p-keychain>sanitize-filename": { - "packages": { - "3box>ipfs>libp2p-keychain>sanitize-filename>truncate-utf8-bytes": true - } - }, - "3box>ipfs>libp2p-keychain>sanitize-filename>truncate-utf8-bytes": { - "packages": { - "3box>ipfs>libp2p-keychain>sanitize-filename>truncate-utf8-bytes>utf8-byte-length": true - } - }, - "3box>ipfs>libp2p-record": { - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>libp2p-record>buffer-split": true, - "3box>ipfs>libp2p-record>multihashing-async": true, - "3box>ipfs>protons": true, - "browserify>assert": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true, - "gh-pages>async": true - } - }, - "3box>ipfs>libp2p-record>buffer-split": { - "packages": { - "3box>ipfs>libp2p-record>buffer-split>buffer-indexof": true - } - }, - "3box>ipfs>libp2p-record>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>libp2p-secio": { - "packages": { - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-secio>multihashing-async": true, - "3box>ipfs>libp2p-secio>pull-handshake": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-defer": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-stream": true, - "browserify>assert": true, - "browserify>buffer": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p-secio>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>libp2p-secio>pull-handshake": { - "packages": { - "3box>ipfs>libp2p-secio>pull-handshake>pull-reader": true, - "3box>ipfs>pull-cat": true, - "3box>ipfs>pull-mplex>pull-pair": true, - "3box>ipfs>pull-pushable": true - } - }, - "3box>ipfs>libp2p-secio>pull-handshake>pull-reader": { - "globals": { - "cb": true, - "clearTimeout": true, - "setTimeout": true - }, - "packages": { - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p-secio>pull-length-prefixed": { - "packages": { - "3box>ipfs>libp2p-secio>pull-handshake>pull-reader": true, - "3box>ipfs>pull-pushable": true, - "3box>ipfs>varint": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>ipfs>libp2p-webrtc-star": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>libp2p-webrtc-star>simple-peer": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client": true, - "3box>ipfs>libp2p-webrtc-star>webrtcsupport": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>stream-to-pull-stream": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p-webrtc-star>simple-peer": { - "globals": { - "clearInterval": true, - "console.warn": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>simple-peer>get-browser-rtc": true, - "3box>ipfs>libp2p-webrtc-star>simple-peer>readable-stream": true, - "browserify>buffer": true, - "ethereumjs-wallet>randombytes": true, - "nock>debug": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>libp2p-webrtc-star>simple-peer>get-browser-rtc": { - "globals": { - "RTCIceCandidate": true, - "RTCPeerConnection": true, - "RTCSessionDescription": true, - "mozRTCIceCandidate": true, - "mozRTCPeerConnection": true, - "mozRTCSessionDescription": true, - "webkitRTCIceCandidate": true, - "webkitRTCPeerConnection": true, - "webkitRTCSessionDescription": true - } - }, - "3box>ipfs>libp2p-webrtc-star>simple-peer>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client": { - "globals": { - "clearTimeout": true, - "location": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>component-bind": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>debug": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>indexof": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>parseqs": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>parseuri": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>to-array": true, - "3box>ipfs>libp2p-webrtc-star>socket.io>has-binary2": true, - "mockttp>@httptoolkit/subscriptions-transport-ws>backo2": true, - "pubnub>superagent>component-emitter": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>debug": { - "globals": { - "chrome": true, - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>debug>ms": true, - "browserify>process": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client": { - "globals": { - "MozWebSocket": true, - "WebSocket": true, - "XDomainRequest": true, - "XMLHttpRequest": true, - "addEventListener": true, - "attachEvent": true, - "clearTimeout": true, - "document": true, - "location": true, - "navigator": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>component-inherit": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>debug": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>has-cors": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>yeast": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>indexof": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>parseqs": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>parseuri": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "pubnub>superagent>component-emitter": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>debug": { - "globals": { - "chrome": true, - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>debug>ms": true, - "browserify>process": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser": { - "globals": { - "FileReader": true, - "btoa": true, - "navigator": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser>after": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser>arraybuffer.slice": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser>blob": true, - "3box>ipfs>libp2p-webrtc-star>socket.io>engine.io>engine.io-parser>base64-arraybuffer": true, - "3box>ipfs>libp2p-webrtc-star>socket.io>has-binary2": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>engine.io-parser>blob": { - "globals": { - "Blob": true, - "MSBlobBuilder": true, - "MozBlobBuilder": true, - "WebKitBlobBuilder": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>engine.io-client>has-cors": { - "globals": { - "XMLHttpRequest": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser": { - "globals": { - "Blob": true, - "File": true, - "FileReader": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser>debug": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser>isarray": true, - "browserify>buffer": true, - "pubnub>superagent>component-emitter": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser>debug": { - "globals": { - "chrome": true, - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io-client>socket.io-parser>debug>ms": true, - "browserify>process": true - } - }, - "3box>ipfs>libp2p-webrtc-star>socket.io>has-binary2": { - "globals": { - "Blob": true, - "File": true - }, - "packages": { - "3box>ipfs>libp2p-webrtc-star>socket.io>has-binary2>isarray": true, - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p-webrtc-star>webrtcsupport": { - "globals": { - "AudioContext": true, - "MediaStream": true, - "RTCIceCandidate": true, - "RTCPeerConnection": true, - "RTCSessionDescription": true, - "document": true, - "location.protocol": true, - "mozRTCIceCandidate": true, - "mozRTCPeerConnection": true, - "mozRTCSessionDescription": true, - "navigator.getUserMedia": true, - "navigator.mozGetUserMedia": true, - "navigator.msGetUserMedia": true, - "navigator.userAgent.match": true, - "navigator.webkitGetUserMedia": true, - "webkitAudioContext": true, - "webkitMediaStream": true, - "webkitRTCPeerConnection": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi": { - "globals": { - "setTimeout": true - }, - "packages": { - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star": { - "globals": { - "console.error": true - }, - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-webrtc-star>socket.io-client": true, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true, - "uuid": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream": { - "globals": { - "console.error": true - }, - "packages": { - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>data-queue": true, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>debug": true, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>uuid": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>data-queue": { - "packages": { - "browserify>events": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>debug": { - "globals": { - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "analytics-node>ms": true, - "browserify>process": true - } - }, - "3box>ipfs>libp2p-websocket-star-multi>libp2p-websocket-star>socket.io-pull-stream>uuid": { - "globals": { - "crypto": true, - "msCrypto": true - } - }, - "3box>ipfs>libp2p-websockets": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>libp2p-websockets>pull-ws": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>multiaddr-to-uri": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "browserify>os-browserify": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p-websockets>pull-ws": { - "globals": { - "WebSocket": true, - "location": true - }, - "packages": { - "3box>ipfs>libp2p-websockets>pull-ws>relative-url": true, - "browserify>browser-resolve": true, - "browserify>events": true, - "browserify>https-browserify": true, - "browserify>process": true, - "browserify>stream-http": true, - "browserify>timers-browserify": true, - "browserify>url": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>ipfs>libp2p-websockets>pull-ws>relative-url": { - "packages": { - "browserify>url": true - } - }, - "3box>ipfs>libp2p>libp2p-connection-manager": { - "packages": { - "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor": true, - "browserify>events": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor": { - "globals": { - "clearInterval": true, - "clearTimeout": true, - "document": true, - "performance": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor>debug": true, - "browserify>events": true, - "browserify>process": true, - "lodash": true - } - }, - "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor>debug": { - "globals": { - "chrome": true, - "console": true, - "document": true, - "localStorage": true, - "navigator": true, - "process": true - }, - "packages": { - "3box>ipfs>libp2p>libp2p-connection-manager>latency-monitor>debug>ms": true, - "browserify>process": true - } - }, - "3box>ipfs>libp2p>libp2p-floodsub": { - "packages": { - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub": true, - "3box>ipfs>pull-stream": true, - "browserify>assert": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>err-code": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub>time-cache": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-pushable": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>insert-module-globals>is-buffer": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub>time-cache": { - "packages": { - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub>time-cache>lodash.throttle": true - } - }, - "3box>ipfs>libp2p>libp2p-floodsub>libp2p-pubsub>time-cache>lodash.throttle": { - "globals": { - "clearTimeout": true, - "setTimeout": true - } - }, - "3box>ipfs>libp2p>libp2p-ping": { - "packages": { - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>libp2p-secio>pull-handshake": true, - "3box>ipfs>pull-stream": true, - "browserify>events": true, - "nock>debug": true - } - }, - "3box>ipfs>libp2p>libp2p-switch": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>err-code": true, - "3box>ipfs>fsm-event": true, - "3box>ipfs>ipfs-bitswap>moving-average": true, - "3box>ipfs>libp2p-kad-dht>hashlru": true, - "3box>ipfs>libp2p>libp2p-switch>bignumber.js": true, - "3box>ipfs>libp2p>libp2p-switch>libp2p-circuit": true, - "3box>ipfs>libp2p>libp2p-switch>libp2p-identify": true, - "3box>ipfs>libp2p>libp2p-switch>multistream-select": true, - "3box>ipfs>libp2p>libp2p-switch>retimer": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-stream": true, - "browserify>assert": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>bignumber.js": { - "globals": { - "crypto": true, - "define": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>libp2p-circuit": { - "packages": { - "3box>ipfs>libp2p-secio>pull-handshake": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>mafmt": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-stream": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>libp2p-identify": { - "globals": { - "console.warn": true - }, - "packages": { - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "3box>ipfs>protons": true, - "3box>ipfs>pull-stream": true, - "browserify>buffer": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>multistream-select": { - "packages": { - "3box>ipfs>err-code": true, - "3box>ipfs>libp2p-secio>pull-handshake": true, - "3box>ipfs>libp2p-secio>pull-length-prefixed": true, - "3box>ipfs>libp2p>libp2p-switch>multistream-select>semver": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-stream": true, - "3box>ipfs>varint": true, - "browserify>assert": true, - "browserify>buffer": true, - "gh-pages>async": true, - "nock>debug": true, - "pump>once": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>multistream-select>semver": { - "globals": { - "console": true - }, - "packages": { - "browserify>process": true - } - }, - "3box>ipfs>libp2p>libp2p-switch>retimer": { - "globals": { - "clearTimeout": true, - "setTimeout": true - } - }, - "3box>ipfs>mafmt": { - "packages": { - "3box>ipfs>multiaddr": true - } - }, - "3box>ipfs>merge-options": { - "packages": { - "geckodriver>got>is-plain-obj": true - } - }, - "3box>ipfs>multiaddr": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>class-is": true, - "3box>ipfs>multiaddr>hi-base32": true, - "3box>ipfs>multiaddr>is-ip": true, - "3box>ipfs>varint": true, - "browserify>buffer": true, - "react-devtools>ip": true - } - }, - "3box>ipfs>multiaddr-to-uri": { - "packages": { - "3box>ipfs>multiaddr": true - } - }, - "3box>ipfs>multiaddr>hi-base32": { - "globals": { - "define": true - }, - "packages": { - "browserify>process": true - } - }, - "3box>ipfs>multiaddr>is-ip": { - "packages": { - "chromedriver>tcp-port-used>is2>ip-regex": true - } - }, - "3box>ipfs>multibase": { - "packages": { - "3box>ipfs>multibase>base-x": true, - "browserify>buffer": true - } - }, - "3box>ipfs>multibase>base-x": { - "packages": { - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>ipfs>multicodec": { - "packages": { - "3box>ipfs>varint": true, - "browserify>buffer": true - } - }, - "3box>ipfs>multihashes": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>varint": true, - "browserify>buffer": true - } - }, - "3box>ipfs>multihashing-async": { - "globals": { - "crypto": true, - "msCrypto": true - }, - "packages": { - "3box>ipfs>multihashes": true, - "3box>ipfs>multihashing-async>murmurhash3js": true, - "3box>ipfs>multihashing-async>nodeify": true, - "browserify>buffer": true, - "browserify>process": true, - "ethereumjs-util>ethereum-cryptography>blakejs": true, - "ethers>@ethersproject/keccak256>js-sha3": true - } - }, - "3box>ipfs>multihashing-async>murmurhash3js": { - "globals": { - "define": true - } - }, - "3box>ipfs>multihashing-async>nodeify": { - "globals": { - "setTimeout": true - }, - "packages": { - "3box>ipfs>multihashing-async>nodeify>is-promise": true, - "3box>ipfs>multihashing-async>nodeify>promise": true, - "browserify>process": true, - "browserify>timers-browserify": true - } - }, - "3box>ipfs>multihashing-async>nodeify>promise": { - "globals": { - "setImediate": true, - "setTimeout": true - }, - "packages": { - "3box>ipfs>multihashing-async>nodeify>is-promise": true, - "browserify>process": true - } - }, - "3box>ipfs>peer-book": { - "packages": { - "3box>ipfs>bs58": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>ipfs>peer-id": { - "packages": { - "3box>ipfs>class-is": true, - "3box>ipfs>libp2p-crypto": true, - "3box>ipfs>multihashes": true, - "browserify>assert": true, - "browserify>buffer": true, - "gh-pages>async": true - } - }, - "3box>ipfs>peer-info": { - "packages": { - "3box>ipfs>multiaddr": true, - "3box>ipfs>peer-id": true, - "3box>ipfs>peer-info>unique-by": true, - "browserify>assert": true - } - }, - "3box>ipfs>protons": { - "packages": { - "3box>ipfs>protons>protocol-buffers-schema": true, - "3box>ipfs>protons>signed-varint": true, - "3box>ipfs>varint": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>ipfs>protons>signed-varint": { - "packages": { - "3box>ipfs>varint": true - } - }, - "3box>ipfs>pull-mplex": { - "packages": { - "3box>ipfs>pull-abortable": true, - "3box>ipfs>pull-mplex>interface-connection": true, - "3box>ipfs>pull-mplex>looper": true, - "3box>ipfs>pull-mplex>pull-through": true, - "3box>ipfs>pull-pushable": true, - "3box>ipfs>pull-stream": true, - "3box>ipfs>varint": true, - "browserify>buffer": true, - "browserify>events": true, - "gh-pages>async": true, - "nock>debug": true - } - }, - "3box>ipfs>pull-mplex>interface-connection": { - "packages": { - "3box>ipfs>pull-defer": true - } - }, - "3box>ipfs>pull-mplex>pull-through": { - "packages": { - "3box>ipfs>stream-to-pull-stream>looper": true - } - }, - "3box>ipfs>pull-sort": { - "packages": { - "3box>ipfs>pull-defer": true, - "3box>ipfs>pull-stream": true - } - }, - "3box>ipfs>pull-stream": { - "globals": { - "console.log": true - } - }, - "3box>ipfs>pull-stream-to-async-iterator": { - "packages": { - "3box>ipfs>pull-stream": true - } - }, - "3box>ipfs>pull-stream-to-stream": { - "packages": { - "browserify>process": true, - "browserify>stream-browserify": true, - "browserify>timers-browserify": true - } - }, - "3box>ipfs>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>ipfs>receptacle": { - "globals": { - "clearTimeout": true, - "setTimeout": true - }, - "packages": { - "analytics-node>ms": true - } - }, - "3box>ipfs>stream-to-pull-stream": { - "globals": { - "console.error": true - }, - "packages": { - "3box>ipfs>pull-stream": true, - "3box>ipfs>stream-to-pull-stream>looper": true, - "browserify>process": true - } - }, - "3box>js-sha256": { - "globals": { - "define": true - }, - "packages": { - "browserify>process": true - } - }, - "3box>muport-did-resolver": { - "packages": { - "3box>did-jwt>did-resolver": true, - "@babel/runtime": true, - "node-fetch": true - } - }, - "3box>orbit-db": { - "globals": { - "console.log": true - }, - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>multihashes": true, - "3box>orbit-db>ipfs-pubsub-1on1": true, - "3box>orbit-db>logplease": true, - "3box>orbit-db>orbit-db-access-controllers": true, - "3box>orbit-db>orbit-db-cache": true, - "3box>orbit-db>orbit-db-counterstore": true, - "3box>orbit-db>orbit-db-docstore": true, - "3box>orbit-db>orbit-db-eventstore": true, - "3box>orbit-db>orbit-db-feedstore": true, - "3box>orbit-db>orbit-db-identity-provider": true, - "3box>orbit-db>orbit-db-io": true, - "3box>orbit-db>orbit-db-keystore": true, - "3box>orbit-db>orbit-db-kvstore": true, - "3box>orbit-db>orbit-db-pubsub": true, - "browserify>path-browserify": true - } - }, - "3box>orbit-db>ipfs-pubsub-1on1": { - "globals": { - "clearInterval": true, - "setInterval": true - }, - "packages": { - "3box>orbit-db>ipfs-pubsub-1on1>safe-buffer": true, - "browserify>events": true, - "browserify>path-browserify": true - } - }, - "3box>orbit-db>ipfs-pubsub-1on1>safe-buffer": { - "packages": { - "browserify>buffer": true - } - }, - "3box>orbit-db>logplease": { - "globals": { - "LOG": true, - "console.error": true, - "console.log": true - }, - "packages": { - "browserify>browser-resolve": true, - "browserify>events": true, - "browserify>process": true, - "browserify>util": true - } - }, - "3box>orbit-db>orbit-db-access-controllers": { - "globals": { - "console.log": true - }, - "packages": { - "3box>orbit-db>orbit-db-access-controllers>p-map-series": true, - "3box>orbit-db>orbit-db-io": true, - "browserify>events": true, - "browserify>path-browserify": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>orbit-db>orbit-db-access-controllers>p-map-series": { - "packages": { - "3box>orbit-db>orbit-db-store>p-each-series>p-reduce": true - } - }, - "3box>orbit-db>orbit-db-cache": { - "packages": { - "3box>orbit-db>logplease": true, - "3box>orbit-db>orbit-db-cache>level-js": true, - "browserify>path-browserify": true - } - }, - "3box>orbit-db>orbit-db-cache>level-js": { - "globals": { - "IDBKeyRange.bound": true, - "IDBKeyRange.lowerBound": true, - "IDBKeyRange.upperBound": true, - "indexedDB": true - }, - "packages": { - "3box>orbit-db>orbit-db-cache>level-js>abstract-leveldown": true, - "3box>orbit-db>orbit-db-cache>level-js>immediate": true, - "3box>orbit-db>orbit-db-cache>level-js>ltgt": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true, - "pumpify>inherits": true, - "stylelint>write-file-atomic>typedarray-to-buffer": true - } - }, - "3box>orbit-db>orbit-db-cache>level-js>abstract-leveldown": { - "packages": { - "browserify>insert-module-globals>is-buffer": true, - "browserify>process": true, - "watchify>xtend": true - } - }, - "3box>orbit-db>orbit-db-cache>level-js>immediate": { - "globals": { - "MessageChannel": true, - "MutationObserver": true, - "WebKitMutationObserver": true, - "clearTimeout": true, - "document.createElement": true, - "document.createTextNode": true, - "document.documentElement.appendChild": true, - "setImmediate": true, - "setTimeout": true - }, - "packages": { - "browserify>process": true - } - }, - "3box>orbit-db>orbit-db-cache>level-js>ltgt": { - "packages": { - "browserify>insert-module-globals>is-buffer": true - } - }, - "3box>orbit-db>orbit-db-counterstore": { - "packages": { - "3box>orbit-db>orbit-db-counterstore>crdts": true, - "3box>orbit-db>orbit-db-store": true - } - }, - "3box>orbit-db>orbit-db-docstore": { - "packages": { - "3box>orbit-db>orbit-db-docstore>p-map": true, - "3box>orbit-db>orbit-db-store": true, - "readable-stream": true - } - }, - "3box>orbit-db>orbit-db-eventstore": { - "packages": { - "3box>orbit-db>orbit-db-store": true - } - }, - "3box>orbit-db>orbit-db-feedstore": { - "packages": { - "3box>orbit-db>orbit-db-eventstore": true - } - }, - "3box>orbit-db>orbit-db-identity-provider": { - "packages": { - "3box>orbit-db>orbit-db-keystore": true - } - }, - "3box>orbit-db>orbit-db-io": { - "packages": { - "3box>ipfs>cids": true, - "3box>ipfs>ipld-dag-pb": true, - "browserify>buffer": true - } - }, - "3box>orbit-db>orbit-db-keystore": { - "globals": { - "console.error": true, - "console.log": true - }, - "packages": { - "3box>ethers>elliptic": true, - "3box>ipfs>libp2p-crypto": true, - "3box>orbit-db>orbit-db-cache>level-js": true, - "3box>orbit-db>orbit-db-keystore>levelup": true, - "3box>orbit-db>orbit-db-keystore>lru": true, - "eth-trezor-keyring>hdkey>secp256k1": true, - "ethereumjs-wallet>safe-buffer": true - } - }, - "3box>orbit-db>orbit-db-keystore>levelup": { - "packages": { - "3box>orbit-db>orbit-db-keystore>levelup>deferred-leveldown": true, - "3box>orbit-db>orbit-db-keystore>levelup>level-errors": true, - "3box>orbit-db>orbit-db-keystore>levelup>level-iterator-stream": true, - "browserify>assert": true, - "browserify>events": true, - "browserify>process": true, - "browserify>util": true, - "watchify>xtend": true - } - }, - "3box>orbit-db>orbit-db-keystore>levelup>deferred-leveldown": { - "packages": { - "3box>orbit-db>orbit-db-cache>level-js>abstract-leveldown": true, - "pumpify>inherits": true - } - }, - "3box>orbit-db>orbit-db-keystore>levelup>level-errors": { - "packages": { - "webpack>memory-fs>errno": true - } - }, - "3box>orbit-db>orbit-db-keystore>levelup>level-iterator-stream": { - "packages": { - "3box>orbit-db>orbit-db-keystore>levelup>level-iterator-stream>readable-stream": true, - "pumpify>inherits": true, - "watchify>xtend": true - } - }, - "3box>orbit-db>orbit-db-keystore>levelup>level-iterator-stream>readable-stream": { - "packages": { - "@storybook/api>util-deprecate": true, - "browserify>browser-resolve": true, - "browserify>buffer": true, - "browserify>events": true, - "browserify>process": true, - "browserify>string_decoder": true, - "pumpify>inherits": true - } - }, - "3box>orbit-db>orbit-db-keystore>lru": { - "packages": { - "browserify>events": true, - "pumpify>inherits": true - } - }, - "3box>orbit-db>orbit-db-kvstore": { - "packages": { - "3box>orbit-db>orbit-db-store": true - } - }, - "3box>orbit-db>orbit-db-pubsub": { - "packages": { - "3box>orbit-db>logplease": true, - "3box>orbit-db>orbit-db-pubsub>ipfs-pubsub-peer-monitor": true, - "3box>orbit-db>orbit-db-pubsub>p-series": true, - "browserify>buffer": true - } - }, - "3box>orbit-db>orbit-db-pubsub>ipfs-pubsub-peer-monitor": { - "globals": { - "clearInterval": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "browserify>events": true - } - }, - "3box>orbit-db>orbit-db-pubsub>p-series": { - "packages": { - "3box>orbit-db>orbit-db-pubsub>p-series>@sindresorhus/is": true, - "3box>orbit-db>orbit-db-store>p-each-series>p-reduce": true - } - }, - "3box>orbit-db>orbit-db-pubsub>p-series>@sindresorhus/is": { - "packages": { - "browserify>insert-module-globals>is-buffer": true, - "browserify>util": true - } - }, - "3box>orbit-db>orbit-db-store": { - "globals": { - "clearInterval": true, - "console.error": true, - "console.warn": true, - "setInterval": true, - "setTimeout": true - }, - "packages": { - "3box>3box-orbitdb-plugins>ipfs-log": true, - "3box>ipfs>libp2p-kad-dht>p-times>p-map": true, - "3box>orbit-db>logplease": true, - "3box>orbit-db>orbit-db-io": true, - "3box>orbit-db>orbit-db-store>p-each-series": true, - "browserify>buffer": true, - "browserify>events": true, - "readable-stream": true - } - }, - "3box>orbit-db>orbit-db-store>p-each-series": { - "packages": { - "3box>orbit-db>orbit-db-store>p-each-series>p-reduce": true - } - }, - "3box>store": { - "globals": { - "ActiveXObject": true, - "console": true - } - }, - "3box>tweetnacl": { - "globals": { - "crypto": true, - "msCrypto": true, - "nacl": "write" - }, - "packages": { - "browserify>browser-resolve": true - } - }, - "3box>tweetnacl-util": { - "globals": { - "atob": true, - "btoa": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, "@babel/runtime": { "globals": { "regeneratorRuntime": "write" @@ -2236,9 +47,9 @@ }, "@ensdomains/content-hash>cids>multihashes": { "packages": { - "3box>ipfs>varint": true, "@ensdomains/content-hash>cids>multibase": true, - "@ensdomains/content-hash>cids>uint8arrays": true + "@ensdomains/content-hash>cids>uint8arrays": true, + "@ensdomains/content-hash>multihashes>varint": true } }, "@ensdomains/content-hash>cids>uint8arrays": { @@ -2283,17 +94,17 @@ }, "@ensdomains/content-hash>multihashes": { "packages": { - "3box>ipfs>varint": true, "@ensdomains/content-hash>multihashes>multibase": true, + "@ensdomains/content-hash>multihashes>varint": true, "@ensdomains/content-hash>multihashes>web-encoding": true, "browserify>buffer": true } }, "@ensdomains/content-hash>multihashes>multibase": { "packages": { - "3box>ipfs>bs58>base-x": true, "@ensdomains/content-hash>multihashes>web-encoding": true, - "browserify>buffer": true + "browserify>buffer": true, + "ethereumjs-wallet>bs58check>bs58>base-x": true } }, "@ensdomains/content-hash>multihashes>web-encoding": { @@ -2386,42 +197,13 @@ }, "@keystonehq/bc-ur-registry-eth": { "packages": { - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util": true, "@keystonehq/bc-ur-registry-eth>@keystonehq/bc-ur-registry": true, "@keystonehq/bc-ur-registry-eth>hdkey": true, "browserify>buffer": true, + "eth-lattice-keyring>@ethereumjs/util": true, "uuid": true } }, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util": { - "packages": { - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>@ethereumjs/rlp": true, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>ethereum-cryptography": true, - "browserify>buffer": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>@ethereumjs/rlp": { - "globals": { - "TextEncoder": true - } - }, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>ethereum-cryptography": { - "globals": { - "TextDecoder": true, - "crypto": true - }, - "packages": { - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>ethereum-cryptography>@noble/hashes": true, - "eth-json-rpc-middleware>@metamask/eth-sig-util>ethereum-cryptography>@noble/secp256k1": true - } - }, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util>ethereum-cryptography>@noble/hashes": { - "globals": { - "TextEncoder": true, - "crypto": true - } - }, "@keystonehq/bc-ur-registry-eth>@keystonehq/bc-ur-registry": { "globals": { "define": true @@ -2449,7 +231,7 @@ }, "@keystonehq/bc-ur-registry-eth>hdkey>secp256k1": { "packages": { - "3box>ethers>elliptic": true + "ethers>@ethersproject/signing-key>elliptic": true } }, "@keystonehq/metamask-airgapped-keyring": { @@ -2468,10 +250,10 @@ "packages": { "@ethereumjs/tx": true, "@keystonehq/bc-ur-registry-eth": true, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util": true, "@keystonehq/bc-ur-registry-eth>hdkey": true, "@keystonehq/metamask-airgapped-keyring>@keystonehq/base-eth-keyring>rlp": true, "browserify>buffer": true, + "eth-lattice-keyring>@ethereumjs/util": true, "uuid": true } }, @@ -2879,38 +661,38 @@ "@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": true, "@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": true, "@metamask/controllers>eth-method-registry>ethjs>ethjs-query": true, - "@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-provider-http": true, "ethjs>ethjs-unit": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": { "packages": { "@metamask/controllers>eth-method-registry>ethjs>bn.js": true, - "@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": { "packages": { "@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": true, - "@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "promise-to-callback": true } }, "@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": { "packages": { "@metamask/controllers>eth-method-registry>ethjs>bn.js": true, - "@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, @@ -2925,11 +707,6 @@ "promise-to-callback": true } }, - "@metamask/controllers>eth-method-registry>ethjs>js-sha3": { - "packages": { - "browserify>process": true - } - }, "@metamask/controllers>eth-phishing-detect": { "packages": { "eslint>optionator>fast-levenshtein": true @@ -3094,7 +871,6 @@ }, "@metamask/controllers>web3-provider-engine>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "@metamask/controllers>web3-provider-engine>ethereumjs-util>ethjs-util": true, "bn.js": true, "browserify>assert": true, @@ -3102,7 +878,8 @@ "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>safe-buffer": true + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "@metamask/controllers>web3-provider-engine>ethereumjs-util>ethjs-util": { @@ -3192,7 +969,6 @@ }, "@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>eth-sig-util>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>eth-sig-util>ethereumjs-util>ethjs-util": true, "bn.js": true, "browserify>assert": true, @@ -3200,7 +976,8 @@ "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>safe-buffer": true + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>eth-sig-util>ethereumjs-util>ethjs-util": { @@ -3230,16 +1007,15 @@ }, "@metamask/eth-ledger-bridge-keyring>eth-sig-util": { "packages": { - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util": true, "browserify>buffer": true, + "eth-sig-util>tweetnacl": true, + "eth-sig-util>tweetnacl-util": true, "ethereumjs-abi": true } }, "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethjs-util": true, "bn.js": true, "browserify>assert": true, @@ -3247,7 +1023,8 @@ "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>safe-buffer": true + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethjs-util": { @@ -3259,13 +1036,23 @@ }, "@metamask/eth-ledger-bridge-keyring>hdkey": { "packages": { + "@metamask/eth-ledger-bridge-keyring>hdkey>secp256k1": true, "browserify>assert": true, "browserify>crypto-browserify": true, "eth-trezor-keyring>hdkey>coinstring": true, - "eth-trezor-keyring>hdkey>secp256k1": true, "ethereumjs-wallet>safe-buffer": true } }, + "@metamask/eth-ledger-bridge-keyring>hdkey>secp256k1": { + "packages": { + "bn.js": true, + "browserify>insert-module-globals>is-buffer": true, + "eth-trezor-keyring>hdkey>secp256k1>bip66": true, + "ethereumjs-util>create-hash": true, + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true + } + }, "@metamask/eth-token-tracker": { "globals": { "console.warn": true @@ -3324,38 +1111,38 @@ "@metamask/eth-token-tracker>ethjs>ethjs-abi": true, "@metamask/eth-token-tracker>ethjs>ethjs-contract": true, "@metamask/eth-token-tracker>ethjs>ethjs-query": true, - "@metamask/eth-token-tracker>ethjs>js-sha3": true, "browserify>buffer": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-provider-http": true, "ethjs>ethjs-unit": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/eth-token-tracker>ethjs>ethjs-abi": { "packages": { "@metamask/eth-token-tracker>ethjs>bn.js": true, - "@metamask/eth-token-tracker>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/eth-token-tracker>ethjs>ethjs-contract": { "packages": { "@metamask/eth-token-tracker>ethjs>ethjs-contract>ethjs-abi": true, - "@metamask/eth-token-tracker>ethjs>js-sha3": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "promise-to-callback": true } }, "@metamask/eth-token-tracker>ethjs>ethjs-contract>ethjs-abi": { "packages": { "@metamask/eth-token-tracker>ethjs>bn.js": true, - "@metamask/eth-token-tracker>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, @@ -3370,11 +1157,6 @@ "promise-to-callback": true } }, - "@metamask/eth-token-tracker>ethjs>js-sha3": { - "packages": { - "browserify>process": true - } - }, "@metamask/etherscan-link": { "globals": { "URL": true @@ -3532,38 +1314,38 @@ "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": true, "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": true, "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-query": true, - "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-provider-http": true, "ethjs>ethjs-unit": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-abi": { "packages": { "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>bn.js": true, - "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract": { "packages": { "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": true, - "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "promise-to-callback": true } }, "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>ethjs-contract>ethjs-abi": { "packages": { "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>bn.js": true, - "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": true, "browserify>buffer": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, @@ -3578,11 +1360,6 @@ "promise-to-callback": true } }, - "@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs>js-sha3": { - "packages": { - "browserify>process": true - } - }, "@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet": { "packages": { "@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet>uuid": true, @@ -3682,6 +1459,14 @@ "redux-thunk": true } }, + "@segment/loosely-validate-event": { + "packages": { + "@segment/loosely-validate-event>component-type": true, + "@segment/loosely-validate-event>join-component": true, + "browserify>assert": true, + "browserify>buffer": true + } + }, "@sentry/browser": { "globals": { "XMLHttpRequest": true, @@ -3795,16 +1580,6 @@ "localStorage": true } }, - "@storybook/components>qs": { - "packages": { - "string.prototype.matchall>side-channel": true - } - }, - "@storybook/react>@storybook/store>stable": { - "globals": { - "define": true - } - }, "@truffle/codec": { "packages": { "@truffle/codec>@truffle/abi-utils": true, @@ -4032,7 +1807,15 @@ }, "@truffle/codec>web3-utils>ethereum-bloom-filters": { "packages": { - "ethers>@ethersproject/keccak256>js-sha3": true + "@truffle/codec>web3-utils>ethereum-bloom-filters>js-sha3": true + } + }, + "@truffle/codec>web3-utils>ethereum-bloom-filters>js-sha3": { + "globals": { + "define": true + }, + "packages": { + "browserify>process": true } }, "@truffle/decoder": { @@ -4081,106 +1864,41 @@ } }, "@zxing/browser": { - "globals": { - "HTMLElement": true, - "HTMLImageElement": true, - "HTMLVideoElement": true, - "URL.createObjectURL": true, - "clearTimeout": true, - "console.error": true, - "console.warn": true, - "document": true, - "navigator": true, - "setTimeout": true - }, - "packages": { - "@zxing/library": true - } - }, - "@zxing/library": { - "globals": { - "TextDecoder": true, - "TextEncoder": true, - "btoa": true, - "clearTimeout": true, - "define": true, - "document.createElement": true, - "document.createElementNS": true, - "document.getElementById": true, - "navigator.mediaDevices.enumerateDevices": true, - "navigator.mediaDevices.getUserMedia": true, - "setTimeout": true - } - }, - "addons-linter>sha.js": { - "packages": { - "ethereumjs-wallet>safe-buffer": true, - "pumpify>inherits": true - } - }, - "analytics-node": { - "globals": { - "clearTimeout": true, - "console.log": true, - "setImmediate": true, - "setTimeout": true - }, - "packages": { - "analytics-node>@segment/loosely-validate-event": true, - "analytics-node>axios": true, - "analytics-node>axios-retry": true, - "analytics-node>lodash.isstring": true, - "analytics-node>md5": true, - "analytics-node>ms": true, - "analytics-node>remove-trailing-slash": true, - "analytics-node>uuid": true, - "browserify>assert": true, - "browserify>process": true - } - }, - "analytics-node>@segment/loosely-validate-event": { - "packages": { - "analytics-node>@segment/loosely-validate-event>component-type": true, - "analytics-node>@segment/loosely-validate-event>join-component": true, - "browserify>assert": true, - "browserify>buffer": true - } - }, - "analytics-node>axios": { - "globals": { - "FormData": true, - "URLSearchParams": true, - "XMLHttpRequest": true, - "btoa": true, + "globals": { + "HTMLElement": true, + "HTMLImageElement": true, + "HTMLVideoElement": true, + "URL.createObjectURL": true, + "clearTimeout": true, + "console.error": true, "console.warn": true, "document": true, - "location.href": true, "navigator": true, "setTimeout": true }, "packages": { - "browserify>process": true + "@zxing/library": true } }, - "analytics-node>axios-retry": { + "@zxing/library": { "globals": { + "TextDecoder": true, + "TextEncoder": true, + "btoa": true, + "clearTimeout": true, + "define": true, + "document.createElement": true, + "document.createElementNS": true, + "document.getElementById": true, + "navigator.mediaDevices.enumerateDevices": true, + "navigator.mediaDevices.getUserMedia": true, "setTimeout": true - }, - "packages": { - "geckodriver>got>is-retry-allowed": true } }, - "analytics-node>md5": { + "addons-linter>sha.js": { "packages": { - "analytics-node>md5>charenc": true, - "analytics-node>md5>crypt": true, - "browserify>insert-module-globals>is-buffer": true - } - }, - "analytics-node>uuid": { - "globals": { - "crypto": true, - "msCrypto": true + "ethereumjs-wallet>safe-buffer": true, + "pumpify>inherits": true } }, "await-semaphore": { @@ -4274,7 +1992,7 @@ }, "browserify>crypto-browserify>browserify-cipher>browserify-des>des.js": { "packages": { - "3box>ethers>hash.js>minimalistic-assert": true, + "ethers>@ethersproject/sha2>hash.js>minimalistic-assert": true, "pumpify>inherits": true } }, @@ -4286,7 +2004,6 @@ }, "browserify>crypto-browserify>browserify-sign": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>buffer": true, "browserify>crypto-browserify>create-hmac": true, @@ -4294,14 +2011,15 @@ "browserify>crypto-browserify>public-encrypt>parse-asn1": true, "browserify>stream-browserify": true, "ethereumjs-util>create-hash": true, + "ethers>@ethersproject/signing-key>elliptic": true, "pumpify>inherits": true } }, "browserify>crypto-browserify>create-ecdh": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, - "browserify>buffer": true + "browserify>buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "browserify>crypto-browserify>create-hmac": { @@ -4324,8 +2042,8 @@ }, "browserify>crypto-browserify>diffie-hellman>miller-rabin": { "packages": { - "3box>ethers>elliptic>brorand": true, - "bn.js": true + "bn.js": true, + "ethers>@ethersproject/signing-key>elliptic>brorand": true } }, "browserify>crypto-browserify>pbkdf2": { @@ -4372,10 +2090,10 @@ }, "browserify>crypto-browserify>public-encrypt>parse-asn1>asn1.js": { "packages": { - "3box>ethers>hash.js>minimalistic-assert": true, "bn.js": true, "browserify>buffer": true, "browserify>vm-browserify": true, + "ethers>@ethersproject/sha2>hash.js>minimalistic-assert": true, "pumpify>inherits": true } }, @@ -4604,15 +2322,6 @@ "string.prototype.matchall>call-bind": true } }, - "enzyme>object-inspect": { - "globals": { - "HTMLElement": true, - "WeakRef": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, "enzyme>object-is": { "packages": { "globalthis>define-properties": true, @@ -4718,13 +2427,13 @@ }, "eth-json-rpc-middleware>@metamask/eth-sig-util": { "packages": { - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, - "@keystonehq/bc-ur-registry-eth>@ethereumjs/util": true, "browserify>buffer": true, "eth-json-rpc-middleware>@metamask/eth-sig-util>bn.js": true, "eth-json-rpc-middleware>@metamask/eth-sig-util>ethereum-cryptography": true, - "eth-json-rpc-middleware>@metamask/eth-sig-util>ethjs-util": true + "eth-json-rpc-middleware>@metamask/eth-sig-util>ethjs-util": true, + "eth-lattice-keyring>@ethereumjs/util": true, + "eth-sig-util>tweetnacl": true, + "eth-sig-util>tweetnacl-util": true } }, "eth-json-rpc-middleware>@metamask/eth-sig-util>bn.js": { @@ -4747,14 +2456,6 @@ "crypto": true } }, - "eth-json-rpc-middleware>@metamask/eth-sig-util>ethereum-cryptography>@noble/secp256k1": { - "globals": { - "crypto": true - }, - "packages": { - "browserify>browser-resolve": true - } - }, "eth-json-rpc-middleware>@metamask/eth-sig-util>ethjs-util": { "packages": { "browserify>buffer": true, @@ -4868,44 +2569,62 @@ "clearInterval": true, "fetch": true, "open": true, - "setInterval": true, - "txData.type": true + "setInterval": true }, "packages": { "browserify>buffer": true, "browserify>crypto-browserify": true, "browserify>events": true, - "eth-lattice-keyring>@ethereumjs/common": true, "eth-lattice-keyring>@ethereumjs/tx": true, + "eth-lattice-keyring>@ethereumjs/util": true, "eth-lattice-keyring>bn.js": true, "eth-lattice-keyring>gridplus-sdk": true, - "eth-lattice-keyring>rlp": true, - "eth-lattice-keyring>secp256k1": true, - "ethereumjs-util": true + "eth-lattice-keyring>rlp": true } }, - "eth-lattice-keyring>@ethereumjs/common": { + "eth-lattice-keyring>@ethereumjs/tx": { "packages": { - "@ethereumjs/common>crc-32": true, + "@ethereumjs/common": true, "browserify>buffer": true, - "browserify>events": true, + "browserify>insert-module-globals>is-buffer": true, "ethereumjs-util": true } }, - "eth-lattice-keyring>@ethereumjs/tx": { + "eth-lattice-keyring>@ethereumjs/util": { "packages": { "browserify>buffer": true, "browserify>insert-module-globals>is-buffer": true, - "eth-lattice-keyring>@ethereumjs/tx>@ethereumjs/common": true, - "ethereumjs-util": true + "eth-lattice-keyring>@ethereumjs/util>@ethereumjs/rlp": true, + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography": true + } + }, + "eth-lattice-keyring>@ethereumjs/util>@ethereumjs/rlp": { + "globals": { + "TextEncoder": true + } + }, + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography": { + "globals": { + "TextDecoder": true, + "crypto": true + }, + "packages": { + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@noble/hashes": true, + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@noble/secp256k1": true + } + }, + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@noble/hashes": { + "globals": { + "TextEncoder": true, + "crypto": true } }, - "eth-lattice-keyring>@ethereumjs/tx>@ethereumjs/common": { + "eth-lattice-keyring>@ethereumjs/util>ethereum-cryptography>@noble/secp256k1": { + "globals": { + "crypto": true + }, "packages": { - "@ethereumjs/common>crc-32": true, - "browserify>buffer": true, - "browserify>events": true, - "ethereumjs-util": true + "browserify>browser-resolve": true } }, "eth-lattice-keyring>bn.js": { @@ -4918,13 +2637,18 @@ }, "eth-lattice-keyring>gridplus-sdk": { "globals": { + "AbortController": true, + "Request": true, "__values": true, + "caches": true, + "clearTimeout": true, + "console.error": true, "console.log": true, "console.warn": true, + "fetch": true, "setTimeout": true }, "packages": { - "3box>ethers>elliptic": true, "@ethereumjs/common>crc-32": true, "@metamask/controllers>@ethersproject/abi": true, "bn.js": true, @@ -4937,13 +2661,13 @@ "eth-lattice-keyring>gridplus-sdk>bitwise": true, "eth-lattice-keyring>gridplus-sdk>borc": true, "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser": true, + "eth-lattice-keyring>gridplus-sdk>js-sha3": true, "eth-lattice-keyring>gridplus-sdk>rlp": true, - "eth-lattice-keyring>gridplus-sdk>secp256k1": true, - "eth-lattice-keyring>gridplus-sdk>superagent": true, "ethereumjs-wallet>aes-js": true, "ethereumjs-wallet>bs58check": true, - "ethers>@ethersproject/keccak256>js-sha3": true, "ethers>@ethersproject/sha2>hash.js": true, + "ethers>@ethersproject/signing-key>elliptic": true, + "ganache>secp256k1": true, "lodash": true } }, @@ -4987,10 +2711,10 @@ "console": true }, "packages": { - "3box>ipfs>iso-url": true, "browserify>buffer": true, "browserify>buffer>ieee754": true, - "eth-lattice-keyring>gridplus-sdk>borc>bignumber.js": true + "eth-lattice-keyring>gridplus-sdk>borc>bignumber.js": true, + "eth-lattice-keyring>gridplus-sdk>borc>iso-url": true } }, "eth-lattice-keyring>gridplus-sdk>borc>bignumber.js": { @@ -4999,6 +2723,13 @@ "define": true } }, + "eth-lattice-keyring>gridplus-sdk>borc>iso-url": { + "globals": { + "URL": true, + "URLSearchParams": true, + "location": true + } + }, "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser": { "globals": { "intToBuffer": true @@ -5006,7 +2737,7 @@ "packages": { "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser>bn.js": true, "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser>buffer": true, - "ethers>@ethersproject/keccak256>js-sha3": true + "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser>js-sha3": true } }, "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser>bn.js": { @@ -5026,41 +2757,30 @@ "browserify>buffer>ieee754": true } }, - "eth-lattice-keyring>gridplus-sdk>rlp": { + "eth-lattice-keyring>gridplus-sdk>eth-eip712-util-browser>js-sha3": { "globals": { - "TextEncoder": true - } - }, - "eth-lattice-keyring>gridplus-sdk>secp256k1": { + "define": true + }, "packages": { - "3box>ethers>elliptic": true + "browserify>process": true } }, - "eth-lattice-keyring>gridplus-sdk>superagent": { + "eth-lattice-keyring>gridplus-sdk>js-sha3": { "globals": { - "XMLHttpRequest": true, - "btoa": true, - "clearTimeout": true, - "console.error": true, - "console.warn": true, - "setTimeout": true + "define": true }, "packages": { - "@storybook/components>qs": true, - "browserify>browser-resolve": true, - "browserify>process": true, - "eth-rpc-errors>fast-safe-stringify": true, - "pubnub>superagent>component-emitter": true + "browserify>process": true } }, - "eth-lattice-keyring>rlp": { + "eth-lattice-keyring>gridplus-sdk>rlp": { "globals": { "TextEncoder": true } }, - "eth-lattice-keyring>secp256k1": { - "packages": { - "3box>ethers>elliptic": true + "eth-lattice-keyring>rlp": { + "globals": { + "TextEncoder": true } }, "eth-method-registry": { @@ -5082,16 +2802,15 @@ }, "eth-sig-util": { "packages": { - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, "browserify>buffer": true, "eth-sig-util>ethereumjs-util": true, + "eth-sig-util>tweetnacl": true, + "eth-sig-util>tweetnacl-util": true, "ethereumjs-abi": true } }, "eth-sig-util>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>assert": true, "browserify>buffer": true, @@ -5099,7 +2818,8 @@ "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>safe-buffer": true + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "eth-sig-util>ethereumjs-util>ethjs-util": { @@ -5109,6 +2829,25 @@ "ethjs>ethjs-util>strip-hex-prefix": true } }, + "eth-sig-util>tweetnacl": { + "globals": { + "crypto": true, + "msCrypto": true, + "nacl": "write" + }, + "packages": { + "browserify>browser-resolve": true + } + }, + "eth-sig-util>tweetnacl-util": { + "globals": { + "atob": true, + "btoa": true + }, + "packages": { + "browserify>browser-resolve": true + } + }, "eth-trezor-keyring": { "globals": { "setTimeout": true @@ -5124,9 +2863,9 @@ }, "eth-trezor-keyring>@metamask/eth-sig-util": { "packages": { - "3box>tweetnacl": true, - "3box>tweetnacl-util": true, "browserify>buffer": true, + "eth-sig-util>tweetnacl": true, + "eth-sig-util>tweetnacl-util": true, "eth-trezor-keyring>@metamask/eth-sig-util>ethereumjs-util": true, "eth-trezor-keyring>@metamask/eth-sig-util>ethjs-util": true, "ethereumjs-abi": true @@ -5134,14 +2873,14 @@ }, "eth-trezor-keyring>@metamask/eth-sig-util>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>assert": true, "browserify>buffer": true, "eth-trezor-keyring>@metamask/eth-sig-util>ethjs-util": true, "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, - "ethereumjs-util>rlp": true + "ethereumjs-util>rlp": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "eth-trezor-keyring>@metamask/eth-sig-util>ethjs-util": { @@ -5169,13 +2908,12 @@ }, "eth-trezor-keyring>hdkey>secp256k1": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>insert-module-globals>is-buffer": true, "eth-trezor-keyring>hdkey>secp256k1>bip66": true, - "eth-trezor-keyring>hdkey>secp256k1>drbg.js": true, "ethereumjs-util>create-hash": true, - "ethereumjs-wallet>safe-buffer": true + "ethereumjs-wallet>safe-buffer": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "eth-trezor-keyring>hdkey>secp256k1>bip66": { @@ -5183,12 +2921,6 @@ "ethereumjs-wallet>safe-buffer": true } }, - "eth-trezor-keyring>hdkey>secp256k1>drbg.js": { - "packages": { - "browserify>buffer": true, - "browserify>crypto-browserify>create-hmac": true - } - }, "eth-trezor-keyring>trezor-connect": { "globals": { "__TREZOR_CONNECT_SRC": true, @@ -5211,10 +2943,19 @@ "setTimeout": true }, "packages": { - "3box>graphql-request>cross-fetch": true, "@babel/runtime": true, "browserify>events": true, - "eth-trezor-keyring>@metamask/eth-sig-util": true + "eth-trezor-keyring>@metamask/eth-sig-util": true, + "eth-trezor-keyring>trezor-connect>cross-fetch": true + } + }, + "eth-trezor-keyring>trezor-connect>cross-fetch": { + "globals": { + "Blob": true, + "FileReader": true, + "FormData": true, + "URLSearchParams.prototype.isPrototypeOf": true, + "XMLHttpRequest": true } }, "ethereumjs-abi": { @@ -5226,14 +2967,14 @@ }, "ethereumjs-abi>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>assert": true, "browserify>buffer": true, "ethereumjs-abi>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, - "ethereumjs-util>rlp": true + "ethereumjs-util>rlp": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethereumjs-abi>ethereumjs-util>ethjs-util": { @@ -5324,12 +3065,6 @@ "ethers>@ethersproject/sha2>hash.js": true } }, - "ethereumjs-util>ethereum-cryptography>blakejs": { - "globals": { - "TextEncoder": true, - "console.log": true - } - }, "ethereumjs-util>ethereum-cryptography>browserify-aes": { "packages": { "browserify>buffer": true, @@ -5364,7 +3099,7 @@ }, "ethereumjs-util>ethereum-cryptography>secp256k1": { "packages": { - "3box>ethers>elliptic": true + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethereumjs-util>rlp": { @@ -5401,21 +3136,31 @@ }, "ethereumjs-wallet>bs58check": { "packages": { - "3box>ipfs>bs58": true, "ethereumjs-util>create-hash": true, + "ethereumjs-wallet>bs58check>bs58": true, + "ethereumjs-wallet>safe-buffer": true + } + }, + "ethereumjs-wallet>bs58check>bs58": { + "packages": { + "ethereumjs-wallet>bs58check>bs58>base-x": true + } + }, + "ethereumjs-wallet>bs58check>bs58>base-x": { + "packages": { "ethereumjs-wallet>safe-buffer": true } }, "ethereumjs-wallet>ethereumjs-util": { "packages": { - "3box>ethers>elliptic": true, "bn.js": true, "browserify>assert": true, "browserify>buffer": true, "ethereumjs-util>create-hash": true, "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>ethereumjs-util>ethjs-util": true + "ethereumjs-wallet>ethereumjs-util>ethjs-util": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethereumjs-wallet>ethereumjs-util>ethjs-util": { @@ -5887,10 +3632,10 @@ }, "ethers>@ethersproject/contracts>@ethersproject/transactions>@ethersproject/signing-key": { "packages": { - "3box>ethers>elliptic": true, "ethers>@ethersproject/contracts>@ethersproject/bytes": true, "ethers>@ethersproject/contracts>@ethersproject/logger": true, - "ethers>@ethersproject/contracts>@ethersproject/properties": true + "ethers>@ethersproject/contracts>@ethersproject/properties": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethers>@ethersproject/hash": { @@ -6236,10 +3981,10 @@ }, "ethers>@ethersproject/providers>@ethersproject/transactions>@ethersproject/signing-key": { "packages": { - "3box>ethers>elliptic": true, "ethers>@ethersproject/providers>@ethersproject/bytes": true, "ethers>@ethersproject/providers>@ethersproject/logger": true, - "ethers>@ethersproject/providers>@ethersproject/properties": true + "ethers>@ethersproject/providers>@ethersproject/properties": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethers>@ethersproject/providers>@ethersproject/web": { @@ -6319,16 +4064,16 @@ }, "ethers>@ethersproject/sha2>hash.js": { "packages": { - "3box>ethers>hash.js>minimalistic-assert": true, + "ethers>@ethersproject/sha2>hash.js>minimalistic-assert": true, "pumpify>inherits": true } }, "ethers>@ethersproject/signing-key": { "packages": { - "3box>ethers>elliptic": true, "ethers>@ethersproject/signing-key>@ethersproject/bytes": true, "ethers>@ethersproject/signing-key>@ethersproject/logger": true, - "ethers>@ethersproject/signing-key>@ethersproject/properties": true + "ethers>@ethersproject/signing-key>@ethersproject/properties": true, + "ethers>@ethersproject/signing-key>elliptic": true } }, "ethers>@ethersproject/signing-key>@ethersproject/bytes": { @@ -6346,6 +4091,33 @@ "ethers>@ethersproject/signing-key>@ethersproject/logger": true } }, + "ethers>@ethersproject/signing-key>elliptic": { + "packages": { + "bn.js": true, + "ethers>@ethersproject/sha2>hash.js": true, + "ethers>@ethersproject/sha2>hash.js>minimalistic-assert": true, + "ethers>@ethersproject/signing-key>elliptic>brorand": true, + "ethers>@ethersproject/signing-key>elliptic>hmac-drbg": true, + "ethers>@ethersproject/signing-key>elliptic>minimalistic-crypto-utils": true, + "pumpify>inherits": true + } + }, + "ethers>@ethersproject/signing-key>elliptic>brorand": { + "globals": { + "crypto": true, + "msCrypto": true + }, + "packages": { + "browserify>browser-resolve": true + } + }, + "ethers>@ethersproject/signing-key>elliptic>hmac-drbg": { + "packages": { + "ethers>@ethersproject/sha2>hash.js": true, + "ethers>@ethersproject/sha2>hash.js>minimalistic-assert": true, + "ethers>@ethersproject/signing-key>elliptic>minimalistic-crypto-utils": true + } + }, "ethers>@ethersproject/solidity": { "packages": { "@ethersproject/bignumber": true, @@ -6467,7 +4239,7 @@ }, "ethers>@ethersproject/transactions>@ethersproject/signing-key": { "packages": { - "3box>ethers>elliptic": true, + "ethers>@ethersproject/signing-key>elliptic": true, "ethers>@ethersproject/transactions>@ethersproject/bytes": true, "ethers>@ethersproject/transactions>@ethersproject/logger": true, "ethers>@ethersproject/transactions>@ethersproject/properties": true @@ -6525,7 +4297,15 @@ "ethers>@ethersproject/wallet>@ethersproject/keccak256": { "packages": { "@ethersproject/bignumber>@ethersproject/bytes": true, - "ethers>@ethersproject/keccak256>js-sha3": true + "ethers>@ethersproject/wallet>@ethersproject/keccak256>js-sha3": true + } + }, + "ethers>@ethersproject/wallet>@ethersproject/keccak256>js-sha3": { + "globals": { + "define": true + }, + "packages": { + "browserify>process": true } }, "ethers>@ethersproject/wallet>@ethersproject/properties": { @@ -6541,9 +4321,9 @@ }, "ethers>@ethersproject/wallet>@ethersproject/signing-key": { "packages": { - "3box>ethers>elliptic": true, "@ethersproject/bignumber>@ethersproject/bytes": true, "@ethersproject/bignumber>@ethersproject/logger": true, + "ethers>@ethersproject/signing-key>elliptic": true, "ethers>@ethersproject/wallet>@ethersproject/properties": true } }, @@ -6656,10 +4436,10 @@ "ethjs-contract": { "packages": { "ethjs-contract>ethjs-abi": true, - "ethjs-contract>js-sha3": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-util": true, + "ethjs>js-sha3": true, "promise-to-callback": true } }, @@ -6667,20 +4447,10 @@ "packages": { "browserify>buffer": true, "ethjs-contract>ethjs-abi>bn.js": true, - "ethjs-contract>ethjs-abi>js-sha3": true, + "ethjs>js-sha3": true, "ethjs>number-to-bn": true } }, - "ethjs-contract>ethjs-abi>js-sha3": { - "packages": { - "browserify>process": true - } - }, - "ethjs-contract>js-sha3": { - "packages": { - "browserify>process": true - } - }, "ethjs-query": { "globals": { "console": true @@ -6797,9 +4567,13 @@ "define": true } }, + "ganache>secp256k1": { + "packages": { + "ethers>@ethersproject/signing-key>elliptic": true + } + }, "gh-pages>async": { "globals": { - "clearTimeout": true, "setTimeout": true }, "packages": { @@ -6902,34 +4676,6 @@ "Intl": true } }, - "madge>rc>deep-extend": { - "packages": { - "browserify>buffer": true - } - }, - "mockttp>node-forge": { - "globals": { - "Blob": true, - "MutationObserver": true, - "QuotaExceededError": true, - "URL.createObjectURL": true, - "URL.revokeObjectURL": true, - "Worker": true, - "addEventListener": true, - "document": true, - "jQuery": true, - "localStorage": true, - "navigator": true, - "postMessage": true, - "removeEventListener": true, - "setTimeout": true - }, - "packages": { - "browserify>browser-resolve": true, - "browserify>process": true, - "browserify>timers-browserify": true - } - }, "nanoid": { "globals": { "crypto": true, @@ -7077,12 +4823,6 @@ "react-devtools>react-devtools-core": true } }, - "react-devtools>ip": { - "packages": { - "browserify>buffer": true, - "browserify>os-browserify": true - } - }, "react-devtools>react-devtools-core": { "globals": { "WebSocket": true, @@ -7498,8 +5238,13 @@ "setTimeout": true }, "packages": { - "3box>events": true, - "browserify>util": true + "browserify>util": true, + "safe-event-emitter>events": true + } + }, + "safe-event-emitter>events": { + "globals": { + "console": true } }, "semver": { @@ -7551,19 +5296,6 @@ "string.prototype.matchall>call-bind": true } }, - "string.prototype.matchall>side-channel": { - "packages": { - "enzyme>object-inspect": true, - "string.prototype.matchall>call-bind": true, - "string.prototype.matchall>get-intrinsic": true - } - }, - "stylelint>write-file-atomic>typedarray-to-buffer": { - "packages": { - "browserify>buffer": true, - "jsdom>request>is-typedarray": true - } - }, "textarea-caret": { "globals": { "document.body.appendChild": true, @@ -7615,11 +5347,6 @@ "console.warn": true, "define": true } - }, - "webpack>memory-fs>errno": { - "packages": { - "webpack>memory-fs>errno>prr": true - } } } } \ No newline at end of file diff --git a/lavamoat/browserify/policy-override.json b/lavamoat/browserify/policy-override.json index 388f87f48..9bc338726 100644 --- a/lavamoat/browserify/policy-override.json +++ b/lavamoat/browserify/policy-override.json @@ -20,11 +20,6 @@ "fetch": true } }, - "3box>graphql-request>cross-fetch>node-fetch": { - "globals": { - "fetch": true - } - }, "lodash": { "globals": { "setTimeout": true, diff --git a/lavamoat/build-system/policy.json b/lavamoat/build-system/policy.json index 8ef7fd273..b50930cc5 100644 --- a/lavamoat/build-system/policy.json +++ b/lavamoat/build-system/policy.json @@ -1,11 +1,5 @@ { "resources": { - "3box>ipfs>superstruct>clone-deep>shallow-clone>mixin-object": { - "packages": { - "3box>ipfs>superstruct>clone-deep>shallow-clone>mixin-object>for-in": true, - "webpack>micromatch>extglob>extend-shallow>is-extendable": true - } - }, "@babel/code-frame": { "globals": { "console.warn": true, @@ -2279,7 +2273,7 @@ "process": true }, "packages": { - "analytics-node>ms": true, + "gulp-livereload>debug>ms": true, "sinon>supports-color": true } }, @@ -2392,7 +2386,7 @@ "process": true }, "packages": { - "analytics-node>ms": true, + "gulp-livereload>debug>ms": true, "sinon>supports-color": true } }, @@ -2873,21 +2867,7 @@ }, "packages": { "eslint>file-entry-cache>flat-cache>flatted": true, - "eslint>file-entry-cache>flat-cache>rimraf": true - } - }, - "eslint>file-entry-cache>flat-cache>rimraf": { - "builtin": { - "assert": true, - "fs": true, - "path.join": true - }, - "globals": { - "process.platform": true, - "setTimeout": true - }, - "packages": { - "nyc>glob": true + "nyc>rimraf": true } }, "eslint>glob-parent": { @@ -3456,8 +3436,8 @@ "process": true }, "packages": { - "analytics-node>ms": true, - "gulp-livereload>chalk>supports-color": true + "gulp-livereload>chalk>supports-color": true, + "gulp-livereload>debug>ms": true } }, "gulp-livereload>event-stream": { @@ -3583,7 +3563,7 @@ "process": true }, "packages": { - "analytics-node>ms": true, + "gulp-livereload>debug>ms": true, "sinon>supports-color": true } }, @@ -3908,7 +3888,7 @@ "process": true }, "packages": { - "analytics-node>ms": true, + "gulp-livereload>debug>ms": true, "sinon>supports-color": true } }, @@ -4124,9 +4104,9 @@ }, "gulp-watch>anymatch>micromatch>braces>expand-range>fill-range>randomatic": { "packages": { - "3box>ipfs>kind-of": true, "gulp-watch>anymatch>micromatch>braces>expand-range>fill-range>randomatic>math-random": true, - "gulp>undertaker>bach>array-last>is-number": true + "gulp>undertaker>bach>array-last>is-number": true, + "webpack>micromatch>kind-of": true } }, "gulp-watch>anymatch>micromatch>braces>expand-range>fill-range>randomatic>math-random": { @@ -4796,7 +4776,6 @@ "process.platform": true }, "packages": { - "3box>ipfs>kind-of": true, "gulp>glob-watcher>anymatch>micromatch>define-property": true, "gulp>glob-watcher>anymatch>micromatch>extend-shallow": true, "gulp>glob-watcher>chokidar>braces": true, @@ -4804,6 +4783,7 @@ "webpack>micromatch>array-unique": true, "webpack>micromatch>extglob": true, "webpack>micromatch>fragment-cache": true, + "webpack>micromatch>kind-of": true, "webpack>micromatch>nanomatch": true, "webpack>micromatch>object.pick": true, "webpack>micromatch>regex-not": true, @@ -5018,7 +4998,7 @@ }, "gulp>undertaker>arr-map>make-iterator": { "packages": { - "3box>ipfs>kind-of": true + "webpack>micromatch>kind-of": true } }, "gulp>undertaker>bach": { @@ -5644,9 +5624,9 @@ }, "lavamoat>lavamoat-core>merge-deep>clone-deep>shallow-clone": { "packages": { - "3box>ipfs>superstruct>clone-deep>shallow-clone>mixin-object": true, "lavamoat>lavamoat-core>merge-deep>clone-deep>shallow-clone>kind-of": true, "lavamoat>lavamoat-core>merge-deep>clone-deep>shallow-clone>lazy-cache": true, + "lavamoat>lavamoat-core>merge-deep>clone-deep>shallow-clone>mixin-object": true, "webpack>micromatch>extglob>extend-shallow>is-extendable": true } }, @@ -5663,6 +5643,12 @@ "process.env.UNLAZY": true } }, + "lavamoat>lavamoat-core>merge-deep>clone-deep>shallow-clone>mixin-object": { + "packages": { + "lavamoat>lavamoat-core>merge-deep>clone-deep>shallow-clone>mixin-object>for-in": true, + "webpack>micromatch>extglob>extend-shallow>is-extendable": true + } + }, "lavamoat>lavamoat-core>merge-deep>kind-of": { "packages": { "browserify>insert-module-globals>is-buffer": true @@ -5871,6 +5857,20 @@ "path.resolve": true } }, + "nyc>rimraf": { + "builtin": { + "assert": true, + "fs": true, + "path.join": true + }, + "globals": { + "process.platform": true, + "setTimeout": true + }, + "packages": { + "nyc>glob": true + } + }, "nyc>signal-exit": { "builtin": { "assert.equal": true, @@ -7216,19 +7216,19 @@ }, "webpack>micromatch>define-property>is-descriptor": { "packages": { - "3box>ipfs>kind-of": true, "webpack>micromatch>define-property>is-descriptor>is-accessor-descriptor": true, - "webpack>micromatch>define-property>is-descriptor>is-data-descriptor": true + "webpack>micromatch>define-property>is-descriptor>is-data-descriptor": true, + "webpack>micromatch>kind-of": true } }, "webpack>micromatch>define-property>is-descriptor>is-accessor-descriptor": { "packages": { - "3box>ipfs>kind-of": true + "webpack>micromatch>kind-of": true } }, "webpack>micromatch>define-property>is-descriptor>is-data-descriptor": { "packages": { - "3box>ipfs>kind-of": true + "webpack>micromatch>kind-of": true } }, "webpack>micromatch>extglob": { @@ -7331,11 +7331,11 @@ "util.inspect": true }, "packages": { - "3box>ipfs>kind-of": true, "nyc>spawn-wrap>is-windows": true, "webpack>micromatch>arr-diff": true, "webpack>micromatch>array-unique": true, "webpack>micromatch>fragment-cache": true, + "webpack>micromatch>kind-of": true, "webpack>micromatch>nanomatch>define-property": true, "webpack>micromatch>nanomatch>extend-shallow": true, "webpack>micromatch>nanomatch>is-odd": true, @@ -7648,7 +7648,7 @@ }, "webpack>micromatch>snapdragon>use": { "packages": { - "3box>ipfs>kind-of": true + "webpack>micromatch>kind-of": true } }, "webpack>micromatch>to-regex": { diff --git a/package.json b/package.json index 77a2b535f..8718e81b3 100644 --- a/package.json +++ b/package.json @@ -73,10 +73,10 @@ "lavamoat:build": "lavamoat development/build/index.js --policy lavamoat/build-system/policy.json --policyOverride lavamoat/build-system/policy-override.json", "lavamoat:build:auto": "yarn lavamoat:build --writeAutoPolicy", "lavamoat:debug:build": "yarn lavamoat:build --writeAutoPolicyDebug --policydebug lavamoat/build-system/policy-debug.json", - "lavamoat:background:auto": "node ./development/generate-lavamoat-policies.js", - "lavamoat:background:auto:ci": "node ./development/generate-lavamoat-policies.js --parallel=false", - "lavamoat:auto": "yarn lavamoat:build:auto && yarn lavamoat:background:auto", - "lavamoat:auto:ci": "yarn lavamoat:build:auto && yarn lavamoat:background:auto:ci", + "lavamoat:webapp:auto": "node ./development/generate-lavamoat-policies.js --devMode=true", + "lavamoat:webapp:auto:ci": "node ./development/generate-lavamoat-policies.js --parallel=false", + "lavamoat:auto": "yarn lavamoat:build:auto && yarn lavamoat:webapp:auto", + "lavamoat:auto:ci": "yarn lavamoat:build:auto && yarn lavamoat:webapp:auto:ci", "ts-migration:enumerate": "ts-node development/ts-migration-dashboard/scripts/write-list-of-files-to-convert.ts", "ts-migration:dashboard:watch": "ts-node development/ts-migration-dashboard/scripts/build.ts --watch", "ts-migration:dashboard:build": "ts-node development/ts-migration-dashboard/scripts/build.ts", @@ -91,25 +91,15 @@ "**/redux/symbol-observable": "^2.0.3", "**/redux-devtools-instrument/symbol-observable": "^2.0.3", "**/rxjs/symbol-observable": "^2.0.3", - "**/xmlhttprequest-ssl": "^1.6.2", - "3box/ipfs/ipld-zcash/zcash-bitcore-lib/lodash": "^4.17.21", - "3box/ipfs/ipld-zcash/zcash-bitcore-lib/elliptic": "^6.5.4", - "3box/ipfs/libp2p-mdns/multicast-dns/dns-packet": "^5.2.2", - "3box/ipfs/prometheus-gc-stats/gc-stats/node-pre-gyp/tar": "^6.1.2", - "3box/**/libp2p-crypto/node-forge": "^1.3.0", - "3box/**/libp2p-keychain/node-forge": "^1.3.0", - "3box/ipfs/libp2p-webrtc-star/socket.io/engine.io": "^4.0.0", - "3box/**/@hapi/hoek": "^8.5.1", "analytics-node/axios": "^0.21.2", "ganache-core/lodash": "^4.17.21", "netmask": "^2.0.1", "pubnub/superagent-proxy": "^3.0.0", - "pull-ws": "^3.3.2", "json-schema": "^0.4.0", - "simple-get": "^4.0.1" + "simple-get": "^4.0.1", + "@storybook/**/ast-types": "^0.14.2" }, "dependencies": { - "3box": "^1.10.2", "@babel/runtime": "^7.5.5", "@download/blockies": "^1.0.3", "@ensdomains/content-hash": "^2.5.6", @@ -142,6 +132,7 @@ "@ngraveio/bc-ur": "^1.1.6", "@popperjs/core": "^2.4.0", "@reduxjs/toolkit": "^1.6.2", + "@segment/loosely-validate-event": "^2.0.0", "@sentry/browser": "^6.0.0", "@sentry/integrations": "^6.0.0", "@sentry/types": "^6.0.1", @@ -151,7 +142,6 @@ "@truffle/decoder": "^5.1.0", "@zxing/browser": "^0.0.10", "@zxing/library": "0.8.0", - "analytics-node": "^3.4.0-beta.3", "await-semaphore": "^0.1.1", "base32-encode": "^1.2.0", "base64-js": "^1.5.1", @@ -168,7 +158,7 @@ "eth-json-rpc-filters": "^4.2.1", "eth-json-rpc-middleware": "^9.0.1", "eth-keyring-controller": "^7.0.2", - "eth-lattice-keyring": "^0.12.0", + "eth-lattice-keyring": "^0.12.3", "eth-method-registry": "^2.0.0", "eth-query": "^2.1.2", "eth-rpc-errors": "^4.0.2", @@ -188,6 +178,7 @@ "globalthis": "^1.0.1", "human-standard-token-abi": "^2.0.0", "immer": "^9.0.6", + "is-retry-allowed": "^2.2.0", "jest-junit": "^14.0.1", "json-rpc-engine": "^6.1.0", "json-rpc-middleware-stream": "^2.1.1", @@ -225,6 +216,7 @@ "readable-stream": "^2.3.3", "redux": "^4.0.5", "redux-thunk": "^2.3.0", + "remove-trailing-slash": "^0.1.1", "reselect": "^3.0.1", "safe-event-emitter": "^1.0.1", "ses": "^0.12.4", @@ -303,7 +295,7 @@ "browserify": "^16.5.1", "chalk": "^3.0.0", "chokidar": "^3.5.3", - "chromedriver": "^105.0.0", + "chromedriver": "^107.0.0", "concurrently": "^5.2.0", "copy-webpack-plugin": "^6.0.3", "cross-spawn": "^7.0.3", @@ -417,23 +409,6 @@ "chromedriver": true, "geckodriver": true, "react-devtools>electron": true, - "3box>ipfs-postmsg-proxy>peer-id>libp2p-crypto>libp2p-crypto-secp256k1>secp256k1": false, - "3box>ipfs>ipfs-repo>datastore-level>leveldown": false, - "3box>ipfs>ipfs-unixfs-importer>rabin-wasm>assemblyscript": false, - "3box>ipfs>ipld-ethereum>ethereumjs-account>ethereumjs-util>keccak": false, - "3box>ipfs>ipld-ethereum>ethereumjs-account>ethereumjs-util>secp256k1": false, - "3box>ipfs>ipld-ethereum>ethereumjs-block>ethereumjs-util>keccak": false, - "3box>ipfs>ipld-ethereum>ethereumjs-block>ethereumjs-util>secp256k1": false, - "3box>ipfs>ipld-ethereum>ethereumjs-tx>ethereumjs-util>keccak": false, - "3box>ipfs>ipld-ethereum>ethereumjs-tx>ethereumjs-util>secp256k1": false, - "3box>ipfs>ipld-ethereum>merkle-patricia-tree>ethereumjs-util>keccak": false, - "3box>ipfs>ipld-ethereum>merkle-patricia-tree>ethereumjs-util>secp256k1": false, - "3box>ipfs>libp2p-crypto>libp2p-crypto-secp256k1>secp256k1": false, - "3box>ipfs>libp2p-crypto>ursa-optional": false, - "3box>ipfs>prometheus-gc-stats>gc-stats": false, - "3box>orbit-db>orbit-db-cache>leveldown": false, - "3box>orbit-db>orbit-db-keystore>leveldown": false, - "3box>orbit-db>orbit-db-keystore>libp2p-crypto-secp256k1>secp256k1": false, "@eth-optimism/contracts>@ethersproject/hardware-wallets>@ledgerhq/hw-transport-node-hid>@ledgerhq/hw-transport-node-hid-noevents>node-hid": false, "@eth-optimism/contracts>@ethersproject/hardware-wallets>@ledgerhq/hw-transport-node-hid>node-hid": false, "@eth-optimism/contracts>@ethersproject/hardware-wallets>@ledgerhq/hw-transport-node-hid>usb": false, diff --git a/patches/@keystonehq+bc-ur-registry+0.4.4.patch b/patches/@keystonehq+bc-ur-registry+0.5.0-alpha.5.patch similarity index 87% rename from patches/@keystonehq+bc-ur-registry+0.4.4.patch rename to patches/@keystonehq+bc-ur-registry+0.5.0-alpha.5.patch index eec0a3388..b99840ebf 100644 --- a/patches/@keystonehq+bc-ur-registry+0.4.4.patch +++ b/patches/@keystonehq+bc-ur-registry+0.5.0-alpha.5.patch @@ -40,14 +40,15 @@ index a5f9f7d..0000000 -} diff --git a/node_modules/@keystonehq/bc-ur-registry/src/CryptoAccount.ts b/node_modules/@keystonehq/bc-ur-registry/src/CryptoAccount.ts deleted file mode 100644 -index 753e535..0000000 +index e6efeeb..0000000 --- a/node_modules/@keystonehq/bc-ur-registry/src/CryptoAccount.ts +++ /dev/null -@@ -1,57 +0,0 @@ +@@ -1,58 +0,0 @@ -import { CryptoOutput } from '.'; -import { decodeToDataItem, DataItem } from './lib'; -import { RegistryItem } from './RegistryItem'; -import { RegistryTypes } from './RegistryType'; +-import { DataItemMap } from './types'; - -enum Keys { - masterFingerprint = 1, @@ -70,7 +71,7 @@ index 753e535..0000000 - public getOutputDescriptors = () => this.outputDescriptors; - - public toDataItem = () => { -- const map = {}; +- const map: DataItemMap = {}; - if (this.masterFingerprint) { - map[Keys.masterFingerprint] = this.masterFingerprint.readUInt32BE(0); - } @@ -103,13 +104,14 @@ index 753e535..0000000 -} diff --git a/node_modules/@keystonehq/bc-ur-registry/src/CryptoCoinInfo.ts b/node_modules/@keystonehq/bc-ur-registry/src/CryptoCoinInfo.ts deleted file mode 100644 -index 0201682..0000000 +index 843b50c..0000000 --- a/node_modules/@keystonehq/bc-ur-registry/src/CryptoCoinInfo.ts +++ /dev/null -@@ -1,58 +0,0 @@ +@@ -1,59 +0,0 @@ -import { decodeToDataItem, DataItem } from './lib'; -import { RegistryItem } from './RegistryItem'; -import { RegistryTypes } from './RegistryType'; +-import { DataItemMap } from './types'; - -enum Keys { - type = '1', @@ -143,7 +145,7 @@ index 0201682..0000000 - }; - - public toDataItem = () => { -- const map = {}; +- const map: DataItemMap = {}; - if (this.type) { - map[Keys.type] = this.type; - } @@ -167,13 +169,14 @@ index 0201682..0000000 -} diff --git a/node_modules/@keystonehq/bc-ur-registry/src/CryptoECKey.ts b/node_modules/@keystonehq/bc-ur-registry/src/CryptoECKey.ts deleted file mode 100644 -index 1e964fc..0000000 +index 54c3c4b..0000000 --- a/node_modules/@keystonehq/bc-ur-registry/src/CryptoECKey.ts +++ /dev/null -@@ -1,59 +0,0 @@ +@@ -1,68 +0,0 @@ -import { decodeToDataItem, DataItem } from './lib'; -import { RegistryItem } from './RegistryItem'; -import { RegistryTypes } from './RegistryType'; +-import { DataItemMap, ICryptoKey } from './types'; - -enum Keys { - curve = 1, @@ -181,17 +184,21 @@ index 1e964fc..0000000 - data, -} - --export class CryptoECKey extends RegistryItem { +-export class CryptoECKey extends RegistryItem implements ICryptoKey { - private data: Buffer; -- private curve: number; -- private privateKey: boolean; +- private curve: number | undefined; +- private privateKey: boolean | undefined; - constructor(args: { data: Buffer; curve?: number; privateKey?: boolean }) { - super(); - this.data = args.data; - this.curve = args.curve; -- this.privateKey = args.privateKey; +- this.privateKey = args.privateKey || undefined; - } - +- isECKey = () => { +- return true; +- }; +- - public getCurve = () => this.curve || 0; - public isPrivateKey = () => this.privateKey || false; - public getData = () => this.data; @@ -201,7 +208,7 @@ index 1e964fc..0000000 - }; - - toDataItem = () => { -- const map = {}; +- const map: DataItemMap = {}; - if (this.curve) { - map[Keys.curve] = this.curve; - } @@ -212,6 +219,10 @@ index 1e964fc..0000000 - return new DataItem(map); - }; - +- getOutputDescriptorContent = () => { +- return this.data.toString('hex'); +- } +- - static fromDataItem = (dataItem: DataItem) => { - const map = dataItem.getData(); - const curve = map[Keys.curve]; @@ -232,16 +243,20 @@ index 1e964fc..0000000 -} diff --git a/node_modules/@keystonehq/bc-ur-registry/src/CryptoHDKey.ts b/node_modules/@keystonehq/bc-ur-registry/src/CryptoHDKey.ts deleted file mode 100644 -index bbfd331..0000000 +index 8fc2a82..0000000 --- a/node_modules/@keystonehq/bc-ur-registry/src/CryptoHDKey.ts +++ /dev/null -@@ -1,210 +0,0 @@ +@@ -1,237 +0,0 @@ +-// eslint-disable-next-line @typescript-eslint/ban-ts-comment +-// @ts-ignore -import { encode } from 'bs58check'; -import { CryptoCoinInfo } from './CryptoCoinInfo'; -import { CryptoKeypath } from './CryptoKeypath'; -import { decodeToDataItem, DataItem } from './lib'; -import { RegistryItem } from './RegistryItem'; -import { RegistryTypes } from './RegistryType'; +-import { DataItemMap, ICryptoKey } from './types'; +-import { PathComponent } from './PathComponent'; - -enum Keys { - is_master = 1, @@ -274,17 +289,22 @@ index bbfd331..0000000 - name?: string; - note?: string; -}; --export class CryptoHDKey extends RegistryItem { -- private master: boolean; -- private privateKey: boolean; -- private key: Buffer; -- private chainCode: Buffer; -- private useInfo: CryptoCoinInfo; -- private origin: CryptoKeypath; -- private children: CryptoKeypath; -- private parentFingerprint: Buffer; -- private name: string; -- private note: string; +- +-export class CryptoHDKey extends RegistryItem implements ICryptoKey { +- private master?: boolean; +- private privateKey?: boolean; +- private key?: Buffer; +- private chainCode?: Buffer; +- private useInfo?: CryptoCoinInfo; +- private origin?: CryptoKeypath; +- private children?: CryptoKeypath; +- private parentFingerprint?: Buffer; +- private name?: string; +- private note?: string; +- +- isECKey = () => { +- return false; +- }; - - public getKey = () => this.key; - public getChainCode = () => this.chainCode; @@ -299,22 +319,24 @@ index bbfd331..0000000 - public getBip32Key = () => { - let version: Buffer; - let depth: number; -- let index: number; +- let index = 0; - let parentFingerprint: Buffer = Buffer.alloc(4).fill(0); -- if(this.isMaster()) { +- if (this.isMaster()) { - // version bytes defined on https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#serialization-format -- version = Buffer.from("0488ADE4", "hex") +- version = Buffer.from('0488ADE4', 'hex'); - depth = 0; - index = 0; - } else { -- depth = this.getOrigin().getComponents().length || this.getOrigin().getDepth(); -- const paths = this.getOrigin().getComponents(); +- depth = this.getOrigin()?.getComponents().length || this.getOrigin()?.getDepth() as number; +- const paths = this.getOrigin()?.getComponents() as PathComponent[]; - const lastPath = paths[paths.length - 1]; -- if(lastPath) { +- if (lastPath) { - index = lastPath.isHardened() ? lastPath.getIndex()! + 0x80000000 : lastPath.getIndex()!; -- parentFingerprint = this.getParentFingerprint(); +- if (this.getParentFingerprint()) { +- parentFingerprint = this.getParentFingerprint() as Buffer; +- } - } -- if(this.isPrivateKey()) { +- if (this.isPrivateKey()) { - version = Buffer.from('0488ADE4', 'hex'); - } else { - version = Buffer.from('0488B21E', 'hex'); @@ -326,13 +348,29 @@ index bbfd331..0000000 - indexBuffer.writeUInt32BE(index, 0); - const chainCode = this.getChainCode(); - const key = this.getKey(); -- return encode(Buffer.concat([version, depthBuffer, parentFingerprint, indexBuffer, chainCode, key])); -- } +- return encode(Buffer.concat([version, depthBuffer, parentFingerprint, indexBuffer, chainCode as Buffer, key as Buffer])); +- }; - - public getRegistryType = () => { - return RegistryTypes.CRYPTO_HDKEY; - }; - +- public getOutputDescriptorContent = () => { +- let result = ''; +- if (this.getOrigin()) { +- if (this.getOrigin()?.getSourceFingerprint() && this.getOrigin()?.getPath()) { +- result += `${this.getOrigin()?.getSourceFingerprint()?.toString('hex')}/${this.getOrigin()?.getPath()}`; +- } +- } +- result += this.getBip32Key(); +- if (this.getChildren()) { +- if (this.getChildren()?.getPath()) { +- result += `/${this.getChildren()?.getPath()}`; +- } +- } +- return result; +- }; +- - constructor(args: DeriveKeyProps | MasterKeyProps) { - super(); - if (args.isMaster) { @@ -362,7 +400,7 @@ index bbfd331..0000000 - }; - - public toDataItem = () => { -- const map = {}; +- const map: DataItemMap = {}; - if (this.master) { - map[Keys.is_master] = true; - map[Keys.key_data] = this.key; @@ -418,8 +456,8 @@ index bbfd331..0000000 - const children = map[Keys.children] - ? CryptoKeypath.fromDataItem(map[Keys.children]) - : undefined; -- let _parentFingerprint = map[Keys.parent_fingerprint]; -- let parentFingerprint: Buffer; +- const _parentFingerprint = map[Keys.parent_fingerprint]; +- let parentFingerprint: Buffer | undefined = undefined; - if (_parentFingerprint) { - parentFingerprint = Buffer.alloc(4); - parentFingerprint.writeUInt32BE(_parentFingerprint, 0); @@ -448,14 +486,15 @@ index bbfd331..0000000 -} diff --git a/node_modules/@keystonehq/bc-ur-registry/src/CryptoKeypath.ts b/node_modules/@keystonehq/bc-ur-registry/src/CryptoKeypath.ts deleted file mode 100644 -index 4babe91..0000000 +index 00146ce..0000000 --- a/node_modules/@keystonehq/bc-ur-registry/src/CryptoKeypath.ts +++ /dev/null -@@ -1,95 +0,0 @@ +@@ -1,96 +0,0 @@ -import { decodeToDataItem, DataItem } from './lib'; -import { PathComponent } from './PathComponent'; -import { RegistryItem } from './RegistryItem'; -import { RegistryTypes } from './RegistryType'; +-import { DataItemMap } from './types'; - -enum Keys { - components = 1, @@ -494,16 +533,16 @@ index 4babe91..0000000 - public getDepth = () => this.depth; - - toDataItem = () => { -- const map: Record = {}; -- const components = []; +- const map: DataItemMap = {}; +- const components: (number | boolean | any[])[] = []; - this.components && - this.components.forEach((component) => { - if (component.isWildcard()) { - components.push([]); - } else { -- components.push(component.getIndex()); +- components.push(component.getIndex() as number); - } -- components.push(component.isHardened() ? true : false); +- components.push(component.isHardened()); - }); - map[Keys.components] = components; - if (this.sourceFingerprint) { @@ -533,7 +572,7 @@ index 4babe91..0000000 - } - } - const _sourceFingerprint = map[Keys.source_fingerprint]; -- let sourceFingerprint: Buffer; +- let sourceFingerprint: Buffer | undefined; - if (_sourceFingerprint) { - sourceFingerprint = Buffer.alloc(4); - sourceFingerprint.writeUInt32BE(_sourceFingerprint, 0); @@ -549,10 +588,10 @@ index 4babe91..0000000 -} diff --git a/node_modules/@keystonehq/bc-ur-registry/src/CryptoOutput.ts b/node_modules/@keystonehq/bc-ur-registry/src/CryptoOutput.ts deleted file mode 100644 -index cd3009c..0000000 +index 90abf6f..0000000 --- a/node_modules/@keystonehq/bc-ur-registry/src/CryptoOutput.ts +++ /dev/null -@@ -1,114 +0,0 @@ +@@ -1,127 +0,0 @@ -import { CryptoECKey } from './CryptoECKey'; -import { CryptoHDKey } from './CryptoHDKey'; -import { decodeToDataItem, DataItem } from './lib'; @@ -599,6 +638,18 @@ index cd3009c..0000000 - - public getScriptExpressions = () => this.scriptExpressions; - +- private _toOutputDescriptor = (seIndex: number): string => { +- if (seIndex >= this.scriptExpressions.length) { +- return this.cryptoKey.getOutputDescriptorContent(); +- } else { +- return `${this.scriptExpressions[seIndex].getExpression()}(${this._toOutputDescriptor(seIndex + 1)})`; +- } +- }; +- +- public toString = () => { +- return this._toOutputDescriptor(0); +- }; +- - toDataItem = () => { - let dataItem = this.cryptoKey.toDataItem(); - if ( @@ -625,9 +676,10 @@ index cd3009c..0000000 - public static fromDataItem = (dataItem: DataItem) => { - const scriptExpressions: ScriptExpression[] = []; - let _dataItem = dataItem; +- // eslint-disable-next-line no-constant-condition - while (true) { -- let _tag = _dataItem.getTag() || undefined; -- const se = ScriptExpression.fromTag(_tag); +- let _tag = _dataItem.getTag(); +- const se = ScriptExpression.fromTag(_tag as number); - if (se) { - scriptExpressions.push(se); - if (_dataItem.getData() instanceof DataItem) { @@ -646,7 +698,7 @@ index cd3009c..0000000 - (scriptExpressions[seLength - 1].getExpression() === - ScriptExpressions.MULTISIG.getExpression() || - scriptExpressions[seLength - 1].getExpression() === -- ScriptExpressions.SORTED_MULTISIG.getExpression()); +- ScriptExpressions.SORTED_MULTISIG.getExpression()); - //TODO: judge is multi key by scriptExpressions - if (isMultiKey) { - const multiKey = MultiKey.fromDataItem(_dataItem); @@ -707,10 +759,10 @@ index 626b647..0000000 -} diff --git a/node_modules/@keystonehq/bc-ur-registry/src/Decoder/index.ts b/node_modules/@keystonehq/bc-ur-registry/src/Decoder/index.ts deleted file mode 100644 -index 0460694..0000000 +index 5d7e3fe..0000000 --- a/node_modules/@keystonehq/bc-ur-registry/src/Decoder/index.ts +++ /dev/null -@@ -1,40 +0,0 @@ +@@ -1,41 +0,0 @@ -import { URDecoder } from '@ngraveio/bc-ur'; -import { - Bytes, @@ -723,6 +775,7 @@ index 0460694..0000000 - CryptoPSBT, -} from '..'; -import { RegistryTypes } from '../RegistryType'; +-import { UnknownURTypeError } from '../errors'; - -export class URRegistryDecoder extends URDecoder { - public resultRegistryType = () => { @@ -745,7 +798,7 @@ index 0460694..0000000 - case RegistryTypes.CRYPTO_ACCOUNT.getType(): - return CryptoAccount.fromCBOR(ur.cbor); - default: -- throw new Error( +- throw new UnknownURTypeError( - `#[ur-registry][Decoder][fn.resultRegistryType]: registry type ${ur.type} is not supported now`, - ); - } @@ -753,15 +806,16 @@ index 0460694..0000000 -} diff --git a/node_modules/@keystonehq/bc-ur-registry/src/MultiKey.ts b/node_modules/@keystonehq/bc-ur-registry/src/MultiKey.ts deleted file mode 100644 -index 0522fbd..0000000 +index ced19dc..0000000 --- a/node_modules/@keystonehq/bc-ur-registry/src/MultiKey.ts +++ /dev/null -@@ -1,54 +0,0 @@ +@@ -1,60 +0,0 @@ -import { CryptoECKey } from './CryptoECKey'; -import { CryptoHDKey } from './CryptoHDKey'; -import { DataItem } from './lib/DataItem'; -import { RegistryItem } from './RegistryItem'; -import { RegistryType, RegistryTypes } from './RegistryType'; +-import { DataItemMap } from './types'; - -enum Keys { - threshold = 1, @@ -769,24 +823,24 @@ index 0522fbd..0000000 -} - -export class MultiKey extends RegistryItem { +- // eslint-disable-next-line @typescript-eslint/ban-ts-comment +- // @ts-ignore - getRegistryType: () => RegistryType; - - constructor( - private threshold: number, -- private ecKeys: CryptoECKey[], -- private hdKeys: CryptoHDKey[], +- private keys: (CryptoECKey | CryptoHDKey)[], - ) { - super(); - } - - getThreshold = () => this.threshold; -- getEcKeys = () => this.ecKeys as CryptoECKey[]; -- getHdKeys = () => this.hdKeys as CryptoHDKey[]; +- getKeys = () => this.keys; - - toDataItem = () => { -- const map = {}; +- const map: DataItemMap = {}; - map[Keys.threshold] = this.threshold; -- const keys: DataItem[] = [...this.ecKeys, ...this.hdKeys].map((k) => { +- const keys: DataItem[] = this.keys.map((k) => { - const dataItem = k.toDataItem(); - dataItem.setTag(k.getRegistryType().getTag()); - return dataItem; @@ -795,20 +849,25 @@ index 0522fbd..0000000 - return new DataItem(map); - }; - +- getOutputDescriptorContent = () => { +- return [this.getThreshold(), +- this.keys.map(k => k.getOutputDescriptorContent()).join(','), +- ].join(','); +- }; +- - static fromDataItem = (dataItem: DataItem) => { - const map = dataItem.getData(); - const threshold = map[Keys.threshold]; -- const keys = map[Keys.keys] as DataItem[]; -- const ecKeys = []; -- const hdKeys = []; -- keys.forEach((k) => { +- const _keys = map[Keys.keys] as DataItem[]; +- const keys: (CryptoECKey | CryptoHDKey)[] = []; +- _keys.forEach((k) => { - if (k.getTag() === RegistryTypes.CRYPTO_HDKEY.getTag()) { -- hdKeys.push(CryptoHDKey.fromDataItem(k)); +- keys.push(CryptoHDKey.fromDataItem(k)); - } else if (k.getTag() === RegistryTypes.CRYPTO_ECKEY.getTag()) { -- ecKeys.push(CryptoECKey.fromDataItem(k)); +- keys.push(CryptoECKey.fromDataItem(k)); - } - }); -- return new MultiKey(threshold, ecKeys, hdKeys); +- return new MultiKey(threshold, keys); - }; -} diff --git a/node_modules/@keystonehq/bc-ur-registry/src/PathComponent.ts b/node_modules/@keystonehq/bc-ur-registry/src/PathComponent.ts @@ -914,7 +973,7 @@ index 64637bc..0000000 -}; diff --git a/node_modules/@keystonehq/bc-ur-registry/src/ScriptExpression.ts b/node_modules/@keystonehq/bc-ur-registry/src/ScriptExpression.ts deleted file mode 100644 -index fdd3f05..0000000 +index 8fbf0db..0000000 --- a/node_modules/@keystonehq/bc-ur-registry/src/ScriptExpression.ts +++ /dev/null @@ -1,26 +0,0 @@ @@ -940,16 +999,27 @@ index fdd3f05..0000000 - WITNESS_PUBLIC_KEY_HASH: new ScriptExpression(404, 'wpkh'), - COMBO: new ScriptExpression(405, 'combo'), - MULTISIG: new ScriptExpression(406, 'multi'), -- SORTED_MULTISIG: new ScriptExpression(407, 'sorted'), +- SORTED_MULTISIG: new ScriptExpression(407, 'sortedmulti'), - ADDRESS: new ScriptExpression(307, 'addr'), - RAW_SCRIPT: new ScriptExpression(408, 'raw'), -}; +diff --git a/node_modules/@keystonehq/bc-ur-registry/src/errors/index.ts b/node_modules/@keystonehq/bc-ur-registry/src/errors/index.ts +deleted file mode 100644 +index dd2b0bd..0000000 +--- a/node_modules/@keystonehq/bc-ur-registry/src/errors/index.ts ++++ /dev/null +@@ -1,5 +0,0 @@ +-export class UnknownURTypeError extends Error { +- constructor(message: string) { +- super(message); +- } +-} diff --git a/node_modules/@keystonehq/bc-ur-registry/src/index.ts b/node_modules/@keystonehq/bc-ur-registry/src/index.ts deleted file mode 100644 -index 172a1e5..0000000 +index bb07bc8..0000000 --- a/node_modules/@keystonehq/bc-ur-registry/src/index.ts +++ /dev/null -@@ -1,89 +0,0 @@ +@@ -1,110 +0,0 @@ -import './patchCBOR'; - -import { CryptoHDKey } from './CryptoHDKey'; @@ -971,6 +1041,7 @@ index 172a1e5..0000000 -import { ScriptExpressions } from './ScriptExpression'; -import { PathComponent } from './PathComponent'; - +-import { RegistryItem } from './RegistryItem'; -import { RegistryTypes, RegistryType } from './RegistryType'; - -import { @@ -983,7 +1054,6 @@ index 172a1e5..0000000 -} from './lib'; - -export { DataItem } from './lib'; --export { RegistryItem } from './RegistryItem'; - -import { patchTags } from './utils'; - @@ -1014,9 +1084,12 @@ index 172a1e5..0000000 - -const extend = { - RegistryTypes, +- RegistryItem, - RegistryType, +- - decodeToDataItem, - encodeDataItem, +- - cbor, -}; - @@ -1038,6 +1111,24 @@ index 172a1e5..0000000 - extend, -}; - +-export * from './errors'; +-export * from './Decoder'; +-export * from './lib'; +-export * from './CryptoAccount' +-export * from './CryptoPSBT' +-export * from './CryptoHDKey' +-export * from './CryptoOutput' +-export * from './CryptoCoinInfo' +-export * from './CryptoECKey' +-export * from './MultiKey' +-export * from './CryptoKeypath' +-export * from './patchCBOR' +-export * from './PathComponent' +-export * from './RegistryItem' +-export * from './RegistryType' +-export * from './types' +-export * from './utils' +- -export default URlib; diff --git a/node_modules/@keystonehq/bc-ur-registry/src/lib/DataItem.ts b/node_modules/@keystonehq/bc-ur-registry/src/lib/DataItem.ts deleted file mode 100644 @@ -1070,12 +1161,54 @@ index 9727f7e..0000000 - return this.data; - }; -} +diff --git a/node_modules/@keystonehq/bc-ur-registry/src/lib/cbor-sync.d.ts b/node_modules/@keystonehq/bc-ur-registry/src/lib/cbor-sync.d.ts +deleted file mode 100644 +index 6374ba7..0000000 +--- a/node_modules/@keystonehq/bc-ur-registry/src/lib/cbor-sync.d.ts ++++ /dev/null +@@ -1,36 +0,0 @@ +-export namespace config { +- const useToJSON: boolean; +-} +-export function addWriter(format: any, writerFunction: any): void; +-export function addReader(format: any, readerFunction: any): void; +-export function encode(data: any, format: any): any; +-export function encodeDataItem(data: any, format?: any): any; +-export function decode(data: any, format: any): any; +-export function decodeToDataItem(data: any, format?: any): import("./DataItem").DataItem; +-export function addSemanticEncode(tag: any, fn: any): { +- config: { +- useToJSON: boolean; +- }; +- addWriter: (format: any, writerFunction: any) => void; +- addReader: (format: any, readerFunction: any) => void; +- encode: (data: any, format: any) => any; +- encodeDataItem: (data: any, format: any) => any; +- decode: (data: any, format: any) => any; +- decodeToDataItem: (data: any, format: any) => import("./DataItem").DataItem; +- addSemanticEncode: (tag: any, fn: any) => any; +- addSemanticDecode: (tag: any, fn: any) => any; +-}; +-export function addSemanticDecode(tag: any, fn: any): { +- config: { +- useToJSON: boolean; +- }; +- addWriter: (format: any, writerFunction: any) => void; +- addReader: (format: any, readerFunction: any) => void; +- encode: (data: any, format: any) => any; +- encodeDataItem: (data: any, format: any) => any; +- decode: (data: any, format: any) => any; +- decodeToDataItem: (data: any, format: any) => import("./DataItem").DataItem; +- addSemanticEncode: (tag: any, fn: any) => any; +- addSemanticDecode: (tag: any, fn: any) => any; +-}; +-//# sourceMappingURL=cbor-sync.d.ts.map diff --git a/node_modules/@keystonehq/bc-ur-registry/src/lib/cbor-sync.js b/node_modules/@keystonehq/bc-ur-registry/src/lib/cbor-sync.js deleted file mode 100644 -index 63e5b3a..0000000 +index df8db90..0000000 --- a/node_modules/@keystonehq/bc-ur-registry/src/lib/cbor-sync.js +++ /dev/null -@@ -1,695 +0,0 @@ +@@ -1,693 +0,0 @@ -(function (global, factory) { - if (typeof define === 'function' && define.amd) { - define([], factory); @@ -1531,8 +1664,6 @@ index 63e5b3a..0000000 - semanticDecoders[tag] = fn; - return this; - }, -- Reader: Reader, -- Writer: Writer, - }; - - /** Node.js Buffers **/ @@ -1788,7 +1919,7 @@ index deb0156..0000000 -export { DataItem } from './DataItem'; diff --git a/node_modules/@keystonehq/bc-ur-registry/src/patchCBOR.ts b/node_modules/@keystonehq/bc-ur-registry/src/patchCBOR.ts deleted file mode 100644 -index b9909a7..0000000 +index 218e912..0000000 --- a/node_modules/@keystonehq/bc-ur-registry/src/patchCBOR.ts +++ /dev/null @@ -1,11 +0,0 @@ @@ -1802,17 +1933,29 @@ index b9909a7..0000000 -const scriptExpressionTags = Object.values(ScriptExpressions).map((se) => - se.getTag(), -); --patchTags(registryTags.concat(scriptExpressionTags)); +-patchTags(registryTags.concat(scriptExpressionTags) as number[]); +diff --git a/node_modules/@keystonehq/bc-ur-registry/src/types.ts b/node_modules/@keystonehq/bc-ur-registry/src/types.ts +deleted file mode 100644 +index 29aa370..0000000 +--- a/node_modules/@keystonehq/bc-ur-registry/src/types.ts ++++ /dev/null +@@ -1,6 +0,0 @@ +-export interface ICryptoKey { +- isECKey: () => boolean; +- getOutputDescriptorContent: () => string; +-} +- +-export type DataItemMap = Record; diff --git a/node_modules/@keystonehq/bc-ur-registry/src/utils.ts b/node_modules/@keystonehq/bc-ur-registry/src/utils.ts deleted file mode 100644 -index ee39b78..0000000 +index e38112b..0000000 --- a/node_modules/@keystonehq/bc-ur-registry/src/utils.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { addSemanticDecode, addSemanticEncode, DataItem } from './lib'; - --const alreadyPatchedTag = []; --export const patchTags = (tags: number[]) => { +-const alreadyPatchedTag: number[] = []; +-export const patchTags = (tags: number[]): void => { - tags.forEach((tag) => { - if (alreadyPatchedTag.find((i) => i === tag)) return; - addSemanticEncode(tag, (data: any) => { diff --git a/patches/secp256k1+3.8.0.patch b/patches/secp256k1+3.8.0.patch deleted file mode 100644 index e44de3f04..000000000 --- a/patches/secp256k1+3.8.0.patch +++ /dev/null @@ -1,37 +0,0 @@ -lazy precompute for faster module initialization - -diff --git a/node_modules/secp256k1/lib/js/ecpointg.js b/node_modules/secp256k1/lib/js/ecpointg.js -index 0144364..09a87c5 100644 ---- a/node_modules/secp256k1/lib/js/ecpointg.js -+++ b/node_modules/secp256k1/lib/js/ecpointg.js -@@ -8,11 +8,12 @@ function ECPointG () { - this.x = BN.fromBuffer(Buffer.from('79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798', 'hex')) - this.y = BN.fromBuffer(Buffer.from('483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8', 'hex')) - this.inf = false -- -- this._precompute() -+ this.precomputed = undefined - } - - ECPointG.prototype._precompute = function () { -+ if (this.precomputed !== undefined) return -+ - var ecpoint = new ECPoint(this.x, this.y) - - var dstep = 4 -@@ -34,6 +35,7 @@ ECPointG.prototype._precompute = function () { - } - - ECPointG.prototype.mul = function (num) { -+ this._precompute() - // Algorithm 3.42 Fixed-base NAF windowing method for point multiplication - var step = this.precomputed.doubles.step - var points = this.precomputed.doubles.points -@@ -68,6 +70,7 @@ ECPointG.prototype.mul = function (num) { - } - - ECPointG.prototype.mulAdd = function (k1, p2, k2) { -+ this._precompute() - var nafPointsP1 = this.precomputed.naf - var nafPointsP2 = p2._getNAFPoints1() - var wnd = [nafPointsP1.points, nafPointsP2.points] diff --git a/shared/constants/alarms.js b/shared/constants/alarms.js index c0dbbcf7e..730fdd826 100644 --- a/shared/constants/alarms.js +++ b/shared/constants/alarms.js @@ -1 +1,3 @@ export const AUTO_LOCK_TIMEOUT_ALARM = 'AUTO_LOCK_TIMEOUT_ALARM'; +export const METAMETRICS_FINALIZE_EVENT_FRAGMENT_ALARM = + 'METAMETRICS_FINALIZE_EVENT_FRAGMENT_ALARM'; diff --git a/shared/constants/metametrics.js b/shared/constants/metametrics.js index 78990d81b..f30dc56c2 100644 --- a/shared/constants/metametrics.js +++ b/shared/constants/metametrics.js @@ -178,8 +178,8 @@ * identify the new number_of_tokens trait * @property {'opensea_api_enabled'} OPENSEA_API_ENABLED - when the OpenSea API is enabled * we identify the opensea_api_enabled trait - * @property {'three_box_enabled'} THREE_BOX_ENABLED - when 3box feature is - * toggled we identify the 3box_enabled trait + * @property {'three_box_enabled'} THREE_BOX_ENABLED - When 3Box feature is + * toggled we identify the 3box_enabled trait. This trait has been deprecated. * @property {'theme'} THEME - when the user's theme changes we identify the theme trait * @property {'token_detection_enabled'} TOKEN_DETECTION_ENABLED - when token detection feature is toggled we * identify the token_detection_enabled trait @@ -231,8 +231,8 @@ export const TRAITS = { * the user has across all networks and accounts. * @property {boolean} [opensea_api_enabled] - does the user have the OpenSea * API enabled? - * @property {boolean} [three_box_enabled] - does the user have 3box sync - * enabled? + * @property {boolean} [three_box_enabled] - Does the user have 3box sync + * enabled? (deprecated) * @property {string} [theme] - which theme the user has selected * @property {boolean} [token_detection_enabled] - does the user have token detection is enabled? */ diff --git a/shared/constants/network.ts b/shared/constants/network.ts index 457b62428..89dbe4ec2 100644 --- a/shared/constants/network.ts +++ b/shared/constants/network.ts @@ -210,6 +210,7 @@ export const CHAIN_IDS = { HARMONY: '0x63564c40', PALM: '0x2a15c308d', SEPOLIA: '0xaa36a7', + AURORA: '0x4e454152', } as const; /** @@ -232,6 +233,7 @@ export const OPTIMISM_DISPLAY_NAME = 'Optimism'; export const FANTOM_DISPLAY_NAME = 'Fantom Opera'; export const HARMONY_DISPLAY_NAME = 'Harmony Mainnet Shard 0'; export const PALM_DISPLAY_NAME = 'Palm'; +export const AURORA_DISPLAY_NAME = 'Aurora Mainnet'; export const infuraProjectId = process.env.INFURA_PROJECT_ID; export const getRpcUrl = ({ @@ -257,6 +259,7 @@ export const LOCALHOST_RPC_URL = 'http://localhost:8545'; */ export const CURRENCY_SYMBOLS = { ARBITRUM: 'ETH', + AURORA: 'Aurora ETH', AVALANCHE: 'AVAX', BNB: 'BNB', BUSD: 'BUSD', @@ -410,6 +413,7 @@ export const FTM_TOKEN_IMAGE_URL = './images/fantom-opera.svg'; export const HARMONY_ONE_TOKEN_IMAGE_URL = './images/harmony-one.svg'; export const OPTIMISM_TOKEN_IMAGE_URL = './images/optimism.svg'; export const PALM_TOKEN_IMAGE_URL = './images/palm.svg'; +export const AURORA_TOKEN_IMAGE_URL = './images/aurora.png'; export const INFURA_PROVIDER_TYPES = [ NETWORK_TYPES.MAINNET, @@ -505,6 +509,7 @@ export const CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP = { [CHAIN_IDS.HARMONY]: HARMONY_ONE_TOKEN_IMAGE_URL, [CHAIN_IDS.OPTIMISM]: OPTIMISM_TOKEN_IMAGE_URL, [CHAIN_IDS.PALM]: PALM_TOKEN_IMAGE_URL, + [CHAIN_IDS.AURORA]: AURORA_TOKEN_IMAGE_URL, } as const; export const NETWORK_ID_TO_ETHERS_NETWORK_NAME_MAP = { @@ -861,6 +866,11 @@ export const BUYABLE_CHAINS_MAP: { SUPPORTED_CURRENCY_SYMBOLS.USDS, ], }, + [CHAIN_IDS.AURORA]: { + nativeCurrency: CURRENCY_SYMBOLS.AURORA, + network: 'aurora', + transakCurrencies: [SUPPORTED_CURRENCY_SYMBOLS.AURORA], + }, }; export const FEATURED_RPCS: RPCDefinition[] = [ @@ -874,6 +884,16 @@ export const FEATURED_RPCS: RPCDefinition[] = [ imageUrl: AETH_TOKEN_IMAGE_URL, }, }, + { + chainId: CHAIN_IDS.AURORA, + nickname: AURORA_DISPLAY_NAME, + rpcUrl: `https://aurora-mainnet.infura.io/v3/${infuraProjectId}`, + ticker: CURRENCY_SYMBOLS.AURORA, + rpcPrefs: { + blockExplorerUrl: 'https://aurorascan.dev/', + imageUrl: AURORA_TOKEN_IMAGE_URL, + }, + }, { chainId: CHAIN_IDS.AVALANCHE, nickname: AVALANCHE_DISPLAY_NAME, diff --git a/shared/modules/provider-injection.js b/shared/modules/provider-injection.js index c2ce0ef7e..c4d741823 100644 --- a/shared/modules/provider-injection.js +++ b/shared/modules/provider-injection.js @@ -71,7 +71,6 @@ function blockedDomainCheck() { 'cdn.shopify.com/s/javascripts/tricorder/xtld-read-only-frame.html', 'adyen.com', 'gravityforms.com', - 'docs.google.com', 'harbourair.com', 'ani.gamer.com.tw', 'blueskybooking.com', diff --git a/test/e2e/benchmark.js b/test/e2e/benchmark.js index df4c95756..760f4f70b 100755 --- a/test/e2e/benchmark.js +++ b/test/e2e/benchmark.js @@ -13,22 +13,26 @@ const { } = require('../helpers/file'); const { withFixtures, tinyDelayMs } = require('./helpers'); const { PAGES } = require('./webdriver/driver'); +const FixtureBuilder = require('./fixture-builder'); const DEFAULT_NUM_SAMPLES = 20; const ALL_PAGES = Object.values(PAGES); async function measurePage(pageName) { let metrics; - await withFixtures({ fixtures: 'imported-account' }, async ({ driver }) => { - await driver.delay(tinyDelayMs); - await driver.navigate(); - await driver.fill('#password', 'correct horse battery staple'); - await driver.press('#password', driver.Key.ENTER); - await driver.findElement('.selected-account__name'); - await driver.navigate(pageName); - await driver.delay(1000); - metrics = await driver.collectMetrics(); - }); + await withFixtures( + { fixtures: new FixtureBuilder().build() }, + async ({ driver }) => { + await driver.delay(tinyDelayMs); + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + await driver.findElement('.selected-account__name'); + await driver.navigate(pageName); + await driver.delay(1000); + metrics = await driver.collectMetrics(); + }, + ); return metrics; } diff --git a/test/e2e/fixture-builder.js b/test/e2e/fixture-builder.js new file mode 100644 index 000000000..0eca41d41 --- /dev/null +++ b/test/e2e/fixture-builder.js @@ -0,0 +1,1103 @@ +const { merge } = require('lodash'); + +function defaultFixture() { + return { + data: { + AlertController: { + alertEnabledness: { + unconnectedAccount: true, + web3ShimUsage: true, + }, + unconnectedAccountAlertShownOrigins: {}, + web3ShimUsageOrigins: {}, + }, + AnnouncementController: { + announcements: { + 1: { + date: '2021-03-17', + id: 1, + image: { + height: '230px', + placeImageBelowDescription: true, + src: 'images/mobile-link-qr.svg', + width: '230px', + }, + isShown: false, + }, + 3: { + date: '2021-03-08', + id: 3, + isShown: false, + }, + 4: { + date: '2021-05-11', + id: 4, + image: { + src: 'images/source-logos-bsc.svg', + width: '100%', + }, + isShown: false, + }, + 5: { + date: '2021-06-09', + id: 5, + isShown: false, + }, + 6: { + date: '2021-05-26', + id: 6, + isShown: false, + }, + 7: { + date: '2021-09-17', + id: 7, + isShown: false, + }, + 8: { + date: '2021-11-01', + id: 8, + isShown: false, + }, + 9: { + date: '2021-12-07', + id: 9, + image: { + src: 'images/txinsights.png', + width: '80%', + }, + isShown: false, + }, + 10: { + date: '2022-09-15', + id: 10, + image: { + src: 'images/token-detection.svg', + width: '100%', + }, + isShown: true, + }, + 11: { + date: '2022-09-15', + id: 11, + isShown: true, + }, + 12: { + date: '2022-05-18', + id: 12, + image: { + src: 'images/darkmode-banner.png', + width: '100%', + }, + isShown: false, + }, + 13: { + date: '2022-09-15', + id: 13, + isShown: false, + }, + 14: { + date: '2022-09-15', + id: 14, + isShown: true, + }, + 15: { + date: '2022-09-15', + id: 15, + isShown: true, + }, + }, + }, + AppStateController: { + browserEnvironment: {}, + collectiblesDetectionNoticeDismissed: false, + collectiblesDropdownState: {}, + connectedStatusPopoverHasBeenShown: true, + defaultHomeActiveTabName: null, + enableEIP1559V2NoticeDismissed: false, + fullScreenGasPollTokens: [], + notificationGasPollTokens: [], + popupGasPollTokens: [], + qrHardware: {}, + recoveryPhraseReminderHasBeenShown: true, + recoveryPhraseReminderLastShown: + '__FIXTURE_SUBSTITUTION__currentDateInMilliseconds', + showPortfolioTooltip: false, + showTestnetMessageInDropdown: true, + trezorModel: null, + usedNetworks: { + '0x1': true, + '0x5': true, + '0x539': true, + }, + }, + CachedBalancesController: { + cachedBalances: { + '0x539': {}, + }, + }, + CurrencyController: { + conversionDate: 1665507600.0, + conversionRate: 1300.0, + currentCurrency: 'usd', + nativeCurrency: 'ETH', + usdConversionRate: 1300.0, + }, + GasFeeController: { + estimatedGasFeeTimeBounds: {}, + gasEstimateType: 'none', + gasFeeEstimates: {}, + }, + IncomingTransactionsController: { + incomingTransactions: {}, + incomingTxLastFetchedBlockByChainId: { + '0x1': null, + '0x5': null, + '0xaa36a7': null, + }, + }, + KeyringController: { + vault: + '{"data":"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT","iv":"FbeHDAW5afeWNORfNJBR0Q==","salt":"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8="}', + }, + MetaMetricsController: { + eventsBeforeMetricsOptIn: [], + fragments: {}, + metaMetricsId: null, + participateInMetaMetrics: false, + traits: {}, + }, + NetworkController: { + network: '1337', + provider: { + chainId: '0x539', + nickname: 'Localhost 8545', + rpcPrefs: {}, + rpcUrl: 'http://localhost:8545', + ticker: 'ETH', + type: 'rpc', + }, + }, + OnboardingController: { + completedOnboarding: true, + firstTimeFlowType: 'import', + onboardingTabs: {}, + seedPhraseBackedUp: true, + }, + PermissionController: { + subjects: {}, + }, + PreferencesController: { + advancedGasFee: null, + currentLocale: 'en', + dismissSeedBackUpReminder: true, + featureFlags: { + showIncomingTransactions: true, + }, + forgottenPassword: false, + frequentRpcListDetail: [ + { + chainId: '0x539', + nickname: 'Localhost 8545', + rpcPrefs: {}, + rpcUrl: 'http://localhost:8545', + ticker: 'ETH', + }, + ], + identities: { + '0x5cfe73b6021e818b776b421b1c4db2474086a7e1': { + address: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', + lastSelected: 1665507600000, + name: 'Account 1', + }, + }, + infuraBlocked: false, + ipfsGateway: 'dweb.link', + knownMethodData: {}, + ledgerTransportType: 'webhid', + lostIdentities: {}, + openSeaEnabled: false, + preferences: { + hideZeroBalanceTokens: false, + showFiatInTestnets: false, + showTestNetworks: false, + useNativeCurrencyAsPrimaryCurrency: true, + }, + selectedAddress: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', + theme: 'light', + useBlockie: false, + useCollectibleDetection: false, + useNonceField: false, + usePhishDetect: true, + useTokenDetection: false, + }, + SmartTransactionsController: { + smartTransactionsState: { + fees: {}, + liveness: true, + smartTransactions: { + '0x1': [], + }, + }, + }, + SubjectMetadataController: { + subjectMetadata: { + 'https://metamask.github.io': { + extensionId: null, + iconUrl: null, + name: 'MetaMask < = > Ledger Bridge', + origin: 'https://metamask.github.io', + subjectType: 'website', + }, + }, + }, + TokensController: { + allDetectedTokens: {}, + allIgnoredTokens: {}, + allTokens: {}, + detectedTokens: [], + ignoredTokens: [], + suggestedAssets: [], + tokens: [], + }, + TransactionController: { + transactions: {}, + }, + config: {}, + firstTimeInfo: { + date: 1665507600000, + version: '10.21.0', + }, + }, + }; +} +function onboardingFixture() { + return { + data: { + AppStateController: { + browserEnvironment: {}, + collectiblesDetectionNoticeDismissed: false, + collectiblesDropdownState: {}, + connectedStatusPopoverHasBeenShown: true, + defaultHomeActiveTabName: null, + enableEIP1559V2NoticeDismissed: false, + fullScreenGasPollTokens: [], + notificationGasPollTokens: [], + popupGasPollTokens: [], + qrHardware: {}, + recoveryPhraseReminderHasBeenShown: false, + recoveryPhraseReminderLastShown: + '__FIXTURE_SUBSTITUTION__currentDateInMilliseconds', + showPortfolioTooltip: true, + showTestnetMessageInDropdown: true, + trezorModel: null, + usedNetworks: { + '0x1': true, + '0x5': true, + '0x539': true, + }, + }, + NetworkController: { + network: '1337', + provider: { + ticker: 'ETH', + type: 'rpc', + rpcUrl: 'http://localhost:8545', + chainId: '0x539', + nickname: 'Localhost 8545', + }, + }, + PreferencesController: { + advancedGasFee: null, + currentLocale: 'en', + dismissSeedBackUpReminder: false, + featureFlags: { + showIncomingTransactions: true, + }, + forgottenPassword: false, + frequentRpcListDetail: [ + { + chainId: '0x539', + nickname: 'Localhost 8545', + rpcPrefs: {}, + rpcUrl: 'http://localhost:8545', + ticker: 'ETH', + }, + ], + identities: {}, + infuraBlocked: false, + ipfsGateway: 'dweb.link', + knownMethodData: {}, + ledgerTransportType: 'webhid', + lostIdentities: {}, + openSeaEnabled: false, + preferences: { + hideZeroBalanceTokens: false, + showFiatInTestnets: false, + showTestNetworks: false, + useNativeCurrencyAsPrimaryCurrency: true, + }, + theme: 'light', + useBlockie: false, + useCollectibleDetection: false, + useNonceField: false, + usePhishDetect: true, + useTokenDetection: false, + }, + SmartTransactionsController: { + smartTransactionsState: { + fees: {}, + liveness: true, + smartTransactions: { + '0x1': [], + }, + }, + }, + TokensController: { + allDetectedTokens: {}, + allIgnoredTokens: {}, + allTokens: {}, + detectedTokens: [], + ignoredTokens: [], + suggestedAssets: [], + tokens: [], + }, + config: {}, + firstTimeInfo: { + date: 1665507600000, + version: '10.21.0', + }, + }, + }; +} + +class FixtureBuilder { + constructor({ onboarding = false } = {}) { + this.fixture = onboarding === true ? onboardingFixture() : defaultFixture(); + } + + withAddressBookController(data) { + merge( + this.fixture.data.AddressBookController + ? this.fixture.data.AddressBookController + : (this.fixture.data.AddressBookController = {}), + data, + ); + return this; + } + + withAlertController(data) { + merge(this.fixture.data.AlertController, data); + return this; + } + + withAnnouncementController(data) { + merge(this.fixture.data.AnnouncementController, data); + return this; + } + + withAppStateController(data) { + merge(this.fixture.data.AppStateController, data); + return this; + } + + withCachedBalancesController(data) { + merge(this.fixture.data.CachedBalancesController, data); + return this; + } + + withCollectiblesController(data) { + merge( + this.fixture.data.CollectiblesController + ? this.fixture.data.CollectiblesController + : (this.fixture.data.CollectiblesController = {}), + data, + ); + return this; + } + + withCurrencyController(data) { + merge(this.fixture.data.CurrencyController, data); + return this; + } + + withGasFeeController(data) { + merge(this.fixture.data.GasFeeController, data); + return this; + } + + withIncomingTransactionsController(data) { + merge( + this.fixture.data.IncomingTransactionsController + ? this.fixture.data.IncomingTransactionsController + : (this.fixture.data.IncomingTransactionsController = {}), + data, + ); + return this; + } + + withKeyringController(data) { + merge(this.fixture.data.KeyringController, data); + return this; + } + + withKeyringControllerImportedAccountVault() { + return this.withKeyringController({ + vault: + '{"data":"Ot+BTtJPag0xubdiv1nO9bsSvTHivHCd6CD7Lxgb1McYw3VqMjgp5rPMZmblJ1lscuMxyiqp99G52uXO9S0em6F9htpa+t/wn6qubRKTTNG9fxNzQrKXRDNhdgfYckVk5VAZ4fgl2iMZcRDvS8H/+gucVKJ33Sl6mXyPofdexXhWDCU6uR2YecnfaIum9cL2u/GqOMPE3jxzy0Wip0x2Jyp3QOKhvu8A3GIjzagLOaQ7a1APdl8=","iv":"lbsyPeGYWU6U1+jvmW9UHg==","salt":"Zmbhpskwxe4rYfXtELBvlcvW4HISPBATRmMqzsnZPMg="}', + }); + } + + withMetaMetricsController(data) { + merge(this.fixture.data.MetaMetricsController, data); + return this; + } + + withNetworkController(data) { + merge(this.fixture.data.NetworkController, data); + return this; + } + + withOnboardingController(data) { + merge(this.fixture.data.OnboardingController, data); + return this; + } + + withPermissionController(data) { + merge(this.fixture.data.PermissionController, data); + return this; + } + + withPermissionControllerConnectedToTestDapp() { + return this.withPermissionController({ + subjects: { + 'http://127.0.0.1:8080': { + origin: 'http://127.0.0.1:8080', + permissions: { + eth_accounts: { + id: 'ZaqPEWxyhNCJYACFw93jE', + parentCapability: 'eth_accounts', + invoker: 'http://127.0.0.1:8080', + caveats: [ + { + type: 'restrictReturnedAccounts', + value: ['0x5cfe73b6021e818b776b421b1c4db2474086a7e1'], + }, + ], + date: 1664388714636, + }, + }, + }, + }, + }); + } + + withPermissionControllerConnectedToSnapDapp() { + return this.withPermissionController({ + subjects: { + 'https://metamask.github.io': { + origin: 'https://metamask.github.io', + permissions: { + 'wallet_snap_npm:@metamask/test-snap-bip32': { + id: 'CwdJq0x8N_b9FNxn6dVuP', + parentCapability: 'wallet_snap_npm:@metamask/test-snap-bip32', + invoker: 'https://metamask.github.io', + caveats: null, + date: 1664388714636, + }, + 'wallet_snap_npm:@metamask/test-snap-bip44': { + id: '8zH-0opWuZhvJew41FMVh', + parentCapability: 'wallet_snap_npm:@metamask/test-snap-bip44', + invoker: 'https://metamask.github.io', + caveats: null, + date: 1664388714636, + }, + 'wallet_snap_npm:@metamask/test-snap-confirm': { + id: 'Wb_1c9toBggBQWfOJwjMg', + parentCapability: 'wallet_snap_npm:@metamask/test-snap-confirm', + invoker: 'https://metamask.github.io', + caveats: null, + date: 1664388714636, + }, + 'wallet_snap_npm:@metamask/test-snap-error': { + id: '5FUZoCyimOWKTbuLCEOWa', + parentCapability: 'wallet_snap_npm:@metamask/test-snap-error', + invoker: 'https://metamask.github.io', + caveats: null, + date: 1664388714636, + }, + 'wallet_snap_npm:@metamask/test-snap-managestate': { + id: 'Z6XPdyuCHCf1pyqSiU7nh', + parentCapability: + 'wallet_snap_npm:@metamask/test-snap-managestate', + invoker: 'https://metamask.github.io', + caveats: null, + date: 1664388714636, + }, + 'wallet_snap_npm:@metamask/test-snap-notification': { + id: '_xfRMXzq0bs8QcXRcvjcP', + parentCapability: + 'wallet_snap_npm:@metamask/test-snap-notification', + invoker: 'https://metamask.github.io', + caveats: null, + date: 1664388714636, + }, + }, + }, + }, + }); + } + + withPermissionLogController(data) { + merge( + this.fixture.data.PermissionLogController + ? this.fixture.data.PermissionLogController + : (this.fixture.data.PermissionLogController = {}), + data, + ); + return this; + } + + withPreferencesController(data) { + merge(this.fixture.data.PreferencesController, data); + return this; + } + + withPreferencesControllerImportedAccountIdentities() { + return this.withPreferencesController({ + identities: { + '0x0cc5261ab8ce458dc977078a3623e2badd27afd3': { + name: 'Account 1', + address: '0x0cc5261ab8ce458dc977078a3623e2badd27afd3', + lastSelected: 1665507600000, + }, + '0x3ed0ee22e0685ebbf07b2360a8331693c413cc59': { + name: 'Account 2', + address: '0x3ed0ee22e0685ebbf07b2360a8331693c413cc59', + }, + '0xd38d853771fb546bd8b18b2f3638491bc0b0e906': { + name: 'Account 3', + address: '0xd38d853771fb546bd8b18b2f3638491bc0b0e906', + }, + }, + selectedAddress: '0x0cc5261ab8ce458dc977078a3623e2badd27afd3', + }); + } + + withSmartTransactionsController(data) { + merge(this.fixture.data.SmartTransactionsController, data); + return this; + } + + withSubjectMetadataController(data) { + merge(this.fixture.data.SubjectMetadataController, data); + return this; + } + + withTokenListController(data) { + merge( + this.fixture.data.TokenListController + ? this.fixture.data.TokenListController + : (this.fixture.data.TokenListController = {}), + data, + ); + return this; + } + + withTokensController(data) { + merge(this.fixture.data.TokensController, data); + return this; + } + + withTransactionController(data) { + merge( + this.fixture.data.TransactionController + ? this.fixture.data.TransactionController + : (this.fixture.data.TransactionController = {}), + data, + ); + return this; + } + + withTransactionControllerMultipleTransactions() { + return this.withTransactionController({ + transactions: { + 7911313280012623: { + chainId: '0x539', + dappSuggestedGasFees: { + gas: '0x5208', + gasPrice: '0x4a817c800', + }, + history: [ + { + chainId: '0x539', + dappSuggestedGasFees: { + gas: '0x5208', + gasPrice: '0x4a817c800', + }, + id: 7911313280012623, + loadingDefaults: true, + metamaskNetworkId: '1337', + origin: 'https://metamask.github.io', + status: 'unapproved', + time: 1631545991949, + txParams: { + from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', + gas: '0x5208', + gasPrice: '0x4a817c800', + to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', + value: '0x29a2241af62c0000', + }, + type: 'simpleSend', + }, + [ + { + note: 'Added new unapproved transaction.', + op: 'replace', + path: '/loadingDefaults', + timestamp: 1631545992244, + value: false, + }, + ], + ], + id: 7911313280012623, + loadingDefaults: false, + metamaskNetworkId: '1337', + origin: 'https://metamask.github.io', + status: 'unapproved', + time: 1631545991949, + txParams: { + from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', + gas: '0x5208', + gasPrice: '0x4a817c800', + to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', + value: '0x29a2241af62c0000', + }, + type: 'simpleSend', + }, + 7911313280012624: { + chainId: '0x539', + dappSuggestedGasFees: { + gas: '0x5208', + gasPrice: '0x4a817c800', + }, + history: [ + { + chainId: '0x539', + dappSuggestedGasFees: { + gas: '0x5208', + gasPrice: '0x4a817c800', + }, + id: 7911313280012624, + loadingDefaults: true, + metamaskNetworkId: '1337', + origin: 'https://metamask.github.io', + status: 'unapproved', + time: 1631545994578, + txParams: { + from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', + gas: '0x5208', + gasPrice: '0x4a817c800', + to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', + value: '0x29a2241af62c0000', + }, + type: 'simpleSend', + }, + [ + { + note: 'Added new unapproved transaction.', + op: 'replace', + path: '/loadingDefaults', + timestamp: 1631545994695, + value: false, + }, + ], + ], + id: 7911313280012624, + loadingDefaults: false, + metamaskNetworkId: '1337', + origin: 'https://metamask.github.io', + status: 'unapproved', + time: 1631545994578, + txParams: { + from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', + gas: '0x5208', + gasPrice: '0x4a817c800', + to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', + value: '0x29a2241af62c0000', + }, + type: 'simpleSend', + }, + 7911313280012625: { + chainId: '0x539', + dappSuggestedGasFees: { + gas: '0x5208', + gasPrice: '0x4a817c800', + }, + history: [ + { + chainId: '0x539', + dappSuggestedGasFees: { + gas: '0x5208', + gasPrice: '0x4a817c800', + }, + id: 7911313280012625, + loadingDefaults: true, + metamaskNetworkId: '1337', + origin: 'https://metamask.github.io', + status: 'unapproved', + time: 1631545996673, + txParams: { + from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', + gas: '0x5208', + gasPrice: '0x4a817c800', + to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', + value: '0x29a2241af62c0000', + }, + type: 'simpleSend', + }, + [ + { + note: 'Added new unapproved transaction.', + op: 'replace', + path: '/loadingDefaults', + timestamp: 1631545996678, + value: false, + }, + ], + ], + id: 7911313280012625, + loadingDefaults: false, + metamaskNetworkId: '1337', + origin: 'https://metamask.github.io', + status: 'unapproved', + time: 1631545996673, + txParams: { + from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', + gas: '0x5208', + gasPrice: '0x4a817c800', + to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', + value: '0x29a2241af62c0000', + }, + type: 'simpleSend', + }, + 7911313280012626: { + chainId: '0x539', + dappSuggestedGasFees: { + gas: '0x5208', + gasPrice: '0x4a817c800', + }, + history: [ + { + chainId: '0x539', + dappSuggestedGasFees: { + gas: '0x5208', + gasPrice: '0x4a817c800', + }, + id: 7911313280012626, + loadingDefaults: true, + metamaskNetworkId: '1337', + origin: 'https://metamask.github.io', + status: 'unapproved', + time: 1631545998675, + txParams: { + from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', + gas: '0x5208', + gasPrice: '0x4a817c800', + to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', + value: '0x29a2241af62c0000', + }, + type: 'simpleSend', + }, + [ + { + note: 'Added new unapproved transaction.', + op: 'replace', + path: '/loadingDefaults', + timestamp: 1631545998677, + value: false, + }, + ], + ], + id: 7911313280012626, + loadingDefaults: false, + metamaskNetworkId: '1337', + origin: 'https://metamask.github.io', + status: 'unapproved', + time: 1631545998675, + txParams: { + from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', + gas: '0x5208', + gasPrice: '0x4a817c800', + to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', + value: '0x29a2241af62c0000', + }, + type: 'simpleSend', + }, + }, + }); + } + + withTransactionControllerTypeOneTransaction() { + return this.withTransactionController({ + transactions: { + 4046084157914634: { + chainId: '0x539', + history: [ + { + chainId: '0x539', + id: 4046084157914634, + loadingDefaults: true, + metamaskNetworkId: '1337', + 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: 4046084157914634, + loadingDefaults: false, + metamaskNetworkId: '1337', + origin: 'metamask', + primaryTransaction: { + chainId: '0x539', + id: 4046084157914634, + loadingDefaults: true, + metamaskNetworkId: '1337', + 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: { + 4046084157914634: { + chainId: '0x539', + history: [ + { + chainId: '0x539', + id: 4046084157914634, + loadingDefaults: true, + metamaskNetworkId: '1337', + 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: 4046084157914634, + loadingDefaults: false, + metamaskNetworkId: '1337', + origin: 'metamask', + primaryTransaction: { + chainId: '0x539', + id: 4046084157914634, + loadingDefaults: true, + metamaskNetworkId: '1337', + 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', + }, + }, + }); + } + + withTransactionControllerApprovedTransaction() { + return this.withTransactionController({ + transactions: { + 4046084157914634: { + chainId: '0x539', + history: [ + { + chainId: '0x539', + id: 4046084157914634, + loadingDefaults: true, + metamaskNetworkId: '1337', + 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, + }, + ], + [ + { + op: 'add', + path: '/txParams/nonce', + value: '0x0', + note: 'transactions#approveTransaction', + timestamp: 1617228031069, + }, + { + op: 'add', + path: '/nonceDetails', + value: { + params: { + highestLocallyConfirmed: 0, + highestSuggested: 0, + nextNetworkNonce: 0, + }, + local: { + name: 'local', + nonce: 0, + details: { + startPoint: 0, + highest: 0, + }, + }, + network: { + name: 'network', + nonce: 0, + details: { + blockNumber: '0x0', + baseCount: 0, + }, + }, + }, + }, + ], + ], + id: 4046084157914634, + loadingDefaults: false, + metamaskNetworkId: '1337', + origin: 'metamask', + primaryTransaction: { + chainId: '0x539', + id: 4046084157914634, + loadingDefaults: true, + metamaskNetworkId: '1337', + origin: 'metamask', + status: 'approved', + time: 1617228030067, + txParams: { + from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', + gas: '0x61a8', + maxFeePerGas: '0x59682f0c', + maxPriorityFeePerGas: '0x59682f00', + to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970', + type: '0x2', + value: '0xde0b6b3a7640000', + }, + type: 'sentEther', + }, + status: 'approved', + time: 1617228030067, + txParams: { + from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', + gas: '0x61a8', + maxFeePerGas: '0x59682f0c', + maxPriorityFeePerGas: '0x59682f00', + to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970', + type: '0x2', + value: '0xde0b6b3a7640000', + }, + type: 'simpleSend', + }, + }, + }); + } + + build() { + this.fixture.meta = { + version: 74, + }; + return this.fixture; + } +} + +module.exports = FixtureBuilder; diff --git a/test/e2e/fixture-server.js b/test/e2e/fixture-server.js index e27f0cfa2..bad4bc165 100644 --- a/test/e2e/fixture-server.js +++ b/test/e2e/fixture-server.js @@ -1,5 +1,3 @@ -const { promises: fs } = require('fs'); -const path = require('path'); const Koa = require('koa'); const { isObject, mapValues } = require('lodash'); @@ -57,7 +55,6 @@ class FixtureServer { constructor() { this._app = new Koa(); this._stateMap = new Map([[DEFAULT_STATE_KEY, Object.create(null)]]); - this._initialStateCache = new Map(); this._app.use(async (ctx) => { // Firefox is _super_ strict about needing CORS headers @@ -94,19 +91,8 @@ class FixtureServer { }); } - async loadState(directory) { - const statePath = path.resolve(__dirname, directory, 'state.json'); - - let state; - if (this._initialStateCache.has(statePath)) { - state = this._initialStateCache.get(statePath); - } else { - const data = await fs.readFile(statePath); - const rawState = JSON.parse(data.toString('utf-8')); - state = performStateSubstitutions(rawState); - this._initialStateCache.set(statePath, state); - } - + loadJsonState(rawState) { + const state = performStateSubstitutions(rawState); this._stateMap.set(CURRENT_STATE_KEY, state); } diff --git a/test/e2e/fixtures/address-entry/state.json b/test/e2e/fixtures/address-entry/state.json deleted file mode 100644 index 6cfdc82e6..000000000 --- a/test/e2e/fixtures/address-entry/state.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "data": { - "AddressBookController": { - "addressBook": { - "0x539": { - "0x2f318C334780961FB129D2a6c30D0763d9a5C970": { - "address": "0x2f318C334780961FB129D2a6c30D0763d9a5C970", - "chainId": "0x539", - "isEns": false, - "memo": "", - "name": "Test Name 1" - } - } - } - }, - "AppStateController": { - "mkrMigrationReminderTimestamp": null, - "swapsWelcomeMessageHasBeenShown": true, - "showPortfolioTooltip": false - }, - "CachedBalancesController": { - "cachedBalances": { - "4": {} - } - }, - "CurrencyController": { - "conversionDate": 1575697244.188, - "conversionRate": 149.61, - "currentCurrency": "usd", - "nativeCurrency": "ETH" - }, - "IncomingTransactionsController": { - "incomingTransactions": {}, - "incomingTxLastFetchedBlocksByNetwork": { - "goerli": null, - "mainnet": null, - "sepolia": null - } - }, - "KeyringController": { - "vault": "{\"data\":\"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT\",\"iv\":\"FbeHDAW5afeWNORfNJBR0Q==\",\"salt\":\"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8=\"}" - }, - "NetworkController": { - "network": "1337", - "provider": { - "nickname": "Localhost 8545", - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "ticker": "ETH", - "type": "rpc" - } - }, - "NotificationController": { - "notifications": { - "1": { - "isShown": true - }, - "3": { - "isShown": true - }, - "5": { - "isShown": true - }, - "6": { - "isShown": true - }, - "8": { - "isShown": true - }, - "10": { - "isShown": true - }, - "11": { - "isShown": true - }, - "12": { - "isShown": true - }, - "14": { - "isShown": true - }, - "15": { - "isShown": true - } - } - }, - "OnboardingController": { - "onboardingTabs": {}, - "seedPhraseBackedUp": false - }, - "PermissionsMetadata": { - "domainMetadata": { - "metamask.github.io": { - "icon": null, - "name": "M E T A M A S K M E S H T E S T" - } - }, - "permissionsHistory": {}, - "permissionsLog": [ - { - "id": 746677923, - "method": "eth_accounts", - "methodType": "restricted", - "origin": "metamask.github.io", - "request": { - "id": 746677923, - "jsonrpc": "2.0", - "method": "eth_accounts", - "origin": "metamask.github.io", - "params": [] - }, - "requestTime": 1575697241368, - "response": { - "id": 746677923, - "jsonrpc": "2.0", - "result": [] - }, - "responseTime": 1575697241370, - "success": true - } - ] - }, - "PreferencesController": { - "accountTokens": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "goerli": [], - "sepolia": [] - } - }, - "assetImages": {}, - "completedOnboarding": true, - "currentLocale": "en", - "featureFlags": { - "showIncomingTransactions": true, - "transactionTime": false - }, - "firstTimeFlowType": "create", - "forgottenPassword": false, - "frequentRpcListDetail": [], - "identities": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "address": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "name": "Account 1" - } - }, - "knownMethodData": {}, - "lostIdentities": {}, - "metaMetricsId": null, - "participateInMetaMetrics": false, - "preferences": { - "useNativeCurrencyAsPrimaryCurrency": true - }, - "selectedAddress": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "suggestedTokens": {}, - "tokens": [], - "useBlockie": false, - "useNonceField": false, - "usePhishDetect": true - }, - "config": {}, - "firstTimeInfo": { - "date": 1575697234195, - "version": "7.7.0" - } - }, - "meta": { - "version": 40 - } -} diff --git a/test/e2e/fixtures/connected-state/state.json b/test/e2e/fixtures/connected-state/state.json deleted file mode 100644 index 4eebbb241..000000000 --- a/test/e2e/fixtures/connected-state/state.json +++ /dev/null @@ -1,200 +0,0 @@ -{ - "data": { - "AppStateController": { - "connectedStatusPopoverHasBeenShown": false, - "showPortfolioTooltip": false - }, - "CachedBalancesController": { - "cachedBalances": { - "4": {}, - "1337": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": "0x15af1d78b58c40000" - } - } - }, - "CurrencyController": { - "conversionDate": 1594348502.519, - "conversionRate": 240.09, - "currentCurrency": "usd", - "nativeCurrency": "ETH" - }, - "IncomingTransactionsController": { - "incomingTransactions": {}, - "incomingTxLastFetchedBlocksByNetwork": { - "goerli": null, - "mainnet": null, - "sepolia": null, - "localhost": 98 - } - }, - "KeyringController": { - "vault": "{\"data\":\"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT\",\"iv\":\"FbeHDAW5afeWNORfNJBR0Q==\",\"salt\":\"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8=\"}" - }, - "NetworkController": { - "provider": { - "nickname": "Localhost 8545", - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "ticker": "ETH", - "type": "rpc" - }, - "network": "1337" - }, - "NotificationController": { - "notifications": { - "1": { - "isShown": true - }, - "3": { - "isShown": true - }, - "5": { - "isShown": true - }, - "6": { - "isShown": true - }, - "8": { - "isShown": true - }, - "10": { - "isShown": true - }, - "11": { - "isShown": true - }, - "12": { - "isShown": true - }, - "14": { - "isShown": true - }, - "15": { - "isShown": true - } - } - }, - "OnboardingController": { - "onboardingTabs": {}, - "seedPhraseBackedUp": false - }, - "PermissionsMetadata": { - "permissionsLog": [ - { - "id": 1764280960, - "method": "eth_requestAccounts", - "methodType": "restricted", - "origin": "http://127.0.0.1:8080", - "request": { - "method": "eth_requestAccounts", - "jsonrpc": "2.0", - "id": 1764280960, - "origin": "http://127.0.0.1:8080", - "tabId": 2 - }, - "requestTime": 1594348329232, - "response": { - "id": 1764280960, - "jsonrpc": "2.0", - "result": ["0x5cfe73b6021e818b776b421b1c4db2474086a7e1"] - }, - "responseTime": 1594348332276, - "success": true - } - ], - "permissionsHistory": { - "http://127.0.0.1:8080": { - "eth_accounts": { - "accounts": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": 1594348332276 - }, - "lastApproved": 1594348332276 - } - } - }, - "domainMetadata": { - "http://127.0.0.1:8080": { - "name": "E2E Test Dapp", - "icon": "http://127.0.0.1:8080/metamask-fox.svg", - "lastUpdated": 1594348323811, - "host": "127.0.0.1:8080" - } - } - }, - "PreferencesController": { - "frequentRpcListDetail": [], - "accountTokens": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "goerli": [], - "sepolia": [] - } - }, - "assetImages": {}, - "tokens": [], - "suggestedTokens": {}, - "useBlockie": false, - "useNonceField": false, - "usePhishDetect": true, - "featureFlags": { - "showIncomingTransactions": true, - "transactionTime": false - }, - "knownMethodData": {}, - "participateInMetaMetrics": false, - "firstTimeFlowType": "create", - "currentLocale": "en", - "identities": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "address": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "name": "Account 1" - } - }, - "lostIdentities": {}, - "forgottenPassword": false, - "preferences": { - "useNativeCurrencyAsPrimaryCurrency": true - }, - "completedOnboarding": true, - "metaMetricsId": null, - "ipfsGateway": "dweb.link", - "selectedAddress": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1" - }, - "config": {}, - "firstTimeInfo": { - "date": 1575697234195, - "version": "7.7.0" - }, - "PermissionsController": { - "permissionsRequests": [], - "permissionsDescriptions": {}, - "domains": { - "http://127.0.0.1:8080": { - "permissions": [ - { - "@context": ["https://github.com/MetaMask/rpc-cap"], - "parentCapability": "eth_accounts", - "id": "f55a1c15-ea48-4088-968e-63be474d42fa", - "date": 1594348332268, - "invoker": "http://127.0.0.1:8080", - "caveats": [ - { - "type": "limitResponseLength", - "value": 1, - "name": "primaryAccountOnly" - }, - { - "type": "filterResponse", - "value": ["0x5cfe73b6021e818b776b421b1c4db2474086a7e1"], - "name": "exposedAccounts" - } - ] - } - ] - } - } - } - }, - "meta": { - "version": 47 - } -} diff --git a/test/e2e/fixtures/custom-rpc/state.json b/test/e2e/fixtures/custom-rpc/state.json deleted file mode 100644 index ef85b1d44..000000000 --- a/test/e2e/fixtures/custom-rpc/state.json +++ /dev/null @@ -1,170 +0,0 @@ -{ - "data": { - "AppStateController": { - "mkrMigrationReminderTimestamp": null, - "showPortfolioTooltip": false - }, - "CachedBalancesController": { - "cachedBalances": { - "4": {} - } - }, - "CurrencyController": { - "conversionDate": 1575697244.188, - "conversionRate": 149.61, - "currentCurrency": "usd", - "nativeCurrency": "ETH" - }, - "IncomingTransactionsController": { - "incomingTransactions": {}, - "incomingTxLastFetchedBlocksByNetwork": { - "goerli": null, - "mainnet": null, - "sepolia": null - } - }, - "KeyringController": { - "vault": "{\"data\":\"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT\",\"iv\":\"FbeHDAW5afeWNORfNJBR0Q==\",\"salt\":\"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8=\"}" - }, - "NetworkController": { - "network": "1337", - "provider": { - "nickname": "Localhost 8545", - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "ticker": "ETH", - "type": "rpc" - } - }, - "NotificationController": { - "notifications": { - "1": { - "isShown": true - }, - "3": { - "isShown": true - }, - "5": { - "isShown": true - }, - "6": { - "isShown": true - }, - "8": { - "isShown": true - }, - "10": { - "isShown": true - }, - "11": { - "isShown": true - }, - "12": { - "isShown": true - }, - "14": { - "isShown": true - }, - "15": { - "isShown": true - } - } - }, - "OnboardingController": { - "onboardingTabs": {}, - "seedPhraseBackedUp": false - }, - "PermissionsMetadata": { - "domainMetadata": { - "metamask.github.io": { - "icon": null, - "name": "M E T A M A S K M E S H T E S T" - } - }, - "permissionsHistory": {}, - "permissionsLog": [ - { - "id": 746677923, - "method": "eth_accounts", - "methodType": "restricted", - "origin": "metamask.github.io", - "request": { - "id": 746677923, - "jsonrpc": "2.0", - "method": "eth_accounts", - "origin": "metamask.github.io", - "params": [] - }, - "requestTime": 1575697241368, - "response": { - "id": 746677923, - "jsonrpc": "2.0", - "result": [] - }, - "responseTime": 1575697241370, - "success": true - } - ] - }, - "PreferencesController": { - "frequentRpcListDetail": [ - { - "rpcUrl": "http://127.0.0.1:8545/1", - "chainId": "0x539", - "ticker": "ETH", - "nickname": "http://127.0.0.1:8545/1", - "rpcPrefs": {} - }, - { - "rpcUrl": "http://127.0.0.1:8545/2", - "chainId": "0x539", - "ticker": "ETH", - "nickname": "http://127.0.0.1:8545/2", - "rpcPrefs": {} - } - ], - "accountTokens": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "goerli": [], - "sepolia": [] - } - }, - "assetImages": {}, - "completedOnboarding": true, - "currentLocale": "en", - "featureFlags": { - "showIncomingTransactions": true, - "transactionTime": false - }, - "firstTimeFlowType": "create", - "forgottenPassword": false, - "identities": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "address": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "name": "Account 1" - } - }, - "knownMethodData": {}, - "lostIdentities": {}, - "metaMetricsId": null, - "participateInMetaMetrics": false, - "preferences": { - "useNativeCurrencyAsPrimaryCurrency": true - }, - "selectedAddress": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "suggestedTokens": {}, - "tokens": [], - "useBlockie": false, - "useNonceField": false, - "usePhishDetect": true - }, - "config": {}, - "firstTimeInfo": { - "date": 1575697234195, - "version": "7.7.0" - } - }, - "meta": { - "version": 40 - } -} diff --git a/test/e2e/fixtures/custom-token/state.json b/test/e2e/fixtures/custom-token/state.json deleted file mode 100644 index c04eee9d4..000000000 --- a/test/e2e/fixtures/custom-token/state.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "data": { - "AlertController": { - "alertEnabledness": { - "unconnectedAccount": true, - "web3ShimUsage": true - }, - "unconnectedAccountAlertShownOrigins": {}, - "web3ShimUsageOrigins": {} - }, - "AppStateController": { - "connectedStatusPopoverHasBeenShown": true, - "defaultHomeActiveTabName": null, - "recoveryPhraseReminderHasBeenShown": true, - "recoveryPhraseReminderLastShown": "__FIXTURE_SUBSTITUTION__currentDateInMilliseconds", - "showPortfolioTooltip": false - }, - "CachedBalancesController": { - "cachedBalances": { - "0x5": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": "0x0" - } - } - }, - "CurrencyController": { - "conversionDate": 1626907353.891, - "conversionRate": 1968.5, - "currentCurrency": "usd", - "nativeCurrency": "ETH", - "pendingCurrentCurrency": null, - "pendingNativeCurrency": null, - "usdConversionRate": 1968.5 - }, - "IncomingTransactionsController": { - "incomingTransactions": {}, - "incomingTxLastFetchedBlockByChainId": { - "0x1": null, - "0x5": 8977934 - } - }, - "KeyringController": { - "vault": "{\"data\":\"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT\",\"iv\":\"FbeHDAW5afeWNORfNJBR0Q==\",\"salt\":\"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8=\"}" - }, - "MetaMetricsController": { - "metaMetricsId": "0xff3e952b9f5a27ffcab42b0b4abf689e77dcc1f9f441871dc962d622b089fb51", - "participateInMetaMetrics": true - }, - "NetworkController": { - "network": "1337", - "networkDetails": { - "EIPS": {} - }, - "previousProviderStore": { - "chainId": "0x5", - "ticker": "ETH", - "type": "goerli" - }, - "provider": { - "chainId": "0x539", - "nickname": "Localhost 8545", - "rpcPrefs": {}, - "rpcUrl": "http://localhost:8545", - "ticker": "ETH", - "type": "rpc" - } - }, - "NotificationController": { - "notifications": { - "8": { - "isShown": true - }, - "10": { - "isShown": true - }, - "11": { - "isShown": true - }, - "12": { - "isShown": true - }, - "14": { - "isShown": true - }, - "15": { - "isShown": true - } - } - }, - "OnboardingController": { - "onboardingTabs": {}, - "seedPhraseBackedUp": true - }, - "PermissionsController": { - "domains": {}, - "permissionsDescriptions": {}, - "permissionsRequests": [] - }, - "PreferencesController": { - "completedOnboarding": true, - "currentLocale": "en", - "dismissSeedBackUpReminder": true, - "featureFlags": { - "showIncomingTransactions": true - }, - "firstTimeFlowType": "import", - "forgottenPassword": false, - "frequentRpcListDetail": [ - { - "chainId": "0x539", - "nickname": "Localhost 8545", - "rpcPrefs": {}, - "rpcUrl": "http://localhost:8545", - "ticker": "ETH" - } - ], - "identities": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "address": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "lastSelected": 1626907346643, - "name": "Account 1" - } - }, - "infuraBlocked": false, - "ipfsGateway": "dweb.link", - "knownMethodData": {}, - "lostIdentities": {}, - "preferences": { - "hideZeroBalanceTokens": false, - "showFiatInTestnets": false, - "useNativeCurrencyAsPrimaryCurrency": true - }, - "selectedAddress": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "useBlockie": false, - "useLedgerLive": false, - "useNonceField": false, - "usePhishDetect": true, - "useStaticTokenList": false - }, - "TokensController": { - "allTokens": { - "0x539": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": [ - { - "address": "0x86002be4cdd922de1ccb831582bf99284b99ac12", - "decimals": 4, - "image": null, - "isERC721": false, - "symbol": "TST" - } - ] - } - }, - "ignoredTokens": [], - "suggestedAssets": [], - "allIgnoredTokens": {}, - "tokens": [ - { - "address": "0x86002be4cdd922de1ccb831582bf99284b99ac12", - "decimals": 4, - "image": null, - "isERC721": false, - "symbol": "TST" - } - ] - }, - "TransactionController": { - "transactions": {} - }, - "config": {}, - "firstTimeInfo": { - "date": 1626907328205, - "version": "9.8.1" - } - }, - "meta": { - "version": 63 - } -} diff --git a/test/e2e/fixtures/eip-1559-v2-dapp/state.json b/test/e2e/fixtures/eip-1559-v2-dapp/state.json deleted file mode 100644 index 4a2effda3..000000000 --- a/test/e2e/fixtures/eip-1559-v2-dapp/state.json +++ /dev/null @@ -1,160 +0,0 @@ -{ - "data": { - "AppStateController": { - "mkrMigrationReminderTimestamp": null, - "swapsWelcomeMessageHasBeenShown": true, - "showPortfolioTooltip": false - }, - "CachedBalancesController": { - "cachedBalances": { - "4": {} - } - }, - "CurrencyController": { - "conversionDate": 1575697244.188, - "conversionRate": 149.61, - "currentCurrency": "usd", - "nativeCurrency": "ETH" - }, - "IncomingTransactionsController": { - "incomingTransactions": {}, - "incomingTxLastFetchedBlocksByNetwork": { - "goerli": null, - "mainnet": null, - "sepolia": null - } - }, - "KeyringController": { - "vault": "{\"data\":\"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT\",\"iv\":\"FbeHDAW5afeWNORfNJBR0Q==\",\"salt\":\"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8=\"}" - }, - "NetworkController": { - "network": "1337", - "provider": { - "nickname": "Localhost 8545", - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "ticker": "ETH", - "type": "rpc" - } - }, - "NotificationController": { - "notifications": { - "1": { - "isShown": true - }, - "3": { - "isShown": true - }, - "5": { - "isShown": true - }, - "6": { - "isShown": true - }, - "8": { - "isShown": true - }, - "10": { - "isShown": true - }, - "11": { - "isShown": true - }, - "12": { - "isShown": true - }, - "14": { - "isShown": true - }, - "15": { - "isShown": true - } - } - }, - "OnboardingController": { - "onboardingTabs": {}, - "seedPhraseBackedUp": false - }, - "PermissionsMetadata": { - "domainMetadata": { - "metamask.github.io": { - "icon": null, - "name": "M E T A M A S K M E S H T E S T" - } - }, - "permissionsHistory": {}, - "permissionsLog": [ - { - "id": 746677923, - "method": "eth_accounts", - "methodType": "restricted", - "origin": "metamask.github.io", - "request": { - "id": 746677923, - "jsonrpc": "2.0", - "method": "eth_accounts", - "origin": "metamask.github.io", - "params": [] - }, - "requestTime": 1575697241368, - "response": { - "id": 746677923, - "jsonrpc": "2.0", - "result": [] - }, - "responseTime": 1575697241370, - "success": true - } - ] - }, - "PreferencesController": { - "accountTokens": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "goerli": [], - "sepolia": [] - } - }, - "assetImages": {}, - "completedOnboarding": true, - "eip1559V2Enabled": true, - "currentLocale": "en", - "featureFlags": { - "showIncomingTransactions": true, - "transactionTime": false - }, - "firstTimeFlowType": "create", - "forgottenPassword": false, - "frequentRpcListDetail": [], - "identities": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "address": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "name": "Account 1" - } - }, - "knownMethodData": {}, - "lostIdentities": {}, - "metaMetricsId": null, - "participateInMetaMetrics": false, - "preferences": { - "useNativeCurrencyAsPrimaryCurrency": true - }, - "selectedAddress": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "suggestedTokens": {}, - "tokens": [], - "useBlockie": false, - "useNonceField": false, - "usePhishDetect": true - }, - "TransactionController": { - "transactions": {} - }, - "config": {}, - "firstTimeInfo": { - "date": 1575697234195, - "version": "7.7.0" - } - }, - "meta": { - "version": 40 - } -} diff --git a/test/e2e/fixtures/eip-1559-v2/state.json b/test/e2e/fixtures/eip-1559-v2/state.json deleted file mode 100644 index 1777bbf9f..000000000 --- a/test/e2e/fixtures/eip-1559-v2/state.json +++ /dev/null @@ -1,229 +0,0 @@ -{ - "data": { - "AppStateController": { - "mkrMigrationReminderTimestamp": null, - "swapsWelcomeMessageHasBeenShown": true, - "showPortfolioTooltip": false - }, - "CachedBalancesController": { - "cachedBalances": { - "4": {} - } - }, - "CurrencyController": { - "conversionDate": 1575697244.188, - "conversionRate": 149.61, - "currentCurrency": "usd", - "nativeCurrency": "ETH" - }, - "IncomingTransactionsController": { - "incomingTransactions": {}, - "incomingTxLastFetchedBlocksByNetwork": { - "goerli": null, - "mainnet": null, - "sepolia": null - } - }, - "KeyringController": { - "vault": "{\"data\":\"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT\",\"iv\":\"FbeHDAW5afeWNORfNJBR0Q==\",\"salt\":\"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8=\"}" - }, - "NetworkController": { - "network": "1337", - "provider": { - "nickname": "Localhost 8545", - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "ticker": "ETH", - "type": "rpc" - } - }, - "NotificationController": { - "notifications": { - "1": { - "isShown": true - }, - "3": { - "isShown": true - }, - "5": { - "isShown": true - }, - "6": { - "isShown": true - }, - "8": { - "isShown": true - }, - "10": { - "isShown": true - }, - "11": { - "isShown": true - }, - "12": { - "isShown": true - }, - "14": { - "isShown": true - }, - "15": { - "isShown": true - } - } - }, - "OnboardingController": { - "onboardingTabs": {}, - "seedPhraseBackedUp": false - }, - "PermissionsMetadata": { - "domainMetadata": { - "metamask.github.io": { - "icon": null, - "name": "M E T A M A S K M E S H T E S T" - } - }, - "permissionsHistory": {}, - "permissionsLog": [ - { - "id": 746677923, - "method": "eth_accounts", - "methodType": "restricted", - "origin": "metamask.github.io", - "request": { - "id": 746677923, - "jsonrpc": "2.0", - "method": "eth_accounts", - "origin": "metamask.github.io", - "params": [] - }, - "requestTime": 1575697241368, - "response": { - "id": 746677923, - "jsonrpc": "2.0", - "result": [] - }, - "responseTime": 1575697241370, - "success": true - } - ] - }, - "PreferencesController": { - "accountTokens": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "goerli": [], - "sepolia": [] - } - }, - "assetImages": {}, - "completedOnboarding": true, - "eip1559V2Enabled": true, - "currentLocale": "en", - "featureFlags": { - "showIncomingTransactions": true, - "transactionTime": false - }, - "firstTimeFlowType": "create", - "forgottenPassword": false, - "frequentRpcListDetail": [], - "identities": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "address": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "name": "Account 1" - } - }, - "knownMethodData": {}, - "lostIdentities": {}, - "metaMetricsId": null, - "participateInMetaMetrics": false, - "preferences": { - "useNativeCurrencyAsPrimaryCurrency": true - }, - "selectedAddress": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "suggestedTokens": {}, - "tokens": [], - "useBlockie": false, - "useNonceField": false, - "usePhishDetect": true - }, - "TransactionController": { - "transactions": { - "4046084157914634": { - "chainId": "0x539", - "primaryTransaction": { - "chainId": "0x539", - "id": 4046084157914634, - "loadingDefaults": true, - "metamaskNetworkId": "1337", - "origin": "metamask", - "status": "unapproved", - "time": 1617228030067, - "txParams": { - "from": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "gas": "0x61a8", - "maxFeePerGas": "0x59682f0c", - "maxPriorityFeePerGas": "0x59682f00", - "type": "0x2", - "to": "0x2f318C334780961FB129D2a6c30D0763d9a5C970", - "value": "0x1e87F85809dc0000" - }, - "type": "sentEther" - }, - "history": [ - { - "chainId": "0x539", - "id": 4046084157914634, - "loadingDefaults": true, - "metamaskNetworkId": "1337", - "origin": "metamask", - "status": "unapproved", - "time": 1617228030067, - "txParams": { - "from": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "gas": "0x61a8", - "maxFeePerGas": "0x59682f0c", - "maxPriorityFeePerGas": "0x59682f00", - "type": "0x2", - "to": "0x2f318C334780961FB129D2a6c30D0763d9a5C970", - "value": "0x1e87F85809dc0000" - }, - "type": "simpleSend" - }, - [ - { - "note": "Added new unapproved transaction.", - "op": "replace", - "path": "/loadingDefaults", - "timestamp": 1617228030069, - "value": false - } - ] - ], - "id": 4046084157914634, - "loadingDefaults": false, - "metamaskNetworkId": "1337", - "origin": "metamask", - "status": "unapproved", - "time": 1617228030067, - "txParams": { - "from": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "gas": "0x61a8", - "maxFeePerGas": "0x59682f0c", - "maxPriorityFeePerGas": "0x59682f00", - "type": "0x2", - "to": "0x2f318C334780961FB129D2a6c30D0763d9a5C970", - "value": "0x1e87F85809dc0000" - }, - "type": "simpleSend" - } - } - }, - "config": {}, - "firstTimeInfo": { - "date": 1575697234195, - "version": "7.7.0" - } - }, - "meta": { - "version": 40 - } -} diff --git a/test/e2e/fixtures/import-ui/state.json b/test/e2e/fixtures/import-ui/state.json deleted file mode 100644 index a055509ce..000000000 --- a/test/e2e/fixtures/import-ui/state.json +++ /dev/null @@ -1,272 +0,0 @@ -{ - "data": { - "config": {}, - "PreferencesController": { - "frequentRpcListDetail": [ - { - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "ticker": "ETH", - "nickname": "Localhost 8545", - "rpcPrefs": {} - } - ], - "accountTokens": { - "0x0cc5261ab8ce458dc977078a3623e2badd27afd3": { - "0x539": [] - }, - "0x3ed0ee22e0685ebbf07b2360a8331693c413cc59": {}, - "0xd38d853771fb546bd8b18b2f3638491bc0b0e906": { - "0x539": [] - } - }, - "accountHiddenTokens": { - "0x0cc5261ab8ce458dc977078a3623e2badd27afd3": { - "0x539": [] - }, - "0x3ed0ee22e0685ebbf07b2360a8331693c413cc59": {}, - "0xd38d853771fb546bd8b18b2f3638491bc0b0e906": { - "0x539": [] - } - }, - "assetImages": {}, - "tokens": [], - "hiddenTokens": [], - "suggestedTokens": {}, - "useBlockie": false, - "useNonceField": false, - "usePhishDetect": true, - "featureFlags": { - "showIncomingTransactions": true - }, - "knownMethodData": {}, - "firstTimeFlowType": "import", - "currentLocale": "en", - "identities": { - "0x0cc5261ab8ce458dc977078a3623e2badd27afd3": { - "name": "Account 1", - "address": "0x0cc5261ab8ce458dc977078a3623e2badd27afd3", - "lastSelected": 1618940443499 - }, - "0x3ed0ee22e0685ebbf07b2360a8331693c413cc59": { - "name": "Account 2", - "address": "0x3ed0ee22e0685ebbf07b2360a8331693c413cc59" - }, - "0xd38d853771fb546bd8b18b2f3638491bc0b0e906": { - "name": "2nd account", - "address": "0xd38d853771fb546bd8b18b2f3638491bc0b0e906", - "lastSelected": 1618940443010 - } - }, - "lostIdentities": {}, - "forgottenPassword": false, - "preferences": { - "showFiatInTestnets": false, - "useNativeCurrencyAsPrimaryCurrency": true, - "hideZeroBalanceTokens": false - }, - "completedOnboarding": true, - "ipfsGateway": "dweb.link", - "infuraBlocked": false, - "selectedAddress": "0x0cc5261ab8ce458dc977078a3623e2badd27afd3" - }, - "firstTimeInfo": { - "version": "9.3.0", - "date": 1617927806790 - }, - "NetworkController": { - "provider": { - "ticker": "ETH", - "type": "rpc", - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "nickname": "Localhost 8545" - }, - "previousProviderStore": { - "ticker": "ETH", - "type": "rpc", - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "nickname": "Localhost 8545" - }, - "network": "1337" - }, - "NotificationController": { - "notifications": { - "1": { - "isShown": true - }, - "3": { - "isShown": true - }, - "5": { - "isShown": true - }, - "6": { - "isShown": true - }, - "8": { - "isShown": true - }, - "10": { - "isShown": true - }, - "11": { - "isShown": true - }, - "12": { - "isShown": true - }, - "14": { - "isShown": true - }, - "15": { - "isShown": true - } - } - }, - "CurrencyController": { - "conversionDate": 1618940438.187, - "conversionRate": 2254.54, - "currentCurrency": "usd", - "nativeCurrency": "ETH", - "usdConversionRate": 2254.54 - }, - "CachedBalancesController": { - "cachedBalances": { - "0x539": { - "0x0cc5261ab8ce458dc977078a3623e2badd27afd3": "0x14cffbeaf5a7d3000", - "0x3ed0ee22e0685ebbf07b2360a8331693c413cc59": "0x0", - "0xd38d853771fb546bd8b18b2f3638491bc0b0e906": "0x0" - } - } - }, - "MetaMetricsController": { - "participateInMetaMetrics": false, - "metaMetricsId": null - }, - "PermissionsController": { - "permissionsRequests": [], - "permissionsDescriptions": {}, - "domains": {} - }, - "TransactionController": { - "transactions": { - "1374812123920442": { - "id": 1374812123920442, - "time": 1618940444708, - "status": "confirmed", - "metamaskNetworkId": "1337", - "chainId": "0x539", - "loadingDefaults": false, - "txParams": { - "from": "0x0cc5261ab8ce458dc977078a3623e2badd27afd3", - "to": "0x2f318c334780961fb129d2a6c30d0763d9a5c970", - "nonce": "0x0", - "value": "0xde0b6b3a7640000", - "gas": "0x5208", - "gasPrice": "0x363fe1da00" - }, - "origin": "metamask", - "type": "simpleSend", - "history": [], - "nonceDetails": { - "params": { - "highestLocallyConfirmed": 0, - "highestSuggested": 0, - "nextNetworkNonce": 0 - }, - "local": { - "name": "local", - "nonce": 0, - "details": { - "startPoint": 0, - "highest": 0 - } - }, - "network": { - "name": "network", - "nonce": 0, - "details": { - "blockNumber": "0x5", - "baseCount": 0 - } - } - }, - "r": "0x035de1d588f67547bd9c7bb9b34a8330c10085155e42af0017986911ca922e61", - "s": "0x36c3c12a323121afe6d63bc8c5929766d385e2e7b7fc892ecd0f10a7ec4ab59e", - "v": "0x0a95", - "rawTx": "0xf86e8085363fe1da00825208942f318c334780961fb129d2a6c30d0763d9a5c970880de0b6b3a764000080820a95a0035de1d588f67547bd9c7bb9b34a8330c10085155e42af0017986911ca922e61a036c3c12a323121afe6d63bc8c5929766d385e2e7b7fc892ecd0f10a7ec4ab59e", - "hash": "0xaba403a1dff459d7549b57369cfdd323c70fc79a307ed8f9cae811ddd6883a74", - "submittedTime": 1618940445208, - "txReceipt": { - "transactionHash": "0xaba403a1dff459d7549b57369cfdd323c70fc79a307ed8f9cae811ddd6883a74", - "transactionIndex": { - "negative": 0, - "words": [0, null], - "length": 1, - "red": null - }, - "blockHash": "0x734618e63369e7ea10872e68cec4d400d77c55ed525cbc295802d00d7b4bd1d2", - "blockNumber": { - "negative": 0, - "words": [6, null], - "length": 1, - "red": null - }, - "from": "0x0cc5261ab8ce458dc977078a3623e2badd27afd3", - "to": "0x2f318c334780961fb129d2a6c30d0763d9a5c970", - "gasUsed": "5208", - "cumulativeGasUsed": { - "negative": 0, - "words": [21000, null], - "length": 1, - "red": null - }, - "contractAddress": null, - "logs": [], - "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - } - } - } - }, - "KeyringController": { - "vault": "{\"data\":\"Ot+BTtJPag0xubdiv1nO9bsSvTHivHCd6CD7Lxgb1McYw3VqMjgp5rPMZmblJ1lscuMxyiqp99G52uXO9S0em6F9htpa+t/wn6qubRKTTNG9fxNzQrKXRDNhdgfYckVk5VAZ4fgl2iMZcRDvS8H/+gucVKJ33Sl6mXyPofdexXhWDCU6uR2YecnfaIum9cL2u/GqOMPE3jxzy0Wip0x2Jyp3QOKhvu8A3GIjzagLOaQ7a1APdl8=\",\"iv\":\"lbsyPeGYWU6U1+jvmW9UHg==\",\"salt\":\"Zmbhpskwxe4rYfXtELBvlcvW4HISPBATRmMqzsnZPMg=\"}" - }, - "AlertController": { - "alertEnabledness": { - "unconnectedAccount": true, - "web3ShimUsage": true - }, - "unconnectedAccountAlertShownOrigins": {}, - "web3ShimUsageOrigins": {} - }, - "OnboardingController": { - "seedPhraseBackedUp": true, - "onboardingTabs": {} - }, - "AddressBookController": { - "addressBook": { - "0x539": { - "0x2f318C334780961FB129D2a6c30D0763d9a5C970": { - "address": "0x2f318C334780961FB129D2a6c30D0763d9a5C970", - "chainId": "0x539", - "isEns": false, - "memo": "", - "name": "" - } - } - } - }, - "AppStateController": { - "connectedStatusPopoverHasBeenShown": true, - "swapsWelcomeMessageHasBeenShown": false, - "defaultHomeActiveTabName": "Activity", - "showPortfolioTooltip": false - } - }, - "meta": { - "version": 57 - } -} diff --git a/test/e2e/fixtures/imported-account/state.json b/test/e2e/fixtures/imported-account/state.json deleted file mode 100644 index ebe94144b..000000000 --- a/test/e2e/fixtures/imported-account/state.json +++ /dev/null @@ -1,157 +0,0 @@ -{ - "data": { - "AppStateController": { - "mkrMigrationReminderTimestamp": null, - "showPortfolioTooltip": false - }, - "CachedBalancesController": { - "cachedBalances": { - "4": {} - } - }, - "CurrencyController": { - "conversionDate": 1575697244.188, - "conversionRate": 149.61, - "currentCurrency": "usd", - "nativeCurrency": "ETH" - }, - "IncomingTransactionsController": { - "incomingTransactions": {}, - "incomingTxLastFetchedBlocksByNetwork": { - "goerli": null, - "mainnet": null, - "sepolia": null - } - }, - "KeyringController": { - "vault": "{\"data\":\"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT\",\"iv\":\"FbeHDAW5afeWNORfNJBR0Q==\",\"salt\":\"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8=\"}" - }, - "NetworkController": { - "network": "1337", - "provider": { - "nickname": "Localhost 8545", - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "ticker": "ETH", - "type": "rpc" - } - }, - "NotificationController": { - "notifications": { - "1": { - "isShown": true - }, - "3": { - "isShown": true - }, - "5": { - "isShown": true - }, - "6": { - "isShown": true - }, - "8": { - "isShown": true - }, - "10": { - "isShown": true - }, - "11": { - "isShown": true - }, - "12": { - "isShown": true - }, - "14": { - "isShown": true - }, - "15": { - "isShown": true - } - } - }, - "OnboardingController": { - "onboardingTabs": {}, - "seedPhraseBackedUp": false - }, - "PermissionsMetadata": { - "domainMetadata": { - "metamask.github.io": { - "icon": null, - "name": "M E T A M A S K M E S H T E S T" - } - }, - "permissionsHistory": {}, - "permissionsLog": [ - { - "id": 746677923, - "method": "eth_accounts", - "methodType": "restricted", - "origin": "metamask.github.io", - "request": { - "id": 746677923, - "jsonrpc": "2.0", - "method": "eth_accounts", - "origin": "metamask.github.io", - "params": [] - }, - "requestTime": 1575697241368, - "response": { - "id": 746677923, - "jsonrpc": "2.0", - "result": [] - }, - "responseTime": 1575697241370, - "success": true - } - ] - }, - "PreferencesController": { - "accountTokens": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "goerli": [], - "sepolia": [] - } - }, - "assetImages": {}, - "completedOnboarding": true, - "dismissSeedBackUpReminder": true, - "currentLocale": "en", - "featureFlags": { - "showIncomingTransactions": true, - "transactionTime": false - }, - "firstTimeFlowType": "create", - "forgottenPassword": false, - "frequentRpcListDetail": [], - "identities": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "address": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "name": "Account 1" - } - }, - "knownMethodData": {}, - "lostIdentities": {}, - "metaMetricsId": null, - "participateInMetaMetrics": false, - "preferences": { - "useNativeCurrencyAsPrimaryCurrency": true - }, - "selectedAddress": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "suggestedTokens": {}, - "tokens": [], - "useBlockie": false, - "useNonceField": false, - "usePhishDetect": true, - "useTokenDetection": true - }, - "config": {}, - "firstTimeInfo": { - "date": 1575697234195, - "version": "7.7.0" - } - }, - "meta": { - "version": 40 - } -} diff --git a/test/e2e/fixtures/localization/state.json b/test/e2e/fixtures/localization/state.json deleted file mode 100644 index d4c04bb0e..000000000 --- a/test/e2e/fixtures/localization/state.json +++ /dev/null @@ -1,156 +0,0 @@ -{ - "data": { - "AppStateController": { - "mkrMigrationReminderTimestamp": null, - "showPortfolioTooltip": false - }, - "CachedBalancesController": { - "cachedBalances": { - "4": {} - } - }, - "CurrencyController": { - "conversionDate": 1594323667.203, - "conversionRate": 14205.88, - "currentCurrency": "php", - "nativeCurrency": "ETH" - }, - "IncomingTransactionsController": { - "incomingTransactions": {}, - "incomingTxLastFetchedBlocksByNetwork": { - "goerli": null, - "mainnet": null, - "sepolia": null - } - }, - "KeyringController": { - "vault": "{\"data\":\"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT\",\"iv\":\"FbeHDAW5afeWNORfNJBR0Q==\",\"salt\":\"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8=\"}" - }, - "NetworkController": { - "network": "1337", - "provider": { - "nickname": "Localhost 8545", - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "ticker": "ETH", - "type": "rpc" - } - }, - "NotificationController": { - "notifications": { - "1": { - "isShown": true - }, - "3": { - "isShown": true - }, - "5": { - "isShown": true - }, - "6": { - "isShown": true - }, - "8": { - "isShown": true - }, - "10": { - "isShown": true - }, - "11": { - "isShown": true - }, - "12": { - "isShown": true - }, - "14": { - "isShown": true - }, - "15": { - "isShown": true - } - } - }, - "OnboardingController": { - "onboardingTabs": {}, - "seedPhraseBackedUp": false - }, - "PermissionsMetadata": { - "domainMetadata": { - "metamask.github.io": { - "icon": null, - "name": "M E T A M A S K M E S H T E S T" - } - }, - "permissionsHistory": {}, - "permissionsLog": [ - { - "id": 746677923, - "method": "eth_accounts", - "methodType": "restricted", - "origin": "metamask.github.io", - "request": { - "id": 746677923, - "jsonrpc": "2.0", - "method": "eth_accounts", - "origin": "metamask.github.io", - "params": [] - }, - "requestTime": 1575697241368, - "response": { - "id": 746677923, - "jsonrpc": "2.0", - "result": [] - }, - "responseTime": 1575697241370, - "success": true - } - ] - }, - "PreferencesController": { - "accountTokens": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "goerli": [], - "sepolia": [] - } - }, - "assetImages": {}, - "completedOnboarding": true, - "currentLocale": "en", - "featureFlags": { - "showIncomingTransactions": true, - "transactionTime": false - }, - "firstTimeFlowType": "create", - "forgottenPassword": false, - "frequentRpcListDetail": [], - "identities": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "address": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "name": "Account 1" - } - }, - "knownMethodData": {}, - "lostIdentities": {}, - "metaMetricsId": null, - "participateInMetaMetrics": false, - "preferences": { - "showFiatInTestnets": true, - "useNativeCurrencyAsPrimaryCurrency": true - }, - "selectedAddress": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "suggestedTokens": {}, - "tokens": [], - "useBlockie": false, - "useNonceField": false, - "usePhishDetect": true - }, - "config": {}, - "firstTimeInfo": { - "date": 1575697234195, - "version": "7.7.0" - } - }, - "meta": { - "version": 40 - } -} diff --git a/test/e2e/fixtures/metrics-enabled/state.json b/test/e2e/fixtures/metrics-enabled/state.json deleted file mode 100644 index bf8dae606..000000000 --- a/test/e2e/fixtures/metrics-enabled/state.json +++ /dev/null @@ -1,200 +0,0 @@ -{ - "data": { - "AppStateController": { - "connectedStatusPopoverHasBeenShown": false, - "showPortfolioTooltip": false - }, - "CachedBalancesController": { - "cachedBalances": { - "4": {}, - "1337": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": "0x15af1d78b58c40000" - } - } - }, - "CurrencyController": { - "conversionDate": 1594348502.519, - "conversionRate": 240.09, - "currentCurrency": "usd", - "nativeCurrency": "ETH" - }, - "IncomingTransactionsController": { - "incomingTransactions": {}, - "incomingTxLastFetchedBlocksByNetwork": { - "goerli": null, - "mainnet": null, - "sepolia": null, - "localhost": 98 - } - }, - "KeyringController": { - "vault": "{\"data\":\"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT\",\"iv\":\"FbeHDAW5afeWNORfNJBR0Q==\",\"salt\":\"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8=\"}" - }, - "NetworkController": { - "provider": { - "nickname": "Localhost 8545", - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "ticker": "ETH", - "type": "rpc" - }, - "network": "1337" - }, - "NotificationController": { - "notifications": { - "1": { - "isShown": true - }, - "3": { - "isShown": true - }, - "5": { - "isShown": true - }, - "6": { - "isShown": true - }, - "8": { - "isShown": true - }, - "10": { - "isShown": true - }, - "11": { - "isShown": true - }, - "12": { - "isShown": true - }, - "14": { - "isShown": true - }, - "15": { - "isShown": true - } - } - }, - "OnboardingController": { - "onboardingTabs": {}, - "seedPhraseBackedUp": false - }, - "PermissionsMetadata": { - "permissionsLog": [ - { - "id": 1764280960, - "method": "eth_requestAccounts", - "methodType": "restricted", - "origin": "http://127.0.0.1:8080", - "request": { - "method": "eth_requestAccounts", - "jsonrpc": "2.0", - "id": 1764280960, - "origin": "http://127.0.0.1:8080", - "tabId": 2 - }, - "requestTime": 1594348329232, - "response": { - "id": 1764280960, - "jsonrpc": "2.0", - "result": ["0x5cfe73b6021e818b776b421b1c4db2474086a7e1"] - }, - "responseTime": 1594348332276, - "success": true - } - ], - "permissionsHistory": { - "http://127.0.0.1:8080": { - "eth_accounts": { - "accounts": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": 1594348332276 - }, - "lastApproved": 1594348332276 - } - } - }, - "domainMetadata": { - "http://127.0.0.1:8080": { - "name": "E2E Test Dapp", - "icon": "http://127.0.0.1:8080/metamask-fox.svg", - "lastUpdated": 1594348323811, - "host": "127.0.0.1:8080" - } - } - }, - "PreferencesController": { - "frequentRpcListDetail": [], - "accountTokens": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "goerli": [], - "sepolia": [] - } - }, - "assetImages": {}, - "tokens": [], - "suggestedTokens": {}, - "useBlockie": false, - "useNonceField": false, - "usePhishDetect": true, - "featureFlags": { - "showIncomingTransactions": true, - "transactionTime": false - }, - "knownMethodData": {}, - "participateInMetaMetrics": true, - "firstTimeFlowType": "create", - "currentLocale": "en", - "identities": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "address": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "name": "Account 1" - } - }, - "lostIdentities": {}, - "forgottenPassword": false, - "preferences": { - "useNativeCurrencyAsPrimaryCurrency": true - }, - "completedOnboarding": true, - "metaMetricsId": "fake-metrics-id", - "ipfsGateway": "dweb.link", - "selectedAddress": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1" - }, - "config": {}, - "firstTimeInfo": { - "date": 1575697234195, - "version": "7.7.0" - }, - "PermissionsController": { - "permissionsRequests": [], - "permissionsDescriptions": {}, - "domains": { - "http://127.0.0.1:8080": { - "permissions": [ - { - "@context": ["https://github.com/MetaMask/rpc-cap"], - "parentCapability": "eth_accounts", - "id": "f55a1c15-ea48-4088-968e-63be474d42fa", - "date": 1594348332268, - "invoker": "http://127.0.0.1:8080", - "caveats": [ - { - "type": "limitResponseLength", - "value": 1, - "name": "primaryAccountOnly" - }, - { - "type": "filterResponse", - "value": ["0x5cfe73b6021e818b776b421b1c4db2474086a7e1"], - "name": "exposedAccounts" - } - ] - } - ] - } - } - } - }, - "meta": { - "version": 47 - } -} diff --git a/test/e2e/fixtures/navigate-transactions/state.json b/test/e2e/fixtures/navigate-transactions/state.json deleted file mode 100644 index ab741e601..000000000 --- a/test/e2e/fixtures/navigate-transactions/state.json +++ /dev/null @@ -1,442 +0,0 @@ -{ - "data": { - "AppStateController": { - "mkrMigrationReminderTimestamp": null, - "showPortfolioTooltip": false - }, - "CachedBalancesController": { - "cachedBalances": { - "4": {} - } - }, - "CurrencyController": { - "conversionDate": 1575697244.188, - "conversionRate": 149.61, - "currentCurrency": "usd", - "nativeCurrency": "ETH" - }, - "IncomingTransactionsController": { - "incomingTransactions": {}, - "incomingTxLastFetchedBlocksByNetwork": { - "goerli": null, - "mainnet": null, - "sepolia": null - } - }, - "KeyringController": { - "vault": "{\"data\":\"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT\",\"iv\":\"FbeHDAW5afeWNORfNJBR0Q==\",\"salt\":\"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8=\"}" - }, - "NetworkController": { - "network": "1337", - "provider": { - "nickname": "Localhost 8545", - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "ticker": "ETH", - "type": "rpc" - } - }, - "NotificationController": { - "notifications": { - "1": { - "isShown": true - }, - "3": { - "isShown": true - }, - "5": { - "isShown": true - }, - "6": { - "isShown": true - }, - "8": { - "isShown": true - }, - "10": { - "isShown": true - }, - "11": { - "isShown": true - }, - "12": { - "isShown": true - }, - "14": { - "isShown": true - }, - "15": { - "isShown": true - } - } - }, - "OnboardingController": { - "onboardingTabs": {}, - "seedPhraseBackedUp": false - }, - "PermissionsMetadata": { - "domainMetadata": { - "metamask.github.io": { - "icon": null, - "name": "M E T A M A S K M E S H T E S T" - } - }, - "permissionsHistory": {}, - "permissionsLog": [ - { - "id": 746677923, - "method": "eth_accounts", - "methodType": "restricted", - "origin": "metamask.github.io", - "request": { - "id": 746677923, - "jsonrpc": "2.0", - "method": "eth_accounts", - "origin": "metamask.github.io", - "params": [] - }, - "requestTime": 1575697241368, - "response": { - "id": 746677923, - "jsonrpc": "2.0", - "result": [] - }, - "responseTime": 1575697241370, - "success": true - } - ] - }, - "PreferencesController": { - "accountTokens": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "goerli": [], - "sepolia": [] - } - }, - "assetImages": {}, - "completedOnboarding": true, - "dismissSeedBackUpReminder": true, - "currentLocale": "en", - "featureFlags": { - "showIncomingTransactions": true, - "transactionTime": false - }, - "firstTimeFlowType": "create", - "forgottenPassword": false, - "frequentRpcListDetail": [], - "identities": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "address": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "name": "Account 1" - } - }, - "knownMethodData": {}, - "lostIdentities": {}, - "metaMetricsId": null, - "participateInMetaMetrics": false, - "preferences": { - "useNativeCurrencyAsPrimaryCurrency": true - }, - "selectedAddress": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "suggestedTokens": {}, - "tokens": [], - "useBlockie": false, - "useNonceField": false, - "usePhishDetect": true, - "useTokenDetection": true - }, - "MetaMetricsController": { - "fragments": { - "transaction-added-7911313280012623": { - "category": "Transactions", - "initialEvent": "Transaction Added", - "successEvent": "Transaction Approved", - "failureEvent": "Transaction Rejected", - "properties": {}, - "persist": true, - "uniqueIdentifier": "transaction-added-7911313280012623" - }, - "transaction-added-7911313280012624": { - "category": "Transactions", - "initialEvent": "Transaction Added", - "successEvent": "Transaction Approved", - "failureEvent": "Transaction Rejected", - "properties": {}, - "persist": true, - "uniqueIdentifier": "transaction-added-7911313280012624" - }, - "transaction-added-7911313280012625": { - "category": "Transactions", - "initialEvent": "Transaction Added", - "successEvent": "Transaction Approved", - "failureEvent": "Transaction Rejected", - "properties": {}, - "persist": true, - "uniqueIdentifier": "transaction-added-7911313280012625" - }, - "transaction-added-7911313280012626": { - "category": "Transactions", - "initialEvent": "Transaction Added", - "successEvent": "Transaction Approved", - "failureEvent": "Transaction Rejected", - "properties": {}, - "persist": true, - "uniqueIdentifier": "transaction-added-7911313280012626" - } - } - }, - "TransactionController": { - "transactions": { - "7911313280012623": { - "chainId": "0x539", - "dappSuggestedGasFees": { - "gas": "0x5208", - "gasPrice": "0x4a817c800" - }, - "history": [ - { - "chainId": "0x539", - "dappSuggestedGasFees": { - "gas": "0x5208", - "gasPrice": "0x4a817c800" - }, - "id": 7911313280012623, - "loadingDefaults": true, - "metamaskNetworkId": "1337", - "origin": "https://metamask.github.io", - "status": "unapproved", - "time": 1631545991949, - "txParams": { - "from": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "gas": "0x5208", - "gasPrice": "0x4a817c800", - "to": "0x2f318c334780961fb129d2a6c30d0763d9a5c970", - "value": "0x29a2241af62c0000" - }, - "type": "sentEther" - }, - [ - { - "note": "Added new unapproved transaction.", - "op": "replace", - "path": "/loadingDefaults", - "timestamp": 1631545992244, - "value": false - } - ] - ], - "id": 7911313280012623, - "loadingDefaults": false, - "metamaskNetworkId": "1337", - "origin": "https://metamask.github.io", - "status": "unapproved", - "time": 1631545991949, - "txParams": { - "from": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "gas": "0x5208", - "gasPrice": "0x4a817c800", - "to": "0x2f318c334780961fb129d2a6c30d0763d9a5c970", - "value": "0x29a2241af62c0000" - }, - "type": "sentEther" - }, - "7911313280012624": { - "chainId": "0x539", - "dappSuggestedGasFees": { - "gas": "0x5208", - "gasPrice": "0x4a817c800" - }, - "history": [ - { - "chainId": "0x539", - "dappSuggestedGasFees": { - "gas": "0x5208", - "gasPrice": "0x4a817c800" - }, - "id": 7911313280012624, - "loadingDefaults": true, - "metamaskNetworkId": "1337", - "origin": "https://metamask.github.io", - "status": "unapproved", - "time": 1631545994578, - "txParams": { - "from": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "gas": "0x5208", - "gasPrice": "0x4a817c800", - "to": "0x2f318c334780961fb129d2a6c30d0763d9a5c970", - "value": "0x29a2241af62c0000" - }, - "type": "sentEther" - }, - [ - { - "note": "Added new unapproved transaction.", - "op": "replace", - "path": "/loadingDefaults", - "timestamp": 1631545994695, - "value": false - } - ] - ], - "id": 7911313280012624, - "loadingDefaults": false, - "metamaskNetworkId": "1337", - "origin": "https://metamask.github.io", - "status": "unapproved", - "time": 1631545994578, - "txParams": { - "from": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "gas": "0x5208", - "gasPrice": "0x4a817c800", - "to": "0x2f318c334780961fb129d2a6c30d0763d9a5c970", - "value": "0x29a2241af62c0000" - }, - "type": "sentEther" - }, - "7911313280012625": { - "chainId": "0x539", - "dappSuggestedGasFees": { - "gas": "0x5208", - "gasPrice": "0x4a817c800" - }, - "history": [ - { - "chainId": "0x539", - "dappSuggestedGasFees": { - "gas": "0x5208", - "gasPrice": "0x4a817c800" - }, - "id": 7911313280012625, - "loadingDefaults": true, - "metamaskNetworkId": "1337", - "origin": "https://metamask.github.io", - "status": "unapproved", - "time": 1631545996673, - "txParams": { - "from": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "gas": "0x5208", - "gasPrice": "0x4a817c800", - "to": "0x2f318c334780961fb129d2a6c30d0763d9a5c970", - "value": "0x29a2241af62c0000" - }, - "type": "sentEther" - }, - [ - { - "note": "Added new unapproved transaction.", - "op": "replace", - "path": "/loadingDefaults", - "timestamp": 1631545996678, - "value": false - } - ] - ], - "id": 7911313280012625, - "loadingDefaults": false, - "metamaskNetworkId": "1337", - "origin": "https://metamask.github.io", - "status": "unapproved", - "time": 1631545996673, - "txParams": { - "from": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "gas": "0x5208", - "gasPrice": "0x4a817c800", - "to": "0x2f318c334780961fb129d2a6c30d0763d9a5c970", - "value": "0x29a2241af62c0000" - }, - "type": "sentEther" - }, - "7911313280012626": { - "chainId": "0x539", - "dappSuggestedGasFees": { - "gas": "0x5208", - "gasPrice": "0x4a817c800" - }, - "history": [ - { - "chainId": "0x539", - "dappSuggestedGasFees": { - "gas": "0x5208", - "gasPrice": "0x4a817c800" - }, - "id": 7911313280012626, - "loadingDefaults": true, - "metamaskNetworkId": "1337", - "origin": "https://metamask.github.io", - "status": "unapproved", - "time": 1631545998675, - "txParams": { - "from": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "gas": "0x5208", - "gasPrice": "0x4a817c800", - "to": "0x2f318c334780961fb129d2a6c30d0763d9a5c970", - "value": "0x29a2241af62c0000" - }, - "type": "sentEther" - }, - [ - { - "note": "Added new unapproved transaction.", - "op": "replace", - "path": "/loadingDefaults", - "timestamp": 1631545998677, - "value": false - } - ] - ], - "id": 7911313280012626, - "loadingDefaults": false, - "metamaskNetworkId": "1337", - "origin": "https://metamask.github.io", - "status": "unapproved", - "time": 1631545998675, - "txParams": { - "from": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "gas": "0x5208", - "gasPrice": "0x4a817c800", - "to": "0x2f318c334780961fb129d2a6c30d0763d9a5c970", - "value": "0x29a2241af62c0000" - }, - "type": "sentEther" - } - } - }, - "PermissionsController": { - "permissionsRequests": [], - "permissionsDescriptions": {}, - "domains": { - "http://127.0.0.1:8080": { - "permissions": [ - { - "@context": ["https://github.com/MetaMask/rpc-cap"], - "parentCapability": "eth_accounts", - "id": "f55a1c15-ea48-4088-968e-63be474d42fa", - "date": 1594348332268, - "invoker": "http://127.0.0.1:8080", - "caveats": [ - { - "type": "limitResponseLength", - "value": 1, - "name": "primaryAccountOnly" - }, - { - "type": "filterResponse", - "value": ["0x5cfe73b6021e818b776b421b1c4db2474086a7e1"], - "name": "exposedAccounts" - } - ] - } - ] - } - } - }, - "config": {}, - "firstTimeInfo": { - "date": 1575697234195, - "version": "7.7.0" - } - }, - "meta": { - "version": 40 - } -} diff --git a/test/e2e/fixtures/onboarding/state.json b/test/e2e/fixtures/onboarding/state.json deleted file mode 100644 index 42b51a422..000000000 --- a/test/e2e/fixtures/onboarding/state.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "data": { - "config": {}, - "PreferencesController": { - "frequentRpcListDetail": [ - { - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "ticker": "ETH", - "nickname": "Localhost 8545", - "rpcPrefs": {} - } - ] - }, - "firstTimeInfo": { - "version": "9.3.0", - "date": 1617927806790 - }, - "NetworkController": { - "provider": { - "ticker": "ETH", - "type": "rpc", - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "nickname": "Localhost 8545" - }, - "network": "1337" - }, - "NotificationController": { - "notifications": { - "10": { - "isShown": true - }, - "11": { - "isShown": true - }, - "12": { - "isShown": true - }, - "14": { - "isShown": true - }, - "15": { - "isShown": true - } - } - }, - "CurrencyController": { - "conversionDate": 1617927806.941, - "conversionRate": 2084.64, - "currentCurrency": "usd", - "nativeCurrency": "ETH", - "usdConversionRate": 2084.64 - } - }, - "meta": { - "version": 57 - } -} diff --git a/test/e2e/fixtures/send-edit-v2/state.json b/test/e2e/fixtures/send-edit-v2/state.json deleted file mode 100644 index 76d21936f..000000000 --- a/test/e2e/fixtures/send-edit-v2/state.json +++ /dev/null @@ -1,229 +0,0 @@ -{ - "data": { - "AppStateController": { - "mkrMigrationReminderTimestamp": null, - "swapsWelcomeMessageHasBeenShown": true, - "showPortfolioTooltip": false - }, - "CachedBalancesController": { - "cachedBalances": { - "4": {} - } - }, - "CurrencyController": { - "conversionDate": 1575697244.188, - "conversionRate": 149.61, - "currentCurrency": "usd", - "nativeCurrency": "ETH" - }, - "IncomingTransactionsController": { - "incomingTransactions": {}, - "incomingTxLastFetchedBlocksByNetwork": { - "goerli": null, - "mainnet": null, - "sepolia": null - } - }, - "KeyringController": { - "vault": "{\"data\":\"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT\",\"iv\":\"FbeHDAW5afeWNORfNJBR0Q==\",\"salt\":\"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8=\"}" - }, - "NetworkController": { - "network": "1337", - "provider": { - "nickname": "Localhost 8545", - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "ticker": "ETH", - "type": "rpc" - } - }, - "NotificationController": { - "notifications": { - "1": { - "isShown": true - }, - "3": { - "isShown": true - }, - "5": { - "isShown": true - }, - "6": { - "isShown": true - }, - "8": { - "isShown": true - }, - "10": { - "isShown": true - }, - "11": { - "isShown": true - }, - "12": { - "isShown": true - }, - "14": { - "isShown": true - }, - "15": { - "isShown": true - } - } - }, - "OnboardingController": { - "onboardingTabs": {}, - "seedPhraseBackedUp": false - }, - "PermissionsMetadata": { - "domainMetadata": { - "metamask.github.io": { - "icon": null, - "name": "M E T A M A S K M E S H T E S T" - } - }, - "permissionsHistory": {}, - "permissionsLog": [ - { - "id": 746677923, - "method": "eth_accounts", - "methodType": "restricted", - "origin": "metamask.github.io", - "request": { - "id": 746677923, - "jsonrpc": "2.0", - "method": "eth_accounts", - "origin": "metamask.github.io", - "params": [] - }, - "requestTime": 1575697241368, - "response": { - "id": 746677923, - "jsonrpc": "2.0", - "result": [] - }, - "responseTime": 1575697241370, - "success": true - } - ] - }, - "PreferencesController": { - "accountTokens": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "goerli": [], - "sepolia": [] - } - }, - "assetImages": {}, - "completedOnboarding": true, - "eip1559V2Enabled": true, - "currentLocale": "en", - "featureFlags": { - "showIncomingTransactions": true, - "transactionTime": false - }, - "firstTimeFlowType": "create", - "forgottenPassword": false, - "frequentRpcListDetail": [], - "identities": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "address": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "name": "Account 1" - } - }, - "knownMethodData": {}, - "lostIdentities": {}, - "metaMetricsId": null, - "participateInMetaMetrics": false, - "preferences": { - "useNativeCurrencyAsPrimaryCurrency": true - }, - "selectedAddress": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "suggestedTokens": {}, - "tokens": [], - "useBlockie": false, - "useNonceField": false, - "usePhishDetect": true - }, - "TransactionController": { - "transactions": { - "4046084157914634": { - "chainId": "0x539", - "primaryTransaction": { - "chainId": "0x539", - "id": 4046084157914634, - "loadingDefaults": true, - "metamaskNetworkId": "1337", - "origin": "metamask", - "status": "unapproved", - "time": 1617228030067, - "txParams": { - "from": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "gas": "0x61a8", - "maxFeePerGas": "0x59682f0c", - "maxPriorityFeePerGas": "0x59682f00", - "type": "0x2", - "to": "0x2f318C334780961FB129D2a6c30D0763d9a5C970", - "value": "0xde0b6b3a7640000" - }, - "type": "sentEther" - }, - "history": [ - { - "chainId": "0x539", - "id": 4046084157914634, - "loadingDefaults": true, - "metamaskNetworkId": "1337", - "origin": "metamask", - "status": "unapproved", - "time": 1617228030067, - "txParams": { - "from": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "gas": "0x61a8", - "maxFeePerGas": "0x59682f0c", - "maxPriorityFeePerGas": "0x59682f00", - "type": "0x2", - "to": "0x2f318C334780961FB129D2a6c30D0763d9a5C970", - "value": "0xde0b6b3a7640000" - }, - "type": "simpleSend" - }, - [ - { - "note": "Added new unapproved transaction.", - "op": "replace", - "path": "/loadingDefaults", - "timestamp": 1617228030069, - "value": false - } - ] - ], - "id": 4046084157914634, - "loadingDefaults": false, - "metamaskNetworkId": "1337", - "origin": "metamask", - "status": "unapproved", - "time": 1617228030067, - "txParams": { - "from": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "gas": "0x61a8", - "maxFeePerGas": "0x59682f0c", - "maxPriorityFeePerGas": "0x59682f00", - "type": "0x2", - "to": "0x2f318C334780961FB129D2a6c30D0763d9a5C970", - "value": "0xde0b6b3a7640000" - }, - "type": "simpleSend" - } - } - }, - "config": {}, - "firstTimeInfo": { - "date": 1575697234195, - "version": "7.7.0" - } - }, - "meta": { - "version": 40 - } -} diff --git a/test/e2e/fixtures/send-edit/state.json b/test/e2e/fixtures/send-edit/state.json deleted file mode 100644 index 0e17eb4a9..000000000 --- a/test/e2e/fixtures/send-edit/state.json +++ /dev/null @@ -1,235 +0,0 @@ -{ - "data": { - "AppStateController": { - "mkrMigrationReminderTimestamp": null, - "swapsWelcomeMessageHasBeenShown": true, - "showPortfolioTooltip": false - }, - "CachedBalancesController": { - "cachedBalances": { - "4": {} - } - }, - "CurrencyController": { - "conversionDate": 1575697244.188, - "conversionRate": 149.61, - "currentCurrency": "usd", - "nativeCurrency": "ETH" - }, - "IncomingTransactionsController": { - "incomingTransactions": {}, - "incomingTxLastFetchedBlocksByNetwork": { - "goerli": null, - "mainnet": null, - "sepolia": null - } - }, - "KeyringController": { - "vault": "{\"data\":\"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT\",\"iv\":\"FbeHDAW5afeWNORfNJBR0Q==\",\"salt\":\"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8=\"}" - }, - "NetworkController": { - "network": "1337", - "provider": { - "nickname": "Localhost 8545", - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "ticker": "ETH", - "type": "rpc" - } - }, - "NotificationController": { - "notifications": { - "1": { - "isShown": true - }, - "3": { - "isShown": true - }, - "5": { - "isShown": true - }, - "6": { - "isShown": true - }, - "8": { - "isShown": true - }, - "10": { - "isShown": true - }, - "11": { - "isShown": true - }, - "12": { - "isShown": true - }, - "14": { - "isShown": true - }, - "15": { - "isShown": true - } - } - }, - "OnboardingController": { - "onboardingTabs": {}, - "seedPhraseBackedUp": false - }, - "PermissionsMetadata": { - "domainMetadata": { - "metamask.github.io": { - "icon": null, - "name": "M E T A M A S K M E S H T E S T" - } - }, - "permissionsHistory": {}, - "permissionsLog": [ - { - "id": 746677923, - "method": "eth_accounts", - "methodType": "restricted", - "origin": "metamask.github.io", - "request": { - "id": 746677923, - "jsonrpc": "2.0", - "method": "eth_accounts", - "origin": "metamask.github.io", - "params": [] - }, - "requestTime": 1575697241368, - "response": { - "id": 746677923, - "jsonrpc": "2.0", - "result": [] - }, - "responseTime": 1575697241370, - "success": true - } - ] - }, - "PreferencesController": { - "accountTokens": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "goerli": [], - "sepolia": [] - } - }, - "assetImages": {}, - "completedOnboarding": true, - "currentLocale": "en", - "featureFlags": { - "showIncomingTransactions": true, - "transactionTime": false - }, - "firstTimeFlowType": "create", - "forgottenPassword": false, - "frequentRpcListDetail": [], - "identities": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "address": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "name": "Account 1" - } - }, - "knownMethodData": {}, - "lostIdentities": {}, - "metaMetricsId": null, - "participateInMetaMetrics": false, - "preferences": { - "useNativeCurrencyAsPrimaryCurrency": true - }, - "selectedAddress": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "suggestedTokens": {}, - "tokens": [], - "useBlockie": false, - "useNonceField": false, - "usePhishDetect": true - }, - "MetaMetricsController": { - "fragments": { - "transaction-added-4046084157914634": { - "category": "Transactions", - "initialEvent": "Transaction Added", - "successEvent": "Transaction Approved", - "failureEvent": "Transaction Rejected", - "properties": {}, - "persist": true, - "uniqueIdentifier": "transaction-added-4046084157914634" - } - } - }, - "TransactionController": { - "transactions": { - "4046084157914634": { - "chainId": "0x539", - "primaryTransaction": { - "chainId": "0x539", - "id": 4046084157914634, - "loadingDefaults": true, - "metamaskNetworkId": "1337", - "origin": "metamask", - "status": "unapproved", - "time": 1617228030067, - "txParams": { - "from": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "gas": "0x61a8", - "gasPrice": "0x2540be400", - "to": "0x2f318C334780961FB129D2a6c30D0763d9a5C970", - "value": "0xde0b6b3a7640000" - }, - "type": "sentEther" - }, - "history": [ - { - "chainId": "0x539", - "id": 4046084157914634, - "loadingDefaults": true, - "metamaskNetworkId": "1337", - "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": 4046084157914634, - "loadingDefaults": false, - "metamaskNetworkId": "1337", - "origin": "metamask", - "status": "unapproved", - "time": 1617228030067, - "txParams": { - "from": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "gas": "0x61a8", - "gasPrice": "0x2540be400", - "to": "0x2f318C334780961FB129D2a6c30D0763d9a5C970", - "value": "0xde0b6b3a7640000" - }, - "type": "simpleSend" - } - } - }, - "config": {}, - "firstTimeInfo": { - "date": 1575697234195, - "version": "7.7.0" - } - }, - "meta": { - "version": 40 - } -} diff --git a/test/e2e/fixtures/special-settings/state.json b/test/e2e/fixtures/special-settings/state.json deleted file mode 100644 index 64e2d023e..000000000 --- a/test/e2e/fixtures/special-settings/state.json +++ /dev/null @@ -1,158 +0,0 @@ -{ - "data": { - "AppStateController": { - "mkrMigrationReminderTimestamp": null, - "showPortfolioTooltip": false - }, - "CachedBalancesController": { - "cachedBalances": { - "4": {} - } - }, - "CurrencyController": { - "conversionDate": 1575697244.188, - "conversionRate": 149.61, - "currentCurrency": "usd", - "nativeCurrency": "ETH" - }, - "IncomingTransactionsController": { - "incomingTransactions": {}, - "incomingTxLastFetchedBlocksByNetwork": { - "goerli": null, - "mainnet": null, - "sepolia": null - } - }, - "KeyringController": { - "vault": "{\"data\":\"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT\",\"iv\":\"FbeHDAW5afeWNORfNJBR0Q==\",\"salt\":\"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8=\"}" - }, - "NetworkController": { - "network": "1337", - "provider": { - "nickname": "Localhost 8545", - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "ticker": "ETH", - "type": "rpc" - } - }, - "NotificationController": { - "notifications": { - "1": { - "isShown": true - }, - "3": { - "isShown": true - }, - "5": { - "isShown": true - }, - "6": { - "isShown": true - }, - "8": { - "isShown": true - }, - "10": { - "isShown": true - }, - "11": { - "isShown": true - }, - "12": { - "isShown": true - }, - "14": { - "isShown": true - }, - "15": { - "isShown": true - } - } - }, - "OnboardingController": { - "onboardingTabs": {}, - "seedPhraseBackedUp": false - }, - "PermissionsMetadata": { - "domainMetadata": { - "metamask.github.io": { - "icon": null, - "name": "M E T A M A S K M E S H T E S T" - } - }, - "permissionsHistory": {}, - "permissionsLog": [ - { - "id": 746677923, - "method": "eth_accounts", - "methodType": "restricted", - "origin": "metamask.github.io", - "request": { - "id": 746677923, - "jsonrpc": "2.0", - "method": "eth_accounts", - "origin": "metamask.github.io", - "params": [] - }, - "requestTime": 1575697241368, - "response": { - "id": 746677923, - "jsonrpc": "2.0", - "result": [] - }, - "responseTime": 1575697241370, - "success": true - } - ] - }, - "PreferencesController": { - "accountTokens": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "goerli": [], - "sepolia": [] - } - }, - "assetImages": {}, - "completedOnboarding": true, - "dismissSeedBackUpReminder": true, - "currentLocale": "en", - "featureFlags": { - "showIncomingTransactions": true, - "transactionTime": false, - "sendHexData": true - }, - "firstTimeFlowType": "create", - "forgottenPassword": false, - "frequentRpcListDetail": [], - "identities": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "address": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "name": "Account 1" - } - }, - "knownMethodData": {}, - "lostIdentities": {}, - "metaMetricsId": null, - "participateInMetaMetrics": false, - "preferences": { - "useNativeCurrencyAsPrimaryCurrency": true - }, - "selectedAddress": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "suggestedTokens": {}, - "tokens": [], - "useBlockie": false, - "useNonceField": false, - "usePhishDetect": true, - "useTokenDetection": false - }, - "config": {}, - "firstTimeInfo": { - "date": 1575697234195, - "version": "7.7.0" - } - }, - "meta": { - "version": 40 - } -} diff --git a/test/e2e/fixtures/threebox-enabled/state.json b/test/e2e/fixtures/threebox-enabled/state.json deleted file mode 100644 index 7b9027fcc..000000000 --- a/test/e2e/fixtures/threebox-enabled/state.json +++ /dev/null @@ -1,155 +0,0 @@ -{ - "data": { - "AppStateController": { - "swapsWelcomeMessageHasBeenShown": true, - "connectedStatusPopoverHasBeenShown": false, - "showPortfolioTooltip": false - }, - "CachedBalancesController": { - "cachedBalances": { - "0x539": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": "0x15af1d78b58c40000" - } - } - }, - "CurrencyController": { - "conversionDate": 1617897791.928, - "conversionRate": 2072.49, - "currentCurrency": "usd", - "nativeCurrency": "ETH", - "usdConversionRate": 2072.49 - }, - "IncomingTransactionsController": { - "incomingTransactions": {}, - "incomingTxLastFetchedBlockByChainId": { - "0xaa36a7": null, - "0x1": null, - "0x5": 5570536 - } - }, - "KeyringController": { - "vault": "{\"data\":\"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT\",\"iv\":\"FbeHDAW5afeWNORfNJBR0Q==\",\"salt\":\"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8=\"}" - }, - "NetworkController": { - "provider": { - "nickname": "Localhost 8545", - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "ticker": "ETH", - "type": "rpc" - }, - "previousProviderStore": { - "nickname": "Localhost 8545", - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "ticker": "ETH", - "type": "rpc" - }, - "network": "1337" - }, - "NotificationController": { - "notifications": { - "1": { - "isShown": true - }, - "3": { - "isShown": true - }, - "5": { - "isShown": true - }, - "6": { - "isShown": true - }, - "8": { - "isShown": true - }, - "10": { - "isShown": true - }, - "11": { - "isShown": true - }, - "12": { - "isShown": true - }, - "14": { - "isShown": true - }, - "15": { - "isShown": true - } - } - }, - "OnboardingController": { - "onboardingTabs": {}, - "seedPhraseBackedUp": true - }, - "PreferencesController": { - "frequentRpcListDetail": [ - { - "rpcUrl": "http://localhost:8545", - "chainId": "0x539", - "ticker": "ETH", - "nickname": "Localhost 8545", - "rpcPrefs": {} - } - ], - "accountTokens": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "0x5": [], - "0xaa36a7": [] - } - }, - "accountHiddenTokens": {}, - "assetImages": {}, - "tokens": [], - "hiddenTokens": [], - "suggestedTokens": {}, - "useBlockie": true, - "useNonceField": false, - "usePhishDetect": true, - "featureFlags": { - "showIncomingTransactions": true, - "transactionTime": false - }, - "knownMethodData": {}, - "firstTimeFlowType": "create", - "currentLocale": "en", - "identities": { - "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { - "address": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", - "name": "Account 1" - } - }, - "lostIdentities": {}, - "forgottenPassword": false, - "preferences": { - "useNativeCurrencyAsPrimaryCurrency": true - }, - "completedOnboarding": true, - "ipfsGateway": "dweb.link", - "selectedAddress": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1" - }, - "config": {}, - "firstTimeInfo": { - "date": 1575697234195, - "version": "7.7.0" - }, - "MetaMetricsController": { - "metaMetricsId": null, - "participateInMetaMetrics": false - }, - "ThreeBoxController": { - "threeBoxSyncingAllowed": true, - "showRestorePrompt": true, - "threeBoxLastUpdated": 0, - "threeBoxAddress": "0x64480aa2768ef12f3f19c5a01206ceb0f82d06b9", - "threeBoxSynced": true, - "threeBoxDisabled": false - } - }, - "meta": { - "version": 57 - } -} diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index 6dadb1e23..b3f74418a 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -73,7 +73,7 @@ async function withFixtures(options, testSuite) { }); } await fixtureServer.start(); - await fixtureServer.loadState(path.join(__dirname, 'fixtures', fixtures)); + fixtureServer.loadJsonState(fixtures); await phishingPageServer.start(); if (dapp) { if (dappOptions?.numberOfDapps) { @@ -198,26 +198,6 @@ const getWindowHandles = async (driver, handlesCount) => { return { extension, dapp, popup }; }; -const connectDappWithExtensionPopup = async (driver) => { - await driver.openNewPage(`http://127.0.0.1:${dappBasePort}/`); - await driver.delay(regularDelayMs); - await driver.clickElement({ text: 'Connect', tag: 'button' }); - await driver.delay(regularDelayMs); - - const windowHandles = await getWindowHandles(driver, 3); - - // open extension popup and confirm connect - await driver.switchToWindow(windowHandles.popup); - await driver.delay(largeDelayMs); - await driver.clickElement({ text: 'Next', tag: 'button' }); - await driver.clickElement({ text: 'Connect', tag: 'button' }); - - // send from dapp - await driver.waitUntilXWindowHandles(2); - await driver.switchToWindow(windowHandles.dapp); - await driver.delay(regularDelayMs); -}; - const completeImportSRPOnboardingFlow = async ( driver, seedPhrase, @@ -333,7 +313,6 @@ module.exports = { largeDelayMs, veryLargeDelayMs, withFixtures, - connectDappWithExtensionPopup, completeImportSRPOnboardingFlow, completeImportSRPOnboardingFlowWordByWord, createDownloadFolder, diff --git a/test/e2e/fixtures/import-utc-json/test-json-import-account-file.json b/test/e2e/import-utc-json/test-json-import-account-file.json similarity index 100% rename from test/e2e/fixtures/import-utc-json/test-json-import-account-file.json rename to test/e2e/import-utc-json/test-json-import-account-file.json diff --git a/test/e2e/lavamoat-stats.js b/test/e2e/lavamoat-stats.js index 4abf00a68..2dcf83ac2 100755 --- a/test/e2e/lavamoat-stats.js +++ b/test/e2e/lavamoat-stats.js @@ -7,41 +7,45 @@ const yargs = require('yargs/yargs'); const { hideBin } = require('yargs/helpers'); const { exitWithError } = require('../../development/lib/exit-with-error'); const { withFixtures, tinyDelayMs } = require('./helpers'); +const FixtureBuilder = require('./fixture-builder'); async function measurePage() { let metrics; try { - await withFixtures({ fixtures: 'imported-account' }, async ({ driver }) => { - await driver.delay(tinyDelayMs); - await driver.navigate(); - await driver.findElement('#password'); - await driver.delay(1000); - const logs = await driver.checkBrowserForLavamoatLogs(); - - let logString = ''; - let inObject = false; - - const parsedLogs = []; - - logs.forEach((log) => { - if (log.indexOf('"version": 1') >= 0) { - logString += log; - parsedLogs.push(`{${logString}}`); - logString = ''; - inObject = false; - } else if (inObject) { - logString += log; - } else if ( - log.search(/"name": ".*app\/scripts\/background.js",/u) >= 0 || - log.search(/"name": ".*app\/scripts\/ui.js",/u) >= 0 - ) { - logString += log; - inObject = true; - } - }); - - metrics = parsedLogs.map((pl) => JSON.parse(pl)); - }); + await withFixtures( + { fixtures: new FixtureBuilder().build() }, + async ({ driver }) => { + await driver.delay(tinyDelayMs); + await driver.navigate(); + await driver.findElement('#password'); + await driver.delay(1000); + const logs = await driver.checkBrowserForLavamoatLogs(); + + let logString = ''; + let inObject = false; + + const parsedLogs = []; + + logs.forEach((log) => { + if (log.indexOf('"version": 1') >= 0) { + logString += log; + parsedLogs.push(`{${logString}}`); + logString = ''; + inObject = false; + } else if (inObject) { + logString += log; + } else if ( + log.search(/"name": ".*app\/scripts\/background.js",/u) >= 0 || + log.search(/"name": ".*app\/scripts\/ui.js",/u) >= 0 + ) { + logString += log; + inObject = true; + } + }); + + metrics = parsedLogs.map((pl) => JSON.parse(pl)); + }, + ); } catch (error) { // do nothing } diff --git a/test/e2e/mock-3box/threebox-mock-server.js b/test/e2e/mock-3box/threebox-mock-server.js deleted file mode 100644 index e6308bada..000000000 --- a/test/e2e/mock-3box/threebox-mock-server.js +++ /dev/null @@ -1,57 +0,0 @@ -const http = require('http'); - -const PORT = 8889; - -class ThreeboxMockServer { - constructor() { - this.server = http.createServer(this.requestHandler); - this.database = {}; - } - - async start() { - return new Promise((resolve, reject) => { - this.server = this.server.listen(PORT); - this.server.once('error', reject); - this.server.once('listening', resolve); - }); - } - - async stop() { - if (!this.server) { - return; - } - - await new Promise((resolve, reject) => { - this.server.close(); - this.server.once('error', reject); - this.server.once('close', resolve); - }); - } - - requestHandler = (request, response) => { - response.setHeader('Content-Type', 'application/json'); - if (request.method === 'POST') { - let body = ''; - request.on('data', (chunk) => { - body += chunk.toString(); // convert Buffer to string - }); - request.on('end', () => { - const { key, data } = JSON.parse(body); - this.database[key] = data; - response.setHeader('Access-Control-Allow-Headers', '*'); - response.end('ok'); - }); - } else if (request.method === 'GET') { - const key = new URL(request.url, 'https://example.org/').searchParams.get( - 'key', - ); - - response.setHeader('Access-Control-Allow-Headers', '*'); - response.end(JSON.stringify(this.database[key] || '')); - } else { - response.end('unknown request'); - } - }; -} - -module.exports = ThreeboxMockServer; diff --git a/test/e2e/mock-e2e.js b/test/e2e/mock-e2e.js index f1975fbdc..a6cd0a70d 100644 --- a/test/e2e/mock-e2e.js +++ b/test/e2e/mock-e2e.js @@ -189,19 +189,10 @@ async function setupMocking(server, testSpecificMock) { }; }); + // It disables loading of token icons, e.g. this URL: https://static.metaswap.codefi.network/api/v1/tokenIcons/1337/0x0000000000000000000000000000000000000000.png await server .forGet( - 'https://static.metaswap.codefi.network/api/v1/tokenIcons/1337/0x0d8775f648430679a709e98d2b0cb6250d2887ef.png', - ) - .thenCallback(() => { - return { - statusCode: 200, - }; - }); - - await server - .forGet( - 'https://static.metaswap.codefi.network/api/v1/tokenIcons/1337/0x2efa2cb29c2341d8e5ba7d3262c9e9d6f1bf3711.png', + /^https:\/\/static\.metaswap\.codefi\.network\/api\/v1\/tokenIcons\/1337\/.*\.png/u, ) .thenCallback(() => { return { diff --git a/test/e2e/mv3-perf-stats/init-load-stats.js b/test/e2e/mv3-perf-stats/init-load-stats.js index de5194031..f9975557d 100755 --- a/test/e2e/mv3-perf-stats/init-load-stats.js +++ b/test/e2e/mv3-perf-stats/init-load-stats.js @@ -12,6 +12,7 @@ const { getFirstParentDirectoryThatExists, } = require('../../helpers/file'); const { withFixtures, tinyDelayMs } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); /** * The e2e test case is used to capture load and initialisation time statistics for extension in MV3 environment. @@ -20,42 +21,45 @@ const { withFixtures, tinyDelayMs } = require('../helpers'); async function profilePageLoad() { const parsedLogs = {}; try { - await withFixtures({ fixtures: 'imported-account' }, async ({ driver }) => { - await driver.delay(tinyDelayMs); - await driver.navigate(); - await driver.delay(1000); - const logs = await driver.checkBrowserForLavamoatLogs(); + await withFixtures( + { fixtures: new FixtureBuilder().build() }, + async ({ driver }) => { + await driver.delay(tinyDelayMs); + await driver.navigate(); + await driver.delay(1000); + const logs = await driver.checkBrowserForLavamoatLogs(); - let logString = ''; - let logType = ''; + let logString = ''; + let logType = ''; - logs.forEach((log) => { - if (log.indexOf('"version": 1') >= 0) { - // log end here - logString += log; - parsedLogs[logType] = JSON.parse(`{${logString}}`); - logString = ''; - logType = ''; - } else if (logType) { - // log string continues - logString += log; - } else if ( - log.search(/"name": ".*app\/scripts\/background.js",/u) >= 0 - ) { - // background log starts - logString += log; - logType = 'background'; - } else if (log.search(/"name": ".*app\/scripts\/ui.js",/u) >= 0) { - // ui log starts - logString += log; - logType = 'ui'; - } else if (log.search(/"name": "Total"/u) >= 0) { - // load time log starts - logString += log; - logType = 'loadTime'; - } - }); - }); + logs.forEach((log) => { + if (log.indexOf('"version": 1') >= 0) { + // log end here + logString += log; + parsedLogs[logType] = JSON.parse(`{${logString}}`); + logString = ''; + logType = ''; + } else if (logType) { + // log string continues + logString += log; + } else if ( + log.search(/"name": ".*app\/scripts\/background.js",/u) >= 0 + ) { + // background log starts + logString += log; + logType = 'background'; + } else if (log.search(/"name": ".*app\/scripts\/ui.js",/u) >= 0) { + // ui log starts + logString += log; + logType = 'ui'; + } else if (log.search(/"name": "Total"/u) >= 0) { + // load time log starts + logString += log; + logType = 'loadTime'; + } + }); + }, + ); } catch (error) { console.log('Error in trying to parse logs.'); } diff --git a/test/e2e/mv3-stats.js b/test/e2e/mv3-stats.js index 8e8180e02..2dd24791e 100755 --- a/test/e2e/mv3-stats.js +++ b/test/e2e/mv3-stats.js @@ -12,6 +12,7 @@ const { getFirstParentDirectoryThatExists, } = require('../helpers/file'); const { withFixtures, tinyDelayMs } = require('./helpers'); +const FixtureBuilder = require('./fixture-builder'); /** * The e2e test case is used to capture load and initialisation time statistics for extension in MV3 environment. @@ -20,42 +21,45 @@ const { withFixtures, tinyDelayMs } = require('./helpers'); async function profilePageLoad() { const parsedLogs = {}; try { - await withFixtures({ fixtures: 'imported-account' }, async ({ driver }) => { - await driver.delay(tinyDelayMs); - await driver.navigate(); - await driver.delay(1000); - const logs = await driver.checkBrowserForLavamoatLogs(); + await withFixtures( + { fixtures: new FixtureBuilder().build() }, + async ({ driver }) => { + await driver.delay(tinyDelayMs); + await driver.navigate(); + await driver.delay(1000); + const logs = await driver.checkBrowserForLavamoatLogs(); - let logString = ''; - let logType = ''; + let logString = ''; + let logType = ''; - logs.forEach((log) => { - if (log.indexOf('"version": 1') >= 0) { - // log end here - logString += log; - parsedLogs[logType] = JSON.parse(`{${logString}}`); - logString = ''; - logType = ''; - } else if (logType) { - // log string continues - logString += log; - } else if ( - log.search(/"name": ".*app\/scripts\/background.js",/u) >= 0 - ) { - // background log starts - logString += log; - logType = 'background'; - } else if (log.search(/"name": ".*app\/scripts\/ui.js",/u) >= 0) { - // ui log starts - logString += log; - logType = 'ui'; - } else if (log.search(/"name": "Total"/u) >= 0) { - // load time log starts - logString += log; - logType = 'loadTime'; - } - }); - }); + logs.forEach((log) => { + if (log.indexOf('"version": 1') >= 0) { + // log end here + logString += log; + parsedLogs[logType] = JSON.parse(`{${logString}}`); + logString = ''; + logType = ''; + } else if (logType) { + // log string continues + logString += log; + } else if ( + log.search(/"name": ".*app\/scripts\/background.js",/u) >= 0 + ) { + // background log starts + logString += log; + logType = 'background'; + } else if (log.search(/"name": ".*app\/scripts\/ui.js",/u) >= 0) { + // ui log starts + logString += log; + logType = 'ui'; + } else if (log.search(/"name": "Total"/u) >= 0) { + // load time log starts + logString += log; + logType = 'loadTime'; + } + }); + }, + ); } catch (error) { console.log('Error in trying to parse logs.'); } diff --git a/test/e2e/restore/MetaMaskUserData.json b/test/e2e/restore/MetaMaskUserData.json new file mode 100644 index 000000000..abea11e14 --- /dev/null +++ b/test/e2e/restore/MetaMaskUserData.json @@ -0,0 +1,50 @@ +{ + "addressBook": { + "addressBook": { + "0x539": { + "0x0c54FcCd2e384b4BB6f2E405Bf5Cbc15a017AaFb": { + "address": "0x0c54FcCd2e384b4BB6f2E405Bf5Cbc15a017AaFb", + "chainId": "0x539", + "isEns": false, + "memo": "", + "name": "Test Account" + } + } + } + }, + "preferences": { + "advancedGasFee": null, + "currentLocale": "en", + "dismissSeedBackUpReminder": true, + "featureFlags": { + "showIncomingTransactions": true + }, + "forgottenPassword": false, + "frequentRpcListDetail": [ + { + "chainId": "0x539", + "nickname": "Localhost 8545", + "rpcPrefs": {}, + "rpcUrl": "http://localhost:8545", + "ticker": "ETH" + } + ], + "infuraBlocked": false, + "ipfsGateway": "dweb.link", + "knownMethodData": {}, + "ledgerTransportType": "webhid", + "openSeaEnabled": false, + "preferences": { + "hideZeroBalanceTokens": false, + "showFiatInTestnets": false, + "showTestNetworks": false, + "useNativeCurrencyAsPrimaryCurrency": true + }, + "theme": "light", + "useBlockie": false, + "useCollectibleDetection": false, + "useNonceField": false, + "usePhishDetect": true, + "useTokenDetection": false + } +} diff --git a/test/e2e/run-all.js b/test/e2e/run-all.js index 70e184652..2623f9ba9 100644 --- a/test/e2e/run-all.js +++ b/test/e2e/run-all.js @@ -5,6 +5,14 @@ const { hideBin } = require('yargs/helpers'); const { runInShell } = require('../../development/lib/run-command'); const { exitWithError } = require('../../development/lib/exit-with-error'); +const getTestPathsForTestDir = async (testDir) => { + const testFilenames = await fs.readdir(testDir); + const testPaths = testFilenames.map((filename) => + path.join(testDir, filename), + ); + return testPaths; +}; + async function main() { const { argv } = yargs(hideBin(process.argv)) .usage( @@ -38,13 +46,14 @@ async function main() { testDir = path.join(__dirname, 'snaps'); } - const testFilenames = await fs.readdir(testDir); - const testPaths = testFilenames.map((filename) => - path.join(testDir, filename), - ); + let testPaths = await getTestPathsForTestDir(testDir); if (!snaps) { - testPaths.push(path.join(__dirname, 'metamask-ui.spec.js')); + testPaths = [ + ...testPaths, + ...(await getTestPathsForTestDir(path.join(__dirname, 'swaps'))), + path.join(__dirname, 'metamask-ui.spec.js'), + ]; } const runE2eTestPath = path.join(__dirname, 'run-e2e-test.js'); diff --git a/test/e2e/snaps/enums.js b/test/e2e/snaps/enums.js index 7df5887ba..d18f41755 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/test-snaps/3.0.1', + TEST_SNAPS_WEBSITE_URL: 'https://metamask.github.io/test-snaps/3.1.0', }; diff --git a/test/e2e/snaps/test-snap-bip-32.spec.js b/test/e2e/snaps/test-snap-bip-32.spec.js new file mode 100644 index 000000000..b179461e7 --- /dev/null +++ b/test/e2e/snaps/test-snap-bip-32.spec.js @@ -0,0 +1,157 @@ +const { strict: assert } = require('assert'); +const { withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); +const { TEST_SNAPS_WEBSITE_URL } = require('./enums'); + +describe('Test Snap bip-32', function () { + it('tests various functions of bip-32', async function () { + const ganacheOptions = { + accounts: [ + { + secretKey: + '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', + }, + ], + }; + await withFixtures( + { + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToSnapDapp() + .build(), + ganacheOptions, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + + // enter pw into extension + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + // navigate to test snaps page and connect + await driver.driver.get(TEST_SNAPS_WEBSITE_URL); + await driver.delay(1000); + + // find and scroll to the correct card and click first + const snapButton = await driver.findElement('#sendUpdateHello'); + await driver.scrollToElement(snapButton); + await driver.delay(500); + await driver.fill('#snapId6', 'npm:@metamask/test-snap-bip32'); + await driver.clickElement('#connectBip32'); + + // approve install of snap + await driver.waitUntilXWindowHandles(2, 5000, 10000); + let windowHandles = await driver.getAllWindowHandles(); + await driver.switchToWindowWithTitle( + 'MetaMask Notification', + windowHandles, + ); + await driver.clickElement({ + text: 'Approve & install', + tag: 'button', + }); + + // wait for permissions popover, click checkboxes and confirm + await driver.delay(1000); + await driver.clickElement('#key-access-bip32-m-44h-0h-secp256k1-0'); + await driver.clickElement('#key-access-bip32-m-44h-0h-ed25519-0'); + await driver.clickElement({ + text: 'Confirm', + tag: 'button', + }); + + // switch back to test-snaps window + await driver.waitUntilXWindowHandles(1, 5000, 10000); + windowHandles = await driver.getAllWindowHandles(); + await driver.switchToWindowWithTitle('Test Snaps', windowHandles); + + // wait then run SECP256K1 test + await driver.delay(1000); + await driver.fill('#bip32SignMessage', 'foo bar'); + await driver.clickElement('#sendBip32Secp256k1'); + + // hit 'approve' on the custom confirm + await driver.waitUntilXWindowHandles(2, 5000, 10000); + windowHandles = await driver.getAllWindowHandles(); + await driver.switchToWindowWithTitle( + 'MetaMask Notification', + windowHandles, + ); + await driver.clickElement({ + text: 'Approve', + tag: 'button', + }); + + await driver.waitUntilXWindowHandles(1, 5000, 10000); + windowHandles = await driver.getAllWindowHandles(); + await driver.switchToWindowWithTitle('Test Snaps', windowHandles); + + // check result + await driver.delay(1000); + const secp256k1Result = await driver.findElement( + '#bip32Secp256k1Result', + ); + assert.equal( + await secp256k1Result.getText(), + 'Signature: "0xd30561eb9e3195e47d49198fb0bc66eda867a7dff4c5e8b60c2ec13851aa7d8cc3d485da177de63dad331f315d440cbb693a629efe228389c4693ea90465b101"', + ); + + // wait then run ed25519 test + await driver.delay(1000); + await driver.clickElement('#sendBip32Ed25519'); + + // hit 'approve' on the custom confirm + await driver.waitUntilXWindowHandles(2, 5000, 10000); + windowHandles = await driver.getAllWindowHandles(); + await driver.switchToWindowWithTitle( + 'MetaMask Notification', + windowHandles, + ); + await driver.clickElement({ + text: 'Approve', + tag: 'button', + }); + + await driver.waitUntilXWindowHandles(1, 5000, 10000); + windowHandles = await driver.getAllWindowHandles(); + await driver.switchToWindowWithTitle('Test Snaps', windowHandles); + + // check result + await driver.delay(1000); + const ed25519Result = await driver.findElement('#bip32Ed25519Result'); + assert.equal( + await ed25519Result.getText(), + 'Signature: "0xf3215b4d6c59aac7e01b4ceef530d1e2abf4857926b85a81aaae3894505699243768a887b7da4a8c2e0f25196196ba290b6531050db8dc15c252bdd508532a0a"', + ); + + const publicKeyButton = await driver.findElement('#sendBip32PublicKey'); + await driver.scrollToElement(publicKeyButton); + // wait then run public key test + await driver.delay(1000); + await driver.clickElement('#sendBip32PublicKey'); + // check result + await driver.delay(1000); + const publicKeyResult = await driver.findElement( + '#bip32PublicKeyResult', + ); + assert.equal( + await publicKeyResult.getText(), + 'Public key: "043e98d696ae15caef75fa8dd204a7c5c08d1272b2218ba3c20feeb4c691eec366606ece56791c361a2320e7fad8bcbb130f66d51c591fc39767ab2856e93f8dfb"', + ); + + // wait then run compressed public key test + await driver.delay(1000); + await driver.clickElement('#sendBip32CompressedPublicKey'); + // check result + await driver.delay(1000); + const compressedPublicKeyResult = await driver.findElement( + '#bip32CompressedPublicKeyResult', + ); + assert.equal( + await compressedPublicKeyResult.getText(), + 'Public key: "033e98d696ae15caef75fa8dd204a7c5c08d1272b2218ba3c20feeb4c691eec366"', + ); + }, + ); + }); +}); diff --git a/test/e2e/snaps/test-snap-bip-44.spec.js b/test/e2e/snaps/test-snap-bip-44.spec.js index 448557aff..ce617a350 100644 --- a/test/e2e/snaps/test-snap-bip-44.spec.js +++ b/test/e2e/snaps/test-snap-bip-44.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); const { TEST_SNAPS_WEBSITE_URL } = require('./enums'); describe('Test Snap bip-44', function () { @@ -15,7 +16,9 @@ describe('Test Snap bip-44', function () { }; await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToSnapDapp() + .build(), ganacheOptions, title: this.test.title, }, @@ -31,34 +34,16 @@ describe('Test Snap bip-44', function () { await driver.delay(1000); await driver.fill('#snapId3', 'npm:@metamask/test-snap-bip44'); - // reveal snapId3 by finding and scrolling to #snapId4 - const snapButton = await driver.findElement('#snapId4'); + const snapButton = await driver.findElement('#snapId3'); await driver.scrollToElement(snapButton); await driver.delay(500); // connect the snap await driver.clickElement('#connectBip44'); - // switch to metamask extension and click connect - await driver.waitUntilXWindowHandles(2, 5000, 10000); - let windowHandles = await driver.getAllWindowHandles(); - await driver.switchToWindowWithTitle( - 'MetaMask Notification', - windowHandles, - ); - await driver.clickElement( - { - text: 'Connect', - tag: 'button', - }, - 10000, - ); - - await driver.delay(2000); - // approve install of snap await driver.waitUntilXWindowHandles(2, 5000, 10000); - windowHandles = await driver.getAllWindowHandles(); + let windowHandles = await driver.getAllWindowHandles(); await driver.switchToWindowWithTitle( 'MetaMask Notification', windowHandles, @@ -67,9 +52,10 @@ describe('Test Snap bip-44', function () { text: 'Approve & install', tag: 'button', }); + // deal with permissions popover await driver.delay(1000); - await driver.press('#key-access-bip44-1-0', driver.Key.SPACE); + await driver.clickElement('#key-access-bip44-1-0'); await driver.clickElement({ text: 'Confirm', tag: 'button', @@ -87,7 +73,7 @@ describe('Test Snap bip-44', function () { const bip44Result = await driver.findElement('#bip44Result'); assert.equal( await bip44Result.getText(), - 'Public key: "0x86debb44fb3a984d93f326131d4c1db0bc39644f1a67b673b3ab45941a1cea6a385981755185ac4594b6521e4d1e8d1"', + 'Public key: "0x86debb44fb3a984d93f326131d4c1db0bc39644f1a67b673b3ab45941a1cea6a385981755185ac4594b6521e4d1e08d1"', ); }, ); diff --git a/test/e2e/snaps/test-snap-confirm.spec.js b/test/e2e/snaps/test-snap-confirm.spec.js index c6a35657a..9d85977df 100644 --- a/test/e2e/snaps/test-snap-confirm.spec.js +++ b/test/e2e/snaps/test-snap-confirm.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); const { TEST_SNAPS_WEBSITE_URL } = require('./enums'); describe('Test Snap Confirm', function () { @@ -15,7 +16,9 @@ describe('Test Snap Confirm', function () { }; await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToSnapDapp() + .build(), ganacheOptions, title: this.test.title, }, @@ -31,26 +34,9 @@ describe('Test Snap Confirm', function () { await driver.fill('#snapId1', 'npm:@metamask/test-snap-confirm'); await driver.clickElement('#connectHello'); - // switch to metamask extension and click connect - await driver.waitUntilXWindowHandles(2, 5000, 10000); - let windowHandles = await driver.getAllWindowHandles(); - await driver.switchToWindowWithTitle( - 'MetaMask Notification', - windowHandles, - ); - await driver.clickElement( - { - text: 'Connect', - tag: 'button', - }, - 10000, - ); - - await driver.delay(2000); - // approve install of snap await driver.waitUntilXWindowHandles(2, 5000, 10000); - windowHandles = await driver.getAllWindowHandles(); + let windowHandles = await driver.getAllWindowHandles(); await driver.switchToWindowWithTitle( 'MetaMask Notification', windowHandles, @@ -64,6 +50,10 @@ describe('Test Snap Confirm', function () { await driver.waitUntilXWindowHandles(1, 5000, 10000); windowHandles = await driver.getAllWindowHandles(); await driver.switchToWindowWithTitle('Test Snaps', windowHandles); + + const snapButton = await driver.findElement('#sendConfirmButton'); + await driver.scrollToElement(snapButton); + await driver.delay(1000); await driver.clickElement('#sendConfirmButton'); diff --git a/test/e2e/snaps/test-snap-error.spec.js b/test/e2e/snaps/test-snap-error.spec.js index 177184727..337b932df 100644 --- a/test/e2e/snaps/test-snap-error.spec.js +++ b/test/e2e/snaps/test-snap-error.spec.js @@ -1,6 +1,7 @@ const { strict: assert } = require('assert'); const { withFixtures } = require('../helpers'); const { PAGES } = require('../webdriver/driver'); +const FixtureBuilder = require('../fixture-builder'); const { TEST_SNAPS_WEBSITE_URL } = require('./enums'); describe('Test Snap Error', function () { @@ -16,7 +17,9 @@ describe('Test Snap Error', function () { }; await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToSnapDapp() + .build(), ganacheOptions, title: this.test.title, }, @@ -30,27 +33,15 @@ describe('Test Snap Error', function () { // navigate to test snaps page and connect await driver.driver.get(TEST_SNAPS_WEBSITE_URL); await driver.fill('#snapId2', 'npm:@metamask/test-snap-error'); - await driver.clickElement('#connectError'); - // switch to metamask extension and click connect - await driver.waitUntilXWindowHandles(2, 5000, 10000); - let windowHandles = await driver.getAllWindowHandles(); - await driver.switchToWindowWithTitle( - 'MetaMask Notification', - windowHandles, - ); - await driver.clickElement( - { - text: 'Connect', - tag: 'button', - }, - 10000, - ); + const snapButton = await driver.findElement('#connectError'); + await driver.scrollToElement(snapButton); + await driver.delay(500); - await driver.delay(2000); + await driver.clickElement('#connectError'); // approve install of snap - windowHandles = await driver.getAllWindowHandles(); + let windowHandles = await driver.getAllWindowHandles(); await driver.switchToWindowWithTitle( 'MetaMask Notification', windowHandles, diff --git a/test/e2e/snaps/test-snap-get-snaps.spec.js b/test/e2e/snaps/test-snap-get-snaps.spec.js new file mode 100644 index 000000000..8de5cadbb --- /dev/null +++ b/test/e2e/snaps/test-snap-get-snaps.spec.js @@ -0,0 +1,92 @@ +const { strict: assert } = require('assert'); +const { withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); +const { TEST_SNAPS_WEBSITE_URL } = require('./enums'); + +describe('Test Snap Confirm', function () { + it('can pop up a snap confirm and get its result', async function () { + const ganacheOptions = { + accounts: [ + { + secretKey: + '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', + balance: 25000000000000000000, + }, + ], + }; + await withFixtures( + { + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToSnapDapp() + .build(), + ganacheOptions, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + + // enter pw into extension + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + // navigate to test snaps page and connect + await driver.driver.get(TEST_SNAPS_WEBSITE_URL); + await driver.fill('#snapId1', 'npm:@metamask/test-snap-confirm'); + await driver.clickElement('#connectHello'); + + // approve install of snap + await driver.waitUntilXWindowHandles(2, 5000, 10000); + let windowHandles = await driver.getAllWindowHandles(); + await driver.switchToWindowWithTitle( + 'MetaMask Notification', + windowHandles, + ); + await driver.clickElement({ + text: 'Approve & install', + tag: 'button', + }); + + // click send inputs on test snap page + await driver.waitUntilXWindowHandles(1, 5000, 10000); + windowHandles = await driver.getAllWindowHandles(); + await driver.switchToWindowWithTitle('Test Snaps', windowHandles); + + const errorButton = await driver.findElement('#connectError'); + await driver.scrollToElement(errorButton); + await driver.delay(1000); + await driver.fill('#snapId2', 'npm:@metamask/test-snap-error'); + await driver.clickElement('#connectError'); + + // approve install of snap + await driver.waitUntilXWindowHandles(2, 5000, 10000); + windowHandles = await driver.getAllWindowHandles(); + await driver.switchToWindowWithTitle( + 'MetaMask Notification', + windowHandles, + ); + await driver.clickElement({ + text: 'Approve & install', + tag: 'button', + }); + + await driver.waitUntilXWindowHandles(1, 5000, 10000); + windowHandles = await driver.getAllWindowHandles(); + await driver.switchToWindowWithTitle('Test Snaps', windowHandles); + + const getInstalledSnapsButton = await driver.findElement( + '#getInstalledSnapsButton', + ); + await driver.scrollToElement(getInstalledSnapsButton); + await driver.delay(1000); + await driver.clickElement('#getInstalledSnapsButton'); + await driver.delay(1000); + + const result = await driver.findElement('#getInstalledSnapsResult'); + assert.equal( + await result.getText(), + 'npm:@metamask/test-snap-confirm, npm:@metamask/test-snap-error', + ); + }, + ); + }); +}); diff --git a/test/e2e/snaps/test-snap-managestate.spec.js b/test/e2e/snaps/test-snap-managestate.spec.js index 06fddda59..58fc36862 100644 --- a/test/e2e/snaps/test-snap-managestate.spec.js +++ b/test/e2e/snaps/test-snap-managestate.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); const { TEST_SNAPS_WEBSITE_URL } = require('./enums'); describe('Test Snap manageState', function () { @@ -16,7 +17,9 @@ describe('Test Snap manageState', function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToSnapDapp() + .build(), ganacheOptions, title: this.test.title, }, @@ -40,25 +43,9 @@ describe('Test Snap manageState', function () { // connect the snap await driver.clickElement('#connectManageState'); - // switch to metamask extension and click connect - await driver.waitUntilXWindowHandles(2, 5000, 10000); - let windowHandles = await driver.getAllWindowHandles(); - await driver.switchToWindowWithTitle( - 'MetaMask Notification', - windowHandles, - ); - await driver.clickElement( - { - text: 'Connect', - tag: 'button', - }, - 10000, - ); - await driver.delay(2000); - // approve install of snap await driver.waitUntilXWindowHandles(2, 5000, 10000); - windowHandles = await driver.getAllWindowHandles(); + let windowHandles = await driver.getAllWindowHandles(); await driver.switchToWindowWithTitle( 'MetaMask Notification', windowHandles, diff --git a/test/e2e/snaps/test-snap-notification.spec.js b/test/e2e/snaps/test-snap-notification.spec.js index 25f7cbe34..ff2002881 100644 --- a/test/e2e/snaps/test-snap-notification.spec.js +++ b/test/e2e/snaps/test-snap-notification.spec.js @@ -1,6 +1,7 @@ const { strict: assert } = require('assert'); const { withFixtures } = require('../helpers'); const { PAGES } = require('../webdriver/driver'); +const FixtureBuilder = require('../fixture-builder'); const { TEST_SNAPS_WEBSITE_URL } = require('./enums'); describe('Test Snap Notification', function () { @@ -16,7 +17,9 @@ describe('Test Snap Notification', function () { }; await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToSnapDapp() + .build(), ganacheOptions, title: this.test.title, }, @@ -40,25 +43,9 @@ describe('Test Snap Notification', function () { // connect the snap await driver.clickElement('#connectNotification'); - // switch to metamask extension and click connect - await driver.waitUntilXWindowHandles(2, 5000, 10000); - let windowHandles = await driver.getAllWindowHandles(); - await driver.switchToWindowWithTitle( - 'MetaMask Notification', - windowHandles, - ); - await driver.clickElement( - { - text: 'Connect', - tag: 'button', - }, - 10000, - ); - await driver.delay(2000); - // approve install of snap await driver.waitUntilXWindowHandles(2, 5000, 10000); - windowHandles = await driver.getAllWindowHandles(); + let windowHandles = await driver.getAllWindowHandles(); await driver.switchToWindowWithTitle( 'MetaMask Notification', windowHandles, diff --git a/test/e2e/snaps/test-snap-update.spec.js b/test/e2e/snaps/test-snap-update.spec.js index 497da3d25..862e95045 100644 --- a/test/e2e/snaps/test-snap-update.spec.js +++ b/test/e2e/snaps/test-snap-update.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); const { TEST_SNAPS_WEBSITE_URL } = require('./enums'); describe('Test Snap update', function () { @@ -15,7 +16,9 @@ describe('Test Snap update', function () { }; await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToSnapDapp() + .build(), ganacheOptions, title: this.test.title, }, @@ -36,30 +39,13 @@ describe('Test Snap update', function () { await driver.fill('#snapId7', 'npm:@metamask/test-snap-confirm'); await driver.clickElement('#connectUpdateOld'); - // switch to metamask extension and click connect - await driver.waitUntilXWindowHandles(3, 5000, 10000); + // approve install of snap let windowHandles = await driver.getAllWindowHandles(); const extensionPage = windowHandles[0]; await driver.switchToWindowWithTitle( 'MetaMask Notification', windowHandles, ); - await driver.clickElement( - { - text: 'Connect', - tag: 'button', - }, - 10000, - ); - - await driver.delay(1000); - - // approve install of snap - windowHandles = await driver.getAllWindowHandles(); - await driver.switchToWindowWithTitle( - 'MetaMask Notification', - windowHandles, - ); await driver.clickElement({ text: 'Approve & install', tag: 'button', diff --git a/test/e2e/swaps/shared.js b/test/e2e/swaps/shared.js new file mode 100644 index 000000000..1a2dc40a3 --- /dev/null +++ b/test/e2e/swaps/shared.js @@ -0,0 +1,71 @@ +const FixtureBuilder = require('../fixture-builder'); + +const ganacheOptions = { + accounts: [ + { + secretKey: + '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', + balance: 25000000000000000000, + }, + ], +}; + +const withFixturesOptions = { + fixtures: new FixtureBuilder().build(), + ganacheOptions, +}; + +const loadSwaps = async (driver) => { + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + await driver.clickElement( + '.wallet-overview__buttons .icon-button:nth-child(3)', + ); +}; + +const buildQuote = async (driver, options) => { + await driver.clickElement( + '[class*="dropdown-search-list"] + div[class*="MuiFormControl-root MuiTextField-root"]', + ); + await driver.fill('input[placeholder*="0"]', options.amount); + await driver.clickElement( + '[class="dropdown-search-list__closed-primary-label dropdown-search-list__select-default"]', + ); + await driver.wait(async () => { + const tokens = await driver.findElements('.searchable-item-list__item'); + return tokens.length > 1; + }); + await driver.clickElement('.searchable-item-list__labels'); + await driver.clickElement('.dropdown-input-pair__to'); + await driver.clickElement('input[data-testid="search-list-items"]'); + await driver.fill( + 'input[data-testid="search-list-items"]', + options.swapTo || options.swapToContractAddress, + ); + if (options.swapTo) { + await driver.wait(async () => { + const tokenNames = await driver.findElements( + '.searchable-item-list__primary-label', + ); + if (tokenNames.length === 0) { + return false; + } + const tokenName = await tokenNames[0].getText(); + return tokenName === options.swapTo; + }); + } + if (options.swapToContractAddress) { + await driver.waitForSelector({ + css: '.searchable-item-list__item button.btn-primary', + text: 'Import', + }); + } + await driver.clickElement('.searchable-item-list__primary-label'); +}; + +module.exports = { + withFixturesOptions, + loadSwaps, + buildQuote, +}; diff --git a/test/e2e/tests/swap-eth.spec.js b/test/e2e/swaps/swap-eth.spec.js similarity index 59% rename from test/e2e/tests/swap-eth.spec.js rename to test/e2e/swaps/swap-eth.spec.js index 771a5e050..d67c258d8 100644 --- a/test/e2e/tests/swap-eth.spec.js +++ b/test/e2e/swaps/swap-eth.spec.js @@ -1,57 +1,21 @@ const { strict: assert } = require('assert'); + const { withFixtures } = require('../helpers'); +const { withFixturesOptions, loadSwaps, buildQuote } = require('./shared'); describe('Swap Eth for another Token', function () { - const ganacheOptions = { - accounts: [ - { - secretKey: - '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', - balance: 25000000000000000000, - }, - ], - }; it('Completes a Swap between Eth and Matic', async function () { await withFixtures( { - fixtures: 'special-settings', - ganacheOptions, + ...withFixturesOptions, title: this.test.title, - failOnConsoleError: false, - driverOptions: { - timeOut: 20000, - }, }, async ({ driver }) => { - await driver.navigate(); - await driver.fill('#password', 'correct horse battery staple'); - await driver.press('#password', driver.Key.ENTER); - await driver.clickElement( - '.wallet-overview__buttons .icon-button:nth-child(3)', - ); - await driver.clickElement( - '[class*="dropdown-search-list"] + div[class*="MuiFormControl-root MuiTextField-root"]', - ); - await driver.fill('input[placeholder*="0"]', '2'); - await driver.clickElement( - '[class*="dropdown-search-list"] + div[class*="MuiFormControl-root MuiTextField-root"]', - ); - await driver.clickElement( - '[class="dropdown-search-list__closed-primary-label dropdown-search-list__select-default"]', - ); - await driver.clickElement( - '[placeholder="Search name or paste address"]', - ); - await driver.fill( - '[placeholder="Search name or paste address"]', - 'DAI', - ); - await driver.waitForSelector( - '[class="searchable-item-list__primary-label"]', - ); - await driver.clickElement( - '[class="searchable-item-list__primary-label"]', - ); + await loadSwaps(driver); + await buildQuote(driver, { + amount: 2, + swapTo: 'DAI', + }); await driver.clickElement({ text: 'Review swap', tag: 'button' }); await driver.waitForSelector('[class*="box--align-items-center"]'); const estimatedEth = await driver.waitForSelector({ diff --git a/test/e2e/swaps/swaps-notifications.spec.js b/test/e2e/swaps/swaps-notifications.spec.js new file mode 100644 index 000000000..07c845f98 --- /dev/null +++ b/test/e2e/swaps/swaps-notifications.spec.js @@ -0,0 +1,130 @@ +const { strict: assert } = require('assert'); + +const { withFixtures } = require('../helpers'); + +const { withFixturesOptions, loadSwaps, buildQuote } = require('./shared'); + +describe('Swaps - notifications', function () { + it('tests notifications for verified token on 1 source and price difference', async function () { + await withFixtures( + { + ...withFixturesOptions, + title: this.test.title, + }, + async ({ driver }) => { + await loadSwaps(driver); + await buildQuote(driver, { + amount: 2, + swapTo: 'INUINU', + }); + const reviewSwapButton = await driver.findElement( + '[data-testid="page-container-footer-next"]', + ); + assert.equal(await reviewSwapButton.getText(), 'Review swap'); + assert.equal(await reviewSwapButton.isEnabled(), false); + const continueButton = await driver.findClickableElement( + '.actionable-message__action-warning', + ); + assert.equal(await continueButton.getText(), 'Continue'); + await continueButton.click(); + assert.equal(await reviewSwapButton.isEnabled(), true); + await reviewSwapButton.click(); + await driver.waitForSelector({ + css: '[class*="box--align-items-center"]', + text: 'Estimated gas fee', + }); + const swapButton = await driver.findElement( + '[data-testid="page-container-footer-next"]', + ); + assert.equal(await swapButton.isEnabled(), false); + await driver.clickElement({ text: 'I understand', tag: 'button' }); + assert.equal(await swapButton.getText(), 'Swap'); + assert.equal(await swapButton.isEnabled(), true); + }, + ); + }); + + it('tests a notification for not enough balance', async function () { + await withFixtures( + { + ...withFixturesOptions, + title: this.test.title, + }, + async ({ driver }) => { + await loadSwaps(driver); + await buildQuote(driver, { + amount: 50, + swapTo: 'USDC', + }); + const reviewSwapButton = await driver.findElement( + '[data-testid="page-container-footer-next"]', + ); + assert.equal(await reviewSwapButton.getText(), 'Review swap'); + assert.equal(await reviewSwapButton.isEnabled(), true); + await reviewSwapButton.click(); + await driver.waitForSelector({ + css: '[class*="box--align-items-center"]', + text: 'Estimated gas fee', + }); + await driver.waitForSelector({ + css: '[class*="actionable-message__message"]', + text: 'You need 43.4467 more TESTETH to complete this swap', + }); + const swapButton = await driver.findElement( + '[data-testid="page-container-footer-next"]', + ); + assert.equal(await swapButton.getText(), 'Swap'); + assert.equal(await swapButton.isEnabled(), false); + }, + ); + }); + + it('tests notifications for verified token on 0 sources and high slippage', async function () { + await withFixtures( + { + ...withFixturesOptions, + title: this.test.title, + }, + async ({ driver }) => { + await loadSwaps(driver); + await buildQuote(driver, { + amount: 2, + swapToContractAddress: '0x72c9Fb7ED19D3ce51cea5C56B3e023cd918baaDf', + }); + await driver.waitForSelector({ + css: '.popover-header__title', + text: 'Import token?', + }); + await driver.clickElement( + '[data-testid="page-container__import-button"]', + ); + const reviewSwapButton = await driver.findElement( + '[data-testid="page-container-footer-next"]', + ); + assert.equal(await reviewSwapButton.isEnabled(), false); + const continueButton = await driver.findClickableElement( + '.actionable-message__action-danger', + ); + assert.equal(await continueButton.getText(), 'Continue'); + await continueButton.click(); + assert.equal(await reviewSwapButton.isEnabled(), true); + await driver.clickElement('[class="slippage-buttons__header-text"]'); + await driver.clickElement({ text: 'custom', tag: 'button' }); + await driver.fill( + 'input[data-testid="slippage-buttons__custom-slippage"]', + '20', + ); + await driver.waitForSelector({ + css: '[class*="slippage-buttons__error-text"]', + text: 'Slippage amount is too high and will result in a bad rate. Please reduce your slippage tolerance to a value below 15%.', + }); + assert.equal(await reviewSwapButton.isEnabled(), false); + await driver.fill( + 'input[data-testid="slippage-buttons__custom-slippage"]', + '4', + ); + assert.equal(await reviewSwapButton.isEnabled(), true); + }, + ); + }); +}); diff --git a/test/e2e/tests/account-details.spec.js b/test/e2e/tests/account-details.spec.js index cfdbdf238..8b8c990f0 100644 --- a/test/e2e/tests/account-details.spec.js +++ b/test/e2e/tests/account-details.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Show account details', function () { const ganacheOptions = { @@ -14,7 +15,7 @@ describe('Show account details', function () { it('should show the QR code for the account', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/add-account.spec.js b/test/e2e/tests/add-account.spec.js index ca9415ac3..5e1c15bd0 100644 --- a/test/e2e/tests/add-account.spec.js +++ b/test/e2e/tests/add-account.spec.js @@ -6,6 +6,7 @@ const { completeImportSRPOnboardingFlow, } = require('../helpers'); const enLocaleMessages = require('../../../app/_locales/en/messages.json'); +const FixtureBuilder = require('../fixture-builder'); describe('Add account', function () { const testSeedPhrase = @@ -24,7 +25,7 @@ describe('Add account', function () { it('should display correct new account name after create', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, @@ -50,7 +51,7 @@ describe('Add account', function () { it('should add the same account addresses when a secret recovery phrase is imported, the account is locked, and the same secret recovery phrase is imported again', async function () { await withFixtures( { - fixtures: 'onboarding', + fixtures: new FixtureBuilder({ onboarding: true }).build(), ganacheOptions, title: this.test.title, failOnConsoleError: false, @@ -205,7 +206,7 @@ describe('Add account', function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/add-hide-token.spec.js b/test/e2e/tests/add-hide-token.spec.js index 8722bcfb0..688823081 100644 --- a/test/e2e/tests/add-hide-token.spec.js +++ b/test/e2e/tests/add-hide-token.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Hide token', function () { const ganacheOptions = { @@ -14,7 +15,32 @@ describe('Hide token', function () { it('hides the token when clicked', async function () { await withFixtures( { - fixtures: 'custom-token', + fixtures: new FixtureBuilder() + .withTokensController({ + allTokens: { + '0x539': { + '0x5cfe73b6021e818b776b421b1c4db2474086a7e1': [ + { + address: '0x86002be4cdd922de1ccb831582bf99284b99ac12', + decimals: 4, + image: null, + isERC721: false, + symbol: 'TST', + }, + ], + }, + }, + tokens: [ + { + address: '0x86002be4cdd922de1ccb831582bf99284b99ac12', + decimals: 4, + image: null, + isERC721: false, + symbol: 'TST', + }, + ], + }) + .build(), ganacheOptions, title: this.test.title, }, @@ -69,12 +95,11 @@ describe('Add existing token using search', function () { it('renders the balance for the chosen token', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder() + .withPreferencesController({ useTokenDetection: true }) + .build(), ganacheOptions, title: this.test.title, - driverOptions: { - timeOut: 20000, - }, }, async ({ driver }) => { await driver.navigate(); diff --git a/test/e2e/tests/address-book.spec.js b/test/e2e/tests/address-book.spec.js index b0121bcab..00f3caa2c 100644 --- a/test/e2e/tests/address-book.spec.js +++ b/test/e2e/tests/address-book.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Address Book', function () { const ganacheOptions = { @@ -14,7 +15,7 @@ describe('Address Book', function () { it('Adds an entry to the address book and sends eth to that address', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, @@ -77,7 +78,21 @@ describe('Address Book', function () { it('Sends to an address book entry', async function () { await withFixtures( { - fixtures: 'address-entry', + fixtures: new FixtureBuilder() + .withAddressBookController({ + addressBook: { + '0x539': { + '0x2f318C334780961FB129D2a6c30D0763d9a5C970': { + address: '0x2f318C334780961FB129D2a6c30D0763d9a5C970', + chainId: '0x539', + isEns: false, + memo: '', + name: 'Test Name 1', + }, + }, + }, + }) + .build(), ganacheOptions, title: this.test.title, }, @@ -90,6 +105,7 @@ describe('Address Book', function () { const recipientRowTitle = await driver.findElement( '.send__select-recipient-wrapper__group-item__title', ); + const recipientRowTitleString = await recipientRowTitle.getText(); assert.equal(recipientRowTitleString, 'Test Name 1'); await driver.clickElement( @@ -120,4 +136,107 @@ describe('Address Book', function () { }, ); }); + it('Edit entry in address book', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder() + .withAddressBookController({ + addressBook: { + '0x539': { + '0x2f318C334780961FB129D2a6c30D0763d9a5C970': { + address: '0x2f318C334780961FB129D2a6c30D0763d9a5C970', + chainId: '0x539', + isEns: false, + memo: '', + name: 'Test Name 1', + }, + }, + }, + }) + .build(), + ganacheOptions, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + await driver.clickElement('.identicon__address-wrapper'); + await driver.clickElement({ text: 'Settings', tag: 'div' }); + await driver.clickElement({ text: 'Contacts', tag: 'div' }); + await driver.clickElement('[data-testid="recipient"]'); + + await driver.clickElement({ text: 'Edit', tag: 'button' }); + const inputUsername = await driver.findElement('#nickname'); + await inputUsername.fill('Test Name Edit'); + + const inputAddress = await driver.findElement('#address'); + await inputAddress.fill('0x74cE91B75935D6Bedc27eE002DeFa566c5946f74'); + + await driver.clickElement('[data-testid="page-container-footer-next"]'); + + const recipientUsername = await driver.findElement({ + text: 'Test Name Edit', + tag: 'div', + }); + assert.equal( + await recipientUsername.getText(), + 'Test Name Edit', + 'Username is not edited correctly', + ); + + const recipientAddress = await driver.findElement( + '.send__select-recipient-wrapper__group-item__subtitle', + ); + assert.equal( + await recipientAddress.getText(), + '0x74cE...6f74', + 'Recipient address is not edited correctly', + ); + }, + ); + }); + it('Deletes existing entry from address book', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder() + .withAddressBookController({ + addressBook: { + '0x539': { + '0x2f318C334780961FB129D2a6c30D0763d9a5C970': { + address: '0x2f318C334780961FB129D2a6c30D0763d9a5C970', + chainId: '0x539', + isEns: false, + memo: '', + name: 'Test Name 1', + }, + }, + }, + }) + .build(), + ganacheOptions, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + await driver.clickElement('.identicon__address-wrapper'); + await driver.clickElement({ text: 'Settings', tag: 'div' }); + await driver.clickElement({ text: 'Contacts', tag: 'div' }); + + await driver.clickElement({ text: 'Test Name 1', tag: 'div' }); + await driver.clickElement({ text: 'Edit', tag: 'button' }); + await driver.clickElement({ text: 'Delete account', tag: 'a' }); + // it checks if account is deleted + const contact = await driver.findElement( + '.send__select-recipient-wrapper__group-item', + ); + const exists = await driver.isElementPresent(contact); + assert.equal(exists, false, 'Contact is not deleted'); + }, + ); + }); }); diff --git a/test/e2e/tests/advanced-settings.spec.js b/test/e2e/tests/advanced-settings.spec.js index b0d1eea35..88a4a7f27 100644 --- a/test/e2e/tests/advanced-settings.spec.js +++ b/test/e2e/tests/advanced-settings.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Advanced Settings', function () { const ganacheOptions = { @@ -16,7 +17,7 @@ describe('Advanced Settings', function () { await withFixtures( { dapp: true, - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, @@ -53,7 +54,7 @@ describe('Advanced Settings', function () { await withFixtures( { dapp: true, - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/auto-lock.spec.js b/test/e2e/tests/auto-lock.spec.js index 7401540ac..c49680f0d 100644 --- a/test/e2e/tests/auto-lock.spec.js +++ b/test/e2e/tests/auto-lock.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Auto-Lock Timer', function () { const ganacheOptions = { @@ -15,7 +16,7 @@ describe('Auto-Lock Timer', function () { it('should automatically lock the wallet once the idle time has elapsed', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/backup.spec.js b/test/e2e/tests/backup-restore.spec.js similarity index 56% rename from test/e2e/tests/backup.spec.js rename to test/e2e/tests/backup-restore.spec.js index 99b3a43ea..1310abd53 100644 --- a/test/e2e/tests/backup.spec.js +++ b/test/e2e/tests/backup-restore.spec.js @@ -1,10 +1,12 @@ const { strict: assert } = require('assert'); const { promises: fs } = require('fs'); +const path = require('path'); const { convertToHexValue, withFixtures, createDownloadFolder, } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); const downloadsFolder = `${process.cwd()}/test-artifacts/downloads`; @@ -35,7 +37,14 @@ const backupExists = async () => { } }; -describe('Backup', function () { +const restoreFile = path.join( + __dirname, + '..', + 'restore', + 'MetaMaskUserData.json', +); + +describe('Backup and Restore', function () { const ganacheOptions = { accounts: [ { @@ -45,10 +54,10 @@ describe('Backup', function () { }, ], }; - it('should create backup for the account', async function () { + it('should backup the account settings', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, failOnConsoleError: false, @@ -78,4 +87,40 @@ describe('Backup', function () { }, ); }); + + it('should restore the account settings', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder().build(), + ganacheOptions, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + // Restore + await driver.clickElement('.account-menu__icon'); + await driver.clickElement({ text: 'Settings', tag: 'div' }); + await driver.clickElement({ text: 'Advanced', tag: 'div' }); + const restore = await driver.findElement('#restore-file'); + await restore.sendKeys(restoreFile); + + // Dismiss success message + await driver.waitForSelector({ + css: '.actionable-message__message', + text: 'Your data has been restored successfully', + }); + await driver.clickElement({ text: 'Dismiss', tag: 'button' }); + + // Verify restore + await driver.clickElement({ text: 'Contacts', tag: 'div' }); + const recipient = await driver.findElement('[data-testid="recipient"]'); + assert.ok( + /Test\sAccount\s*0x0c54...AaFb/u.test(await recipient.getText()), + ); + }, + ); + }); }); diff --git a/test/e2e/tests/chain-interactions.spec.js b/test/e2e/tests/chain-interactions.spec.js index c95d3d211..42feb3913 100644 --- a/test/e2e/tests/chain-interactions.spec.js +++ b/test/e2e/tests/chain-interactions.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Chain Interactions', function () { const port = 8546; @@ -18,7 +19,7 @@ describe('Chain Interactions', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, @@ -70,7 +71,7 @@ describe('Chain Interactions', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, @@ -99,7 +100,9 @@ describe('Chain Interactions', function () { await driver.switchToWindow(extension); // verify current network - const networkDisplay = await driver.findElement('.network-display'); + const networkDisplay = await driver.findElement( + '[data-testid="network-display"]', + ); assert.equal(await networkDisplay.getText(), `Localhost ${port}`); }, ); diff --git a/test/e2e/tests/collectibles.spec.js b/test/e2e/tests/collectibles.spec.js index 692c8ac08..55424d36a 100644 --- a/test/e2e/tests/collectibles.spec.js +++ b/test/e2e/tests/collectibles.spec.js @@ -1,6 +1,7 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); const { SMART_CONTRACTS } = require('../seeder/smart-contracts'); +const FixtureBuilder = require('../fixture-builder'); describe('Collectibles', function () { const smartContract = SMART_CONTRACTS.COLLECTIBLES; @@ -17,7 +18,9 @@ describe('Collectibles', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, smartContract, title: this.test.title, @@ -69,7 +72,9 @@ describe('Collectibles', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, smartContract, title: this.test.title, @@ -134,7 +139,9 @@ describe('Collectibles', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, smartContract, title: this.test.title, @@ -203,7 +210,9 @@ describe('Collectibles', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, smartContract, title: this.test.title, diff --git a/test/e2e/tests/contract-interactions.spec.js b/test/e2e/tests/contract-interactions.spec.js index d50ac6cb9..71c5962cb 100644 --- a/test/e2e/tests/contract-interactions.spec.js +++ b/test/e2e/tests/contract-interactions.spec.js @@ -1,6 +1,7 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); const { SMART_CONTRACTS } = require('../seeder/smart-contracts'); +const FixtureBuilder = require('../fixture-builder'); describe('Deploy contract and call contract methods', function () { const ganacheOptions = { @@ -17,7 +18,9 @@ describe('Deploy contract and call contract methods', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, smartContract, title: this.test.title, diff --git a/test/e2e/tests/custom-rpc-history.spec.js b/test/e2e/tests/custom-rpc-history.spec.js index 908fc2ad5..1ab2aa1ef 100644 --- a/test/e2e/tests/custom-rpc-history.spec.js +++ b/test/e2e/tests/custom-rpc-history.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures, largeDelayMs } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Stores custom RPC history', function () { const ganacheOptions = { @@ -17,7 +18,7 @@ describe('Stores custom RPC history', function () { const symbol = 'TEST'; await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions: { ...ganacheOptions, concurrent: { port, chainId } }, title: this.test.title, }, @@ -74,7 +75,7 @@ describe('Stores custom RPC history', function () { it('warns user when they enter url for an already configured network', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, @@ -117,7 +118,7 @@ describe('Stores custom RPC history', function () { it('warns user when they enter chainId for an already configured network', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, failOnConsoleError: false, @@ -129,7 +130,7 @@ describe('Stores custom RPC history', function () { // duplicate network const newRpcUrl = 'http://localhost:8544'; - const duplicateChainId = '0x539'; + const duplicateChainId = '1'; await driver.delay(largeDelayMs); @@ -153,7 +154,7 @@ describe('Stores custom RPC history', function () { await chainIdInput.clear(); await chainIdInput.sendKeys(duplicateChainId); await driver.findElement({ - text: 'This Chain ID is currently used by the Localhost 8545 network.', + text: 'This Chain ID is currently used by the mainnet network.', tag: 'h6', }); @@ -171,7 +172,7 @@ describe('Stores custom RPC history', function () { it('selects another provider', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, @@ -192,7 +193,26 @@ describe('Stores custom RPC history', function () { it('finds all recent RPCs in history', async function () { await withFixtures( { - fixtures: 'custom-rpc', + fixtures: new FixtureBuilder() + .withPreferencesController({ + frequentRpcListDetail: [ + { + rpcUrl: 'http://127.0.0.1:8545/1', + chainId: '0x539', + ticker: 'ETH', + nickname: 'http://127.0.0.1:8545/1', + rpcPrefs: {}, + }, + { + rpcUrl: 'http://127.0.0.1:8545/2', + chainId: '0x539', + ticker: 'ETH', + nickname: 'http://127.0.0.1:8545/2', + rpcPrefs: {}, + }, + ], + }) + .build(), ganacheOptions, title: this.test.title, }, @@ -221,7 +241,26 @@ describe('Stores custom RPC history', function () { it('deletes a custom RPC', async function () { await withFixtures( { - fixtures: 'custom-rpc', + fixtures: new FixtureBuilder() + .withPreferencesController({ + frequentRpcListDetail: [ + { + rpcUrl: 'http://127.0.0.1:8545/1', + chainId: '0x539', + ticker: 'ETH', + nickname: 'http://127.0.0.1:8545/1', + rpcPrefs: {}, + }, + { + rpcUrl: 'http://127.0.0.1:8545/2', + chainId: '0x539', + ticker: 'ETH', + nickname: 'http://127.0.0.1:8545/2', + rpcPrefs: {}, + }, + ], + }) + .build(), ganacheOptions, title: this.test.title, failOnConsoleError: false, diff --git a/test/e2e/tests/custom-token-add-approve.spec.js b/test/e2e/tests/custom-token-add-approve.spec.js index 7b68e093e..67e045325 100644 --- a/test/e2e/tests/custom-token-add-approve.spec.js +++ b/test/e2e/tests/custom-token-add-approve.spec.js @@ -6,6 +6,7 @@ const { withFixtures, getWindowHandles, } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe.skip('Create token, approve token and approve token without gas', function () { describe('Add a custom token from a dapp', function () { @@ -23,7 +24,9 @@ describe.skip('Create token, approve token and approve token without gas', funct await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, title: this.test.title, }, @@ -114,7 +117,9 @@ describe.skip('Create token, approve token and approve token without gas', funct await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, title: this.test.title, }, @@ -182,7 +187,9 @@ describe.skip('Create token, approve token and approve token without gas', funct await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, title: this.test.title, }, @@ -292,7 +299,9 @@ describe.skip('Create token, approve token and approve token without gas', funct await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/dapp-interactions.spec.js b/test/e2e/tests/dapp-interactions.spec.js index ae8b72482..652f28c1e 100644 --- a/test/e2e/tests/dapp-interactions.spec.js +++ b/test/e2e/tests/dapp-interactions.spec.js @@ -1,9 +1,6 @@ const { strict: assert } = require('assert'); -const { - convertToHexValue, - withFixtures, - connectDappWithExtensionPopup, -} = require('../helpers'); +const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Dapp interactions', function () { let windowHandles; @@ -22,7 +19,7 @@ describe('Dapp interactions', function () { await withFixtures( { dapp: true, - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions: { ...ganacheOptions, concurrent: { port: 8546, chainId: 1338 }, @@ -34,8 +31,7 @@ describe('Dapp interactions', function () { await driver.fill('#password', 'correct horse battery staple'); await driver.press('#password', driver.Key.ENTER); - // Connect to Dapp0 - await connectDappWithExtensionPopup(driver, 0); + await driver.openNewPage('http://127.0.0.1:8080/'); windowHandles = await driver.getAllWindowHandles(); extension = windowHandles[0]; @@ -68,7 +64,9 @@ describe('Dapp interactions', function () { await withFixtures( { dapp: true, - fixtures: 'imported-account', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, dappOptions: { numberOfDapps: 2 }, title: this.test.title, @@ -78,8 +76,7 @@ describe('Dapp interactions', function () { await driver.fill('#password', 'correct horse battery staple'); await driver.press('#password', driver.Key.ENTER); - // Connect to Dapp0 - await connectDappWithExtensionPopup(driver, 0); + await driver.openNewPage('http://127.0.0.1:8080/'); windowHandles = await driver.getAllWindowHandles(); extension = windowHandles[0]; @@ -115,11 +112,11 @@ describe('Dapp interactions', function () { await driver.clickElement({ text: 'Connected sites', tag: 'span' }); const connectedDapp1 = await driver.isElementPresent({ text: 'http://127.0.0.1:8080', - tag: 'span', + tag: 'bdi', }); const connectedDapp2 = await driver.isElementPresent({ text: 'http://127.0.0.1:8081', - tag: 'span', + tag: 'bdi', }); assert.ok(connectedDapp1, 'Account not connected to Dapp1'); diff --git a/test/e2e/tests/edit-gas-fee.spec.js b/test/e2e/tests/edit-gas-fee.spec.js index ced967300..db1da859b 100644 --- a/test/e2e/tests/edit-gas-fee.spec.js +++ b/test/e2e/tests/edit-gas-fee.spec.js @@ -1,10 +1,10 @@ const { strict: assert } = require('assert'); const { convertToHexValue, - connectDappWithExtensionPopup, getWindowHandles, withFixtures, } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Editing Confirm Transaction', function () { it('allows selecting high, medium, low gas estimates on edit gas fee popover', async function () { @@ -20,7 +20,12 @@ describe('Editing Confirm Transaction', function () { }; await withFixtures( { - fixtures: 'eip-1559-v2', + fixtures: new FixtureBuilder() + .withPreferencesController({ + eip1559V2Enabled: true, + }) + .withTransactionControllerTypeTwoTransaction() + .build(), ganacheOptions, title: this.test.title, }, @@ -34,7 +39,7 @@ describe('Editing Confirm Transaction', function () { '.currency-display-component__text', ); const transactionAmount = transactionAmounts[0]; - assert.equal(await transactionAmount.getText(), '2.2'); + assert.equal(await transactionAmount.getText(), '1'); // update estimates to high await driver.clickElement('[data-testid="edit-gas-fee-button"]'); @@ -80,7 +85,7 @@ describe('Editing Confirm Transaction', function () { '.transaction-list-item__primary-currency', ); assert.equal(txValues.length, 1); - assert.ok(/-2.2\s*ETH/u.test(await txValues[0].getText())); + assert.ok(/-1\s*ETH/u.test(await txValues[0].getText())); }, ); }); @@ -98,7 +103,12 @@ describe('Editing Confirm Transaction', function () { }; await withFixtures( { - fixtures: 'eip-1559-v2', + fixtures: new FixtureBuilder() + .withPreferencesController({ + eip1559V2Enabled: true, + }) + .withTransactionControllerTypeTwoTransaction() + .build(), ganacheOptions, title: this.test.title, }, @@ -112,7 +122,7 @@ describe('Editing Confirm Transaction', function () { '.currency-display-component__text', ); const transactionAmount = transactionAmounts[0]; - assert.equal(await transactionAmount.getText(), '2.2'); + assert.equal(await transactionAmount.getText(), '1'); // update estimates to high await driver.clickElement('[data-testid="edit-gas-fee-button"]'); @@ -145,7 +155,7 @@ describe('Editing Confirm Transaction', function () { }); await driver.waitForSelector({ css: '.transaction-detail-item:nth-of-type(2) h6:nth-of-type(2)', - text: '2.20085 ETH', + text: '1.00085 ETH', }); // confirms the transaction @@ -163,7 +173,7 @@ describe('Editing Confirm Transaction', function () { '.transaction-list-item__primary-currency', ); assert.equal(txValues.length, 1); - assert.ok(/-2.2\s*ETH/u.test(await txValues[0].getText())); + assert.ok(/-1\s*ETH/u.test(await txValues[0].getText())); }, ); }); @@ -181,7 +191,12 @@ describe('Editing Confirm Transaction', function () { }; await withFixtures( { - fixtures: 'eip-1559-v2-dapp', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .withPreferencesController({ + eip1559V2Enabled: true, + }) + .build(), ganacheOptions, title: this.test.title, dapp: true, @@ -194,7 +209,7 @@ describe('Editing Confirm Transaction', function () { await driver.press('#password', driver.Key.ENTER); // open dapp and connect - await connectDappWithExtensionPopup(driver); + await driver.openNewPage('http://127.0.0.1:8080/'); await driver.clickElement({ text: 'Send EIP 1559 Transaction', tag: 'button', diff --git a/test/e2e/tests/encrypt-decrypt.spec.js b/test/e2e/tests/encrypt-decrypt.spec.js new file mode 100644 index 000000000..e34908117 --- /dev/null +++ b/test/e2e/tests/encrypt-decrypt.spec.js @@ -0,0 +1,93 @@ +const { strict: assert } = require('assert'); +const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); + +describe('Encrypt Decrypt', function () { + const ganacheOptions = { + accounts: [ + { + secretKey: + '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', + balance: convertToHexValue(25000000000000000000), + }, + ], + }; + const encryptionKey = 'fxYXfCbun026g5zcCQh7Ia+O0urAEVZWLG8H4Jzu7Xs='; + const message = 'Hello, Bob!'; + it('should decrypt an encrypted message', async function () { + await withFixtures( + { + dapp: true, + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), + ganacheOptions, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + await driver.openNewPage('http://127.0.0.1:8080'); + + // Get Encryption key + await driver.clickElement('#getEncryptionKeyButton'); + await driver.waitUntilXWindowHandles(3); + let windowHandles = await driver.getAllWindowHandles(); + await driver.switchToWindowWithTitle( + 'MetaMask Notification', + windowHandles, + ); + await driver.waitForSelector({ + css: '.request-encryption-public-key__header__text', + text: 'Request encryption public key', + }); + await driver.clickElement({ text: 'Provide', tag: 'button' }); + await driver.waitUntilXWindowHandles(2); + windowHandles = await driver.getAllWindowHandles(); + await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles); + const encryptionKeyLabel = await driver.findElement( + '#encryptionKeyDisplay', + ); + assert.equal(await encryptionKeyLabel.getText(), encryptionKey); + + // Encrypt + await driver.fill('#encryptMessageInput', message); + await driver.clickElement('#encryptButton'); + await driver.waitForSelector({ + css: '#ciphertextDisplay', + text: '0x', + }); + + // Decrypt + await driver.clickElement('#decryptButton'); + await driver.waitUntilXWindowHandles(3); + windowHandles = await driver.getAllWindowHandles(); + await driver.switchToWindowWithTitle( + 'MetaMask Notification', + windowHandles, + ); + await driver.waitForSelector({ + css: '.request-decrypt-message__header__text', + text: 'Decrypt request', + }); + + // Verify message in MetaMask Notification + await driver.clickElement({ text: 'Decrypt message', tag: 'div' }); + const notificationMessage = await driver.isElementPresent({ + text: message, + tag: 'div', + }); + assert.equal(notificationMessage, true); + await driver.clickElement({ text: 'Decrypt', tag: 'button' }); + + // Verify message in Test Dapp + await driver.waitUntilXWindowHandles(2); + windowHandles = await driver.getAllWindowHandles(); + await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles); + const clearTextLabel = await driver.findElement('#cleartextDisplay'); + assert.equal(await clearTextLabel.getText(), message); + }, + ); + }); +}); diff --git a/test/e2e/tests/errors.spec.js b/test/e2e/tests/errors.spec.js index 880844386..7538850cd 100644 --- a/test/e2e/tests/errors.spec.js +++ b/test/e2e/tests/errors.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Sentry errors', function () { async function mockSegment(mockServer) { @@ -26,7 +27,12 @@ describe('Sentry errors', function () { it('should send error events', async function () { await withFixtures( { - fixtures: 'metrics-enabled', + fixtures: new FixtureBuilder() + .withMetaMetricsController({ + metaMetricsId: 'fake-metrics-id', + participateInMetaMetrics: true, + }) + .build(), ganacheOptions, title: this.test.title, failOnConsoleError: false, diff --git a/test/e2e/tests/eth-sign.spec.js b/test/e2e/tests/eth-sign.spec.js index cf685726a..5bd90cea6 100644 --- a/test/e2e/tests/eth-sign.spec.js +++ b/test/e2e/tests/eth-sign.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Eth sign', function () { it('can initiate and confirm a eth sign', async function () { @@ -19,7 +20,9 @@ describe('Eth sign', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/failing-contract.spec.js b/test/e2e/tests/failing-contract.spec.js index bdeb6373b..6b15c6a05 100644 --- a/test/e2e/tests/failing-contract.spec.js +++ b/test/e2e/tests/failing-contract.spec.js @@ -1,6 +1,7 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); const { SMART_CONTRACTS } = require('../seeder/smart-contracts'); +const FixtureBuilder = require('../fixture-builder'); describe('Failing contract interaction ', function () { const smartContract = SMART_CONTRACTS.FAILING; @@ -18,7 +19,9 @@ describe('Failing contract interaction ', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, smartContract, title: this.test.title, diff --git a/test/e2e/tests/from-import-ui.spec.js b/test/e2e/tests/from-import-ui.spec.js index 74298956c..9c87f6c66 100644 --- a/test/e2e/tests/from-import-ui.spec.js +++ b/test/e2e/tests/from-import-ui.spec.js @@ -8,6 +8,7 @@ const { completeImportSRPOnboardingFlow, completeImportSRPOnboardingFlowWordByWord, } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('MetaMask Import UI', function () { it('Importing wallet using Secret Recovery Phrase', async function () { @@ -27,7 +28,7 @@ describe('MetaMask Import UI', function () { await withFixtures( { - fixtures: 'onboarding', + fixtures: new FixtureBuilder({ onboarding: true }).build(), ganacheOptions, title: this.test.title, failOnConsoleError: false, @@ -145,7 +146,7 @@ describe('MetaMask Import UI', function () { await withFixtures( { - fixtures: 'onboarding', + fixtures: new FixtureBuilder({ onboarding: true }).build(), ganacheOptions, title: this.test.title, failOnConsoleError: false, @@ -192,7 +193,10 @@ describe('MetaMask Import UI', function () { await withFixtures( { - fixtures: 'import-ui', + fixtures: new FixtureBuilder() + .withKeyringControllerImportedAccountVault() + .withPreferencesControllerImportedAccountIdentities() + .build(), ganacheOptions, title: this.test.title, }, @@ -295,7 +299,10 @@ describe('MetaMask Import UI', function () { await withFixtures( { - fixtures: 'import-ui', + fixtures: new FixtureBuilder() + .withKeyringControllerImportedAccountVault() + .withPreferencesControllerImportedAccountIdentities() + .build(), ganacheOptions, title: this.test.title, }, @@ -315,7 +322,6 @@ describe('MetaMask Import UI', function () { const importJsonFile = path.join( __dirname, '..', - 'fixtures', 'import-utc-json', 'test-json-import-account-file.json', ); @@ -368,7 +374,10 @@ describe('MetaMask Import UI', function () { await withFixtures( { - fixtures: 'import-ui', + fixtures: new FixtureBuilder() + .withKeyringControllerImportedAccountVault() + .withPreferencesControllerImportedAccountIdentities() + .build(), ganacheOptions, title: this.test.title, }, @@ -407,7 +416,7 @@ describe('MetaMask Import UI', function () { await withFixtures( { - fixtures: 'import-ui', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/gas-api-fallback.spec.js b/test/e2e/tests/gas-api-fallback.spec.js new file mode 100644 index 000000000..9ccc023e5 --- /dev/null +++ b/test/e2e/tests/gas-api-fallback.spec.js @@ -0,0 +1,70 @@ +const { strict: assert } = require('assert'); +const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); + +describe('Gas API fallback', function () { + async function mockGasApiDown(mockServer) { + await mockServer + .forGet( + 'https://gas-api.metaswap.codefi.network/networks/1/suggestedGasFees', + ) + .thenCallback(() => { + return { + statusCode: 500, + json: {}, + }; + }); + } + + const ganacheOptions = { + hardfork: 'london', + accounts: [ + { + secretKey: + '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', + balance: convertToHexValue(25000000000000000000), + }, + ], + }; + + it('error message is displayed but gas recommendation is not displayed', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder().build(), + testSpecificMock: mockGasApiDown, + ganacheOptions, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + await driver.clickElement('[data-testid="eth-overview-send"]'); + + await driver.fill( + 'input[placeholder="Search, public address (0x), or ENS"]', + '0x2f318C334780961FB129D2a6c30D0763d9a5C970', + ); + + const inputAmount = await driver.findElement('.unit-input__input'); + await inputAmount.fill('1'); + + await driver.clickElement({ text: 'Next', tag: 'button' }); + await driver.clickElement({ text: 'Edit', tag: 'button' }); + + const error = await driver.isElementPresent('.error-message__text'); + const gasRecommendation = await driver.isElementPresent( + '[data-testid="gas-recommendation"]', + ); + + assert.equal(error, true, 'Error message is not displayed'); + assert.equal( + gasRecommendation, + false, + 'Gas recommendation is displayed', + ); + }, + ); + }); +}); diff --git a/test/e2e/tests/incremental-security.spec.js b/test/e2e/tests/incremental-security.spec.js index d7ba9e0b7..f54f9563a 100644 --- a/test/e2e/tests/incremental-security.spec.js +++ b/test/e2e/tests/incremental-security.spec.js @@ -1,6 +1,7 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures, tinyDelayMs } = require('../helpers'); const enLocaleMessages = require('../../../app/_locales/en/messages.json'); +const FixtureBuilder = require('../fixture-builder'); describe('Incremental Security', function () { const ganacheOptions = { @@ -21,7 +22,7 @@ describe('Incremental Security', function () { await withFixtures( { dapp: true, - fixtures: 'onboarding', + fixtures: new FixtureBuilder({ onboarding: true }).build(), ganacheOptions, title: this.test.title, failOnConsoleError: false, @@ -130,6 +131,7 @@ describe('Incremental Security', function () { const revealedSeedPhrase = await driver.findElement( '.reveal-seed-phrase__secret-words', ); + await driver.waitForNonEmptyElement(revealedSeedPhrase); const seedPhrase = await revealedSeedPhrase.getText(); assert.equal(seedPhrase.split(' ').length, 12); diff --git a/test/e2e/tests/localization.spec.js b/test/e2e/tests/localization.spec.js index a4859de68..0e41d1d71 100644 --- a/test/e2e/tests/localization.spec.js +++ b/test/e2e/tests/localization.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Localization', function () { it('can correctly display Philippine peso symbol and code', async function () { @@ -13,7 +14,20 @@ describe('Localization', function () { ], }; await withFixtures( - { fixtures: 'localization', ganacheOptions, title: this.test.title }, + { + fixtures: new FixtureBuilder() + .withCurrencyController({ + currentCurrency: 'php', + }) + .withPreferencesController({ + preferences: { + showFiatInTestnets: true, + }, + }) + .build(), + ganacheOptions, + title: this.test.title, + }, async ({ driver }) => { await driver.navigate(); await driver.fill('#password', 'correct horse battery staple'); diff --git a/test/e2e/tests/lock-account.spec.js b/test/e2e/tests/lock-account.spec.js index 345a6ec78..1fd2910a6 100644 --- a/test/e2e/tests/lock-account.spec.js +++ b/test/e2e/tests/lock-account.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Lock and unlock', function () { const ganacheOptions = { @@ -14,7 +15,7 @@ describe('Lock and unlock', function () { it('successfully unlocks after lock', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/lockdown.spec.js b/test/e2e/tests/lockdown.spec.js index cb38725aa..f49baa331 100644 --- a/test/e2e/tests/lockdown.spec.js +++ b/test/e2e/tests/lockdown.spec.js @@ -6,6 +6,7 @@ const { } = require('../../helpers/protect-intrinsics-helpers'); const { convertToHexValue, withFixtures } = require('../helpers'); const { PAGES } = require('../webdriver/driver'); +const FixtureBuilder = require('../fixture-builder'); const isFirefox = process.env.SELENIUM_BROWSER === Browser.FIREFOX; @@ -65,7 +66,7 @@ describe('lockdown', function () { await withFixtures( { // The fixtures used here is arbitrary. Any fixture would do. - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/metamask-responsive-ui.spec.js b/test/e2e/tests/metamask-responsive-ui.spec.js index d0f6906db..0fba51b13 100644 --- a/test/e2e/tests/metamask-responsive-ui.spec.js +++ b/test/e2e/tests/metamask-responsive-ui.spec.js @@ -1,6 +1,7 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures, tinyDelayMs } = require('../helpers'); const enLocaleMessages = require('../../../app/_locales/en/messages.json'); +const FixtureBuilder = require('../fixture-builder'); describe('MetaMask Responsive UI', function () { it('Creating a new wallet', async function () { @@ -8,7 +9,7 @@ describe('MetaMask Responsive UI', function () { await withFixtures( { - fixtures: 'onboarding', + fixtures: new FixtureBuilder({ onboarding: true }).build(), driverOptions, title: this.test.title, failOnConsoleError: false, @@ -154,7 +155,7 @@ describe('MetaMask Responsive UI', function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), driverOptions, title: this.test.title, failOnConsoleError: false, @@ -200,7 +201,7 @@ describe('MetaMask Responsive UI', function () { }; await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), driverOptions, ganacheOptions, title: this.test.title, diff --git a/test/e2e/tests/metrics.spec.js b/test/e2e/tests/metrics.spec.js index d00abd788..21ee6c0fd 100644 --- a/test/e2e/tests/metrics.spec.js +++ b/test/e2e/tests/metrics.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Segment metrics', function () { async function mockSegment(mockServer) { @@ -27,7 +28,12 @@ describe('Segment metrics', function () { it('should send first three Page metric events upon fullscreen page load', async function () { await withFixtures( { - fixtures: 'metrics-enabled', + fixtures: new FixtureBuilder() + .withMetaMetricsController({ + metaMetricsId: 'fake-metrics-id', + participateInMetaMetrics: true, + }) + .build(), ganacheOptions, title: this.test.title, failOnConsoleError: false, diff --git a/test/e2e/tests/navigate-transactions.spec.js b/test/e2e/tests/navigate-transactions.spec.js index 3e1eca68a..d2f964b8e 100644 --- a/test/e2e/tests/navigate-transactions.spec.js +++ b/test/e2e/tests/navigate-transactions.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Navigate transactions', function () { const ganacheOptions = { @@ -14,7 +15,9 @@ describe('Navigate transactions', function () { it('should navigate the unapproved transactions', async function () { await withFixtures( { - fixtures: 'navigate-transactions', + fixtures: new FixtureBuilder() + .withTransactionControllerMultipleTransactions() + .build(), ganacheOptions, title: this.test.title, }, @@ -102,7 +105,10 @@ describe('Navigate transactions', function () { await withFixtures( { dapp: true, - fixtures: 'navigate-transactions', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .withTransactionControllerMultipleTransactions() + .build(), ganacheOptions, title: this.test.title, }, @@ -149,7 +155,9 @@ describe('Navigate transactions', function () { it('should reject and remove an unapproved transaction', async function () { await withFixtures( { - fixtures: 'navigate-transactions', + fixtures: new FixtureBuilder() + .withTransactionControllerMultipleTransactions() + .build(), ganacheOptions, title: this.test.title, }, @@ -180,7 +188,9 @@ describe('Navigate transactions', function () { it('should confirm and remove an unapproved transaction', async function () { await withFixtures( { - fixtures: 'navigate-transactions', + fixtures: new FixtureBuilder() + .withTransactionControllerMultipleTransactions() + .build(), ganacheOptions, title: this.test.title, }, @@ -211,7 +221,9 @@ describe('Navigate transactions', function () { it('should reject and remove all unapproved transactions', async function () { await withFixtures( { - fixtures: 'navigate-transactions', + fixtures: new FixtureBuilder() + .withTransactionControllerMultipleTransactions() + .build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/permissions.spec.js b/test/e2e/tests/permissions.spec.js index 16f786718..3ebcbf117 100644 --- a/test/e2e/tests/permissions.spec.js +++ b/test/e2e/tests/permissions.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Permissions', function () { it('sets permissions and connect to Dapp', async function () { @@ -16,7 +17,7 @@ describe('Permissions', function () { await withFixtures( { dapp: true, - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/personal-sign.spec.js b/test/e2e/tests/personal-sign.spec.js index 040cde609..65f669e4c 100644 --- a/test/e2e/tests/personal-sign.spec.js +++ b/test/e2e/tests/personal-sign.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Personal sign', function () { it('can initiate and confirm a personal sign', async function () { @@ -16,7 +17,9 @@ describe('Personal sign', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/phishing-detection.spec.js b/test/e2e/tests/phishing-detection.spec.js index f1bc16297..897ad66ac 100644 --- a/test/e2e/tests/phishing-detection.spec.js +++ b/test/e2e/tests/phishing-detection.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); const PHISHFORT_CDN_URL = 'https://static.metafi.codefi.network/api/v1/lists/phishfort_hotlist.json'; @@ -43,7 +44,7 @@ describe('Phishing Detection', function () { it('should display the MetaMask Phishing Detection page and take the user to the blocked page if they continue', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, testSpecificMock: mockPhishingDetection, @@ -67,7 +68,7 @@ describe('Phishing Detection', function () { it('should display the MetaMask Phishing Detection page in an iframe and take the user to the blocked page if they continue', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, testSpecificMock: mockPhishingDetection, @@ -103,7 +104,7 @@ describe('Phishing Detection', function () { it('should display the MetaMask Phishing Detection page in an iframe but should NOT take the user to the blocked page if it is not an accessible resource', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, testSpecificMock: mockPhishingDetection, @@ -142,7 +143,7 @@ describe('Phishing Detection', function () { it('should display the MetaMask Phishing Detection page with the correct new issue link if the issue was detected from the phishfort list', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, testSpecificMock: mockPhishfortPhishingDetection, diff --git a/test/e2e/tests/portfolio-site.spec.js b/test/e2e/tests/portfolio-site.spec.js index c6cb09879..06b47ce4b 100644 --- a/test/e2e/tests/portfolio-site.spec.js +++ b/test/e2e/tests/portfolio-site.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Portfolio site', function () { const ganacheOptions = { @@ -15,7 +16,7 @@ describe('Portfolio site', function () { await withFixtures( { dapp: true, - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/provider-api.spec.js b/test/e2e/tests/provider-api.spec.js index b85b4fb32..449f894bd 100644 --- a/test/e2e/tests/provider-api.spec.js +++ b/test/e2e/tests/provider-api.spec.js @@ -1,6 +1,7 @@ const { strict: assert } = require('assert'); const { errorCodes } = require('eth-rpc-errors'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('MetaMask', function () { const ganacheOptions = { @@ -17,7 +18,9 @@ describe('MetaMask', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, title: this.test.title, }, @@ -70,7 +73,9 @@ describe('MetaMask', function () { { dapp: true, failOnConsoleError: false, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/send-edit.spec.js b/test/e2e/tests/send-edit.spec.js index 8060392f2..bd3c7120d 100644 --- a/test/e2e/tests/send-edit.spec.js +++ b/test/e2e/tests/send-edit.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Editing Confirm Transaction', function () { it('goes back from confirm page to edit eth value, gas price and gas limit', async function () { @@ -14,7 +15,9 @@ describe('Editing Confirm Transaction', function () { }; await withFixtures( { - fixtures: 'send-edit', + fixtures: new FixtureBuilder() + .withTransactionControllerTypeOneTransaction() + .build(), ganacheOptions, title: this.test.title, failOnConsoleError: false, @@ -92,7 +95,12 @@ describe('Editing Confirm Transaction', function () { }; await withFixtures( { - fixtures: 'send-edit-v2', + fixtures: new FixtureBuilder() + .withPreferencesController({ + eip1559V2Enabled: true, + }) + .withTransactionControllerTypeTwoTransaction() + .build(), ganacheOptions, title: this.test.title, failOnConsoleError: false, diff --git a/test/e2e/tests/send-eth.spec.js b/test/e2e/tests/send-eth.spec.js index f14bb1bc5..0833a1f85 100644 --- a/test/e2e/tests/send-eth.spec.js +++ b/test/e2e/tests/send-eth.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Send ETH from inside MetaMask using default gas', function () { const ganacheOptions = { @@ -14,7 +15,7 @@ describe('Send ETH from inside MetaMask using default gas', function () { it('finds the transaction in the transactions list', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, @@ -105,7 +106,13 @@ describe('Send ETH non-contract address with data that matches ERC20 transfer da it('renders the correct recipient on the confirmation screen', async function () { await withFixtures( { - fixtures: 'special-settings', + fixtures: new FixtureBuilder() + .withPreferencesController({ + featureFlags: { + sendHexData: true, + }, + }) + .build(), ganacheOptions, title: this.test.title, }, @@ -154,7 +161,7 @@ describe('Send ETH from inside MetaMask using advanced gas modal', function () { it('finds the transaction in the transactions list', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, @@ -221,7 +228,9 @@ describe('Send ETH from dapp using advanced gas controls', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/send-hex-address.spec.js b/test/e2e/tests/send-hex-address.spec.js index 5c5bbf0a9..ade462eb3 100644 --- a/test/e2e/tests/send-hex-address.spec.js +++ b/test/e2e/tests/send-hex-address.spec.js @@ -1,6 +1,7 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); const { SMART_CONTRACTS } = require('../seeder/smart-contracts'); +const FixtureBuilder = require('../fixture-builder'); const hexPrefixedAddress = '0x2f318C334780961FB129D2a6c30D0763d9a5C970'; const nonHexPrefixedAddress = hexPrefixedAddress.substring(2); @@ -18,7 +19,7 @@ describe('Send ETH to a 40 character hexadecimal address', function () { it('should ensure the address is prefixed with 0x when pasted and should send ETH to a valid hexadecimal address', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, failOnConsoleError: false, @@ -69,7 +70,7 @@ describe('Send ETH to a 40 character hexadecimal address', function () { it('should ensure the address is prefixed with 0x when typed and should send ETH to a valid hexadecimal address', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, failOnConsoleError: false, @@ -134,7 +135,9 @@ describe('Send ERC20 to a 40 character hexadecimal address', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, smartContract, title: this.test.title, @@ -223,7 +226,9 @@ describe('Send ERC20 to a 40 character hexadecimal address', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, smartContract, title: this.test.title, diff --git a/test/e2e/tests/send-to-contract.spec.js b/test/e2e/tests/send-to-contract.spec.js index 1cdb47e43..e7dffa5e7 100644 --- a/test/e2e/tests/send-to-contract.spec.js +++ b/test/e2e/tests/send-to-contract.spec.js @@ -1,6 +1,7 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); const { SMART_CONTRACTS } = require('../seeder/smart-contracts'); +const FixtureBuilder = require('../fixture-builder'); describe('Send ERC20 token to contract address', function () { const smartContract = SMART_CONTRACTS.HST; @@ -17,7 +18,9 @@ describe('Send ERC20 token to contract address', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, smartContract, title: this.test.title, diff --git a/test/e2e/tests/settings-general.spec.js b/test/e2e/tests/settings-general.spec.js index e264f3771..bf4a1954d 100644 --- a/test/e2e/tests/settings-general.spec.js +++ b/test/e2e/tests/settings-general.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Settings', function () { const ganacheOptions = { @@ -15,7 +16,7 @@ describe('Settings', function () { it('checks jazzicon and blockies icons', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/settings-search.spec.js b/test/e2e/tests/settings-search.spec.js index 69ac23ec0..b4c3ab278 100644 --- a/test/e2e/tests/settings-search.spec.js +++ b/test/e2e/tests/settings-search.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Settings Search', function () { const ganacheOptions = { @@ -25,7 +26,7 @@ describe('Settings Search', function () { it('should find element inside the General tab', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, @@ -51,7 +52,7 @@ describe('Settings Search', function () { it('should find element inside the Advanced tab', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, @@ -78,7 +79,7 @@ describe('Settings Search', function () { it('should find element inside the Contacts tab', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, @@ -105,7 +106,7 @@ describe('Settings Search', function () { it('should find element inside the Security tab', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, @@ -132,7 +133,7 @@ describe('Settings Search', function () { it('should find element inside the Alerts tab', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, @@ -159,7 +160,7 @@ describe('Settings Search', function () { it('should find element inside the Networks tab', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, @@ -186,7 +187,7 @@ describe('Settings Search', function () { it('should find element inside the Experimental tab', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, @@ -213,7 +214,7 @@ describe('Settings Search', function () { it('should find element inside the About tab', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, @@ -240,7 +241,7 @@ describe('Settings Search', function () { it('should display "Element not found" for a non-existing element', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/signature-request.spec.js b/test/e2e/tests/signature-request.spec.js index 1de8409a1..38141527b 100644 --- a/test/e2e/tests/signature-request.spec.js +++ b/test/e2e/tests/signature-request.spec.js @@ -4,6 +4,7 @@ const { withFixtures, regularDelayMs, } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Sign Typed Data V4 Signature Request', function () { it('can initiate and confirm a Signature Request', async function () { @@ -20,7 +21,9 @@ describe('Sign Typed Data V4 Signature Request', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, title: this.test.title, }, @@ -102,7 +105,9 @@ describe('Sign Typed Data V3 Signature Request', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, title: this.test.title, }, @@ -180,7 +185,9 @@ describe('Sign Typed Data Signature Request', function () { await withFixtures( { dapp: true, - fixtures: 'connected-state', + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/tests/simple-send.spec.js b/test/e2e/tests/simple-send.spec.js index 2d26a1871..c40add66d 100644 --- a/test/e2e/tests/simple-send.spec.js +++ b/test/e2e/tests/simple-send.spec.js @@ -1,4 +1,5 @@ const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Simple send', function () { it('can send a simple transaction from one account to another', async function () { @@ -12,7 +13,11 @@ describe('Simple send', function () { ], }; await withFixtures( - { fixtures: 'imported-account', ganacheOptions, title: this.test.title }, + { + fixtures: new FixtureBuilder().build(), + ganacheOptions, + title: this.test.title, + }, async ({ driver }) => { await driver.navigate(); await driver.fill('#password', 'correct horse battery staple'); diff --git a/test/e2e/tests/state-logs.spec.js b/test/e2e/tests/state-logs.spec.js index ae42abfc1..9b82b0a00 100644 --- a/test/e2e/tests/state-logs.spec.js +++ b/test/e2e/tests/state-logs.spec.js @@ -5,6 +5,7 @@ const { withFixtures, createDownloadFolder, } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); const downloadsFolder = `${process.cwd()}/test-artifacts/downloads`; @@ -31,7 +32,7 @@ describe('State logs', function () { it('should download state logs for the account', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, failOnConsoleError: false, diff --git a/test/e2e/tests/stuck-approved-transaction.spec.js b/test/e2e/tests/stuck-approved-transaction.spec.js new file mode 100644 index 000000000..daf73265d --- /dev/null +++ b/test/e2e/tests/stuck-approved-transaction.spec.js @@ -0,0 +1,47 @@ +const { strict: assert } = require('assert'); +const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); + +describe('Editing Confirm Transaction', function () { + it('approves a transaction stuck in approved state on boot', async function () { + const ganacheOptions = { + hardfork: 'london', + accounts: [ + { + secretKey: + '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', + balance: convertToHexValue(25000000000000000000), + }, + ], + }; + await withFixtures( + { + fixtures: new FixtureBuilder() + .withTransactionControllerApprovedTransaction() + .build(), + ganacheOptions, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + await driver.clickElement('[data-testid="home__activity-tab"]'); + await driver.wait(async () => { + const confirmedTxes = await driver.findElements( + '.transaction-list__completed-transactions .transaction-list-item', + ); + return confirmedTxes.length === 1; + }, 10000); + + const txValues = await driver.findElements( + '.transaction-list-item__primary-currency', + ); + assert.equal(txValues.length, 1); + assert.ok(/-1\s*ETH/u.test(await txValues[0].getText())); + }, + ); + }); +}); diff --git a/test/e2e/tests/threebox.spec.js b/test/e2e/tests/threebox.spec.js deleted file mode 100644 index 162108e80..000000000 --- a/test/e2e/tests/threebox.spec.js +++ /dev/null @@ -1,92 +0,0 @@ -const { convertToHexValue, withFixtures, largeDelayMs } = require('../helpers'); -const ThreeboxMockServer = require('../mock-3box/threebox-mock-server'); - -describe('Threebox', function () { - const ganacheOptions = { - accounts: [ - { - secretKey: - '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', - balance: convertToHexValue(25000000000000000000), - }, - ], - }; - let threeboxServer; - before(async function () { - threeboxServer = new ThreeboxMockServer(); - await threeboxServer.start(); - }); - after(async function () { - await threeboxServer.stop(); - }); - - it('Set up data to be restored by 3box', async function () { - await withFixtures( - { - fixtures: 'imported-account', - ganacheOptions, - title: this.test.title, - }, - async ({ driver }) => { - await driver.navigate(); - await driver.fill('#password', 'correct horse battery staple'); - await driver.press('#password', driver.Key.ENTER); - - // turns on threebox syncing - await driver.clickElement('.account-menu__icon'); - await driver.clickElement({ text: 'Settings', tag: 'div' }); - - // turns on threebox syncing - await driver.clickElement({ text: 'Advanced', tag: 'div' }); - await driver.clickElement( - '[data-testid="advanced-setting-3box"] .toggle-button div', - ); - - // updates settings and address book - // navigates to General settings - await driver.clickElement({ text: 'General', tag: 'div' }); - - // turns on use of blockies - await driver.clickElement('.toggle-button > div'); - - // adds an address to the contact list - await driver.clickElement({ text: 'Contacts', tag: 'div' }); - - await driver.clickElement('.address-book__link'); - await driver.fill('#nickname', 'Test User Name 11'); - await driver.fill( - 'input[placeholder="Search, public address (0x), or ENS"]', - '0x2f318C334780961FB129D2a6c30D0763d9a5C970', - ); - await driver.delay(largeDelayMs * 2); - await driver.clickElement({ text: 'Save', tag: 'button' }); - await driver.findElement({ text: 'Test User Name 11', tag: 'div' }); - }, - ); - }); - it('Restore from 3box', async function () { - await withFixtures( - { - fixtures: 'threebox-enabled', - ganacheOptions, - title: this.test.title, - }, - async ({ driver }) => { - await driver.navigate(); - await driver.fill('#password', 'correct horse battery staple'); - await driver.press('#password', driver.Key.ENTER); - - // confirms the 3box restore notification - await driver.clickElement('.home-notification__accept-button'); - - // goes to the settings screen - await driver.clickElement('.account-menu__icon'); - await driver.clickElement({ text: 'Settings', tag: 'div' }); - - // finds the restored address in the contact list - await driver.clickElement({ text: 'Contacts', tag: 'div' }); - await driver.findElement({ text: 'Test User Name 11', tag: 'div' }); - }, - ); - }); -}); diff --git a/test/e2e/tests/token-details.spec.js b/test/e2e/tests/token-details.spec.js index fd93d7d0f..56372bc0a 100644 --- a/test/e2e/tests/token-details.spec.js +++ b/test/e2e/tests/token-details.spec.js @@ -1,5 +1,6 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); describe('Token Details', function () { const ganacheOptions = { @@ -14,7 +15,7 @@ describe('Token Details', function () { it('should show token details for an imported token', async function () { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, title: this.test.title, }, diff --git a/test/e2e/user-actions-benchmark.js b/test/e2e/user-actions-benchmark.js index f91f6c318..821e1b92a 100644 --- a/test/e2e/user-actions-benchmark.js +++ b/test/e2e/user-actions-benchmark.js @@ -8,6 +8,7 @@ const { getFirstParentDirectoryThatExists, } = require('../helpers/file'); const { convertToHexValue, withFixtures } = require('./helpers'); +const FixtureBuilder = require('./fixture-builder'); const ganacheOptions = { accounts: [ @@ -24,7 +25,7 @@ async function loadNewAccount() { await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, }, async ({ driver }) => { @@ -52,7 +53,7 @@ async function confirmTx() { let loadingTimes; await withFixtures( { - fixtures: 'imported-account', + fixtures: new FixtureBuilder().build(), ganacheOptions, }, async ({ driver }) => { diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index 485d32d56..378a0e873 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -161,6 +161,14 @@ class Driver { return wrapElementWithAPI(element, this); } + async waitForNonEmptyElement(element) { + await this.driver.wait(async () => { + const elemText = await element.getText(); + const empty = elemText === ''; + return !empty; + }, this.timeout); + } + async quit() { await this.driver.quit(); } diff --git a/test/env.js b/test/env.js index 38e4a6fed..b932b2a42 100644 --- a/test/env.js +++ b/test/env.js @@ -1 +1,10 @@ process.env.METAMASK_ENV = 'test'; + +/** + * Used for testing components that use the Icon component + * 'ui/components/component-library/icon/icon.js' + */ +process.env.ICON_NAMES = { + LOADING_FILLED: 'loading-filled', + CLOSE_OUTLINE: 'close-outline', +}; diff --git a/test/jest/index.js b/test/jest/index.js index 9e6510ca8..1b4174afa 100644 --- a/test/jest/index.js +++ b/test/jest/index.js @@ -1,4 +1,4 @@ -export { screen, fireEvent } from '@testing-library/react'; +export { screen, fireEvent, waitFor } from '@testing-library/react'; export { createSwapsMockStore } from './mock-store'; export { renderWithProvider } from './rendering'; export { setBackgroundConnection } from './background'; diff --git a/test/jest/mock-store.js b/test/jest/mock-store.js index 54345e831..334d3fe85 100644 --- a/test/jest/mock-store.js +++ b/test/jest/mock-store.js @@ -120,6 +120,13 @@ export const createSwapsMockStore = () => { }, }, fromToken: 'ETH', + toToken: { + symbol: 'USDC', + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + occurances: 4, + }, + currentSmartTransactionsErrorMessageDismissed: false, + swapsSTXLoading: false, }, metamask: { networkDetails: { @@ -314,10 +321,10 @@ export const createSwapsMockStore = () => { fetchParams: { metaData: { sourceTokenInfo: { - symbol: 'BAT', + symbol: 'ETH', }, destinationTokenInfo: { - symbol: 'ETH', + symbol: 'USDC', }, }, }, @@ -326,6 +333,10 @@ export const createSwapsMockStore = () => { quotesLastFetched: 1519211809934, swapsQuoteRefreshTime: 60000, swapsQuotePrefetchingRefreshTime: 60000, + swapsStxBatchStatusRefreshTime: 5000, + swapsStxGetTransactionsRefreshTime: 5000, + swapsStxMaxFeeMultiplier: 1.5, + swapsStxStatusDeadline: 150000, customMaxGas: '', customGasPrice: null, selectedAggId: 'TEST_AGG_2', @@ -412,6 +423,7 @@ export const createSwapsMockStore = () => { { uuid: 'uuid2', status: 'success', + cancellable: false, statusMetadata: { cancellationFeeWei: 36777567771000, cancellationReason: 'not_cancelled', @@ -424,6 +436,7 @@ export const createSwapsMockStore = () => { { uuid: 'uuid2', status: 'pending', + cancellable: true, statusMetadata: { cancellationFeeWei: 36777567771000, cancellationReason: 'not_cancelled', diff --git a/ui/components/app/app-components.scss b/ui/components/app/app-components.scss index afa8734b2..ed008d5f0 100644 --- a/ui/components/app/app-components.scss +++ b/ui/components/app/app-components.scss @@ -97,3 +97,4 @@ @import 'detected-token/detected-token-ignored-popover/index'; @import 'detected-token/detected-token-selection-popover/index'; @import 'network-account-balance-header/index'; +@import 'approve-content-card/index'; diff --git a/ui/components/app/approve-content-card/approve-content-card.js b/ui/components/app/approve-content-card/approve-content-card.js new file mode 100644 index 000000000..34b7e3ee9 --- /dev/null +++ b/ui/components/app/approve-content-card/approve-content-card.js @@ -0,0 +1,241 @@ +import React, { useContext } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import Box from '../../ui/box/box'; +import Button from '../../ui/button'; +import EditGasFeeButton from '../edit-gas-fee-button/edit-gas-fee-button'; +import Typography from '../../ui/typography/typography'; +import { + ALIGN_ITEMS, + BLOCK_SIZES, + COLORS, + DISPLAY, + FLEX_DIRECTION, + FONT_WEIGHT, + JUSTIFY_CONTENT, + TEXT_ALIGN, + TYPOGRAPHY, +} from '../../../helpers/constants/design-system'; +import { I18nContext } from '../../../../.storybook/i18n'; +import GasDetailsItem from '../gas-details-item/gas-details-item'; +import MultiLayerFeeMessage from '../multilayer-fee-message/multi-layer-fee-message'; +import { formatCurrency } from '../../../helpers/utils/confirm-tx.util'; + +export default function ApproveContentCard({ + showHeader = true, + symbol, + title, + showEdit, + showAdvanceGasFeeOptions = false, + onEditClick, + footer, + noBorder, + supportsEIP1559V2, + renderTransactionDetailsContent, + renderDataContent, + isMultiLayerFeeNetwork, + ethTransactionTotal, + nativeCurrency, + fullTxData, + hexTransactionTotal, + fiatTransactionTotal, + currentCurrency, + isSetApproveForAll, + isApprovalOrRejection, + data, +}) { + const t = useContext(I18nContext); + + return ( + + {showHeader && ( + + {supportsEIP1559V2 && title === t('transactionFee') ? null : ( + <> + + {symbol} + + + + {title} + + + + )} + {showEdit && (!showAdvanceGasFeeOptions || !supportsEIP1559V2) && ( + + + + )} + {showEdit && showAdvanceGasFeeOptions && supportsEIP1559V2 && ( + + )} + + )} + + {renderTransactionDetailsContent && + (!isMultiLayerFeeNetwork && supportsEIP1559V2 ? ( + + ) : ( + + {isMultiLayerFeeNetwork ? ( + + + + {t('transactionDetailLayer2GasHeading')} + {`${ethTransactionTotal} ${nativeCurrency}`} + + + + + ) : ( + <> + + + {t('feeAssociatedRequest')} + + + + + + {formatCurrency(fiatTransactionTotal, currentCurrency)} + + + + + {`${ethTransactionTotal} ${nativeCurrency}`} + + + + + )} + + ))} + {renderDataContent && ( + + + + {isSetApproveForAll + ? t('functionSetApprovalForAll') + : t('functionApprove')} + + + {isSetApproveForAll && isApprovalOrRejection !== undefined ? ( + + + {`${t('parameters')}: ${isApprovalOrRejection}`} + + + ) : null} + + + {data} + + + + )} + + {footer} + + ); +} + +ApproveContentCard.propTypes = { + showHeader: PropTypes.bool, + symbol: PropTypes.node, + title: PropTypes.string, + showEdit: PropTypes.bool, + showAdvanceGasFeeOptions: PropTypes.bool, + onEditClick: PropTypes.func, + footer: PropTypes.node, + noBorder: PropTypes.bool, + supportsEIP1559V2: PropTypes.bool, + renderTransactionDetailsContent: PropTypes.bool, + renderDataContent: PropTypes.bool, + isMultiLayerFeeNetwork: PropTypes.bool, + ethTransactionTotal: PropTypes.string, + nativeCurrency: PropTypes.string, + fullTxData: PropTypes.object, + hexTransactionTotal: PropTypes.string, + fiatTransactionTotal: PropTypes.string, + currentCurrency: PropTypes.string, + isSetApproveForAll: PropTypes.bool, + isApprovalOrRejection: PropTypes.bool, + data: PropTypes.string, +}; diff --git a/ui/components/app/approve-content-card/index.js b/ui/components/app/approve-content-card/index.js new file mode 100644 index 000000000..02838ddb5 --- /dev/null +++ b/ui/components/app/approve-content-card/index.js @@ -0,0 +1 @@ +export { default } from './approve-content-card'; diff --git a/ui/components/app/approve-content-card/index.scss b/ui/components/app/approve-content-card/index.scss new file mode 100644 index 000000000..8dd9badc1 --- /dev/null +++ b/ui/components/app/approve-content-card/index.scss @@ -0,0 +1,51 @@ +.approve-content-card-container { + &__card, + &__card--no-border { + border-bottom: 1px solid var(--color-border-default); + position: relative; + padding-inline-start: 24px; + padding-inline-end: 24px; + } + + &__card--no-border { + border-bottom: none; + } + + &__card-header { + position: relative; + + &__symbol { + width: auto; + } + + &__symbol--aligned { + width: 100%; + } + + &__title { + width: 100%; + } + + &__title--aligned { + margin-inline-start: 27px; + position: absolute; + width: auto; + } + } + + &__card-content--aligned { + margin-inline-start: 42px; + } + + &__transaction-details-extra-content { + width: 100%; + } + + &__data { + width: 100%; + + &__data-block { + overflow-wrap: break-word; + } + } +} diff --git a/ui/components/app/asset-list-item/asset-list-item.js b/ui/components/app/asset-list-item/asset-list-item.js index bc19aff87..f05992bb4 100644 --- a/ui/components/app/asset-list-item/asset-list-item.js +++ b/ui/components/app/asset-list-item/asset-list-item.js @@ -111,6 +111,7 @@ const AssetListItem = ({ title={ @@ -105,6 +136,19 @@ export default function ContractDetailsModal({ onClose, address, tokenName }) { @@ -173,6 +238,19 @@ export default function ContractDetailsModal({ onClose, address, tokenName }) { - ); } ContractDetailsModal.propTypes = { + /** + * Function that should close the modal + */ onClose: PropTypes.func, - address: PropTypes.string, + /** + * Name of the token that is waiting to be allowed + */ tokenName: PropTypes.string, + /** + * Address of the token that is waiting to be allowed + */ + tokenAddress: PropTypes.string, + /** + * Contract address requesting spending cap + */ + toAddress: PropTypes.string, + /** + * Current network chainId + */ + chainId: PropTypes.string, + /** + * RPC prefs of the current network + */ + rpcPrefs: PropTypes.object, + /** + * Dapp URL + */ + origin: PropTypes.string, + /** + * Dapp image + */ + siteImage: PropTypes.string, }; diff --git a/ui/components/app/modals/contract-details-modal/contract-details-modal.stories.js b/ui/components/app/modals/contract-details-modal/contract-details-modal.stories.js index 8cf6272fc..fb022d134 100644 --- a/ui/components/app/modals/contract-details-modal/contract-details-modal.stories.js +++ b/ui/components/app/modals/contract-details-modal/contract-details-modal.stories.js @@ -1,23 +1,44 @@ -import React, { useState } from 'react'; -import Button from '../../../ui/button'; +import React from 'react'; import ContractDetailsModal from './contract-details-modal'; export default { title: 'Components/App/Modals/ContractDetailsModal', id: __filename, argTypes: { - onClosePopover: { - action: 'Close Contract Details', - }, - onOpenPopover: { - action: 'Open Contract Details', + onClose: { + action: 'onClose', }, tokenName: { control: { type: 'text', }, }, - address: { + tokenAddress: { + control: { + type: 'text', + }, + }, + toAddress: { + control: { + type: 'text', + }, + }, + chainId: { + control: { + type: 'text', + }, + }, + rpcPrefs: { + control: { + type: 'object', + }, + }, + origin: { + control: { + type: 'text', + }, + }, + siteImage: { control: { type: 'text', }, @@ -25,33 +46,17 @@ export default { }, args: { tokenName: 'DAI', - address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + tokenAddress: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + toAddress: '0x9bc5baf874d2da8d216ae9f137804184ee5afef4', + chainId: '0x3', + rpcPrefs: {}, + origin: 'https://metamask.github.io', + siteImage: 'https://metamask.github.io/test-dapp/metamask-fox.svg', }, }; export const DefaultStory = (args) => { - const [showContractDetails, setshowContractDetails] = useState(false); - return ( - <> - - {showContractDetails && ( - { - args.onClosePopover(); - setshowContractDetails(false); - }} - {...args} - /> - )} - - ); + return ; }; DefaultStory.storyName = 'Default'; diff --git a/ui/components/app/modals/contract-details-modal/index.scss b/ui/components/app/modals/contract-details-modal/index.scss index b36649fd7..52af5a240 100644 --- a/ui/components/app/modals/contract-details-modal/index.scss +++ b/ui/components/app/modals/contract-details-modal/index.scss @@ -9,6 +9,10 @@ margin: 16px 16px 38px 16px; } + &__identicon-for-unknown-contact { + margin: 16px; + } + &__buttons { flex-grow: 1; @@ -22,10 +26,4 @@ } } } - - &__footer { - button + button { - margin-inline-start: 1rem; - } - } } diff --git a/ui/components/app/modals/reject-transactions/__snapshots__/reject-transactions.test.js.snap b/ui/components/app/modals/reject-transactions/__snapshots__/reject-transactions.test.js.snap new file mode 100644 index 000000000..5d993d8a3 --- /dev/null +++ b/ui/components/app/modals/reject-transactions/__snapshots__/reject-transactions.test.js.snap @@ -0,0 +1,52 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Reject Transactions Model should match snapshot 1`] = ` +
+ +`; diff --git a/ui/components/app/modals/reject-transactions/reject-transactions.test.js b/ui/components/app/modals/reject-transactions/reject-transactions.test.js index e8ec7a7b5..ce61a0c04 100644 --- a/ui/components/app/modals/reject-transactions/reject-transactions.test.js +++ b/ui/components/app/modals/reject-transactions/reject-transactions.test.js @@ -1,45 +1,44 @@ import React from 'react'; -import sinon from 'sinon'; -import { mount } from 'enzyme'; -import RejectTransactionsModal from './reject-transactions.container'; +import { fireEvent, waitFor } from '@testing-library/react'; +import { renderWithProvider } from '../../../../../test/lib/render-helpers'; +import RejectTransactionsModal from '.'; describe('Reject Transactions Model', () => { - let wrapper; - const props = { - onSubmit: sinon.spy(), - hideModal: sinon.spy(), + onSubmit: jest.fn(), + hideModal: jest.fn(), unapprovedTxCount: 2, }; - beforeEach(() => { - wrapper = mount(, { - context: { - t: (str) => str, - }, - }); - }); + it('should match snapshot', () => { + const { container } = renderWithProvider( + , + ); - afterEach(() => { - props.hideModal.resetHistory(); + expect(container).toMatchSnapshot(); }); it('hides modal when cancel button is clicked', () => { - const cancelButton = wrapper.find( - '.btn-secondary.modal-container__footer-button', + const { queryByText } = renderWithProvider( + , ); - cancelButton.simulate('click'); - expect(props.hideModal.calledOnce).toStrictEqual(true); + fireEvent.click(queryByText('[cancel]')); + + expect(props.onSubmit).not.toHaveBeenCalled(); + expect(props.hideModal).toHaveBeenCalled(); }); it('onSubmit is called and hides modal when reject all clicked', async () => { - const rejectAllButton = wrapper.find( - '.btn-primary.modal-container__footer-button', + const { queryByText } = renderWithProvider( + , ); - rejectAllButton.simulate('click'); - expect(await props.onSubmit.calledOnce).toStrictEqual(true); - expect(props.hideModal.calledOnce).toStrictEqual(true); + fireEvent.click(queryByText('[rejectAll]')); + + await waitFor(() => { + expect(props.onSubmit).toHaveBeenCalled(); + expect(props.hideModal).toHaveBeenCalled(); + }); }); }); diff --git a/ui/components/app/modals/transaction-confirmed/__snapshots__/transaction-confirmed.test.js.snap b/ui/components/app/modals/transaction-confirmed/__snapshots__/transaction-confirmed.test.js.snap new file mode 100644 index 000000000..becdc38e4 --- /dev/null +++ b/ui/components/app/modals/transaction-confirmed/__snapshots__/transaction-confirmed.test.js.snap @@ -0,0 +1,42 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Transaction Confirmed should match snapshot 1`] = ` +
+ +
+`; diff --git a/ui/components/app/modals/transaction-confirmed/transaction-confirmed.test.js b/ui/components/app/modals/transaction-confirmed/transaction-confirmed.test.js index 0e1658242..411324f4b 100644 --- a/ui/components/app/modals/transaction-confirmed/transaction-confirmed.test.js +++ b/ui/components/app/modals/transaction-confirmed/transaction-confirmed.test.js @@ -1,26 +1,30 @@ import React from 'react'; -import sinon from 'sinon'; -import { mount } from 'enzyme'; -import TransactionConfirmed from './transaction-confirmed.container'; +import { fireEvent } from '@testing-library/react'; +import { renderWithProvider } from '../../../../../test/lib/render-helpers'; +import TransactionConfirmed from '.'; describe('Transaction Confirmed', () => { + it('should match snapshot', () => { + const { container } = renderWithProvider( + , + ); + + expect(container).toMatchSnapshot(); + }); + it('clicks ok to submit and hide modal', () => { const props = { - onSubmit: sinon.spy(), - hideModal: sinon.spy(), + onSubmit: jest.fn(), + hideModal: jest.fn(), }; - const wrapper = mount( + + const { queryByText } = renderWithProvider( , - { - context: { - t: (str) => str, - }, - }, ); - const submit = wrapper.find('.btn-primary.modal-container__footer-button'); - submit.simulate('click'); - expect(props.onSubmit.calledOnce).toStrictEqual(true); - expect(props.hideModal.calledOnce).toStrictEqual(true); + fireEvent.click(queryByText('[ok]')); + + expect(props.onSubmit).toHaveBeenCalled(); + expect(props.hideModal).toHaveBeenCalled(); }); }); diff --git a/ui/components/app/permissions-connect-header/permissions-connect-header.component.js b/ui/components/app/permissions-connect-header/permissions-connect-header.component.js index 1b5484b13..dc2633be9 100644 --- a/ui/components/app/permissions-connect-header/permissions-connect-header.component.js +++ b/ui/components/app/permissions-connect-header/permissions-connect-header.component.js @@ -26,6 +26,7 @@ export default class PermissionsConnectHeader extends Component { headerTitle: PropTypes.node, boxProps: PropTypes.shape({ ...Box.propTypes }), headerText: PropTypes.string, + leftIcon: PropTypes.node, rightIcon: PropTypes.node, ///: BEGIN:ONLY_INCLUDE_IN(flask) snapVersion: PropTypes.string, @@ -45,6 +46,7 @@ export default class PermissionsConnectHeader extends Component { iconUrl, iconName, siteOrigin, + leftIcon, rightIcon, ///: BEGIN:ONLY_INCLUDE_IN(flask) isSnapInstallOrUpdate, @@ -64,6 +66,7 @@ export default class PermissionsConnectHeader extends Component { siteOrigin={siteOrigin} iconSrc={iconUrl} name={iconName} + leftIcon={leftIcon} rightIcon={rightIcon} />
diff --git a/ui/components/app/selected-account/__snapshots__/selected-account-component.test.js.snap b/ui/components/app/selected-account/__snapshots__/selected-account-component.test.js.snap new file mode 100644 index 000000000..30f4376f7 --- /dev/null +++ b/ui/components/app/selected-account/__snapshots__/selected-account-component.test.js.snap @@ -0,0 +1,56 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SelectedAccount Component should match snapshot 1`] = ` +
+ +
+`; diff --git a/ui/components/app/selected-account/selected-account-component.test.js b/ui/components/app/selected-account/selected-account-component.test.js index bc55c7e7e..d2bd5197d 100644 --- a/ui/components/app/selected-account/selected-account-component.test.js +++ b/ui/components/app/selected-account/selected-account-component.test.js @@ -1,24 +1,32 @@ import React from 'react'; -import { render } from 'enzyme'; -import SelectedAccount from './selected-account.component'; +import configureMockStore from 'redux-mock-store'; +import copyToClipboard from 'copy-to-clipboard'; +import { fireEvent } from '@testing-library/react'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import mockState from '../../../../test/data/mock-state.json'; +import SelectedAccount from '.'; + +jest.mock('copy-to-clipboard'); describe('SelectedAccount Component', () => { - it('should render checksummed address', () => { - const wrapper = render( - , - { context: { t: () => undefined } }, - ); - // Checksummed version of address is displayed - expect(wrapper.find('.selected-account__address').text()).toStrictEqual( - '0x1B8...5C9D', + const mockStore = configureMockStore()(mockState); + + it('should match snapshot', () => { + const { container } = renderWithProvider(, mockStore); + + expect(container).toMatchSnapshot(); + }); + + it('should copy checksum address to clipboard when button is clicked', () => { + const { queryByTestId } = renderWithProvider( + , + mockStore, ); - expect(wrapper.find('.selected-account__name').text()).toStrictEqual( - 'testName', + + fireEvent.click(queryByTestId('selected-account-click')); + + expect(copyToClipboard).toHaveBeenCalledWith( + '0x0DCD5D886577d5081B0c52e242Ef29E70Be3E7bc', ); }); }); diff --git a/ui/components/app/selected-account/selected-account.component.js b/ui/components/app/selected-account/selected-account.component.js index 06609b54f..df7b07e18 100644 --- a/ui/components/app/selected-account/selected-account.component.js +++ b/ui/components/app/selected-account/selected-account.component.js @@ -48,6 +48,7 @@ class SelectedAccount extends Component { > + +
+

+ $0.52 USD +

+
+ + + +`; diff --git a/ui/components/app/token-cell/token-cell.test.js b/ui/components/app/token-cell/token-cell.test.js index e7fe6069b..8179047e8 100644 --- a/ui/components/app/token-cell/token-cell.test.js +++ b/ui/components/app/token-cell/token-cell.test.js @@ -1,18 +1,12 @@ import React from 'react'; import thunk from 'redux-thunk'; -import { Provider } from 'react-redux'; import configureMockStore from 'redux-mock-store'; -import { mount } from 'enzyme'; -import sinon from 'sinon'; -import { MemoryRouter } from 'react-router-dom'; - -import Identicon from '../../ui/identicon'; +import { fireEvent } from '@testing-library/react'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; import TokenCell from '.'; describe('Token Cell', () => { - let wrapper; - - const state = { + const mockState = { metamask: { currentCurrency: 'usd', selectedAddress: '0xAddress', @@ -29,60 +23,33 @@ describe('Token Cell', () => { }, }; - const middlewares = [thunk]; - const mockStore = configureMockStore(middlewares); - const store = mockStore(state); + const mockStore = configureMockStore([thunk])(mockState); - let onClick; + const props = { + address: '0xAnotherToken', + symbol: 'TEST', + string: '5.000', + currentCurrency: 'usd', + onClick: jest.fn(), + }; - beforeEach(() => { - onClick = sinon.stub(); - wrapper = mount( - - - - - , + it('should match snapshot', () => { + const { container } = renderWithProvider( + , + mockStore, ); - }); - afterEach(() => { - sinon.restore(); + expect(container).toMatchSnapshot(); }); - it('renders Identicon with props from token cell', () => { - expect(wrapper.find(Identicon).prop('address')).toStrictEqual( - '0xAnotherToken', - ); - }); - - it('renders token balance', () => { - expect(wrapper.find('.asset-list-item__token-value').text()).toStrictEqual( - '5.000', - ); - }); - - it('renders token symbol', () => { - expect(wrapper.find('.asset-list-item__token-symbol').text()).toStrictEqual( - 'TEST', + it('calls onClick when clicked', () => { + const { queryByTestId } = renderWithProvider( + , + mockStore, ); - }); - it('renders converted fiat amount', () => { - expect(wrapper.find('.list-item__subheading').text()).toStrictEqual( - '$0.52 USD', - ); - }); + fireEvent.click(queryByTestId('token-button')); - it('calls onClick when clicked', () => { - expect(!onClick.called).toStrictEqual(true); - wrapper.simulate('click'); - expect(onClick.called).toStrictEqual(true); + expect(props.onClick).toHaveBeenCalled(); }); }); diff --git a/ui/components/app/transaction-activity-log/__snapshots__/transaction-activity-log.component.test.js.snap b/ui/components/app/transaction-activity-log/__snapshots__/transaction-activity-log.component.test.js.snap new file mode 100644 index 000000000..cc5eeea68 --- /dev/null +++ b/ui/components/app/transaction-activity-log/__snapshots__/transaction-activity-log.component.test.js.snap @@ -0,0 +1,103 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TransactionActivityLog Component should match snapshot 1`] = ` +
+
+
+ [activityLog] +
+
+
+
+ +
+
+
+ [transactionCreated] +
+
+
+
+
+ +
+
+
+ [transactionSubmitted] +
+
+
+
+
+ +
+
+
+ [transactionResubmitted] +
+
+
+
+
+ +
+
+
+ [transactionConfirmed] +
+
+
+
+
+
+`; diff --git a/ui/components/app/transaction-activity-log/transaction-activity-log.component.test.js b/ui/components/app/transaction-activity-log/transaction-activity-log.component.test.js index 1c80d9fa9..3308136d1 100644 --- a/ui/components/app/transaction-activity-log/transaction-activity-log.component.test.js +++ b/ui/components/app/transaction-activity-log/transaction-activity-log.component.test.js @@ -1,163 +1,55 @@ import React from 'react'; -import { shallow } from 'enzyme'; -import TransactionActivityLog from './transaction-activity-log.component'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import TransactionActivityLog from '.'; describe('TransactionActivityLog Component', () => { - it('should render properly', () => { - const activities = [ - { - eventKey: 'transactionCreated', - hash: '0xe46c7f9b39af2fbf1c53e66f72f80343ab54c2c6dba902d51fb98ada08fe1a63', - id: 2005383477493174, - timestamp: 1543957986150, - value: '0x2386f26fc10000', - }, - { - eventKey: 'transactionSubmitted', - hash: '0xe46c7f9b39af2fbf1c53e66f72f80343ab54c2c6dba902d51fb98ada08fe1a63', - id: 2005383477493174, - timestamp: 1543957987853, - value: '0x1319718a5000', - }, - { - eventKey: 'transactionResubmitted', - hash: '0x7d09d337fc6f5d6fe2dbf3a6988d69532deb0a82b665f9180b5a20db377eea87', - id: 2005383477493175, - timestamp: 1543957991563, - value: '0x1502634b5800', - }, - { - eventKey: 'transactionConfirmed', - hash: '0x7d09d337fc6f5d6fe2dbf3a6988d69532deb0a82b665f9180b5a20db377eea87', - id: 2005383477493175, - timestamp: 1543958029960, - value: '0x1502634b5800', - }, - ]; - - const wrapper = shallow( - undefined} - onRetry={() => undefined} - primaryTransactionStatus="confirmed" - />, - { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, + const activities = [ + { + eventKey: 'transactionCreated', + hash: '0xe46c7f9b39af2fbf1c53e66f72f80343ab54c2c6dba902d51fb98ada08fe1a63', + id: 2005383477493174, + timestamp: 1543957986150, + value: '0x2386f26fc10000', + }, + { + eventKey: 'transactionSubmitted', + hash: '0xe46c7f9b39af2fbf1c53e66f72f80343ab54c2c6dba902d51fb98ada08fe1a63', + id: 2005383477493174, + timestamp: 1543957987853, + value: '0x1319718a5000', + }, + { + eventKey: 'transactionResubmitted', + hash: '0x7d09d337fc6f5d6fe2dbf3a6988d69532deb0a82b665f9180b5a20db377eea87', + id: 2005383477493175, + timestamp: 1543957991563, + value: '0x1502634b5800', + }, + { + eventKey: 'transactionConfirmed', + hash: '0x7d09d337fc6f5d6fe2dbf3a6988d69532deb0a82b665f9180b5a20db377eea87', + id: 2005383477493175, + timestamp: 1543958029960, + value: '0x1502634b5800', + }, + ]; + + const props = { + activities, + className: 'test-class', + inlineRetryIndex: -1, + inlineCancelIndex: -1, + nativeCurrency: 'ETH', + onCancel: jest.fn(), + onRetry: jest.fn(), + primaryTransactionStatus: 'confirmed', + }; + + it('should match snapshot', () => { + const { container } = renderWithProvider( + , ); - expect(wrapper.hasClass('transaction-activity-log')).toStrictEqual(true); - expect(wrapper.hasClass('test-class')).toStrictEqual(true); - }); - - it('should render inline retry and cancel buttons for earliest pending transaction', () => { - const activities = [ - { - eventKey: 'transactionCreated', - hash: '0xa', - id: 1, - timestamp: 1, - value: '0x1', - }, - { - eventKey: 'transactionSubmitted', - hash: '0xa', - id: 1, - timestamp: 2, - value: '0x1', - }, - { - eventKey: 'transactionResubmitted', - hash: '0x7d09d337fc6f5d6fe2dbf3a6988d69532deb0a82b665f9180b5a20db377eea87', - id: 2, - timestamp: 3, - value: '0x1', - }, - { - eventKey: 'transactionCancelAttempted', - hash: '0x7d09d337fc6f5d6fe2dbf3a6988d69532deb0a82b665f9180b5a20db377eea87', - id: 3, - timestamp: 4, - value: '0x1', - }, - ]; - - const wrapper = shallow( - undefined} - onRetry={() => undefined} - primaryTransactionStatus="pending" - isEarliestNonce - />, - { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, - ); - - expect(wrapper.hasClass('transaction-activity-log')).toStrictEqual(true); - expect(wrapper.hasClass('test-class')).toStrictEqual(true); - expect(wrapper.find('.transaction-activity-log__action-link')).toHaveLength( - 2, - ); - }); - - it('should not render inline retry and cancel buttons for newer pending transactions', () => { - const activities = [ - { - eventKey: 'transactionCreated', - hash: '0xa', - id: 1, - timestamp: 1, - value: '0x1', - }, - { - eventKey: 'transactionSubmitted', - hash: '0xa', - id: 1, - timestamp: 2, - value: '0x1', - }, - { - eventKey: 'transactionResubmitted', - hash: '0x7d09d337fc6f5d6fe2dbf3a6988d69532deb0a82b665f9180b5a20db377eea87', - id: 2, - timestamp: 3, - value: '0x1', - }, - { - eventKey: 'transactionCancelAttempted', - hash: '0x7d09d337fc6f5d6fe2dbf3a6988d69532deb0a82b665f9180b5a20db377eea87', - id: 3, - timestamp: 4, - value: '0x1', - }, - ]; - - const wrapper = shallow( - undefined} - onRetry={() => undefined} - primaryTransactionStatus="pending" - isEarliestNonce={false} - />, - { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, - ); - - expect(wrapper.hasClass('transaction-activity-log')).toStrictEqual(true); - expect(wrapper.hasClass('test-class')).toStrictEqual(true); - expect(wrapper.find('.transaction-activity-log__action-link')).toHaveLength( - 0, - ); + expect(container).toMatchSnapshot(); }); }); diff --git a/ui/components/app/transaction-breakdown/transaction-breakdown-row/__snapshots__/transaction-breakdown-row.component.test.js.snap b/ui/components/app/transaction-breakdown/transaction-breakdown-row/__snapshots__/transaction-breakdown-row.component.test.js.snap new file mode 100644 index 000000000..3796099b9 --- /dev/null +++ b/ui/components/app/transaction-breakdown/transaction-breakdown-row/__snapshots__/transaction-breakdown-row.component.test.js.snap @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TransactionBreakdownRow Component should match snapshot 1`] = ` +
+
+
+ test +
+
+ +
+
+
+`; diff --git a/ui/components/app/transaction-breakdown/transaction-breakdown-row/transaction-breakdown-row.component.test.js b/ui/components/app/transaction-breakdown/transaction-breakdown-row/transaction-breakdown-row.component.test.js index 45117b571..0d0a8f3fc 100644 --- a/ui/components/app/transaction-breakdown/transaction-breakdown-row/transaction-breakdown-row.component.test.js +++ b/ui/components/app/transaction-breakdown/transaction-breakdown-row/transaction-breakdown-row.component.test.js @@ -1,40 +1,21 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { renderWithProvider } from '../../../../../test/lib/render-helpers'; import Button from '../../../ui/button'; -import TransactionBreakdownRow from './transaction-breakdown-row.component'; +import TransactionBreakdownRow from '.'; describe('TransactionBreakdownRow Component', () => { - it('should render text properly', () => { - const wrapper = shallow( - - Test - , - { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, - ); - - expect(wrapper.hasClass('transaction-breakdown-row')).toStrictEqual(true); - expect( - wrapper.find('.transaction-breakdown-row__title').text(), - ).toStrictEqual('test'); - expect( - wrapper.find('.transaction-breakdown-row__value').text(), - ).toStrictEqual('Test'); - }); + it('should match snapshot', () => { + const props = { + title: 'test', + className: 'test-class', + }; - it('should render components properly', () => { - const wrapper = shallow( - + const { container } = renderWithProvider( + , - { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, ); - expect(wrapper.hasClass('transaction-breakdown-row')).toStrictEqual(true); - expect( - wrapper.find('.transaction-breakdown-row__title').text(), - ).toStrictEqual('test'); - expect( - wrapper.find('.transaction-breakdown-row__value').find(Button), - ).toHaveLength(1); + expect(container).toMatchSnapshot(); }); }); diff --git a/ui/components/app/transaction-status/__snapshots__/transaction-status.component.test.js.snap b/ui/components/app/transaction-status/__snapshots__/transaction-status.component.test.js.snap new file mode 100644 index 000000000..14e5eefaa --- /dev/null +++ b/ui/components/app/transaction-status/__snapshots__/transaction-status.component.test.js.snap @@ -0,0 +1,60 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TransactionStatus Component should render CONFIRMED properly 1`] = ` +
+
+ June 1 +
+
+`; + +exports[`TransactionStatus Component should render PENDING properly 1`] = ` +
+
+ [pending] +
+
+`; + +exports[`TransactionStatus Component should render PENDING properly when status is APPROVED 1`] = ` +
+
+
+ [pending] +
+
+
+`; + +exports[`TransactionStatus Component should render QUEUED properly 1`] = ` +
+
+ [queued] +
+
+`; + +exports[`TransactionStatus Component should render UNAPPROVED properly 1`] = ` +
+
+ [unapproved] +
+
+`; diff --git a/ui/components/app/transaction-status/transaction-status.component.test.js b/ui/components/app/transaction-status/transaction-status.component.test.js index 220d898ff..068b47e25 100644 --- a/ui/components/app/transaction-status/transaction-status.component.test.js +++ b/ui/components/app/transaction-status/transaction-status.component.test.js @@ -1,63 +1,62 @@ import React from 'react'; -import { mount } from 'enzyme'; -import sinon from 'sinon'; -import * as i18nHook from '../../../hooks/useI18nContext'; -import Tooltip from '../../ui/tooltip'; -import TransactionStatus from './transaction-status.component'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import TransactionStatus from '.'; describe('TransactionStatus Component', () => { - beforeAll(() => { - sinon.stub(i18nHook, 'useI18nContext').returns((str) => str.toUpperCase()); - }); - - afterAll(() => { - sinon.restore(); - }); - it('should render CONFIRMED properly', () => { - const wrapper = mount( - , + const confirmedProps = { + status: 'confirmed', + date: 'June 1', + }; + + const { container } = renderWithProvider( + , ); - expect(wrapper.find(TransactionStatus)).toHaveLength(1); - expect(wrapper.text()).toStrictEqual('June 1'); + expect(container).toMatchSnapshot(); }); it('should render PENDING properly when status is APPROVED', () => { - const wrapper = mount( - , - ); + const props = { + status: 'approved', + isEarliestNonce: true, + error: { message: 'test-title' }, + }; - expect(wrapper.text()).toStrictEqual('PENDING'); - expect(wrapper.find(Tooltip).props().title).toStrictEqual('test-title'); + const { container } = renderWithProvider(); + + expect(container).toMatchSnapshot(); }); it('should render PENDING properly', () => { - const wrapper = mount( - , - ); + const props = { + date: 'June 1', + status: 'submitted', + isEarliestNonce: true, + }; + + const { container } = renderWithProvider(); - expect(wrapper.find(TransactionStatus)).toHaveLength(1); - expect(wrapper.text()).toStrictEqual('PENDING'); + expect(container).toMatchSnapshot(); }); it('should render QUEUED properly', () => { - const wrapper = mount(); + const props = { + status: 'queued', + }; - expect(wrapper.find(TransactionStatus)).toHaveLength(1); - expect(wrapper.find('.transaction-status--queued')).toHaveLength(1); - expect(wrapper.text()).toStrictEqual('QUEUED'); + const { container } = renderWithProvider(); + + expect(container).toMatchSnapshot(); }); it('should render UNAPPROVED properly', () => { - const wrapper = mount(); + const props = { + status: 'unapproved', + }; + + const { container } = renderWithProvider(); - expect(wrapper.find(TransactionStatus)).toHaveLength(1); - expect(wrapper.find('.transaction-status--unapproved')).toHaveLength(1); - expect(wrapper.text()).toStrictEqual('UNAPPROVED'); + expect(container).toMatchSnapshot(); }); }); diff --git a/ui/components/app/user-preferenced-currency-display/__snapshots__/user-preferenced-currency-display.test.js.snap b/ui/components/app/user-preferenced-currency-display/__snapshots__/user-preferenced-currency-display.test.js.snap new file mode 100644 index 000000000..61224fdb0 --- /dev/null +++ b/ui/components/app/user-preferenced-currency-display/__snapshots__/user-preferenced-currency-display.test.js.snap @@ -0,0 +1,24 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`UserPreferencedCurrencyDisplay Component rendering should match snapshot 1`] = ` +
+
+ + + 0 + + + ETH + +
+
+`; diff --git a/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.test.js b/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.test.js deleted file mode 100644 index 6c73d7576..000000000 --- a/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.test.js +++ /dev/null @@ -1,41 +0,0 @@ -import React from 'react'; -import { shallow } from 'enzyme'; -import sinon from 'sinon'; -import CurrencyDisplay from '../../ui/currency-display'; -import * as currencyHook from '../../../hooks/useCurrencyDisplay'; -import * as currencyPrefHook from '../../../hooks/useUserPreferencedCurrency'; -import UserPreferencedCurrencyDisplay from '.'; - -describe('UserPreferencedCurrencyDisplay Component', () => { - describe('rendering', () => { - beforeEach(() => { - sinon.stub(currencyHook, 'useCurrencyDisplay').returns(['1', {}]); - sinon - .stub(currencyPrefHook, 'useUserPreferencedCurrency') - .returns({ currency: 'ETH', decimals: 6 }); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('should render properly', () => { - const wrapper = shallow(); - - expect(wrapper).toHaveLength(1); - expect(wrapper.find(CurrencyDisplay)).toHaveLength(1); - }); - - it('should pass all props to the CurrencyDisplay child component', () => { - const wrapper = shallow( - , - ); - - expect(wrapper).toHaveLength(1); - expect(wrapper.find(CurrencyDisplay)).toHaveLength(1); - expect(wrapper.find(CurrencyDisplay).props().prop1).toStrictEqual(true); - expect(wrapper.find(CurrencyDisplay).props().prop2).toStrictEqual('test'); - expect(wrapper.find(CurrencyDisplay).props().prop3).toStrictEqual(1); - }); - }); -}); diff --git a/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.test.js b/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.test.js new file mode 100644 index 000000000..046964bb3 --- /dev/null +++ b/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.test.js @@ -0,0 +1,29 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import UserPreferencedCurrencyDisplay from '.'; + +describe('UserPreferencedCurrencyDisplay Component', () => { + describe('rendering', () => { + const mockState = { + metamask: { + provider: { + chainId: '0x99', + }, + preferences: { + useNativeCurrencyAsPrimaryCurrency: true, + }, + }, + }; + const mockStore = configureMockStore()(mockState); + + it('should match snapshot', () => { + const { container } = renderWithProvider( + , + mockStore, + ); + + expect(container).toMatchSnapshot(); + }); + }); +}); diff --git a/ui/components/app/user-preferenced-currency-input/__snapshots__/user-preferenced-currency-input.test.js.snap b/ui/components/app/user-preferenced-currency-input/__snapshots__/user-preferenced-currency-input.test.js.snap new file mode 100644 index 000000000..a2423f00b --- /dev/null +++ b/ui/components/app/user-preferenced-currency-input/__snapshots__/user-preferenced-currency-input.test.js.snap @@ -0,0 +1,45 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`UserPreferencedCurrencyInput Component rendering should match snapshot 1`] = ` +
+
+
+
+ +
+ ETH +
+
+
+ No conversion rate available +
+
+ +
+
+`; diff --git a/ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.component.test.js b/ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.component.test.js deleted file mode 100644 index 39c3bb736..000000000 --- a/ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.component.test.js +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react'; -import { shallow } from 'enzyme'; -import CurrencyInput from '../currency-input'; -import UserPreferencedCurrencyInput from './user-preferenced-currency-input.component'; - -describe('UserPreferencedCurrencyInput Component', () => { - describe('rendering', () => { - it('should render properly', () => { - const wrapper = shallow(); - - expect(wrapper).toHaveLength(1); - expect(wrapper.find(CurrencyInput)).toHaveLength(1); - }); - - it('should render featureSecondary for CurrencyInput based on preferences.useNativeCurrencyAsPrimaryCurrency', () => { - const wrapper = shallow( - , - ); - - expect(wrapper).toHaveLength(1); - expect(wrapper.find(CurrencyInput)).toHaveLength(1); - expect( - wrapper.find(CurrencyInput).props().featureSecondary, - ).toStrictEqual(false); - wrapper.setProps({ useNativeCurrencyAsPrimaryCurrency: false }); - expect( - wrapper.find(CurrencyInput).props().featureSecondary, - ).toStrictEqual(true); - }); - }); -}); diff --git a/ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.test.js b/ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.test.js deleted file mode 100644 index 93e3cb81b..000000000 --- a/ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.test.js +++ /dev/null @@ -1,32 +0,0 @@ -/* eslint-disable import/unambiguous */ -let mapStateToProps; - -jest.mock('react-redux', () => ({ - connect: (ms) => { - mapStateToProps = ms; - return () => ({}); - }, -})); - -require('./user-preferenced-currency-input.container'); - -describe('UserPreferencedCurrencyInput container', () => { - describe('mapStateToProps()', () => { - it('should return the correct props', () => { - const mockState = { - metamask: { - preferences: { - useNativeCurrencyAsPrimaryCurrency: true, - }, - }, - appState: { - sendInputCurrencySwitched: false, - }, - }; - expect(mapStateToProps(mockState)).toStrictEqual({ - useNativeCurrencyAsPrimaryCurrency: true, - sendInputCurrencySwitched: false, - }); - }); - }); -}); diff --git a/ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.test.js b/ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.test.js new file mode 100644 index 000000000..fcf74fb52 --- /dev/null +++ b/ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.test.js @@ -0,0 +1,20 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import mockState from '../../../../test/data/mock-state.json'; +import UserPreferencedCurrencyInput from '.'; + +describe('UserPreferencedCurrencyInput Component', () => { + describe('rendering', () => { + it('should match snapshot', () => { + const mockStore = configureMockStore()(mockState); + + const { container } = renderWithProvider( + , + mockStore, + ); + + expect(container).toMatchSnapshot(); + }); + }); +}); diff --git a/ui/components/app/user-preferenced-token-input/__snapshots__/user-preferenced-token-input.test.js.snap b/ui/components/app/user-preferenced-token-input/__snapshots__/user-preferenced-token-input.test.js.snap new file mode 100644 index 000000000..ac57f21ac --- /dev/null +++ b/ui/components/app/user-preferenced-token-input/__snapshots__/user-preferenced-token-input.test.js.snap @@ -0,0 +1,31 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`UserPreferencedCurrencyInput Component rendering should match snapshot 1`] = ` +
+
+
+
+ +
+
+ No conversion rate available +
+
+
+
+`; diff --git a/ui/components/app/user-preferenced-token-input/user-preferenced-token-input.component.test.js b/ui/components/app/user-preferenced-token-input/user-preferenced-token-input.component.test.js deleted file mode 100644 index 70e4ca0eb..000000000 --- a/ui/components/app/user-preferenced-token-input/user-preferenced-token-input.component.test.js +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import { shallow } from 'enzyme'; -import TokenInput from '../../ui/token-input'; -import UserPreferencedTokenInput from './user-preferenced-token-input.component'; - -describe('UserPreferencedCurrencyInput Component', () => { - describe('rendering', () => { - it('should render properly', () => { - const wrapper = shallow( - , - ); - - expect(wrapper).toHaveLength(1); - expect(wrapper.find(TokenInput)).toHaveLength(1); - }); - - it('should render showFiat for TokenInput based on preferences.useNativeCurrencyAsPrimaryCurrency', () => { - const wrapper = shallow( - , - ); - - expect(wrapper).toHaveLength(1); - expect(wrapper.find(TokenInput)).toHaveLength(1); - expect(wrapper.find(TokenInput).props().showFiat).toStrictEqual(false); - wrapper.setProps({ useNativeCurrencyAsPrimaryCurrency: false }); - expect(wrapper.find(TokenInput).props().showFiat).toStrictEqual(true); - }); - }); -}); diff --git a/ui/components/app/user-preferenced-token-input/user-preferenced-token-input.container.test.js b/ui/components/app/user-preferenced-token-input/user-preferenced-token-input.container.test.js deleted file mode 100644 index 8c94ffa44..000000000 --- a/ui/components/app/user-preferenced-token-input/user-preferenced-token-input.container.test.js +++ /dev/null @@ -1,29 +0,0 @@ -// eslint-disable-next-line import/unambiguous -let mapStateToProps; - -jest.mock('react-redux', () => ({ - connect: (ms) => { - mapStateToProps = ms; - return () => ({}); - }, -})); - -require('./user-preferenced-token-input.container'); - -describe('UserPreferencedTokenInput container', () => { - describe('mapStateToProps()', () => { - it('should return the correct props', () => { - const mockState = { - metamask: { - preferences: { - useNativeCurrencyAsPrimaryCurrency: true, - }, - }, - }; - - expect(mapStateToProps(mockState)).toStrictEqual({ - useNativeCurrencyAsPrimaryCurrency: true, - }); - }); - }); -}); diff --git a/ui/components/app/user-preferenced-token-input/user-preferenced-token-input.test.js b/ui/components/app/user-preferenced-token-input/user-preferenced-token-input.test.js new file mode 100644 index 000000000..b4c6387ff --- /dev/null +++ b/ui/components/app/user-preferenced-token-input/user-preferenced-token-input.test.js @@ -0,0 +1,26 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import mockState from '../../../../test/data/mock-state.json'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import UserPreferencedTokenInput from '.'; + +describe('UserPreferencedCurrencyInput Component', () => { + describe('rendering', () => { + const mockStore = configureMockStore()(mockState); + + const props = { + token: { + address: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', + }, + }; + + it('should match snapshot', () => { + const { container } = renderWithProvider( + , + mockStore, + ); + + expect(container).toMatchSnapshot(); + }); + }); +}); diff --git a/ui/components/component-library/avatar-account/README.mdx b/ui/components/component-library/avatar-account/README.mdx new file mode 100644 index 000000000..da8be813c --- /dev/null +++ b/ui/components/component-library/avatar-account/README.mdx @@ -0,0 +1,43 @@ +import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; + +import { AvatarAccount } from './avatar-account'; + +# AvatarAccount + +The `AvatarAccount` is a type of avatar reserved for representing accounts. + + + + + +## Props + +The `AvatarAccount` accepts all props below + + + +### Size + +Use the `size` prop to set the size of the `AvatarAccount`. + +Possible sizes include: + +- `xs` 16px +- `sm` 24px +- `md` 32px +- `lg` 40px +- `xl` 48px + +Defaults to `md` + + + + + +### type + +Use the `type` prop for the avatar to be rendered, it can either be a Jazzicon or a Blockie + + + + \ No newline at end of file diff --git a/ui/components/component-library/avatar-account/avatar-account.constants.js b/ui/components/component-library/avatar-account/avatar-account.constants.js new file mode 100644 index 000000000..fd4e7e7cd --- /dev/null +++ b/ui/components/component-library/avatar-account/avatar-account.constants.js @@ -0,0 +1,12 @@ +export const DIAMETERS = { + xs: '16', + sm: '24', + md: '32', + lg: '40', + xl: '48', +}; + +export const TYPES = { + JAZZICON: 'Jazzicon', + BLOCKIES: 'Blockie', +}; diff --git a/ui/components/component-library/avatar-account/avatar-account.js b/ui/components/component-library/avatar-account/avatar-account.js new file mode 100644 index 000000000..032703718 --- /dev/null +++ b/ui/components/component-library/avatar-account/avatar-account.js @@ -0,0 +1,54 @@ +import React from 'react'; +import classnames from 'classnames'; +import PropTypes from 'prop-types'; +import Jazzicon from '../../ui/jazzicon/jazzicon.component'; +import BlockieIdenticon from '../../ui/identicon/blockieIdenticon/blockieIdenticon.component'; +import { BaseAvatar } from '../base-avatar'; + +import { SIZES } from '../../../helpers/constants/design-system'; +import { DIAMETERS, TYPES } from './avatar-account.constants'; + +export const AvatarAccount = ({ size, address, className, type, ...props }) => { + return ( + + {type === 'Jazzicon' ? ( + + ) : ( + + )} + + ); +}; + +AvatarAccount.propTypes = { + /** + * The size of the AvatarAccount. + * Possible values could be 'SIZES.XS', 'SIZES.SM', 'SIZES.MD', 'SIZES.LG', 'SIZES.XL' + * Defaults to SIZES.MD + */ + size: PropTypes.oneOf(Object.values(SIZES)), + /** + * The type of the avatar to be rendered, it can render either a Jazzicon or a Blockie + */ + type: PropTypes.oneOf(Object.values(TYPES)), + /** + * Address used for generating random image + */ + address: PropTypes.string, + /** + * Add custom css class + */ + className: PropTypes.string, +}; diff --git a/ui/components/component-library/avatar-account/avatar-account.scss b/ui/components/component-library/avatar-account/avatar-account.scss new file mode 100644 index 000000000..72d32de8a --- /dev/null +++ b/ui/components/component-library/avatar-account/avatar-account.scss @@ -0,0 +1,5 @@ +.avatar-account { + &__jazzicon { + display: flex; + } +} diff --git a/ui/components/component-library/avatar-account/avatar-account.stories.js b/ui/components/component-library/avatar-account/avatar-account.stories.js new file mode 100644 index 000000000..f3fb9ce31 --- /dev/null +++ b/ui/components/component-library/avatar-account/avatar-account.stories.js @@ -0,0 +1,59 @@ +import React from 'react'; +import Box from '../../ui/box/box'; +import { + ALIGN_ITEMS, + DISPLAY, + SIZES, +} from '../../../helpers/constants/design-system'; +import { AvatarAccount } from './avatar-account'; +import { TYPES } from './avatar-account.constants'; + +import README from './README.mdx'; + +export default { + title: 'Components/ComponentLibrary/AvatarAccount', + id: __filename, + component: AvatarAccount, + parameters: { + docs: { + page: README, + }, + }, + argTypes: { + size: { + control: 'select', + options: Object.values(SIZES), + }, + address: { control: 'text' }, + type: { + control: 'select', + options: Object.values(TYPES), + }, + }, + args: { + address: '0x5CfE73b6021E818B776b421B1c4Db2474086a7e1', + size: SIZES.MD, + type: TYPES.JAZZICON, + }, +}; + +export const DefaultStory = (args) => ; + +DefaultStory.storyName = 'Default'; + +export const Size = (args) => ( + + + + + + + +); + +export const Type = (args) => ( + + + + +); diff --git a/ui/components/component-library/avatar-account/avatar-account.test.js b/ui/components/component-library/avatar-account/avatar-account.test.js new file mode 100644 index 000000000..94cf2783d --- /dev/null +++ b/ui/components/component-library/avatar-account/avatar-account.test.js @@ -0,0 +1,23 @@ +/* eslint-disable jest/require-top-level-describe */ +import { render } from '@testing-library/react'; +import React from 'react'; +import { AvatarAccount } from './avatar-account'; +import 'jest-canvas-mock'; + +describe('AvatarAccount', () => { + const args = { + address: '0x5CfE73b6021E818B776b421B1c4Db2474086a7e1', + }; + it('should render Jazzicon correctly', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('avatar-account')).toBeDefined(); + }); + it('should render Blockie correctly', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('avatar-account')).toBeDefined(); + }); +}); diff --git a/ui/components/component-library/avatar-account/index.js b/ui/components/component-library/avatar-account/index.js new file mode 100644 index 000000000..f314e744d --- /dev/null +++ b/ui/components/component-library/avatar-account/index.js @@ -0,0 +1 @@ +export { AvatarAccount } from './avatar-account'; diff --git a/ui/components/component-library/avatar-favicon/README.mdx b/ui/components/component-library/avatar-favicon/README.mdx new file mode 100644 index 000000000..adcaabc69 --- /dev/null +++ b/ui/components/component-library/avatar-favicon/README.mdx @@ -0,0 +1,44 @@ +import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; + +import { AvatarFavicon } from './avatar-favicon'; + +# AvatarFavicon + +The `AvatarFavicon` is an image component that renders an icon that is provided in the form of a URL. + + + + + +## Props + +The `AvatarFavicon` accepts all props below as well as all [Box](/docs/ui-components-ui-box-box-stories-js--default-story) component props + + + +### Size + +Use the `size` prop to set the size of the `AvatarFavicon`. + +Possible sizes include: + +- `xs` 16px +- `sm` 24px +- `md` 32px +- `lg` 40px +- `xl` 48px + +Defaults to `md` + + + + + +### Image Source + +Use the `imageSource` prop to set the image to be rendered of the `AvatarFavicon`. + +### Fallback Icon Props + +If there is no `imageSource` then in that case an [icon](/docs/ui-components-component-library-icon-icon-stories-js--default-story) will be used as the fallback display and it can be customised via `fallbackIconProps`. + diff --git a/ui/components/component-library/avatar-favicon/avatar-favicon.js b/ui/components/component-library/avatar-favicon/avatar-favicon.js new file mode 100644 index 000000000..2f460685f --- /dev/null +++ b/ui/components/component-library/avatar-favicon/avatar-favicon.js @@ -0,0 +1,82 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { BaseAvatar } from '../base-avatar'; +import Box from '../../ui/box/box'; +import { ICON_NAMES, Icon } from '../icon'; +import { + COLORS, + BORDER_COLORS, + SIZES, + DISPLAY, + ALIGN_ITEMS, + JUSTIFY_CONTENT, +} from '../../../helpers/constants/design-system'; + +export const AvatarFavicon = ({ + size = SIZES.MD, + imageSource, + imgAlt = 'avatar-favicon', + className, + fallbackIconProps, + borderColor = BORDER_COLORS.TRANSPARENT, + ...props +}) => { + return ( + + {imageSource ? ( + {imgAlt} + ) : ( + + )} + + ); +}; + +AvatarFavicon.propTypes = { + /** + * The imageSource accepts the string of the image to be rendered + */ + imageSource: PropTypes.string, + /** + * The alt text for the favicon avatar to be rendered + */ + imgAlt: PropTypes.string, + /** + * Props for the fallback icon. All Icon props can be used + */ + fallbackIconProps: PropTypes.shape(Icon.PropTypes), + /** + * The size of the AvatarFavicon + * Possible values could be 'SIZES.XS', 'SIZES.SM', 'SIZES.MD', 'SIZES.LG', 'SIZES.XL' + * Defaults to SIZES.MD + */ + size: PropTypes.oneOf(Object.values(SIZES)), + /** + * The border color of the AvatarFavicon + * Defaults to COLORS.TRANSPARENT + */ + borderColor: Box.propTypes.borderColor, + /** + * Additional classNames to be added to the AvatarFavicon + */ + className: PropTypes.string, + /** + * AvatarFavicon also accepts all Box props including but not limited to + * className, as(change root element of HTML element) and margin props + */ + ...Box.propTypes, +}; diff --git a/ui/components/component-library/avatar-favicon/avatar-favicon.scss b/ui/components/component-library/avatar-favicon/avatar-favicon.scss new file mode 100644 index 000000000..f9d461c63 --- /dev/null +++ b/ui/components/component-library/avatar-favicon/avatar-favicon.scss @@ -0,0 +1,5 @@ +.avatar-favicon { + &__image { + width: 100%; + } +} diff --git a/ui/components/component-library/avatar-favicon/avatar-favicon.stories.js b/ui/components/component-library/avatar-favicon/avatar-favicon.stories.js new file mode 100644 index 000000000..92e6b3175 --- /dev/null +++ b/ui/components/component-library/avatar-favicon/avatar-favicon.stories.js @@ -0,0 +1,57 @@ +import React from 'react'; +import { + SIZES, + DISPLAY, + ALIGN_ITEMS, + BORDER_COLORS, +} from '../../../helpers/constants/design-system'; + +import Box from '../../ui/box/box'; + +import README from './README.mdx'; +import { AvatarFavicon } from './avatar-favicon'; + +export default { + title: 'Components/ComponentLibrary/AvatarFavicon', + id: __filename, + component: AvatarFavicon, + parameters: { + docs: { + page: README, + }, + }, + argTypes: { + size: { + control: 'select', + options: Object.values(SIZES), + }, + imageSource: { + control: 'text', + }, + borderColor: { + options: Object.values(BORDER_COLORS), + control: 'select', + }, + }, + args: { + imageSource: 'https://uniswap.org/favicon.ico', + size: SIZES.MD, + }, +}; + +const Template = (args) => { + return ; +}; + +export const DefaultStory = Template.bind({}); +DefaultStory.storyName = 'Default'; + +export const Size = (args) => ( + + + + + + + +); diff --git a/ui/components/component-library/avatar-favicon/avatar-favicon.test.js b/ui/components/component-library/avatar-favicon/avatar-favicon.test.js new file mode 100644 index 000000000..f23bef224 --- /dev/null +++ b/ui/components/component-library/avatar-favicon/avatar-favicon.test.js @@ -0,0 +1,46 @@ +/* eslint-disable jest/require-top-level-describe */ +import { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { AvatarFavicon } from './avatar-favicon'; + +describe('AvatarFavicon', () => { + const args = { + imageSource: './images/eth_logo.svg', + }; + + it('should render correctly', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('avatar-favicon')).toBeDefined(); + }); + + it('should render image of Avatar Favicon', () => { + render(); + const image = screen.getByRole('img'); + expect(image).toBeDefined(); + expect(image).toHaveAttribute('src', args.imageSource); + }); + + it('should render fallback image if no ImageSource is provided', () => { + const { container } = render( + , + ); + expect(container.getElementsByClassName('icon')).toHaveLength(1); + }); + + it('should render fallback image with custom fallbackIconProps if no ImageSource is provided', () => { + const container = ( + + ); + expect(container.props.fallbackIconProps['data-testid']).toStrictEqual( + 'fallback-icon', + ); + }); +}); diff --git a/ui/components/component-library/avatar-favicon/index.js b/ui/components/component-library/avatar-favicon/index.js new file mode 100644 index 000000000..5d080ad57 --- /dev/null +++ b/ui/components/component-library/avatar-favicon/index.js @@ -0,0 +1 @@ +export { AvatarFavicon } from './avatar-favicon'; diff --git a/ui/components/component-library/avatar-with-badge/README.mdx b/ui/components/component-library/avatar-with-badge/README.mdx new file mode 100644 index 000000000..17989b178 --- /dev/null +++ b/ui/components/component-library/avatar-with-badge/README.mdx @@ -0,0 +1,37 @@ +import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; + +import { AvatarWithBadge } from './avatar-with-badge'; + +# AvatarWithBadge + +The `AvatarWithBadge` is a wrapper component that adds badge display options to avatars. + + + + + +## Props + +The `AvatarWithBadge` accepts all props below + + + +### Badge Position + +Use the `badgePosition` prop to set the position of the badge, it can have two values `Top` and `Bottom` + + + + + +### Badge + +Used to define the badge component to be rendered inside the `AvatarWithBadge` + +### Badge Props + +The required props to be passed to the badge. + +### Children + +The children to be rendered inside the AvatarWithBadge. Generally used with the `AvatarAccount` \ No newline at end of file diff --git a/ui/components/component-library/avatar-with-badge/avatar-with-badge.constants.js b/ui/components/component-library/avatar-with-badge/avatar-with-badge.constants.js new file mode 100644 index 000000000..9cb89439e --- /dev/null +++ b/ui/components/component-library/avatar-with-badge/avatar-with-badge.constants.js @@ -0,0 +1,4 @@ +export const BADGE_POSITIONS = { + TOP: 'top', + BOTTOM: 'bottom', +}; diff --git a/ui/components/component-library/avatar-with-badge/avatar-with-badge.js b/ui/components/component-library/avatar-with-badge/avatar-with-badge.js new file mode 100644 index 000000000..d55147d4b --- /dev/null +++ b/ui/components/component-library/avatar-with-badge/avatar-with-badge.js @@ -0,0 +1,56 @@ +import React from 'react'; +import classnames from 'classnames'; +import PropTypes from 'prop-types'; +import Box from '../../ui/box/box'; +import { BADGE_POSITIONS } from './avatar-with-badge.constants'; + +export const AvatarWithBadge = ({ + children, + badgePosition, + className, + badge, + badgeWrapperProps, + ...props +}) => { + return ( + + {/* Generally the AvatarAccount */} + {children} + + {/* Generally the AvatarNetwork at SIZES.XS */} + {badge} + + + ); +}; + +AvatarWithBadge.propTypes = { + /** + * The position of the Badge + * Possible values could be 'top', 'bottom', + */ + badgePosition: PropTypes.oneOf(Object.values(BADGE_POSITIONS)), + /** + * The Badge Wrapper props of the component. All Box props can be used + */ + badgeWrapperProps: PropTypes.shape(Box.PropTypes), + /** + * The children to be rendered inside the AvatarWithBadge + */ + children: PropTypes.node, + /** + * The badge to be rendered inside the AvatarWithBadge + */ + badge: PropTypes.object, + /** + * Add custom css class + */ + className: PropTypes.string, +}; diff --git a/ui/components/component-library/avatar-with-badge/avatar-with-badge.scss b/ui/components/component-library/avatar-with-badge/avatar-with-badge.scss new file mode 100644 index 000000000..27adfcdd7 --- /dev/null +++ b/ui/components/component-library/avatar-with-badge/avatar-with-badge.scss @@ -0,0 +1,16 @@ +.avatar-with-badge { + position: relative; + width: fit-content; + + &__badge-wrapper--position-top { + position: absolute; + top: -4px; + right: -4px; + } + + &__badge-wrapper--position-bottom { + position: absolute; + bottom: -4px; + right: -4px; + } +} diff --git a/ui/components/component-library/avatar-with-badge/avatar-with-badge.stories.js b/ui/components/component-library/avatar-with-badge/avatar-with-badge.stories.js new file mode 100644 index 000000000..b489c3671 --- /dev/null +++ b/ui/components/component-library/avatar-with-badge/avatar-with-badge.stories.js @@ -0,0 +1,91 @@ +import React from 'react'; +import { AvatarAccount } from '../avatar-account'; +import { TYPES } from '../avatar-account/avatar-account.constants'; +import { AvatarNetwork } from '../avatar-network'; +import Box from '../../ui/box/box'; +import { + ALIGN_ITEMS, + DISPLAY, + SIZES, +} from '../../../helpers/constants/design-system'; +import { BADGE_POSITIONS } from './avatar-with-badge.constants'; +import README from './README.mdx'; +import { AvatarWithBadge } from './avatar-with-badge'; + +export default { + title: 'Components/ComponentLibrary/AvatarWithBadge', + id: __filename, + component: AvatarWithBadge, + parameters: { + docs: { + page: README, + }, + }, + argTypes: { + badgePosition: { + options: Object.values(BADGE_POSITIONS), + control: 'select', + }, + }, + args: { + badgePosition: BADGE_POSITIONS.top, + }, +}; + +export const DefaultStory = (args) => ( + + } + {...args} + > + + +); +DefaultStory.storyName = 'Default'; + +export const BadgePosition = () => ( + + + } + > + + + + + } + > + + + +); diff --git a/ui/components/component-library/avatar-with-badge/avatar-with-badge.test.js b/ui/components/component-library/avatar-with-badge/avatar-with-badge.test.js new file mode 100644 index 000000000..b8a317a88 --- /dev/null +++ b/ui/components/component-library/avatar-with-badge/avatar-with-badge.test.js @@ -0,0 +1,90 @@ +/* eslint-disable jest/require-top-level-describe */ +import { render } from '@testing-library/react'; +import React from 'react'; +import { AvatarNetwork } from '../avatar-network/avatar-network'; +import { COLORS } from '../../../helpers/constants/design-system'; +import { AvatarWithBadge } from './avatar-with-badge'; +import { BADGE_POSITIONS } from './avatar-with-badge.constants'; + +describe('AvatarWithBadge', () => { + it('should render correctly', () => { + const { getByTestId } = render( + + } + />, + ); + expect(getByTestId('avatar-with-badge')).toBeDefined(); + expect(getByTestId('badge')).toBeDefined(); + }); + + it('should render badge network with bottom right position correctly', () => { + const { container } = render( + + } + />, + ); + + expect( + container.getElementsByClassName( + 'avatar-with-badge__badge-wrapper--position-bottom', + ), + ).toHaveLength(1); + }); + + it('should render badge network with top right position correctly', () => { + const { container } = render( + + } + />, + ); + + expect( + container.getElementsByClassName( + 'avatar-with-badge__badge-wrapper--position-top', + ), + ).toHaveLength(1); + }); + it('should render badge network with badgeWrapperProps', () => { + const container = ( + + } + /> + ); + expect(container.props.badgeWrapperProps.borderColor).toStrictEqual( + 'error-default', + ); + }); +}); diff --git a/ui/components/component-library/avatar-with-badge/index.js b/ui/components/component-library/avatar-with-badge/index.js new file mode 100644 index 000000000..5fcefde68 --- /dev/null +++ b/ui/components/component-library/avatar-with-badge/index.js @@ -0,0 +1 @@ +export { AvatarWithBadge } from './avatar-with-badge'; diff --git a/ui/components/component-library/base-avatar/base-avatar.scss b/ui/components/component-library/base-avatar/base-avatar.scss index 7ead0dafb..cf558da6f 100644 --- a/ui/components/component-library/base-avatar/base-avatar.scss +++ b/ui/components/component-library/base-avatar/base-avatar.scss @@ -23,6 +23,8 @@ height: var(--avatar-size); width: var(--avatar-size); + max-width: var(--avatar-size); + flex: 0 0 var(--avatar-size); border-radius: 100%; overflow: hidden; display: flex; diff --git a/ui/components/component-library/button-base/README.mdx b/ui/components/component-library/button-base/README.mdx new file mode 100644 index 000000000..ad79e0747 --- /dev/null +++ b/ui/components/component-library/button-base/README.mdx @@ -0,0 +1,130 @@ +import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; +import { ButtonBase } from './button-base'; + +### This is a base component. It should not be used in your feature code directly but as a "base" for other UI components + +# ButtonBase + +The `ButtonBase` is the base component for buttons. + + + + + +## Props + +The `ButtonBase` accepts all props below as well as all [Box](/docs/ui-components-ui-box-box-stories-js--default-story#props) component props + + + +### Size + +Use the `size` prop and the `SIZES` object from `./ui/helpers/constants/design-system.js` +to change the size of `ButtonBase`. Defaults to `SIZES.MD` + +Optional: `BUTTON_SIZES` from `./button-base` object can be used instead of `SIZES`. + +Possible sizes include: + +- `SIZES.AUTO` inherits the font-size of the parent element. +- `SIZES.SM` 32px +- `SIZES.MD` 40px +- `SIZES.LG` 48px + + + + + +```jsx +import { SIZES } from '../../../helpers/constants/design-system'; +import { ButtonBase } from '../ui/component-library'; + + + + + +``` + +### Block + +Use boolean `block` prop to quickly enable a full width block button + + + + + +```jsx +import { DISPLAY } from '../../../helpers/constants/design-system'; +import { ButtonBase } from '../ui/component-library'; + +Default Button +Block Button +``` + +### As + +Use the `as` box prop to change the element of `ButtonBase`. Defaults to `button`. + +When an `href` prop is passed it will change the element to an anchor(`a`) tag. + +Button `as` options: + +- `button` +- `a` + + + + + +```jsx +import { ButtonBase } from '../ui/component-library'; + + +Button Element + + Anchor Element + +``` + +### Disabled + +Use the boolean `disabled` prop to disable button + + + + + +```jsx +import { ButtonBase } from '../ui/component-library'; + +Disabled Button; +``` + +### Loading + +Use the boolean `loading` prop to set loading spinner + + + + + +```jsx +import { ButtonBase } from '../ui/component-library'; + +Loading Button; +``` + +### Icon + +Use the `icon` prop and the `ICON_NAMES` object from `./ui/components/component-library/icon` to select icon. + + + + + +```jsx +import { ButtonBase } from '../ui/component-library'; +import { ICON_NAMES } from '../icon'; + +Button; +``` diff --git a/ui/components/component-library/button-base/button-base.js b/ui/components/component-library/button-base/button-base.js new file mode 100644 index 000000000..9f3a3dffe --- /dev/null +++ b/ui/components/component-library/button-base/button-base.js @@ -0,0 +1,139 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; + +import Box from '../../ui/box'; +import { Icon, ICON_NAMES } from '../icon'; +import { Text } from '../text'; + +import { + ALIGN_ITEMS, + DISPLAY, + JUSTIFY_CONTENT, + TEXT_COLORS, + TEXT, + SIZES, + FLEX_DIRECTION, +} from '../../../helpers/constants/design-system'; +import { BUTTON_SIZES } from './button.constants'; + +export const ButtonBase = ({ + as = 'button', + block, + children, + className, + size = BUTTON_SIZES.MD, + icon, + iconPositionRight, + loading, + disabled, + iconProps, + ...props +}) => { + const Tag = props?.href ? 'a' : as; + return ( + + + {icon && ( + + )} + {children} + + {loading && ( + + )} + + ); +}; + +ButtonBase.propTypes = { + /** + * The polymorphic `as` prop allows you to change the root HTML element of the Button component between `button` and `a` tag + */ + as: PropTypes.string, + /** + * Boolean prop to quickly activate box prop display block + */ + block: PropTypes.bool, + /** + * The children to be rendered inside the ButtonBase + */ + children: PropTypes.node, + /** + * An additional className to apply to the ButtonBase. + */ + className: PropTypes.string, + /** + * Boolean to disable button + */ + disabled: PropTypes.bool, + /** + * Add icon to left side of button text passing icon name + * The name of the icon to display. Should be one of ICON_NAMES + */ + icon: PropTypes.string, // Can't set PropTypes.oneOf(ICON_NAMES) because ICON_NAMES is an environment variable + /** + * Boolean that when true will position the icon on right of children + * Icon default position left + */ + iconPositionRight: PropTypes.bool, + /** + * iconProps accepts all the props from Icon + */ + iconProps: PropTypes.object, + /** + * Boolean to show loading spinner in button + */ + loading: PropTypes.bool, + /** + * The size of the ButtonBase. + * Possible values could be 'SIZES.AUTO', 'SIZES.SM', 'SIZES.MD', 'SIZES.LG', + */ + size: PropTypes.oneOf(Object.values(BUTTON_SIZES)), + /** + * Addition style properties to apply to the button. + */ + style: PropTypes.object, + /** + * ButtonBase accepts all the props from Box + */ + ...Box.propTypes, +}; diff --git a/ui/components/component-library/button-base/button-base.scss b/ui/components/component-library/button-base/button-base.scss new file mode 100644 index 000000000..9e4bd0282 --- /dev/null +++ b/ui/components/component-library/button-base/button-base.scss @@ -0,0 +1,79 @@ +.mm-button { + position: relative; + height: 40px; + padding: 0; + border-radius: 999px; + cursor: pointer; + color: var(--color-text-default); + background-color: var(--brand-colors-grey-grey100); + vertical-align: middle; + user-select: none; + + &:active, + &:hover { + color: var(--color-text-default); + } + + &--block { + display: block; + width: 100%; + } + + &__content { + height: 100%; + } + + + &--size-sm { + height: 32px; + } + + &--size-md { + height: 40px; + } + + &--size-lg { + height: 48px; + } + + &--size-auto { + height: auto; + background-color: transparent; + border-radius: 0; + vertical-align: top; + font-family: inherit; + font-weight: inherit; + font-size: inherit; + line-height: inherit; + letter-spacing: inherit; + } + + &--loading { + cursor: not-allowed; + } + + &--loading &__content { + color: transparent; + } + + &--disabled, + &:disabled { + opacity: 0.3; + cursor: not-allowed; + } + + &__icon-loading { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + animation: spinner 1.2s linear infinite; + } +} + + + +@keyframes spinner { + to { transform: translate(-50%, -50%) rotate(360deg); } +} + diff --git a/ui/components/component-library/button-base/button-base.stories.js b/ui/components/component-library/button-base/button-base.stories.js new file mode 100644 index 000000000..320223fa8 --- /dev/null +++ b/ui/components/component-library/button-base/button-base.stories.js @@ -0,0 +1,168 @@ +import React from 'react'; +import { + ALIGN_ITEMS, + DISPLAY, + FLEX_DIRECTION, + SIZES, + TEXT, +} from '../../../helpers/constants/design-system'; +import Box from '../../ui/box/box'; +import { ICON_NAMES } from '../icon'; +import { Text } from '../text'; +import { BUTTON_SIZES } from './button.constants'; +import { ButtonBase } from './button-base'; +import README from './README.mdx'; + +const marginSizeControlOptions = [ + undefined, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 'auto', +]; + +export default { + title: 'Components/ComponentLibrary/ButtonBase', + id: __filename, + component: ButtonBase, + parameters: { + docs: { + page: README, + }, + }, + argTypes: { + as: { + control: 'select', + options: ['button', 'a'], + }, + block: { + control: 'boolean', + }, + children: { + control: 'text', + }, + className: { + control: 'text', + }, + disabled: { + control: 'boolean', + }, + icon: { + control: 'select', + options: Object.values(ICON_NAMES), + }, + loading: { + control: 'boolean', + }, + size: { + control: 'select', + options: Object.values(BUTTON_SIZES), + }, + marginTop: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginRight: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginBottom: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginLeft: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + }, + args: { + children: 'Button Base', + }, +}; + +export const DefaultStory = (args) => ; + +DefaultStory.storyName = 'Default'; + +export const Size = (args) => ( + <> + + + Button SM + + + Button MD + + + Button LG + + + + + Button Auto + {' '} + inherits the font-size of the parent element. + + +); + +export const Block = (args) => ( + <> + + Default Button + + + Block Button + + +); + +export const As = (args) => ( + + Button Element + + Anchor Element + + +); + +export const Disabled = (args) => ( + Disabled Button +); + +Disabled.args = { + disabled: true, +}; + +export const Loading = (args) => ( + Loading Button +); + +Loading.args = { + loading: true, +}; + +export const Icon = (args) => ( + + Button + +); diff --git a/ui/components/component-library/button-base/button-base.test.js b/ui/components/component-library/button-base/button-base.test.js new file mode 100644 index 000000000..a62bec7aa --- /dev/null +++ b/ui/components/component-library/button-base/button-base.test.js @@ -0,0 +1,91 @@ +/* eslint-disable jest/require-top-level-describe */ +import { render } from '@testing-library/react'; +import React from 'react'; +import { BUTTON_SIZES } from './button.constants'; +import { ButtonBase } from './button-base'; + +describe('ButtonBase', () => { + it('should render button element correctly', () => { + const { getByTestId, getByText, container } = render( + Button base, + ); + expect(getByText('Button base')).toBeDefined(); + expect(container.querySelector('button')).toBeDefined(); + expect(getByTestId('button-base')).toHaveClass('mm-button'); + }); + + it('should render anchor element correctly', () => { + const { getByTestId, container } = render( + , + ); + expect(getByTestId('button-base')).toHaveClass('mm-button'); + const anchor = container.getElementsByTagName('a').length; + expect(anchor).toBe(1); + }); + + it('should render anchor element correctly by href only being passed', () => { + const { getByTestId, container } = render( + , + ); + expect(getByTestId('button-base')).toHaveClass('mm-button'); + const anchor = container.getElementsByTagName('a').length; + expect(anchor).toBe(1); + }); + + it('should render button as block', () => { + const { getByTestId } = render(); + expect(getByTestId('block')).toHaveClass(`mm-button--block`); + }); + + it('should render with different size classes', () => { + const { getByTestId } = render( + <> + + + + + , + ); + expect(getByTestId(BUTTON_SIZES.AUTO)).toHaveClass( + `mm-button--size-${BUTTON_SIZES.AUTO}`, + ); + expect(getByTestId(BUTTON_SIZES.SM)).toHaveClass( + `mm-button--size-${BUTTON_SIZES.SM}`, + ); + expect(getByTestId(BUTTON_SIZES.MD)).toHaveClass( + `mm-button--size-${BUTTON_SIZES.MD}`, + ); + expect(getByTestId(BUTTON_SIZES.LG)).toHaveClass( + `mm-button--size-${BUTTON_SIZES.LG}`, + ); + }); + + it('should render with added classname', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('classname')).toHaveClass('mm-button--test'); + }); + + it('should render with different button states', () => { + const { getByTestId } = render( + <> + + + , + ); + expect(getByTestId('loading')).toHaveClass(`mm-button--loading`); + expect(getByTestId('disabled')).toHaveClass(`mm-button--disabled`); + }); + it('should render with icon', () => { + const { getByTestId } = render( + , + ); + + expect(getByTestId('base-button-icon')).toBeDefined(); + }); +}); diff --git a/ui/components/component-library/button-base/button.constants.js b/ui/components/component-library/button-base/button.constants.js new file mode 100644 index 000000000..bcf67e6f1 --- /dev/null +++ b/ui/components/component-library/button-base/button.constants.js @@ -0,0 +1,8 @@ +import { SIZES } from '../../../helpers/constants/design-system'; + +export const BUTTON_SIZES = { + SM: SIZES.SM, + MD: SIZES.MD, + LG: SIZES.LG, + AUTO: SIZES.AUTO, +}; diff --git a/ui/components/component-library/button-base/index.js b/ui/components/component-library/button-base/index.js new file mode 100644 index 000000000..789a9db9d --- /dev/null +++ b/ui/components/component-library/button-base/index.js @@ -0,0 +1,2 @@ +export { ButtonBase } from './button-base'; +export { BUTTON_SIZES } from './button.constants'; diff --git a/ui/components/component-library/button-link/README.mdx b/ui/components/component-library/button-link/README.mdx new file mode 100644 index 000000000..d1a743912 --- /dev/null +++ b/ui/components/component-library/button-link/README.mdx @@ -0,0 +1,73 @@ +import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; + +import { ButtonLink } from './button-link'; + +# ButtonLink + +The `ButtonLink` is an extension of `ButtonBase` to support link styles. + + + + + +## Props + +The `ButtonLink` accepts all props below as well as all [Box](/docs/ui-components-ui-box-box-stories-js--default-story#props) and [ButtonBase](/docs/ui-components-component-library-button-base-button-base-stories-js--default-story#props) component props + + + +### Size + +Use the `size` prop and the `SIZES` object from `./ui/helpers/constants/design-system.js` to change the size of `ButtonLink`. Defaults to `SIZES.MD` + +Optional: `BUTTON_SIZES` from `./button-base` object can be used instead of `SIZES`. + +Possible sizes include: + +- `SIZES.AUTO` inherits the font-size of the parent element. +- `SIZES.SM` 32px +- `SIZES.MD` 40px +- `SIZES.LG` 48px + + + + + +```jsx +import { SIZES } from '../../../helpers/constants/design-system'; +import { ButtonLink } from '../ui/component-library/button/button-link/button-link'; + + + + + +``` + +### Type + +Use the `type` prop and the `BUTTON_TYPES` object from `./ui/helpers/constants/design-system.js` to change the context of `ButtonLink`. + + + + + +```jsx +import { ButtonLink } from '../ui/component-library/button/button-link/button-link'; + +Normal +Danger +``` + +### Href + +When an `href` is passed the tag element will switch to an `anchor`(`a`) tag. + + + + + +```jsx +import { ButtonLink } from '../ui/component-library/button/button-link/button-link'; + +Href Example; +``` diff --git a/ui/components/component-library/button-link/button-link.constants.js b/ui/components/component-library/button-link/button-link.constants.js new file mode 100644 index 000000000..8133abf50 --- /dev/null +++ b/ui/components/component-library/button-link/button-link.constants.js @@ -0,0 +1,8 @@ +import { SIZES } from '../../../helpers/constants/design-system'; + +export const BUTTON_LINK_SIZES = { + SM: SIZES.SM, + MD: SIZES.MD, + LG: SIZES.LG, + AUTO: SIZES.AUTO, +}; diff --git a/ui/components/component-library/button-link/button-link.js b/ui/components/component-library/button-link/button-link.js new file mode 100644 index 000000000..f1bfc2c1f --- /dev/null +++ b/ui/components/component-library/button-link/button-link.js @@ -0,0 +1,45 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; + +import { ButtonBase } from '../button-base'; +import { BUTTON_LINK_SIZES } from './button-link.constants'; + +export const ButtonLink = ({ + className, + danger, + size = BUTTON_LINK_SIZES.MD, + ...props +}) => { + return ( + + ); +}; + +ButtonLink.propTypes = { + /** + * An additional className to apply to the ButtonLink. + */ + className: PropTypes.string, + /** + * Boolean to change button type to Danger when true + */ + danger: PropTypes.bool, + /** + * The possible size values for ButtonLink: 'SIZES.AUTO', 'SIZES.SM', 'SIZES.MD', 'SIZES.LG', + * Default value is 'SIZES.MD'. + */ + size: PropTypes.oneOf(Object.values(BUTTON_LINK_SIZES)), + /** + * ButtonLink accepts all the props from ButtonBase + */ + ...ButtonBase.propTypes, +}; + +export default ButtonLink; diff --git a/ui/components/component-library/button-link/button-link.scss b/ui/components/component-library/button-link/button-link.scss new file mode 100644 index 000000000..c17815c6c --- /dev/null +++ b/ui/components/component-library/button-link/button-link.scss @@ -0,0 +1,43 @@ +.mm-button-link { + color: var(--color-primary-default); + background-color: transparent; + + &:hover { + color: var(--color-primary-default); + opacity: 0.5; + } + + &:active { + color: var(--color-primary-default); + opacity: 0.5; + } + + &.mm-button--disabled { + &:hover { + color: var(--color-primary-default); + opacity: 0.3; + } + + &:active { + opacity: 0.3; + } + } + + &--type-danger { + color: var(--color-error-default); + + &:hover { + color: var(--color-error-default); + opacity: 0.5; + } + + &:active { + color: var(--color-error-default); + opacity: 0.5; + } + + &.mm-button--disabled:hover { + color: var(--color-error-default); + } + } +} diff --git a/ui/components/component-library/button-link/button-link.stories.js b/ui/components/component-library/button-link/button-link.stories.js new file mode 100644 index 000000000..e721459f4 --- /dev/null +++ b/ui/components/component-library/button-link/button-link.stories.js @@ -0,0 +1,156 @@ +import React from 'react'; +import { + ALIGN_ITEMS, + DISPLAY, + SIZES, + TEXT, +} from '../../../helpers/constants/design-system'; +import Box from '../../ui/box/box'; +import { ICON_NAMES } from '../icon'; +import { Text } from '../text'; +import { ButtonLink } from './button-link'; +import { BUTTON_LINK_SIZES } from './button-link.constants'; +import README from './README.mdx'; + +const marginSizeControlOptions = [ + undefined, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 'auto', +]; + +export default { + title: 'Components/ComponentLibrary/ButtonLink', + id: __filename, + component: ButtonLink, + parameters: { + docs: { + page: README, + }, + }, + argTypes: { + as: { + control: 'select', + options: ['button', 'a'], + table: { category: 'button base props' }, + }, + block: { + control: 'boolean', + table: { category: 'button base props' }, + }, + children: { + control: 'text', + }, + className: { + control: 'text', + }, + danger: { + control: 'boolean', + }, + disabled: { + control: 'boolean', + table: { category: 'button base props' }, + }, + href: { + control: 'text', + }, + icon: { + control: 'select', + options: Object.values(ICON_NAMES), + table: { category: 'button base props' }, + }, + iconPositionRight: { + control: 'boolean', + table: { category: 'button base props' }, + }, + iconProps: { + control: 'object', + table: { category: 'button base props' }, + }, + + loading: { + control: 'boolean', + table: { category: 'button base props' }, + }, + size: { + control: 'select', + options: Object.values(BUTTON_LINK_SIZES), + }, + marginTop: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginRight: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginBottom: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginLeft: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + }, + args: { + children: 'Button Link', + }, +}; + +export const DefaultStory = (args) => ; + +DefaultStory.storyName = 'Default'; + +export const Size = (args) => ( + <> + + + Small Button + + + Medium (Default) Button + + + Large Button + + + + + Button Auto + {' '} + inherits the font-size of the parent element. + + +); + +export const Type = (args) => ( + + Normal + {/* Test Anchor tag to match exactly as button */} + + Danger + + +); + +export const Href = (args) => Href Example; + +Href.args = { + href: '/metamask', +}; diff --git a/ui/components/component-library/button-link/button-link.test.js b/ui/components/component-library/button-link/button-link.test.js new file mode 100644 index 000000000..473714fb0 --- /dev/null +++ b/ui/components/component-library/button-link/button-link.test.js @@ -0,0 +1,84 @@ +/* eslint-disable jest/require-top-level-describe */ +import { render } from '@testing-library/react'; +import React from 'react'; +import { SIZES } from '../../../helpers/constants/design-system'; +import { ButtonLink } from './button-link'; + +describe('ButtonLink', () => { + it('should render button element correctly', () => { + const { getByText, getByTestId, container } = render( + Button Link, + ); + expect(getByText('Button Link')).toBeDefined(); + expect(container.querySelector('button')).toBeDefined(); + expect(getByTestId('button-link')).toHaveClass('mm-button'); + }); + + it('should render anchor element correctly', () => { + const { getByTestId, container } = render( + , + ); + expect(getByTestId('button-link')).toHaveClass('mm-button'); + const anchor = container.getElementsByTagName('a').length; + expect(anchor).toBe(1); + }); + + it('should render button as block', () => { + const { getByTestId } = render(); + expect(getByTestId('block')).toHaveClass(`mm-button--block`); + }); + + it('should render with added classname', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('classname')).toHaveClass('mm-button--test'); + }); + + it('should render with different size classes', () => { + const { getByTestId } = render( + <> + + + + + , + ); + + expect(getByTestId(SIZES.SM)).toHaveClass(`mm-button--size-${SIZES.SM}`); + expect(getByTestId(SIZES.MD)).toHaveClass(`mm-button--size-${SIZES.MD}`); + expect(getByTestId(SIZES.LG)).toHaveClass(`mm-button--size-${SIZES.LG}`); + expect(getByTestId(SIZES.AUTO)).toHaveClass( + `mm-button--size-${SIZES.AUTO}`, + ); + }); + + it('should render with different types', () => { + const { getByTestId } = render( + <> + + , + ); + + expect(getByTestId('danger')).toHaveClass('mm-button-link--type-danger'); + }); + + it('should render with different button states', () => { + const { getByTestId } = render( + <> + + + , + ); + expect(getByTestId('loading')).toHaveClass(`mm-button--loading`); + expect(getByTestId('disabled')).toHaveClass(`mm-button--disabled`); + }); + it('should render with icon', () => { + const { container } = render( + , + ); + + const icons = container.getElementsByClassName('icon').length; + expect(icons).toBe(1); + }); +}); diff --git a/ui/components/component-library/button-link/index.js b/ui/components/component-library/button-link/index.js new file mode 100644 index 000000000..64bf08bb6 --- /dev/null +++ b/ui/components/component-library/button-link/index.js @@ -0,0 +1 @@ +export { ButtonLink } from './button-link'; diff --git a/ui/components/component-library/button-primary/README.mdx b/ui/components/component-library/button-primary/README.mdx new file mode 100644 index 000000000..69a110540 --- /dev/null +++ b/ui/components/component-library/button-primary/README.mdx @@ -0,0 +1,57 @@ +import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; + +import { ButtonPrimary } from './button-primary'; + +# ButtonPrimary + +The `ButtonPrimary` is an extension of `ButtonBase` to support primary styles. + + + + + +## Props + +The `ButtonPrimary` accepts all props below as well as all [Box](/docs/ui-components-ui-box-box-stories-js--default-story#props) and [ButtonBase](/docs/ui-components-component-library-button-base-button-base-stories-js--default-story#props) component props + + + +### Size + +Use the `size` prop and the `SIZES` object from `./ui/helpers/constants/design-system.js` to change the size of `ButtonPrimary`. Defaults to `SIZES.MD` + +Optional: `BUTTON_SIZES` from `./button-base` object can be used instead of `SIZES`. + +Possible sizes include: + +- `SIZES.SM` 32px +- `SIZES.MD` 40px +- `SIZES.LG` 48px + + + + + +```jsx +import { SIZES } from '../../../helpers/constants/design-system'; +import { ButtonPrimary } from '../ui/component-library/button/button-primary/button-primary'; + + + + +``` + +### Type + +Use the `type` prop and the `BUTTON_TYPES` object from `./ui/helpers/constants/design-system.js` to change the context of `ButtonPrimary`. + + + + + +```jsx +import { ButtonPrimary } from '../ui/component-library/button/button-primary/button-primary'; + +Normal +Danger +``` diff --git a/ui/components/component-library/button-primary/button-primary.constants.js b/ui/components/component-library/button-primary/button-primary.constants.js new file mode 100644 index 000000000..4fa091503 --- /dev/null +++ b/ui/components/component-library/button-primary/button-primary.constants.js @@ -0,0 +1,7 @@ +import { SIZES } from '../../../helpers/constants/design-system'; + +export const BUTTON_PRIMARY_SIZES = { + SM: SIZES.SM, + MD: SIZES.MD, + LG: SIZES.LG, +}; diff --git a/ui/components/component-library/button-primary/button-primary.js b/ui/components/component-library/button-primary/button-primary.js new file mode 100644 index 000000000..78dc3e93d --- /dev/null +++ b/ui/components/component-library/button-primary/button-primary.js @@ -0,0 +1,45 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; + +import { ButtonBase } from '../button-base'; +import { BUTTON_PRIMARY_SIZES } from './button-primary.constants'; + +export const ButtonPrimary = ({ + className, + danger, + size = BUTTON_PRIMARY_SIZES.MD, + ...props +}) => { + return ( + + ); +}; + +ButtonPrimary.propTypes = { + /** + * An additional className to apply to the ButtonPrimary. + */ + className: PropTypes.string, + /** + * Boolean to change button type to Danger when true + */ + danger: PropTypes.bool, + /** + * The possible size values for ButtonPrimary: 'SIZES.SM', 'SIZES.MD', 'SIZES.LG', + * Default value is 'SIZES.MD'. + */ + size: PropTypes.oneOf(Object.values(BUTTON_PRIMARY_SIZES)), + /** + * ButtonPrimary accepts all the props from ButtonBase + */ + ...ButtonBase.propTypes, +}; + +export default ButtonPrimary; diff --git a/ui/components/component-library/button-primary/button-primary.scss b/ui/components/component-library/button-primary/button-primary.scss new file mode 100644 index 000000000..70f0b8bd0 --- /dev/null +++ b/ui/components/component-library/button-primary/button-primary.scss @@ -0,0 +1,43 @@ +.mm-button-primary { + color: var(--color-primary-inverse); + background-color: var(--color-primary-default); + + &:hover { + color: var(--color-primary-inverse); + box-shadow: var(--component-button-primary-shadow); + } + + &:active { + color: var(--color-primary-inverse); + background-color: var(--color-primary-alternative); + } + + &.mm-button--disabled { + &:hover { + box-shadow: none; + } + + &:active { + background-color: var(--color-primary-default); + } + } + + &--type-danger { + color: var(--color-error-inverse); + background-color: var(--color-error-default); + + &:hover { + color: var(--color-error-inverse); + box-shadow: var(--component-button-danger-shadow); + } + + &:active { + color: var(--color-error-inverse); + background-color: var(--color-error-alternative); + } + + &.mm-button--disabled:active { + background-color: var(--color-error-default); + } + } +} diff --git a/ui/components/component-library/button-primary/button-primary.stories.js b/ui/components/component-library/button-primary/button-primary.stories.js new file mode 100644 index 000000000..8f9c3cafc --- /dev/null +++ b/ui/components/component-library/button-primary/button-primary.stories.js @@ -0,0 +1,133 @@ +import React from 'react'; +import { ALIGN_ITEMS, DISPLAY } from '../../../helpers/constants/design-system'; +import Box from '../../ui/box/box'; +import { ICON_NAMES } from '../icon'; +import { ButtonPrimary } from './button-primary'; +import { BUTTON_PRIMARY_SIZES } from './button-primary.constants'; +import README from './README.mdx'; + +const marginSizeControlOptions = [ + undefined, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 'auto', +]; + +export default { + title: 'Components/ComponentLibrary/ButtonPrimary', + id: __filename, + component: ButtonPrimary, + parameters: { + docs: { + page: README, + }, + }, + argTypes: { + as: { + control: 'select', + options: ['button', 'a'], + table: { category: 'button base props' }, + }, + block: { + control: 'boolean', + table: { category: 'button base props' }, + }, + children: { + control: 'text', + }, + className: { + control: 'text', + }, + danger: { + control: 'boolean', + }, + disabled: { + control: 'boolean', + table: { category: 'button base props' }, + }, + icon: { + control: 'select', + options: Object.values(ICON_NAMES), + table: { category: 'button base props' }, + }, + iconPositionRight: { + control: 'boolean', + table: { category: 'button base props' }, + }, + iconProps: { + control: 'object', + table: { category: 'button base props' }, + }, + + loading: { + control: 'boolean', + table: { category: 'button base props' }, + }, + size: { + control: 'select', + options: Object.values(BUTTON_PRIMARY_SIZES), + }, + marginTop: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginRight: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginBottom: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginLeft: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + }, + args: { + children: 'Button Primary', + }, +}; + +export const DefaultStory = (args) => ; + +DefaultStory.storyName = 'Default'; + +export const Size = (args) => ( + + + Small Button + + + Medium (Default) Button + + + Large Button + + +); + +export const Type = (args) => ( + + Normal + {/* Test Anchor tag to match exactly as button */} + + Danger + + +); diff --git a/ui/components/component-library/button-primary/button-primary.test.js b/ui/components/component-library/button-primary/button-primary.test.js new file mode 100644 index 000000000..34751ae7f --- /dev/null +++ b/ui/components/component-library/button-primary/button-primary.test.js @@ -0,0 +1,97 @@ +/* eslint-disable jest/require-top-level-describe */ +import { render } from '@testing-library/react'; +import React from 'react'; +import { ButtonPrimary } from './button-primary'; +import { BUTTON_PRIMARY_SIZES } from './button-primary.constants'; + +describe('ButtonPrimary', () => { + it('should render button element correctly', () => { + const { getByText, getByTestId, container } = render( + + Button Primary + , + ); + expect(getByText('Button Primary')).toBeDefined(); + expect(container.querySelector('button')).toBeDefined(); + expect(getByTestId('button-primary')).toHaveClass('mm-button'); + }); + + it('should render anchor element correctly', () => { + const { getByTestId, container } = render( + , + ); + expect(getByTestId('button-primary')).toHaveClass('mm-button'); + const anchor = container.getElementsByTagName('a').length; + expect(anchor).toBe(1); + }); + + it('should render button as block', () => { + const { getByTestId } = render(); + expect(getByTestId('block')).toHaveClass(`mm-button--block`); + }); + + it('should render with added classname', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('classname')).toHaveClass('mm-button--test'); + }); + + it('should render with different size classes', () => { + const { getByTestId } = render( + <> + + + + , + ); + + expect(getByTestId(BUTTON_PRIMARY_SIZES.SM)).toHaveClass( + `mm-button--size-${BUTTON_PRIMARY_SIZES.SM}`, + ); + expect(getByTestId(BUTTON_PRIMARY_SIZES.MD)).toHaveClass( + `mm-button--size-${BUTTON_PRIMARY_SIZES.MD}`, + ); + expect(getByTestId(BUTTON_PRIMARY_SIZES.LG)).toHaveClass( + `mm-button--size-${BUTTON_PRIMARY_SIZES.LG}`, + ); + }); + + it('should render with different types', () => { + const { getByTestId } = render( + <> + + , + ); + + expect(getByTestId('danger')).toHaveClass('mm-button-primary--type-danger'); + }); + + it('should render with different button states', () => { + const { getByTestId } = render( + <> + + + , + ); + expect(getByTestId('loading')).toHaveClass(`mm-button--loading`); + expect(getByTestId('disabled')).toHaveClass(`mm-button--disabled`); + }); + it('should render with icon', () => { + const { container } = render( + , + ); + + const icons = container.getElementsByClassName('icon').length; + expect(icons).toBe(1); + }); +}); diff --git a/ui/components/component-library/button-primary/index.js b/ui/components/component-library/button-primary/index.js new file mode 100644 index 000000000..e6b99af4c --- /dev/null +++ b/ui/components/component-library/button-primary/index.js @@ -0,0 +1 @@ +export { ButtonPrimary } from './button-primary'; diff --git a/ui/components/component-library/button-secondary/README.mdx b/ui/components/component-library/button-secondary/README.mdx new file mode 100644 index 000000000..16a5a74a6 --- /dev/null +++ b/ui/components/component-library/button-secondary/README.mdx @@ -0,0 +1,57 @@ +import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; + +import { ButtonSecondary } from './button-secondary'; + +# ButtonSecondary + +The `ButtonSecondary` is an extension of `ButtonBase` to support secondary styles. + + + + + +## Props + +The `ButtonSecondary` accepts all props below as well as all [Box](/docs/ui-components-ui-box-box-stories-js--default-story#props) and [ButtonBase](/docs/ui-components-component-library-button-base-button-base-stories-js--default-story#props) component props + + + +### Size + +Use the `size` prop and the `SIZES` object from `./ui/helpers/constants/design-system.js` to change the size of `ButtonSecondary`. Defaults to `SIZES.MD` + +Optional: `BUTTON_SIZES` from `./button-base` object can be used instead of `SIZES`. + +Possible sizes include: + +- `SIZES.SM` 32px +- `SIZES.MD` 40px +- `SIZES.LG` 48px + + + + + +```jsx +import { SIZES } from '../../../helpers/constants/design-system'; +import { ButtonSecondary } from '../ui/component-library/button/button-secondary/button-secondary'; + + + + +``` + +### Type + +Use the `type` prop and the `BUTTON_TYPES` object from `./ui/helpers/constants/design-system.js` to change the context of `ButtonSecondary`. + + + + + +```jsx +import { ButtonSecondary } from '../ui/component-library/button/button-secondary/button-secondary'; + +Normal +Danger +``` diff --git a/ui/components/component-library/button-secondary/button-secondary.constants.js b/ui/components/component-library/button-secondary/button-secondary.constants.js new file mode 100644 index 000000000..0e8af938e --- /dev/null +++ b/ui/components/component-library/button-secondary/button-secondary.constants.js @@ -0,0 +1,7 @@ +import { SIZES } from '../../../helpers/constants/design-system'; + +export const BUTTON_SECONDARY_SIZES = { + SM: SIZES.SM, + MD: SIZES.MD, + LG: SIZES.LG, +}; diff --git a/ui/components/component-library/button-secondary/button-secondary.js b/ui/components/component-library/button-secondary/button-secondary.js new file mode 100644 index 000000000..c8d4ed608 --- /dev/null +++ b/ui/components/component-library/button-secondary/button-secondary.js @@ -0,0 +1,45 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; + +import { ButtonBase } from '../button-base'; +import { BUTTON_SECONDARY_SIZES } from './button-secondary.constants'; + +export const ButtonSecondary = ({ + className, + danger, + size = BUTTON_SECONDARY_SIZES.MD, + ...props +}) => { + return ( + + ); +}; + +ButtonSecondary.propTypes = { + /** + * An additional className to apply to the ButtonSecondary. + */ + className: PropTypes.string, + /** + * Boolean to change button type to Danger when true + */ + danger: PropTypes.bool, + /** + * The possible size values for ButtonSecondary: 'SIZES.SM', 'SIZES.MD', 'SIZES.LG', + * Default value is 'SIZES.MD'. + */ + size: PropTypes.oneOf(Object.values(BUTTON_SECONDARY_SIZES)), + /** + * ButtonSecondary accepts all the props from ButtonBase + */ + ...ButtonBase.propTypes, +}; + +export default ButtonSecondary; diff --git a/ui/components/component-library/button-secondary/button-secondary.scss b/ui/components/component-library/button-secondary/button-secondary.scss new file mode 100644 index 000000000..7724e5701 --- /dev/null +++ b/ui/components/component-library/button-secondary/button-secondary.scss @@ -0,0 +1,51 @@ +.mm-button-secondary { + color: var(--color-primary-default); + border: 1px solid var(--color-primary-default); + background-color: transparent; + + &:hover { + color: var(--color-primary-inverse); + background-color: var(--color-primary-default); + box-shadow: var(--component-button-primary-shadow); + } + + &:active { + color: var(--color-primary-inverse); + background-color: var(--color-primary-alternative); + border-color: var(--color-primary-alternative); + } + + &.mm-button--disabled { + &:hover { + color: var(--color-primary-default); + box-shadow: none; + background-color: transparent; + } + + &:active { + background-color: transparent; + } + } + + &--type-danger { + color: var(--color-error-default); + border: 1px solid var(--color-error-default); + background-color: transparent; + + &:hover { + color: var(--color-error-inverse); + background-color: var(--color-error-default); + box-shadow: var(--component-button-danger-shadow); + } + + &:active { + color: var(--color-error-inverse); + background-color: var(--color-error-alternative); + border-color: var(--color-error-alternative); + } + + &.mm-button--disabled:hover { + color: var(--color-error-default); + } + } +} diff --git a/ui/components/component-library/button-secondary/button-secondary.stories.js b/ui/components/component-library/button-secondary/button-secondary.stories.js new file mode 100644 index 000000000..399cb412e --- /dev/null +++ b/ui/components/component-library/button-secondary/button-secondary.stories.js @@ -0,0 +1,133 @@ +import React from 'react'; +import { ALIGN_ITEMS, DISPLAY } from '../../../helpers/constants/design-system'; +import Box from '../../ui/box/box'; +import { ICON_NAMES } from '../icon'; +import { ButtonSecondary } from './button-secondary'; +import { BUTTON_SECONDARY_SIZES } from './button-secondary.constants'; +import README from './README.mdx'; + +const marginSizeControlOptions = [ + undefined, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 'auto', +]; + +export default { + title: 'Components/ComponentLibrary/ButtonSecondary', + id: __filename, + component: ButtonSecondary, + parameters: { + docs: { + page: README, + }, + }, + argTypes: { + as: { + control: 'select', + options: ['button', 'a'], + table: { category: 'button base props' }, + }, + block: { + control: 'boolean', + table: { category: 'button base props' }, + }, + children: { + control: 'text', + }, + className: { + control: 'text', + }, + danger: { + control: 'boolean', + }, + disabled: { + control: 'boolean', + table: { category: 'button base props' }, + }, + icon: { + control: 'select', + options: Object.values(ICON_NAMES), + table: { category: 'button base props' }, + }, + iconPositionRight: { + control: 'boolean', + table: { category: 'button base props' }, + }, + iconProps: { + control: 'object', + table: { category: 'button base props' }, + }, + + loading: { + control: 'boolean', + table: { category: 'button base props' }, + }, + size: { + control: 'select', + options: Object.values(BUTTON_SECONDARY_SIZES), + }, + marginTop: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginRight: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginBottom: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginLeft: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + }, + args: { + children: 'Button Secondary', + }, +}; + +export const DefaultStory = (args) => ; + +DefaultStory.storyName = 'Default'; + +export const Size = (args) => ( + + + Small Button + + + Medium (Default) Button + + + Large Button + + +); + +export const Type = (args) => ( + + Normal + {/* Test Anchor tag to match exactly as button */} + + Danger + + +); diff --git a/ui/components/component-library/button-secondary/button-secondary.test.js b/ui/components/component-library/button-secondary/button-secondary.test.js new file mode 100644 index 000000000..61f910ab9 --- /dev/null +++ b/ui/components/component-library/button-secondary/button-secondary.test.js @@ -0,0 +1,101 @@ +/* eslint-disable jest/require-top-level-describe */ +import { render } from '@testing-library/react'; +import React from 'react'; +import { ButtonSecondary } from './button-secondary'; +import { BUTTON_SECONDARY_SIZES } from './button-secondary.constants'; + +describe('ButtonSecondary', () => { + it('should render button element correctly', () => { + const { getByText, getByTestId, container } = render( + + Button Secondary + , + ); + expect(getByText('Button Secondary')).toBeDefined(); + expect(container.querySelector('button')).toBeDefined(); + expect(getByTestId('button-secondary')).toHaveClass('mm-button'); + }); + + it('should render anchor element correctly', () => { + const { getByTestId, container } = render( + , + ); + expect(getByTestId('button-secondary')).toHaveClass('mm-button'); + const anchor = container.getElementsByTagName('a').length; + expect(anchor).toBe(1); + }); + + it('should render button as block', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('block')).toHaveClass(`mm-button--block`); + }); + + it('should render with added classname', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('classname')).toHaveClass('mm-button--test'); + }); + + it('should render with different size classes', () => { + const { getByTestId } = render( + <> + + + + , + ); + + expect(getByTestId(BUTTON_SECONDARY_SIZES.SM)).toHaveClass( + `mm-button--size-${BUTTON_SECONDARY_SIZES.SM}`, + ); + expect(getByTestId(BUTTON_SECONDARY_SIZES.MD)).toHaveClass( + `mm-button--size-${BUTTON_SECONDARY_SIZES.MD}`, + ); + expect(getByTestId(BUTTON_SECONDARY_SIZES.LG)).toHaveClass( + `mm-button--size-${BUTTON_SECONDARY_SIZES.LG}`, + ); + }); + + it('should render with different types', () => { + const { getByTestId } = render( + <> + + , + ); + + expect(getByTestId('danger')).toHaveClass( + 'mm-button-secondary--type-danger', + ); + }); + + it('should render with different button states', () => { + const { getByTestId } = render( + <> + + + , + ); + expect(getByTestId('loading')).toHaveClass(`mm-button--loading`); + expect(getByTestId('disabled')).toHaveClass(`mm-button--disabled`); + }); + it('should render with icon', () => { + const { container } = render( + , + ); + + const icons = container.getElementsByClassName('icon').length; + expect(icons).toBe(1); + }); +}); diff --git a/ui/components/component-library/button-secondary/index.js b/ui/components/component-library/button-secondary/index.js new file mode 100644 index 000000000..6b1d2869f --- /dev/null +++ b/ui/components/component-library/button-secondary/index.js @@ -0,0 +1 @@ +export { ButtonSecondary } from './button-secondary'; diff --git a/ui/components/component-library/component-library-components.scss b/ui/components/component-library/component-library-components.scss index 09c0d7a28..af5003d1e 100644 --- a/ui/components/component-library/component-library-components.scss +++ b/ui/components/component-library/component-library-components.scss @@ -1,6 +1,16 @@ /** Please import your files in alphabetical order **/ +@import 'avatar-account/avatar-account'; +@import 'avatar-favicon/avatar-favicon'; @import 'avatar-network/avatar-network'; @import 'avatar-token/avatar-token'; +@import 'avatar-with-badge/avatar-with-badge'; @import 'base-avatar/base-avatar'; +@import 'button-base/button-base'; +@import 'button-link/button-link'; +@import 'button-primary/button-primary'; +@import 'button-secondary/button-secondary'; @import 'icon/icon'; +@import 'tag/tag'; @import 'text/text'; +@import 'text-field/text-field'; +@import 'text-field-base/text-field-base'; diff --git a/ui/components/component-library/icon/icon.js b/ui/components/component-library/icon/icon.js index 9318c4706..8b18b183a 100644 --- a/ui/components/component-library/icon/icon.js +++ b/ui/components/component-library/icon/icon.js @@ -61,7 +61,7 @@ Icon.propTypes = { * Addition style properties to apply to the icon. * The Icon component uses inline styles to apply the icon's mask-image so be wary of overriding */ - style: PropTypes.style, + style: PropTypes.object, /** * Icon accepts all the props from Box */ diff --git a/ui/components/component-library/tag/README.mdx b/ui/components/component-library/tag/README.mdx new file mode 100644 index 000000000..6d85e9e73 --- /dev/null +++ b/ui/components/component-library/tag/README.mdx @@ -0,0 +1,21 @@ +import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; + +import { Tag } from './tag'; + +# Tag + +The `Tag` is a component used to display text within a container. + + + + + +## Props + +The `Tag` accepts all props below as well as all [Box](/docs/ui-components-ui-box-box-stories-js--default-story#props) component props. + + + +### Label + +The text content of the `Tag` component diff --git a/ui/components/component-library/tag/index.js b/ui/components/component-library/tag/index.js new file mode 100644 index 000000000..e533e2003 --- /dev/null +++ b/ui/components/component-library/tag/index.js @@ -0,0 +1 @@ +export { Tag } from './tag'; diff --git a/ui/components/component-library/tag/tag.js b/ui/components/component-library/tag/tag.js new file mode 100644 index 000000000..9836c5649 --- /dev/null +++ b/ui/components/component-library/tag/tag.js @@ -0,0 +1,50 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import Box from '../../ui/box/box'; +import { Text } from '../text'; +import { + ALIGN_ITEMS, + BORDER_RADIUS, + COLORS, + DISPLAY, + JUSTIFY_CONTENT, + TEXT, +} from '../../../helpers/constants/design-system'; + +export const Tag = ({ label, className, labelProps, ...props }) => { + return ( + + + {label} + + + ); +}; + +Tag.propTypes = { + /** + * The text content of the Tag component + */ + label: PropTypes.string, + /** + * The label props of the component. Most Text component props can be used + */ + labelProps: Text.propTypes, + /** + * Additional classNames to be added to the Tag component + */ + className: PropTypes.string, +}; diff --git a/ui/components/component-library/tag/tag.scss b/ui/components/component-library/tag/tag.scss new file mode 100644 index 000000000..1a98cdf71 --- /dev/null +++ b/ui/components/component-library/tag/tag.scss @@ -0,0 +1,6 @@ +.tag { + height: auto; + width: max-content; + padding-top: 1px; + padding-bottom: 1px; +} diff --git a/ui/components/component-library/tag/tag.stories.js b/ui/components/component-library/tag/tag.stories.js new file mode 100644 index 000000000..eb2d6c595 --- /dev/null +++ b/ui/components/component-library/tag/tag.stories.js @@ -0,0 +1,26 @@ +import React from 'react'; +import README from './README.mdx'; +import { Tag } from './tag'; + +export default { + title: 'Components/ComponentLibrary/Tag', + id: __filename, + component: Tag, + parameters: { + docs: { + page: README, + }, + }, + argTypes: { + label: { + control: 'text', + }, + }, + args: { + label: 'Imported', + }, +}; + +export const DefaultStory = (args) => ; + +DefaultStory.storyName = 'Default'; diff --git a/ui/components/component-library/tag/tag.test.js b/ui/components/component-library/tag/tag.test.js new file mode 100644 index 000000000..c4ed72186 --- /dev/null +++ b/ui/components/component-library/tag/tag.test.js @@ -0,0 +1,13 @@ +/* eslint-disable jest/require-top-level-describe */ +import { render } from '@testing-library/react'; +import React from 'react'; + +import { Tag } from './tag'; + +describe('Tag', () => { + it('should render the label inside the tag', () => { + const { getByTestId } = render(); + expect(getByTestId('tag')).toBeDefined(); + expect(getByTestId('tag')).toHaveTextContent('Imported'); + }); +}); diff --git a/ui/components/component-library/text-field-base/README.mdx b/ui/components/component-library/text-field-base/README.mdx new file mode 100644 index 000000000..122b3e156 --- /dev/null +++ b/ui/components/component-library/text-field-base/README.mdx @@ -0,0 +1,302 @@ +import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; + +import { TextFieldBase } from './text-field-base'; + +### This is a base component. It should not be used in your feature code directly but as a "base" for other UI components + +# TextFieldBase + +The `TextFieldBase` is the base component for all text fields. It should not be used directly. It functions as both a uncontrolled and controlled input. + + + + + +## Props + +The `TextFieldBase` accepts all props below as well as all [Box](/docs/ui-components-ui-box-box-stories-js--default-story#props) component props + + + +### Size + +Use the `size` prop to set the height of the `TextFieldBase`. + +Possible sizes include: + +- `sm` 32px +- `md` 40px +- `lg` 48px + +Defaults to `md` + + + + + +```jsx +import { TextFieldBase } from '../../ui/component-library/text-field-base'; +import { SIZES } from '../../../helpers/constants/design-system'; + + + + +``` + +### Type + +Use the `type` prop to change the type of input. + +Possible types include: + +- `text` +- `number` +- `password` + +Defaults to `text`. + + + + + +```jsx +import { TextFieldBase } from '../../ui/component-library/text-field-base'; + + // (Default) + + +``` + +### Truncate + +Use the `truncate` prop to truncate the text of the the `TextFieldBase`. Defaults to `true`. + + + + + +```jsx +import { TextFieldBase } from '../../ui/component-library/text-field-base'; + +; // truncate is set to `true` by default +; +``` + +### Left Accessory Right Accessory + +Use the `leftAccessory` and `rightAccessory` props to add components such as icons or buttons to either side of the `TextFieldBase`. + + + + + +```jsx +import { COLORS, SIZES, DISPLAY } from '../../../helpers/constants/design-system'; +import { Icon, ICON_NAMES } from '../../ui/component-library/icons'; + +import { TextFieldBase } from '../../ui/component-library/text-field'; + + + } +/> + + + + + } +/> + +} + rightAccessory={} +/> + +} + rightAccessory={ + isAddressValid && ( + + ) + } +/> +``` + +### Input Ref + +Use the `inputRef` prop to access the ref of the `` html element of `TextFieldBase`. This is useful for focusing the input from a button or other component. + + + + + +```jsx +import { TextFieldBase } from '../../ui/component-library/text-field-base'; + +const inputRef = useRef(null); +const [value, setValue] = useState(''); +const handleOnClick = () => { + inputRef.current.focus(); +}; +const handleOnChange = (e) => { + setValue(e.target.value); +}; + + +// TODO: replace with Button component + + Edit + +``` + +### Auto Complete + +Use the `autoComplete` prop to set the autocomplete html attribute. It allows the browser to predict the value based on earlier typed values. + + + + + +```jsx +import { TextFieldBase } from '../../ui/component-library/text-field-base'; + +; +``` + +### Auto Focus + +Use the `autoFocus` prop to focus the `TextFieldBase` during the first mount + + + + + +```jsx +import { TextFieldBase } from '../../ui/component-library/text-field-base'; + +; +``` + +### Default Value + +Use the `defaultValue` prop to set the default value of the `TextFieldBase` + + + + + +```jsx +import { TextFieldBase } from '../../ui/component-library/text-field-base'; + +; +``` + +### Disabled + +Use the `disabled` prop to set the disabled state of the `TextFieldBase` + + + + + +```jsx +import { TextFieldBase } from '../../ui/component-library/text-field-base'; + +; +``` + +### Error + +Use the `error` prop to set the error state of the `TextFieldBase` + + + + + +```jsx +import { TextFieldBase } from '../../ui/component-library/text-field-base'; + +; +``` + +### Max Length + +Use the `maxLength` prop to set the maximum allowed input characters for the `TextFieldBase` + + + + + +```jsx +import { TextFieldBase } from '../../ui/component-library/text-field-base'; + +; +``` + +### Read Only + +Use the `readOnly` prop to set the `TextFieldBase` to read only. When `readOnly` is true `TextFieldBase` will not have a focus state. + + + + + +```jsx +import { TextFieldBase } from '../../ui/component-library/text-field-base'; + +; +``` + +### Required + +Use the `required` prop to set the `TextFieldBase` to required. Currently there is no visual difference to the `TextFieldBase` when required. + + + + + +```jsx +import { TextFieldBase } from '../../ui/component-library/text-field-base'; + +// Currently no visual difference +; +``` diff --git a/ui/components/component-library/text-field-base/index.js b/ui/components/component-library/text-field-base/index.js new file mode 100644 index 000000000..748a4de12 --- /dev/null +++ b/ui/components/component-library/text-field-base/index.js @@ -0,0 +1,5 @@ +export { TextFieldBase } from './text-field-base'; +export { + TEXT_FIELD_BASE_SIZES, + TEXT_FIELD_BASE_TYPES, +} from './text-field-base.constants'; diff --git a/ui/components/component-library/text-field-base/text-field-base.constants.js b/ui/components/component-library/text-field-base/text-field-base.constants.js new file mode 100644 index 000000000..decdb364a --- /dev/null +++ b/ui/components/component-library/text-field-base/text-field-base.constants.js @@ -0,0 +1,12 @@ +import { SIZES } from '../../../helpers/constants/design-system'; + +export const TEXT_FIELD_BASE_SIZES = { + SM: SIZES.SM, + MD: SIZES.MD, + LG: SIZES.LG, +}; +export const TEXT_FIELD_BASE_TYPES = { + TEXT: 'text', + NUMBER: 'number', + PASSWORD: 'password', +}; diff --git a/ui/components/component-library/text-field-base/text-field-base.js b/ui/components/component-library/text-field-base/text-field-base.js new file mode 100644 index 000000000..d672f3700 --- /dev/null +++ b/ui/components/component-library/text-field-base/text-field-base.js @@ -0,0 +1,259 @@ +import React, { useState, useRef, useEffect } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; + +import { + DISPLAY, + SIZES, + ALIGN_ITEMS, + TEXT, + COLORS, +} from '../../../helpers/constants/design-system'; + +import Box from '../../ui/box'; + +import { Text } from '../text'; + +import { + TEXT_FIELD_BASE_SIZES, + TEXT_FIELD_BASE_TYPES, +} from './text-field-base.constants'; + +export const TextFieldBase = ({ + autoComplete, + autoFocus, + className, + defaultValue, + disabled, + error, + id, + inputProps, + inputRef, + leftAccessory, + rightAccessory, + maxLength, + name, + onBlur, + onChange, + onClick, + onFocus, + placeholder, + readOnly, + required, + size = SIZES.MD, + type = 'text', + truncate = true, + value, + ...props +}) => { + const internalInputRef = useRef(null); + const [focused, setFocused] = useState(false); + + useEffect(() => { + // The blur won't fire when the disabled state is set on a focused input. + // We need to set the focused state manually. + if (disabled) { + setFocused(false); + } + }, [disabled]); + + const handleClick = (event) => { + const { current } = internalInputRef; + + if (current) { + current.focus(); + setFocused(true); + } + + if (onClick) { + onClick(event); + } + }; + + const handleFocus = (event) => { + setFocused(true); + onFocus && onFocus(event); + }; + + const handleBlur = (event) => { + setFocused(false); + onBlur && onBlur(event); + }; + + const handleInputRef = (ref) => { + internalInputRef.current = ref; + if (inputRef && inputRef.current !== undefined) { + inputRef.current = ref; + } else if (typeof inputRef === 'function') { + inputRef(ref); + } + }; + + return ( + + {leftAccessory} + + {rightAccessory} + + ); +}; + +TextFieldBase.propTypes = { + /** + * Autocomplete allows the browser to predict the value based on earlier typed values + */ + autoComplete: PropTypes.string, + /** + * If `true`, the input will be focused during the first mount. + */ + autoFocus: PropTypes.bool, + /** + * An additional className to apply to the text-field-base + */ + className: PropTypes.string, + /** + * The default input value, useful when not controlling the component. + */ + defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + /** + * If `true`, the input will be disabled. + */ + disabled: PropTypes.bool, + /** + * If `true`, the input will indicate an error + */ + error: PropTypes.bool, + /** + * The id of the `input` element. + */ + id: PropTypes.string, + /** + * Attributes applied to the `input` element. + */ + inputProps: PropTypes.object, + /** + * Component to appear on the left side of the input + */ + leftAccessory: PropTypes.node, + /** + * Component to appear on the right side of the input + */ + rightAccessory: PropTypes.node, + /** + * Use inputRef to pass a ref to the html input element. + */ + inputRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), + /** + * Max number of characters to allow + */ + maxLength: PropTypes.number, + /** + * Name attribute of the `input` element. + */ + name: PropTypes.string, + /** + * Callback fired on blur + */ + onBlur: PropTypes.func, + /** + * Callback fired when the value is changed. + */ + onChange: PropTypes.func, + /** + * Callback fired when the TextField is clicked on + */ + onClick: PropTypes.func, + /** + * Callback fired on focus + */ + onFocus: PropTypes.func, + /** + * The short hint displayed in the input before the user enters a value. + */ + placeholder: PropTypes.string, + /** + * It prevents the user from changing the value of the field (not from interacting with the field). + */ + readOnly: PropTypes.bool, + /** + * If `true`, the input will be required. Currently no visual difference is shown. + */ + required: PropTypes.bool, + /** + * The size of the text field. Changes the height of the component + * Accepts SM(32px), MD(40px), LG(48px) + */ + size: PropTypes.oneOf(Object.values(TEXT_FIELD_BASE_SIZES)), + /** + * Type of the input element. Can be TEXT_FIELD_BASE_TYPES.TEXT, TEXT_FIELD_BASE_TYPES.PASSWORD, TEXT_FIELD_BASE_TYPES.NUMBER + * Defaults to TEXT_FIELD_BASE_TYPES.TEXT ('text') + */ + type: PropTypes.oneOf(Object.values(TEXT_FIELD_BASE_TYPES)), + /** + * If true will ellipse the text of the input + * Defaults to true + */ + truncate: PropTypes.bool, + /** + * The input value, required for a controlled component. + */ + value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + /** + * TextFieldBase accepts all the props from Box + */ + ...Box.propTypes, +}; + +TextFieldBase.displayName = 'TextFieldBase'; diff --git a/ui/components/component-library/text-field-base/text-field-base.scss b/ui/components/component-library/text-field-base/text-field-base.scss new file mode 100644 index 000000000..4bcaf4d50 --- /dev/null +++ b/ui/components/component-library/text-field-base/text-field-base.scss @@ -0,0 +1,53 @@ +.mm-text-field-base { + --text-field-base-height: var(--size, 40px); + + &--size-sm { + --size: 32px; + } + + &--size-md { + --size: 40px; + } + + &--size-lg { + --size: 48px; + } + + height: var(--text-field-base-height); + border-color: var(--color-border-default); + + &--focused { + outline: 5px auto Highlight; // firefox + outline: 5px auto -webkit-focus-ring-color; // chrome + } + + &--error { + border-color: var(--color-error-default); + } + + &--disabled { + opacity: 0.5; + border-color: var(--color-border-default); + } + + // truncates text with ellipsis + &--truncate .mm-text-field-base__input { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + &__input { + border: none; + height: 100%; + flex-grow: 1; + box-sizing: content-box; + margin: 0; + padding: 0; + + &:focus, + &:focus-visible { + outline: none; + } + } +} diff --git a/ui/components/component-library/text-field-base/text-field-base.stories.js b/ui/components/component-library/text-field-base/text-field-base.stories.js new file mode 100644 index 000000000..9169a5f21 --- /dev/null +++ b/ui/components/component-library/text-field-base/text-field-base.stories.js @@ -0,0 +1,381 @@ +import React, { useState, useRef } from 'react'; + +import { + SIZES, + DISPLAY, + COLORS, + FLEX_DIRECTION, + ALIGN_ITEMS, + TEXT, +} from '../../../helpers/constants/design-system'; +import Box from '../../ui/box/box'; + +import { Icon, ICON_NAMES } from '../icon'; +import { AvatarToken } from '../avatar-token'; +import { AvatarAccount } from '../avatar-account'; +import { Text } from '../text'; + +import { + TEXT_FIELD_BASE_SIZES, + TEXT_FIELD_BASE_TYPES, +} from './text-field-base.constants'; +import { TextFieldBase } from './text-field-base'; +import README from './README.mdx'; + +const marginSizeControlOptions = [ + undefined, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 'auto', +]; + +export default { + title: 'Components/ComponentLibrary/TextFieldBase', + id: __filename, + component: TextFieldBase, + parameters: { + docs: { + page: README, + }, + }, + argTypes: { + autoComplete: { + control: 'boolean', + }, + autoFocus: { + control: 'boolean', + }, + className: { + control: 'text', + }, + defaultValue: { + control: 'text', + }, + disabled: { + control: 'boolean', + }, + error: { + control: 'boolean', + }, + id: { + control: 'text', + }, + inputProps: { + control: 'object', + }, + leftAccessory: { + control: 'text', + }, + maxLength: { + control: 'number', + }, + name: { + control: 'text', + }, + onBlur: { + action: 'onBlur', + }, + onChange: { + action: 'onChange', + }, + onClick: { + action: 'onClick', + }, + onFocus: { + action: 'onFocus', + }, + placeholder: { + control: 'text', + }, + readOnly: { + control: 'boolean', + }, + required: { + control: 'boolean', + }, + rightAccessory: { + control: 'text', + }, + size: { + control: 'select', + options: Object.values(TEXT_FIELD_BASE_SIZES), + }, + type: { + control: 'select', + options: Object.values(TEXT_FIELD_BASE_TYPES), + }, + value: { + control: 'text', + }, + marginTop: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginRight: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginBottom: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginLeft: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + }, + args: { + placeholder: 'Placeholder...', + }, +}; + +const Template = (args) => ; + +export const DefaultStory = Template.bind({}); +DefaultStory.storyName = 'Default'; + +export const Size = (args) => { + return ( + + + + + + ); +}; + +export const Type = (args) => ( + + + + + +); + +export const Truncate = Template.bind({}); +Truncate.args = { + placeholder: 'Truncate', + value: 'Truncated text when truncate and width is set', + truncate: true, + style: { width: 240 }, +}; + +export const LeftAccessoryRightAccessory = (args) => { + const [value, setValue] = useState({ + search: '', + address: '', + amount: 1, + accountAddress: '0x514910771af9ca656af840dff83e8264ecf986ca', + }); + const handleOnChange = (e) => { + setValue({ ...value, [e.target.name]: e.target.value }); + }; + const handleTokenPrice = (tokenAmount, priceUSD) => { + return tokenAmount * priceUSD; + }; + return ( + + + } + /> + + + + } + /> + + + AST + + + } + rightAccessory={ + + = ${handleTokenPrice(value.amount, 0.11)} + + } + /> + + ) + } + rightAccessory={ + value.accountAddress.length === 42 && ( + + ) + } + /> + + ); +}; + +export const InputRef = (args) => { + const inputRef = useRef(null); + const [value, setValue] = useState(''); + const handleOnClick = () => { + inputRef.current.focus(); + }; + const handleOnChange = (e) => { + setValue(e.target.value); + }; + return ( + <> + + + Edit + + + ); +}; + +export const AutoComplete = Template.bind({}); +AutoComplete.args = { + autoComplete: true, + type: 'password', + placeholder: 'Enter password', +}; + +export const AutoFocus = Template.bind({}); +AutoFocus.args = { autoFocus: true }; + +export const DefaultValue = Template.bind({}); +DefaultValue.args = { defaultValue: 'Default value' }; + +export const Disabled = Template.bind({}); +Disabled.args = { disabled: true }; + +export const ErrorStory = Template.bind({}); +ErrorStory.args = { error: true }; +ErrorStory.storyName = 'Error'; + +export const MaxLength = Template.bind({}); +MaxLength.args = { maxLength: 10, placeholder: 'Max length 10' }; + +export const ReadOnly = Template.bind({}); +ReadOnly.args = { readOnly: true, value: 'Read only' }; + +export const Required = Template.bind({}); +Required.args = { required: true, placeholder: 'Required' }; diff --git a/ui/components/component-library/text-field-base/text-field-base.test.js b/ui/components/component-library/text-field-base/text-field-base.test.js new file mode 100644 index 000000000..1fdd92fb0 --- /dev/null +++ b/ui/components/component-library/text-field-base/text-field-base.test.js @@ -0,0 +1,238 @@ +/* eslint-disable jest/require-top-level-describe */ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import { SIZES } from '../../../helpers/constants/design-system'; + +import { TextFieldBase } from './text-field-base'; + +describe('TextFieldBase', () => { + it('should render correctly', () => { + const { getByRole } = render(); + expect(getByRole('textbox')).toBeDefined(); + }); + it('should render and be able to input text', () => { + const { getByTestId } = render( + , + ); + const textFieldBase = getByTestId('text-field-base'); + + expect(textFieldBase.value).toBe(''); // initial value is empty string + fireEvent.change(textFieldBase, { target: { value: 'text value' } }); + expect(textFieldBase.value).toBe('text value'); + fireEvent.change(textFieldBase, { target: { value: '' } }); // reset value + expect(textFieldBase.value).toBe(''); // value is empty string after reset + }); + it('should render with focused state when clicked', () => { + const { getByTestId } = render( + , + ); + const textFieldBase = getByTestId('text-field-base'); + + fireEvent.click(textFieldBase); + expect(getByTestId('input')).toHaveFocus(); + expect(getByTestId('text-field-base')).toHaveClass( + 'mm-text-field-base--focused ', + ); + }); + it('should render and fire onFocus and onBlur events', () => { + const onFocus = jest.fn(); + const onBlur = jest.fn(); + const { getByTestId } = render( + , + ); + const textFieldBase = getByTestId('text-field-base'); + + fireEvent.focus(textFieldBase); + expect(onFocus).toHaveBeenCalledTimes(1); + fireEvent.blur(textFieldBase); + expect(onBlur).toHaveBeenCalledTimes(1); + }); + it('should render and fire onChange event', () => { + const onChange = jest.fn(); + const { getByTestId } = render( + , + ); + const textFieldBase = getByTestId('text-field-base'); + + fireEvent.change(textFieldBase, { target: { value: 'text value' } }); + expect(onChange).toHaveBeenCalledTimes(1); + }); + it('should render and fire onClick event', () => { + const onClick = jest.fn(); + const { getByTestId } = render( + , + ); + const textFieldBase = getByTestId('text-field-base'); + + fireEvent.click(textFieldBase); + expect(onClick).toHaveBeenCalledTimes(1); + }); + it('should render with different size classes', () => { + const { getByTestId } = render( + <> + + + + , + ); + expect(getByTestId('sm')).toHaveClass('mm-text-field-base--size-sm'); + expect(getByTestId('md')).toHaveClass('mm-text-field-base--size-md'); + expect(getByTestId('lg')).toHaveClass('mm-text-field-base--size-lg'); + }); + it('should render with different types', () => { + const { getByTestId } = render( + <> + + + + , + ); + expect(getByTestId('text-field-base-text')).toHaveAttribute('type', 'text'); + expect(getByTestId('text-field-base-number')).toHaveAttribute( + 'type', + 'number', + ); + expect(getByTestId('text-field-base-password')).toHaveAttribute( + 'type', + 'password', + ); + }); + it('should render with truncate class as true by default and remove it when truncate is false', () => { + const { getByTestId } = render( + <> + + + , + ); + expect(getByTestId('truncate')).toHaveClass('mm-text-field-base--truncate'); + expect(getByTestId('no-truncate')).not.toHaveClass( + 'mm-text-field-base--truncate', + ); + }); + it('should render with right and left accessories', () => { + const { getByRole, getByText } = render( + left accessory} + rightAccessory={
right accessory
} + />, + ); + expect(getByRole('textbox')).toBeDefined(); + expect(getByText('left accessory')).toBeDefined(); + expect(getByText('right accessory')).toBeDefined(); + }); + it('should render with working ref using inputRef prop', () => { + // Because the 'ref' attribute wont flow down to the DOM + // I'm not exactly sure how to test this? + const mockRef = jest.fn(); + const { getByRole } = render(); + expect(getByRole('textbox')).toBeDefined(); + expect(mockRef).toHaveBeenCalledTimes(1); + }); + it('should render with autoComplete', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('text-field-base-auto-complete')).toHaveAttribute( + 'autocomplete', + 'on', + ); + }); + it('should render with autoFocus', () => { + const { getByRole } = render(); + expect(getByRole('textbox')).toHaveFocus(); + }); + it('should render with a defaultValue', () => { + const { getByRole } = render( + , + ); + expect(getByRole('textbox').value).toBe('default value'); + }); + it('should render in disabled state and not focus or be clickable', () => { + const mockOnClick = jest.fn(); + const mockOnFocus = jest.fn(); + const { getByRole } = render( + , + ); + + getByRole('textbox').focus(); + expect(getByRole('textbox')).toBeDisabled(); + expect(mockOnClick).toHaveBeenCalledTimes(0); + expect(mockOnFocus).toHaveBeenCalledTimes(0); + }); + it('should render with error className when error is true', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('text-field-base-error')).toHaveClass( + 'mm-text-field-base--error', + ); + }); + it('should render with maxLength and not allow more than the set characters', async () => { + const { getByRole } = render(); + const textFieldBase = getByRole('textbox'); + await userEvent.type(textFieldBase, '1234567890'); + expect(getByRole('textbox')).toBeDefined(); + expect(textFieldBase.maxLength).toBe(5); + expect(textFieldBase.value).toBe('12345'); + expect(textFieldBase.value).toHaveLength(5); + }); + it('should render with readOnly attr when readOnly is true', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('read-only')).not.toHaveClass( + 'mm-text-field-base--focused ', + ); + expect(getByTestId('text-field-base-readonly')).toHaveAttribute( + 'readonly', + '', + ); + }); + it('should render with required attr when required is true', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('text-field-base-required')).toHaveAttribute( + 'required', + '', + ); + }); +}); diff --git a/ui/components/component-library/text-field/README.mdx b/ui/components/component-library/text-field/README.mdx new file mode 100644 index 000000000..7a9bc8cd6 --- /dev/null +++ b/ui/components/component-library/text-field/README.mdx @@ -0,0 +1,73 @@ +import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; + +import { TextField } from './text-field'; + +# TextField + +The `TextField` component lets users enter and edit text as well as adding a show clear button option. It wraps `TextFieldBase` and functions only as a controlled input. + + + + + +## Props + +The `TextField` accepts all props below as well as all [Box](/docs/ui-components-ui-box-box-stories-js--default-story#props) and [TextFieldBase](/docs/ui-components-component-library-text-field-base-text-field-base-stories-js--default-story#props) component props + + + +### Show Clear + +Use the `showClear` prop to display a clear button when `TextField` has a value. Clicking the button will clear the value. +You can also attach an `onClear` handler to the `TextField` to perform additional actions when the clear button is clicked. + + + + + +```jsx +import { TextField } from '../../ui/component-library/text-field'; + +; +``` + +### On Clear + +Use the `onClear` prop to perform additional actions when the clear button is clicked. + + + + + +```jsx +import { TextField } from '../../ui/component-library/text-field'; + + console.log('cleared input')} />; +``` + +### Clear Button Props and Clear Button Icon Props + +Use the `clearButtonProps` and `clearButtonIconProps` props to pass props to the clear button and clear button icon respectively. + + + + + +```jsx +import { + SIZES, + COLORS, + BORDER_RADIUS, +} from '../../../helpers/constants/design-system'; +import { TextField } from '../../ui/component-library/text-field'; + +; +``` diff --git a/ui/components/component-library/text-field/index.js b/ui/components/component-library/text-field/index.js new file mode 100644 index 000000000..a680c752d --- /dev/null +++ b/ui/components/component-library/text-field/index.js @@ -0,0 +1,2 @@ +export { TextField } from './text-field'; +export { TEXT_FIELD_SIZES, TEXT_FIELD_TYPES } from './text-field.constants'; diff --git a/ui/components/component-library/text-field/text-field.constants.js b/ui/components/component-library/text-field/text-field.constants.js new file mode 100644 index 000000000..8047344e5 --- /dev/null +++ b/ui/components/component-library/text-field/text-field.constants.js @@ -0,0 +1,7 @@ +import { + TEXT_FIELD_BASE_SIZES, + TEXT_FIELD_BASE_TYPES, +} from '../text-field-base/text-field-base.constants'; + +export const TEXT_FIELD_SIZES = TEXT_FIELD_BASE_SIZES; +export const TEXT_FIELD_TYPES = TEXT_FIELD_BASE_TYPES; diff --git a/ui/components/component-library/text-field/text-field.js b/ui/components/component-library/text-field/text-field.js new file mode 100644 index 000000000..ddf351776 --- /dev/null +++ b/ui/components/component-library/text-field/text-field.js @@ -0,0 +1,108 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; + +import { + SIZES, + DISPLAY, + JUSTIFY_CONTENT, + ALIGN_ITEMS, + COLORS, +} from '../../../helpers/constants/design-system'; + +import Box from '../../ui/box'; + +import { Icon, ICON_NAMES } from '../icon'; + +import { TextFieldBase } from '../text-field-base'; + +export const TextField = ({ + className, + showClear, + clearButtonIconProps, + clearButtonProps, + rightAccessory, + value: valueProp, + onChange, + onClear, + inputProps, + ...props +}) => { + const [value, setValue] = useState(valueProp || ''); + const handleOnChange = (e) => { + setValue(e.target.value); + onChange?.(e); + }; + const handleClear = (e) => { + setValue(''); + clearButtonProps?.onClick?.(e); + onClear?.(e); + }; + return ( + + {/* replace with ButtonIcon */} + + + + {rightAccessory} + + ) : ( + rightAccessory + ) + } + inputProps={{ + marginRight: showClear ? 6 : 0, + ...inputProps, + }} + {...props} + /> + ); +}; + +TextField.propTypes = { + /** + * An additional className to apply to the text-field + */ + className: PropTypes.string, + /** + * Show a clear button to clear the input + */ + showClear: PropTypes.bool, + /** + * The event handler for when the clear button is clicked + */ + onClear: PropTypes.func, + /** + * The props to pass to the clear button + */ + clearButtonProps: PropTypes.shape(Box.PropTypes), + /** + * The props to pass to the icon inside of the close button + */ + clearButtonIconProps: PropTypes.shape(Icon.PropTypes), + /** + * TextField accepts all the props from TextFieldBase and Box + */ + ...TextFieldBase.propTypes, +}; diff --git a/ui/components/component-library/text-field/text-field.scss b/ui/components/component-library/text-field/text-field.scss new file mode 100644 index 000000000..b21024d81 --- /dev/null +++ b/ui/components/component-library/text-field/text-field.scss @@ -0,0 +1,10 @@ +.mm-text-field { + // TOD: remove most of these styles when replaced by ButtonIcon + &__button-clear { + height: 24px; + width: 24px; + max-width: 24px; + flex: 0 0 24px; + margin-left: -24px; + } +} diff --git a/ui/components/component-library/text-field/text-field.stories.js b/ui/components/component-library/text-field/text-field.stories.js new file mode 100644 index 000000000..70832ed2b --- /dev/null +++ b/ui/components/component-library/text-field/text-field.stories.js @@ -0,0 +1,247 @@ +import React, { useState } from 'react'; + +import { + SIZES, + COLORS, + BORDER_RADIUS, +} from '../../../helpers/constants/design-system'; + +import { Text } from '../text'; + +import { TEXT_FIELD_SIZES, TEXT_FIELD_TYPES } from './text-field.constants'; +import { TextField } from './text-field'; + +import README from './README.mdx'; + +const marginSizeControlOptions = [ + undefined, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 'auto', +]; + +export default { + title: 'Components/ComponentLibrary/TextField', + id: __filename, + component: TextField, + parameters: { + docs: { + page: README, + }, + }, + argTypes: { + showClear: { + control: 'boolean', + }, + value: { + control: 'text', + }, + onChange: { + action: 'onChange', + table: { category: 'text field base props' }, + }, + onClear: { + action: 'onClear', + }, + clearButtonIconProps: { + control: 'object', + }, + clearButtonProps: { + control: 'object', + }, + autoComplete: { + control: 'boolean', + table: { category: 'text field base props' }, + }, + autoFocus: { + control: 'boolean', + table: { category: 'text field base props' }, + }, + className: { + control: 'text', + table: { category: 'text field base props' }, + }, + disabled: { + control: 'boolean', + table: { category: 'text field base props' }, + }, + error: { + control: 'boolean', + table: { category: 'text field base props' }, + }, + id: { + control: 'text', + table: { category: 'text field base props' }, + }, + inputProps: { + control: 'object', + table: { category: 'text field base props' }, + }, + leftAccessory: { + control: 'text', + table: { category: 'text field base props' }, + }, + maxLength: { + control: 'number', + table: { category: 'text field base props' }, + }, + name: { + control: 'text', + table: { category: 'text field base props' }, + }, + onBlur: { + action: 'onBlur', + table: { category: 'text field base props' }, + }, + onClick: { + action: 'onClick', + table: { category: 'text field base props' }, + }, + onFocus: { + action: 'onFocus', + table: { category: 'text field base props' }, + }, + onKeyDown: { + action: 'onKeyDown', + table: { category: 'text field base props' }, + }, + onKeyUp: { + action: 'onKeyUp', + table: { category: 'text field base props' }, + }, + placeholder: { + control: 'text', + table: { category: 'text field base props' }, + }, + readOnly: { + control: 'boolean', + table: { category: 'text field base props' }, + }, + required: { + control: 'boolean', + table: { category: 'text field base props' }, + }, + rightAccessory: { + control: 'text', + table: { category: 'text field base props' }, + }, + size: { + control: 'select', + options: Object.values(TEXT_FIELD_SIZES), + table: { category: 'text field base props' }, + }, + type: { + control: 'select', + options: Object.values(TEXT_FIELD_TYPES), + table: { category: 'text field base props' }, + }, + truncate: { + control: 'boolean', + table: { category: 'text field base props' }, + }, + marginTop: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginRight: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginBottom: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + marginLeft: { + options: marginSizeControlOptions, + control: 'select', + table: { category: 'box props' }, + }, + }, + args: { + showClear: false, + placeholder: 'Placeholder...', + autoFocus: false, + disabled: false, + error: false, + id: '', + readOnly: false, + required: false, + size: SIZES.MD, + type: 'text', + truncate: false, + }, +}; + +const Template = (args) => ; + +export const DefaultStory = Template.bind({}); +DefaultStory.storyName = 'Default'; + +export const ShowClear = (args) => { + const [value, setValue] = useState('show clear'); + const handleOnChange = (e) => { + setValue(e.target.value); + }; + return ( + + ); +}; + +export const OnClear = (args) => { + const [value, setValue] = useState('onClear example'); + const [showOnClearMessage, setShowOnClearMessage] = useState(false); + const handleOnChange = (e) => { + setValue(e.target.value); + showOnClearMessage && setShowOnClearMessage(false); + }; + const handleOnClear = () => { + setShowOnClearMessage(true); + }; + return ( + <> + + {showOnClearMessage && onClear called} + + ); +}; + +export const ClearButtonPropsClearButtonIconProps = Template.bind({}); +ClearButtonPropsClearButtonIconProps.args = { + value: 'clear button props', + size: SIZES.LG, + showClear: true, + clearButtonProps: { + backgroundColor: COLORS.BACKGROUND_ALTERNATIVE, + borderRadius: BORDER_RADIUS.XS, + }, + clearButtonIconProps: { + size: SIZES.MD, + }, +}; diff --git a/ui/components/component-library/text-field/text-field.test.js b/ui/components/component-library/text-field/text-field.test.js new file mode 100644 index 000000000..f2d7819be --- /dev/null +++ b/ui/components/component-library/text-field/text-field.test.js @@ -0,0 +1,161 @@ +/* eslint-disable jest/require-top-level-describe */ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react'; + +import { TextField } from './text-field'; + +describe('TextField', () => { + it('should render correctly', () => { + const { getByRole } = render(); + expect(getByRole('textbox')).toBeDefined(); + }); + it('should render and be able to input text', () => { + const { getByTestId } = render( + , + ); + const textField = getByTestId('text-field'); + + expect(textField.value).toBe(''); // initial value is empty string + fireEvent.change(textField, { target: { value: 'text value' } }); + expect(textField.value).toBe('text value'); + fireEvent.change(textField, { target: { value: '' } }); // reset value + expect(textField.value).toBe(''); // value is empty string after reset + }); + it('should render and fire onFocus and onBlur events', () => { + const onFocus = jest.fn(); + const onBlur = jest.fn(); + const { getByTestId } = render( + , + ); + const textField = getByTestId('text-field'); + + fireEvent.focus(textField); + expect(onFocus).toHaveBeenCalledTimes(1); + fireEvent.blur(textField); + expect(onBlur).toHaveBeenCalledTimes(1); + }); + it('should render and fire onChange event', () => { + const onChange = jest.fn(); + const { getByTestId } = render( + , + ); + const textField = getByTestId('text-field'); + + fireEvent.change(textField, { target: { value: 'text value' } }); + expect(onChange).toHaveBeenCalledTimes(1); + }); + it('should render and fire onClick event', () => { + const onClick = jest.fn(); + const { getByTestId } = render( + , + ); + const textField = getByTestId('text-field'); + + fireEvent.click(textField); + expect(onClick).toHaveBeenCalledTimes(1); + }); + it('should render showClear button when showClear is true and value exists', () => { + const { getByRole, getByTestId } = render( + , + ); + const textField = getByRole('textbox'); + expect(textField.value).toBe(''); // initial value is empty string + fireEvent.change(textField, { target: { value: 'text value' } }); + expect(textField.value).toBe('text value'); + expect(getByTestId('clear-button')).toBeDefined(); + expect(getByTestId('clear-button-icon')).toBeDefined(); + }); + it('should render with the rightAccessory', () => { + const { getByText } = render( + right-accessory} />, + ); + expect(getByText('right-accessory')).toBeDefined(); + }); + it('should still render with the rightAccessory when showClear is true', () => { + const { getByRole, getByTestId, getByText } = render( + right-accessory} + showClear + />, + ); + const textField = getByRole('textbox'); + expect(textField.value).toBe(''); // initial value is empty string + fireEvent.change(textField, { target: { value: 'text value' } }); + expect(textField.value).toBe('text value'); + expect(getByTestId('clear-button')).toBeDefined(); + expect(getByTestId('clear-button-icon')).toBeDefined(); + expect(getByText('right-accessory')).toBeDefined(); + }); + it('should clear text when clear button is clicked', () => { + const { getByRole, getByTestId } = render( + right-accessory} + showClear + />, + ); + const textField = getByRole('textbox'); + fireEvent.change(textField, { target: { value: 'text value' } }); + expect(textField.value).toBe('text value'); + fireEvent.click(getByTestId('clear-button')); + expect(textField.value).toBe(''); + }); + it('should fire onClear event when passed to onClear prop', () => { + const onClear = jest.fn(); + const { getByRole, getByTestId } = render( + , + ); + const textField = getByRole('textbox'); + fireEvent.change(textField, { target: { value: 'text value' } }); + expect(textField.value).toBe('text value'); + fireEvent.click(getByTestId('clear-button')); + expect(onClear).toHaveBeenCalledTimes(1); + }); + it('should fire clearButtonProps.onClick event when passed to clearButtonProps.onClick prop', () => { + const onClear = jest.fn(); + const onClick = jest.fn(); + const { getByRole, getByTestId } = render( + , + ); + const textField = getByRole('textbox'); + fireEvent.change(textField, { target: { value: 'text value' } }); + expect(textField.value).toBe('text value'); + fireEvent.click(getByTestId('clear-button')); + expect(onClear).toHaveBeenCalledTimes(1); + expect(onClick).toHaveBeenCalledTimes(1); + }); + it('should be able to accept inputProps', () => { + const { getByRole } = render( + , + ); + const textField = getByRole('textbox'); + expect(textField).toBeDefined(); + }); +}); diff --git a/ui/components/component-library/text/README.mdx b/ui/components/component-library/text/README.mdx index 197cebb2b..4f3650ebf 100644 --- a/ui/components/component-library/text/README.mdx +++ b/ui/components/component-library/text/README.mdx @@ -35,6 +35,7 @@ import { TEXT } from '../../../helpers/constants/design-system'; body-md body-sm body-xs +inherit ``` ### Color @@ -268,6 +269,7 @@ import { Text } from '../../ui/component-library/text'; p span strong + ``` Renders the html: @@ -287,6 +289,7 @@ Renders the html:

p

span strong + ``` ### Box Props diff --git a/ui/components/component-library/text/text.js b/ui/components/component-library/text/text.js index 3ca747b69..d252f59ef 100644 --- a/ui/components/component-library/text/text.js +++ b/ui/components/component-library/text/text.js @@ -29,61 +29,72 @@ export const ValidTags = [ 'strong', 'ul', 'label', + 'input', ]; -export const Text = ({ - variant = TEXT.BODY_MD, - color = TEXT_COLORS.TEXT_DEFAULT, - fontWeight, - fontStyle, - textTransform, - textAlign, - overflowWrap, - ellipsis, - as, - className, - children, - ...props -}) => { - let Tag = as ?? variant; - let strongTagFontWeight; - - if (Tag === 'strong') { - strongTagFontWeight = FONT_WEIGHT.BOLD; - } - - const computedClassName = classnames( - 'text', - className, - `text--${variant}`, - (strongTagFontWeight || fontWeight) && - `text--font-weight-${strongTagFontWeight || fontWeight}`, +export const Text = React.forwardRef( + ( { - [`text--font-style-${fontStyle}`]: Boolean(fontStyle), - [`text--ellipsis`]: Boolean(ellipsis), - [`text--text-transform-${textTransform}`]: Boolean(textTransform), - [`text--text-align-${textAlign}`]: Boolean(textAlign), - [`text--color-${color}`]: Boolean(color), - [`text--overflow-wrap-${overflowWrap}`]: Boolean(overflowWrap), + variant = TEXT.BODY_MD, + color = TEXT_COLORS.TEXT_DEFAULT, + fontWeight, + fontStyle, + textTransform, + textAlign, + overflowWrap, + ellipsis, + as, + className, + children, + ...props }, - ); + ref, + ) => { + let Tag = as ?? variant; + let strongTagFontWeight; - // // Set a default tag based on variant - const splitTag = Tag.split('-')[0]; - if (splitTag === 'body') { - Tag = 'p'; - } else if (splitTag === 'heading') { - Tag = 'h2'; - } else if (splitTag === 'display') { - Tag = 'h1'; - } + if (Tag === 'strong') { + strongTagFontWeight = FONT_WEIGHT.BOLD; + } - return ( - - {children} - - ); -}; + const computedClassName = classnames( + 'text', + className, + `text--${variant}`, + (strongTagFontWeight || fontWeight) && + `text--font-weight-${strongTagFontWeight || fontWeight}`, + { + [`text--font-style-${fontStyle}`]: Boolean(fontStyle), + [`text--ellipsis`]: Boolean(ellipsis), + [`text--text-transform-${textTransform}`]: Boolean(textTransform), + [`text--text-align-${textAlign}`]: Boolean(textAlign), + [`text--color-${color}`]: Boolean(color), + [`text--overflow-wrap-${overflowWrap}`]: Boolean(overflowWrap), + }, + ); + + // // Set a default tag based on variant + const splitTag = Tag.split('-')[0]; + if (splitTag === 'body') { + Tag = 'p'; + } else if (splitTag === 'heading') { + Tag = 'h2'; + } else if (splitTag === 'display') { + Tag = 'h1'; + } + + return ( + + {children} + + ); + }, +); Text.propTypes = { /** @@ -142,4 +153,6 @@ Text.propTypes = { ...Box.propTypes, }; +Text.displayName = 'Text'; // Used for React DevTools profiler + export default Text; diff --git a/ui/components/component-library/text/text.scss b/ui/components/component-library/text/text.scss index 5d1ad4e01..972279570 100644 --- a/ui/components/component-library/text/text.scss +++ b/ui/components/component-library/text/text.scss @@ -82,6 +82,14 @@ $text-variants: ( } } + &--inherit { + font-family: inherit; + font-weight: inherit; + font-size: inherit; + line-height: inherit; + letter-spacing: inherit; + } + &--ellipsis { text-overflow: ellipsis; white-space: nowrap; diff --git a/ui/components/component-library/text/text.stories.js b/ui/components/component-library/text/text.stories.js index 2b8fbfa15..c7efff1fe 100644 --- a/ui/components/component-library/text/text.stories.js +++ b/ui/components/component-library/text/text.stories.js @@ -259,12 +259,17 @@ export const Ellipsis = (args) => ( export const As = (args) => ( <> - {Object.values(ValidTags).map((tag) => ( -
- - {tag} - -
- ))} + {ValidTags.map((tag) => { + if (tag === 'input') { + return ; + } + return ( +
+ + {tag} + +
+ ); + })} ); diff --git a/ui/components/component-library/text/text.test.js b/ui/components/component-library/text/text.test.js index 84a8f1672..5849edbe5 100644 --- a/ui/components/component-library/text/text.test.js +++ b/ui/components/component-library/text/text.test.js @@ -218,4 +218,9 @@ describe('Text', () => { 'text--text-transform-capitalize', ); }); + it('should accept a ref prop that is passed down to the html element', () => { + const mockRef = jest.fn(); + render(); + expect(mockRef).toHaveBeenCalledTimes(1); + }); }); diff --git a/ui/components/ui/account-mismatch-warning/__snapshots__/acccount-mismatch-warning.component.test.js.snap b/ui/components/ui/account-mismatch-warning/__snapshots__/acccount-mismatch-warning.component.test.js.snap new file mode 100644 index 000000000..6225239f6 --- /dev/null +++ b/ui/components/ui/account-mismatch-warning/__snapshots__/acccount-mismatch-warning.component.test.js.snap @@ -0,0 +1,36 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AccountMismatchWarning should match snapshot of mismatch address warning 1`] = ` +
+ +
+`; + +exports[`AccountMismatchWarning should match snapshot of no warning with same address and selected address 1`] = `
`; diff --git a/ui/components/ui/account-mismatch-warning/acccount-mismatch-warning.component.test.js b/ui/components/ui/account-mismatch-warning/acccount-mismatch-warning.component.test.js index e06f8f875..d04cb9179 100644 --- a/ui/components/ui/account-mismatch-warning/acccount-mismatch-warning.component.test.js +++ b/ui/components/ui/account-mismatch-warning/acccount-mismatch-warning.component.test.js @@ -1,35 +1,35 @@ import React from 'react'; -import * as reactRedux from 'react-redux'; -import sinon from 'sinon'; -import { shallow } from 'enzyme'; -import InfoIcon from '../icon/info-icon.component'; -import { getSelectedAccount } from '../../../selectors'; +import configureMockStore from 'redux-mock-store'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import mockState from '../../../../test/data/mock-state.json'; import AccountMismatchWarning from './account-mismatch-warning.component'; describe('AccountMismatchWarning', () => { - beforeAll(() => { - sinon.stub(reactRedux, 'useSelector').callsFake((selector) => { - if (selector === getSelectedAccount) { - return { address: 'mockedAddress' }; - } - throw new Error( - `${selector.name} is not cared for in the AccountMismatchWarning test useSelector stub`, - ); - }); - }); + const mockStore = configureMockStore()(mockState); - afterAll(() => { - sinon.restore(); - }); + it('should match snapshot of no warning with same address and selected address', () => { + const props = { + address: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + }; + + const { container } = renderWithProvider( + , + mockStore, + ); - it('renders nothing when the addresses match', () => { - const wrapper = shallow(); - expect(wrapper.find(InfoIcon)).toHaveLength(0); + expect(container).toMatchSnapshot(); }); - it('renders a warning info icon when addresses do not match', () => { - const wrapper = shallow( - , + + it('should match snapshot of mismatch address warning', () => { + const props = { + address: '0xNotSelectedAddress', + }; + + const { container } = renderWithProvider( + , + mockStore, ); - expect(wrapper.find(InfoIcon)).toHaveLength(1); + + expect(container).toMatchSnapshot(); }); }); diff --git a/ui/components/ui/actionable-message/actionable-message.js b/ui/components/ui/actionable-message/actionable-message.js index bfad8da6b..caa784ea0 100644 --- a/ui/components/ui/actionable-message/actionable-message.js +++ b/ui/components/ui/actionable-message/actionable-message.js @@ -26,6 +26,7 @@ export default function ActionableMessage({ withRightButton = false, type = 'default', useIcon = false, + icon, iconFillColor = '', roundedButtons, dataTestId, @@ -43,7 +44,7 @@ export default function ActionableMessage({ return (
- {useIcon ? : null} + {useIcon ? icon || : null} {infoTooltipText && ( `; + +exports[`Alert renders with visible boolean in state 1`] = ` + +`; diff --git a/ui/components/ui/alert/index.test.js b/ui/components/ui/alert/index.test.js index 7689d6d83..7c5900f81 100644 --- a/ui/components/ui/alert/index.test.js +++ b/ui/components/ui/alert/index.test.js @@ -1,16 +1,25 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; import Alert from '.'; describe('Alert', () => { - let wrapper; + it('renders nothing with no visible boolean in state', () => { + const props = { + visible: false, + }; + + const { container } = renderWithProvider(); - beforeEach(() => { - wrapper = shallow(); + expect(container).toMatchSnapshot(); }); - it('renders nothing with no visible boolean in state', () => { - const alert = wrapper.find('.global-alert'); - expect(alert).toHaveLength(0); + it('renders with visible boolean in state', () => { + const props = { + visible: true, + }; + + const { container } = renderWithProvider(); + + expect(container).toMatchSnapshot(); }); }); diff --git a/ui/components/ui/box/README.mdx b/ui/components/ui/box/README.mdx index c5b282750..ff443c1f6 100644 --- a/ui/components/ui/box/README.mdx +++ b/ui/components/ui/box/README.mdx @@ -14,36 +14,36 @@ Box is a utility component that can be used for layout or as a base for other UI ## Props -| Name | Description | Default | -| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------ | -| children | The children of the Box component. If `function` type will render the child as the Box node instead of a child of the Box | - | -| className | Additional className of the Box component | - | -| margin | 0, 1, 2, 4, 6, 8, 9, 10, 12, 'auto' or array of values [1, 2, 'auto'] for responsive props | - | -| marginTop | 0, 1, 2, 4, 6, 8, 9, 10, 12, 'auto' or array of values for responsive props | - | -| marginBottom | 0, 1, 2, 4, 6, 8, 9, 10, 12, 'auto' or array of values for responsive props | - | -| marginRight | 0, 1, 2, 4, 6, 8, 9, 10, 12, 'auto' or array of values for responsive props | - | -| marginLeft | 0, 1, 2, 4, 6, 8, 9, 10, 12, 'auto' or array of values for responsive props | - | -| padding | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] for responsive props | - | -| paddingTop | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] for responsive props | - | -| paddingBottom | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] for responsive props | - | -| paddingRight | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] for responsive props | - | -| paddingLeft | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] for responsive props | - | -| display | [DISPLAY](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L200-L210) values or array of [DISPLAY](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L200-L210) values for responsive props | - | -| flexDirection | [FLEX_DIRECTION](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L187-L192) values or array of [FLEX_DIRECTION](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L187-L192) values for responsive props | FLEX_DIRECTION.ROW | -| flexWrap | [FLEX_WRAP](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L194-L198) values or array of [FLEX_WRAP](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L194-L198) values for responsive props | - | -| alignItems | [ALIGN_ITEMS](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L170-L176) values or array of [ALIGN_ITEMS](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L170-L176) values for responsive props | - | -| justifyContent | [JUSTIFY_CONTENT](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L178-L185) values or array of [JUSTIFY_CONTENT](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L178-L185) values | - | -| gap | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] for responsive props | - | -| textAlign | [TEXT_ALIGN](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L249-L255) values or array of [TEXT_ALIGN](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L249-L255) values for responsive props | - | -| width | [BLOCK_SIZES](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L241-L247) values or array of [BLOCK_SIZES](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L241-L247) values for responsive props | - | -| height | [BLOCK_SIZES](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L241-L247) values or array of [BLOCK_SIZES](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#LL241-L247) values for responsive props | - | -| color | [COLORS](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L117-L133) values or array of [COLORS](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L117-L133) values for responsive props | - | -| backgroundColor | [BACKGROUND_COLORS](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L62-L88) values or array of [BACKGROUND_COLORS](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L62-L88) values for responsive props | - | -| borderColor | [BORDER_COLORS](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L90-L115) values or array of [BORDER_COLORS](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L90-L115) values for responsive props | - | -| borderWidth | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] for responsive props | - | -| borderRadius | [SIZES](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L149-L156) values or array of [SIZES](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L149-L156) values for responsive props | - | -| borderStyle | [BORDER_STYLE](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L158-L164) values or array of [BORDER_STYLE](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L158-L164) values for responsive props | - | -| as | The polymorphic `as` prop allows you to change the root HTML element of the Box component. Defaults to 'div' | 'div' | +| Name | Description | Default | +| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | +| children | The children of the Box component. If `function` type will render the child as the Box node instead of a child of the Box | - | +| className | Additional className of the Box component | - | +| margin | 0, 1, 2, 4, 6, 8, 9, 10, 12, 'auto' or array of values [1, 2, 'auto'] for responsive props | - | +| marginTop | 0, 1, 2, 4, 6, 8, 9, 10, 12, 'auto' or array of values for responsive props | - | +| marginBottom | 0, 1, 2, 4, 6, 8, 9, 10, 12, 'auto' or array of values for responsive props | - | +| marginRight | 0, 1, 2, 4, 6, 8, 9, 10, 12, 'auto' or array of values for responsive props | - | +| marginLeft | 0, 1, 2, 4, 6, 8, 9, 10, 12, 'auto' or array of values for responsive props | - | +| padding | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] for responsive props | - | +| paddingTop | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] for responsive props | - | +| paddingBottom | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] for responsive props | - | +| paddingRight | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] for responsive props | - | +| paddingLeft | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] for responsive props | - | +| display | DISPLAY values or array of DISPLAY values for responsive props from [../ui/helpers/constants/design-system.js](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js) | - | +| flexDirection | FLEX_DIRECTION values or array of FLEX_DIRECTION values for responsive props from [../ui/helpers/constants/design-system.js](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js) | FLEX_DIRECTION.ROW | +| flexWrap | FLEX_WRAP values or array of FLEX_WRAP values for responsive props from [../ui/helpers/constants/design-system.js](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js) | - | +| alignItems | ALIGN_ITEMS values or array of ALIGN_ITEMS values for responsive props from [../ui/helpers/constants/design-system.js](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js) | - | +| justifyContent | JUSTIFY_CONTENT values or array of JUSTIFY_CONTENT values from [../ui/helpers/constants/design-system.js](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js) | - | +| gap | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] for responsive props | - | +| textAlign | TEXT_ALIGN values or array of TEXT_ALIGN values for responsive props from [../ui/helpers/constants/design-system.js](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js) | - | +| width | BLOCK_SIZES values or array of BLOCK_SIZES values for responsive props from [../ui/helpers/constants/design-system.js](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js) | - | +| height | BLOCK_SIZES values or array of BLOCK_SIZES values for responsive props [../ui/helpers/constants/design-system.js](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js) | - | +| color | COLORS values or array of COLORS values for responsive props [../ui/helpers/constants/design-system.js](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js) | - | +| backgroundColor | BACKGROUND_COLORS values or array of BACKGROUND_COLORS values for responsive props from [../ui/helpers/constants/design-system.js](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js) | - | +| borderColor | BORDER_COLORS values or array of BORDER_COLORS values for responsive props from [../ui/helpers/constants/design-system.js](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js) | - | +| borderWidth | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] for responsive props | - | +| borderRadius | BORDER_RADIUS values or array of BORDER_RADIUS values for responsive props from [../ui/helpers/constants/design-system.js](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js) | - | +| borderStyle | BORDER_STYLE values or array of BORDER_STYLE values for responsive props from [../ui/helpers/constants/design-system.js](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js) | - | +| as | The polymorphic `as` prop allows you to change the root HTML element of the Box component. Defaults to 'div' | 'div' | ## Usage @@ -188,6 +188,29 @@ import Box from '../ui/box'; ; ``` +### Border Radius + +Use the `borderRadius` prop along with the `BORDER_RADIUS` object from `ui/helpers/constants/design-system.js` to change border radius. The `borderRadius` prop accepts [responsive props](#responsive-props) in the form of array props. + + + + + +Example of importing `BORDER_RADIUS` object with `Box` component + +```jsx +import { BORDER_RADIUS } from '../../../helpers/constants/design-system'; +import Box from '../ui/box'; + +BORDER_RADIUS.NONE 0px +BORDER_RADIUS.XS 2px +BORDER_RADIUS.SM 4px +BORDER_RADIUS.MD 6px +BORDER_RADIUS.LG 8px +BORDER_RADIUS.XL 12px +BORDER_RADIUS.PILL 9999px +``` + ### Responsive Props The box component provides a responsive props api in the form of array props. Array props are inspired by [styled-systems array props](https://styled-system.com/guides/array-props). The responsive props follow a mobile first methodology with the first item in the array applying the style to the base level size e.g. `0px` and up. The second item overwrites the first items styles at the next breakpoint. diff --git a/ui/components/ui/box/box.js b/ui/components/ui/box/box.js index bd64c906e..30b379ebe 100644 --- a/ui/components/ui/box/box.js +++ b/ui/components/ui/box/box.js @@ -12,17 +12,18 @@ import { ICON_COLORS, DISPLAY, JUSTIFY_CONTENT, - SIZES, TEXT_ALIGN, FLEX_DIRECTION, FLEX_WRAP, BREAKPOINTS, + BORDER_RADIUS, } from '../../../helpers/constants/design-system'; const BASE_CLASS_NAME = 'box'; const Sizes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; const ValidSize = PropTypes.oneOf(Sizes); +const ValidBlockSize = PropTypes.oneOf(Object.values(BLOCK_SIZES)); const ValidSizeAndAuto = PropTypes.oneOf([...Sizes, 'auto']); export const ValidBackgroundColors = PropTypes.oneOf( Object.values(BACKGROUND_COLORS), @@ -30,6 +31,8 @@ export const ValidBackgroundColors = PropTypes.oneOf( export const ValidBorderColors = PropTypes.oneOf(Object.values(BORDER_COLORS)); export const ValidTextColors = PropTypes.oneOf(Object.values(TEXT_COLORS)); export const ValidIconColors = PropTypes.oneOf(Object.values(ICON_COLORS)); +const ValidAlignItem = PropTypes.oneOf(Object.values(ALIGN_ITEMS)); +const ValidJustifyContent = PropTypes.oneOf(Object.values(JUSTIFY_CONTENT)); const ArrayOfValidSizes = PropTypes.arrayOf(ValidSize); export const MultipleSizes = PropTypes.oneOfType([ @@ -37,6 +40,12 @@ export const MultipleSizes = PropTypes.oneOfType([ ArrayOfValidSizes, ]); +const ArrayOfValidBlockSizes = PropTypes.arrayOf(ValidBlockSize); +export const MultipleBlockSizes = PropTypes.oneOfType([ + ValidBlockSize, + ArrayOfValidBlockSizes, +]); + const ArrayOfValidSizesAndAuto = PropTypes.arrayOf(ValidSizeAndAuto); export const MultipleSizesAndAuto = PropTypes.oneOfType([ ValidSizeAndAuto, @@ -64,6 +73,18 @@ export const MultipleTextColors = PropTypes.oneOfType([ ArrayOfValidIconColors, ]); +const ArrayOfValidAlignItems = PropTypes.arrayOf(ValidAlignItem); +export const MultipleAlignItems = PropTypes.oneOfType([ + ValidAlignItem, + ArrayOfValidAlignItems, +]); + +const ArrayOfValidJustifyContents = PropTypes.arrayOf(ValidJustifyContent); +export const MultipleJustifyContents = PropTypes.oneOfType([ + ValidJustifyContent, + ArrayOfValidJustifyContents, +]); + function isValidSize(type, value) { // Only margin types allow 'auto' return ( @@ -163,37 +184,40 @@ const generateClassNames = memoize( (type, value) => [type, value], ); -export default function Box({ - padding, - paddingTop, - paddingRight, - paddingBottom, - paddingLeft, - margin, - marginTop, - marginRight, - marginBottom, - marginLeft, - borderColor, - borderWidth, - borderRadius, - borderStyle, - alignItems, - justifyContent, - textAlign, - flexDirection = FLEX_DIRECTION.ROW, - flexWrap, - gap, - display, - width, - height, - children, - className, - backgroundColor, - color, - as = 'div', - ...props -}) { +const Box = React.forwardRef(function Box( + { + padding, + paddingTop, + paddingRight, + paddingBottom, + paddingLeft, + margin, + marginTop, + marginRight, + marginBottom, + marginLeft, + borderColor, + borderWidth, + borderRadius, + borderStyle, + alignItems, + justifyContent, + textAlign, + flexDirection = FLEX_DIRECTION.ROW, + flexWrap, + gap, + display, + width, + height, + children, + className, + backgroundColor, + color, + as = 'div', + ...props + }, + ref, +) { const boxClassName = classnames( BASE_CLASS_NAME, className, @@ -252,11 +276,11 @@ export default function Box({ } const Component = as; return ( - + {children} ); -} +}); Box.propTypes = { children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]), @@ -285,21 +309,15 @@ Box.propTypes = { PropTypes.arrayOf(PropTypes.number), ]), borderRadius: PropTypes.oneOfType([ - PropTypes.oneOf(Object.values(SIZES)), - PropTypes.arrayOf(PropTypes.oneOf(Object.values(SIZES))), + PropTypes.oneOf(Object.values(BORDER_RADIUS)), + PropTypes.arrayOf(PropTypes.oneOf(Object.values(BORDER_RADIUS))), ]), borderStyle: PropTypes.oneOfType([ PropTypes.oneOf(Object.values(BORDER_STYLE)), PropTypes.arrayOf(PropTypes.oneOf(Object.values(BORDER_STYLE))), ]), - alignItems: PropTypes.oneOfType([ - PropTypes.oneOf(Object.values(ALIGN_ITEMS)), - PropTypes.arrayOf(PropTypes.oneOf(Object.values(ALIGN_ITEMS))), - ]), - justifyContent: PropTypes.oneOfType([ - PropTypes.oneOf(Object.values(JUSTIFY_CONTENT)), - PropTypes.arrayOf(PropTypes.oneOf(Object.values(JUSTIFY_CONTENT))), - ]), + alignItems: MultipleAlignItems, + justifyContent: MultipleJustifyContents, textAlign: PropTypes.oneOfType([ PropTypes.oneOf(Object.values(TEXT_ALIGN)), PropTypes.arrayOf(PropTypes.oneOf(Object.values(TEXT_ALIGN))), @@ -308,14 +326,8 @@ Box.propTypes = { PropTypes.oneOf(Object.values(DISPLAY)), PropTypes.arrayOf(PropTypes.oneOf(Object.values(DISPLAY))), ]), - width: PropTypes.oneOfType([ - PropTypes.oneOf(Object.values(BLOCK_SIZES)), - PropTypes.arrayOf(PropTypes.oneOf(Object.values(BLOCK_SIZES))), - ]), - height: PropTypes.oneOfType([ - PropTypes.oneOf(Object.values(BLOCK_SIZES)), - PropTypes.arrayOf(PropTypes.oneOf(Object.values(BLOCK_SIZES))), - ]), + width: MultipleBlockSizes, + height: MultipleBlockSizes, backgroundColor: MultipleBackgroundColors, className: PropTypes.string, style: PropTypes.object, @@ -330,3 +342,5 @@ Box.propTypes = { */ color: MultipleTextColors, }; + +export default Box; diff --git a/ui/components/ui/box/box.scss b/ui/components/ui/box/box.scss index 77a7364bf..63f9fb9fa 100644 --- a/ui/components/ui/box/box.scss +++ b/ui/components/ui/box/box.scss @@ -134,23 +134,27 @@ $attributesToApplyExtraProperties: margin; } &--rounded-xs { - border-radius: 0.125rem; + border-radius: 2px; } &--rounded-sm { - border-radius: 0.25rem; + border-radius: 4px; } &--rounded-md { - border-radius: 0.375rem; + border-radius: 6px; } &--rounded-lg { - border-radius: 0.5rem; + border-radius: 8px; } &--rounded-xl { - border-radius: 0.75rem; + border-radius: 12px; + } + + &--rounded-pill { + border-radius: 9999px; } // breakpoint classes diff --git a/ui/components/ui/box/box.stories.js b/ui/components/ui/box/box.stories.js index 0c0cbaff4..6d63f186e 100644 --- a/ui/components/ui/box/box.stories.js +++ b/ui/components/ui/box/box.stories.js @@ -9,10 +9,10 @@ import { BACKGROUND_COLORS, DISPLAY, JUSTIFY_CONTENT, - SIZES, TEXT_ALIGN, FLEX_DIRECTION, FLEX_WRAP, + BORDER_RADIUS, } from '../../../helpers/constants/design-system'; import Typography from '../typography'; @@ -115,7 +115,7 @@ export default { table: { category: 'border' }, }, borderRadius: { - options: Object.values(SIZES), + options: Object.values(BORDER_RADIUS), control: 'select', table: { category: 'border' }, }, @@ -480,6 +480,80 @@ export const BorderColor = () => { ); }; +export const BorderRadius = () => { + return ( + + + BORDER_RADIUS.NONE 0px + + + BORDER_RADIUS.XS 2px + + + BORDER_RADIUS.SM 4px + + + BORDER_RADIUS.MD 6px + + + BORDER_RADIUS.LG 8px + + + BORDER_RADIUS.XL 12px + + + BORDER_RADIUS.PILL 9999px + + + ); +}; + export const ResponsiveProps = () => { return ( <> diff --git a/ui/components/ui/box/box.test.js b/ui/components/ui/box/box.test.js index 894691d80..8e8534589 100644 --- a/ui/components/ui/box/box.test.js +++ b/ui/components/ui/box/box.test.js @@ -9,8 +9,8 @@ import { ALIGN_ITEMS, JUSTIFY_CONTENT, TEXT_ALIGN, - SIZES, BLOCK_SIZES, + BORDER_RADIUS, } from '../../../helpers/constants/design-system'; import Box from '.'; @@ -280,22 +280,67 @@ describe('Box', () => { }); it('should render the Box with the borderRadius class', () => { const { getByText } = render( - Box content, + <> + border radius xs + border radius sm + border radius md + border radius lg + border radius xl + border radius pill + border radius none + , ); - expect(getByText('Box content')).toHaveClass('box--rounded-xs'); + expect(getByText('border radius xs')).toHaveClass('box--rounded-xs'); + expect(getByText('border radius sm')).toHaveClass('box--rounded-sm'); + expect(getByText('border radius md')).toHaveClass('box--rounded-md'); + expect(getByText('border radius lg')).toHaveClass('box--rounded-lg'); + expect(getByText('border radius xl')).toHaveClass('box--rounded-xl'); + expect(getByText('border radius pill')).toHaveClass('box--rounded-pill'); + expect(getByText('border radius none')).toHaveClass('box--rounded-none'); }); it('should render the Box with the responsive borderRadius classes', () => { const { getByText } = render( - - Box content - , + <> + + Border radius set 1 + + + Border radius set 2 + + , ); - expect(getByText('Box content')).toHaveClass('box--rounded-xs'); - expect(getByText('Box content')).toHaveClass('box--sm:rounded-sm'); - expect(getByText('Box content')).toHaveClass('box--md:rounded-md'); - expect(getByText('Box content')).toHaveClass('box--lg:rounded-lg'); + expect(getByText('Border radius set 1')).toHaveClass('box--rounded-xs'); + expect(getByText('Border radius set 1')).toHaveClass( + 'box--sm:rounded-sm', + ); + expect(getByText('Border radius set 1')).toHaveClass( + 'box--md:rounded-md', + ); + expect(getByText('Border radius set 1')).toHaveClass( + 'box--lg:rounded-lg', + ); + expect(getByText('Border radius set 2')).toHaveClass('box--rounded-xl'); + expect(getByText('Border radius set 2')).toHaveClass( + 'box--sm:rounded-pill', + ); + expect(getByText('Border radius set 2')).toHaveClass( + 'box--md:rounded-none', + ); }); }); describe('display, gap, flexDirection, flexWrap, alignItems, justifyContent', () => { @@ -781,4 +826,9 @@ describe('Box', () => { ); }); }); + it('should accept a ref prop that is passed down to the html element', () => { + const mockRef = jest.fn(); + render(); + expect(mockRef).toHaveBeenCalledTimes(1); + }); }); diff --git a/ui/components/ui/breadcrumbs/__snapshots__/breadcrumbs.component.test.js.snap b/ui/components/ui/breadcrumbs/__snapshots__/breadcrumbs.component.test.js.snap new file mode 100644 index 000000000..ea31c0c26 --- /dev/null +++ b/ui/components/ui/breadcrumbs/__snapshots__/breadcrumbs.component.test.js.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Breadcrumbs Component should match snapshot with multiple breakcumbs 1`] = ` +
+ +`; diff --git a/ui/pages/keychains/restore-vault.js b/ui/pages/keychains/restore-vault.js index b9c4c3ed8..78be005dc 100644 --- a/ui/pages/keychains/restore-vault.js +++ b/ui/pages/keychains/restore-vault.js @@ -4,7 +4,6 @@ import { connect } from 'react-redux'; import { createNewVaultAndRestore, unMarkPasswordForgotten, - initializeThreeBox, } from '../../store/actions'; import { DEFAULT_ROUTE } from '../../helpers/constants/routes'; import CreateNewVault from '../../components/app/create-new-vault'; @@ -26,7 +25,6 @@ class RestoreVaultPage extends Component { leaveImportSeedScreenState: PropTypes.func, history: PropTypes.object, isLoading: PropTypes.bool, - initializeThreeBox: PropTypes.func, }; handleImport = async (password, seedPhrase) => { @@ -35,8 +33,6 @@ class RestoreVaultPage extends Component { createNewVaultAndRestore, leaveImportSeedScreenState, history, - // eslint-disable-next-line no-shadow - initializeThreeBox, } = this.props; leaveImportSeedScreenState(); @@ -49,7 +45,6 @@ class RestoreVaultPage extends Component { legacy_event: true, }, }); - initializeThreeBox(); history.push(DEFAULT_ROUTE); }; @@ -139,6 +134,5 @@ export default connect( }, createNewVaultAndRestore: (pw, seed) => dispatch(createNewVaultAndRestore(pw, seed)), - initializeThreeBox: () => dispatch(initializeThreeBox()), }), )(RestoreVaultPage); diff --git a/ui/pages/keychains/reveal-seed.js b/ui/pages/keychains/reveal-seed.js index 44bf74e18..a57611f26 100644 --- a/ui/pages/keychains/reveal-seed.js +++ b/ui/pages/keychains/reveal-seed.js @@ -85,6 +85,7 @@ class RevealSeedPage extends Component {
({ + requestRevealSeedWords: () => mockRequestRevealSeedWords, +})); + describe('Reveal Seed Page', () => { - it('form submit', () => { - const props = { - history: { - push: sinon.spy(), - }, - requestRevealSeedWords: sinon.stub().resolves(), + const mockState = { + history: { mostRecentOverviewPage: '/', - }; - const wrapper = mount(, { - context: { - t: (str) => str, - }, + }, + }; + const mockStore = configureMockStore([thunk])(mockState); + + it('should match snapshot', () => { + const { container } = renderWithProvider(, mockStore); + + expect(container).toMatchSnapshot(); + }); + + it('form submit', () => { + const { queryByTestId, queryByText } = renderWithProvider( + , + mockStore, + ); + + fireEvent.change(queryByTestId('input-password'), { + target: { value: 'password' }, }); - wrapper.find('form').simulate('submit'); - expect(props.requestRevealSeedWords.calledOnce).toStrictEqual(true); + fireEvent.click(queryByText('Next')); + + expect(mockRequestRevealSeedWords).toHaveBeenCalled(); }); }); diff --git a/ui/pages/onboarding-flow/creation-successful/creation-successful.js b/ui/pages/onboarding-flow/creation-successful/creation-successful.js index fbf5e4c97..356fd89b5 100644 --- a/ui/pages/onboarding-flow/creation-successful/creation-successful.js +++ b/ui/pages/onboarding-flow/creation-successful/creation-successful.js @@ -17,6 +17,7 @@ import { ONBOARDING_PRIVACY_SETTINGS_ROUTE, } from '../../../helpers/constants/routes'; import { setCompletedOnboarding } from '../../../store/actions'; +import { isBeta } from '../../../helpers/utils/build-types'; export default function CreationSuccessful() { const history = useHistory(); @@ -52,12 +53,16 @@ export default function CreationSuccessful() {
  • - {t('walletCreationSuccessReminder1')} + {isBeta() + ? t('betaWalletCreationSuccessReminder1') + : t('walletCreationSuccessReminder1')}
  • - {t('walletCreationSuccessReminder2')} + {isBeta() + ? t('betaWalletCreationSuccessReminder2') + : t('walletCreationSuccessReminder2')}
  • diff --git a/ui/pages/pages.scss b/ui/pages/pages.scss index d6160c24f..ec51b6783 100644 --- a/ui/pages/pages.scss +++ b/ui/pages/pages.scss @@ -21,6 +21,7 @@ @import 'send/send'; @import 'settings/index'; @import 'swaps/index'; +@import 'token-allowance/index'; @import 'token-details/index'; @import 'unlock-page/index'; @import 'onboarding-flow/index'; diff --git a/ui/pages/permissions-connect/flask/util.js b/ui/pages/permissions-connect/flask/util.js index ce9f82551..3f7fbe4cf 100644 --- a/ui/pages/permissions-connect/flask/util.js +++ b/ui/pages/permissions-connect/flask/util.js @@ -17,7 +17,9 @@ export function getSnapInstallWarnings(permissions, targetSubjectMetadata, t) { return [ ...flatMap(bip32EntropyPermissions, (permission, i) => permission.caveats[0].value.map(({ path, curve }) => ({ - id: `key-access-bip32-${path.join('/')}-${curve}-${i}`, + id: `key-access-bip32-${path + .join('-') + .replace(/'/gu, 'h')}-${curve}-${i}`, message: t('snapInstallWarningKeyAccess', [ targetSubjectMetadata.name, `${path.join('/')} (${curve})`, diff --git a/ui/pages/settings/advanced-tab/advanced-tab.component.js b/ui/pages/settings/advanced-tab/advanced-tab.component.js index 03a90bb02..469980c3c 100644 --- a/ui/pages/settings/advanced-tab/advanced-tab.component.js +++ b/ui/pages/settings/advanced-tab/advanced-tab.component.js @@ -1,6 +1,5 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; -import classnames from 'classnames'; import ToggleButton from '../../../components/ui/toggle-button'; import TextField from '../../../components/ui/text-field'; import Button from '../../../components/ui/button'; @@ -50,9 +49,6 @@ export default class AdvancedTab extends PureComponent { setAutoLockTimeLimit: PropTypes.func.isRequired, setShowFiatConversionOnTestnetsPreference: PropTypes.func.isRequired, setShowTestNetworks: PropTypes.func.isRequired, - threeBoxSyncingAllowed: PropTypes.bool.isRequired, - setThreeBoxSyncingPermission: PropTypes.func.isRequired, - threeBoxDisabled: PropTypes.bool.isRequired, setIpfsGateway: PropTypes.func.isRequired, ipfsGateway: PropTypes.string.isRequired, ledgerTransportType: PropTypes.oneOf(Object.values(LEDGER_TRANSPORT_TYPES)), @@ -572,55 +568,6 @@ export default class AdvancedTab extends PureComponent { ); } - renderThreeBoxControl() { - const { t } = this.context; - const { - threeBoxSyncingAllowed, - setThreeBoxSyncingPermission, - threeBoxDisabled, - } = this.props; - - let allowed = threeBoxSyncingAllowed; - let description = t('syncWithThreeBoxDescription'); - - if (threeBoxDisabled) { - allowed = false; - description = t('syncWithThreeBoxDisabled'); - } - return ( -
    -
    - {t('syncWithThreeBox')} -
    - {description} -
    -
    -
    -
    - { - if (!threeBoxDisabled) { - setThreeBoxSyncingPermission(!value); - } - }} - offLabel={t('off')} - onLabel={t('on')} - /> -
    -
    -
    - ); - } - renderLedgerLiveControl() { const { t } = this.context; const { @@ -884,7 +831,6 @@ export default class AdvancedTab extends PureComponent { {this.renderAutoLockTimeLimit()} {this.renderUserDataBackup()} {this.renderRestoreUserData()} - {this.renderThreeBoxControl()} {this.renderIpfsGatewayControl()} {notUsingFirefox ? this.renderLedgerLiveControl() : null} {this.renderDismissSeedBackupReminderControl()} diff --git a/ui/pages/settings/advanced-tab/advanced-tab.component.test.js b/ui/pages/settings/advanced-tab/advanced-tab.component.test.js index d9b0af042..bcd56a90b 100644 --- a/ui/pages/settings/advanced-tab/advanced-tab.component.test.js +++ b/ui/pages/settings/advanced-tab/advanced-tab.component.test.js @@ -19,11 +19,8 @@ describe('AdvancedTab Component', () => { setAutoLockTimeLimit={setAutoLockTimeLimitSpy} setIpfsGateway={() => undefined} setShowFiatConversionOnTestnetsPreference={() => undefined} - setThreeBoxSyncingPermission={() => undefined} setShowTestNetworks={toggleTestnet} showTestNetworks={false} - threeBoxDisabled - threeBoxSyncingAllowed={false} ledgerTransportType={LEDGER_TRANSPORT_TYPES.U2F} setLedgerTransportPreference={() => undefined} setDismissSeedBackUpReminder={() => undefined} @@ -42,12 +39,8 @@ describe('AdvancedTab Component', () => { ); }); - it('should render correctly when threeBoxFeatureFlag', () => { - expect(component.find('.settings-page__content-row')).toHaveLength(16); - }); - it('should render backup button', () => { - expect(component.find('.settings-page__content-row')).toHaveLength(16); + expect(component.find('.settings-page__content-row')).toHaveLength(15); expect( component @@ -78,7 +71,7 @@ describe('AdvancedTab Component', () => { }); it('should render restore button', () => { - expect(component.find('.settings-page__content-row')).toHaveLength(16); + expect(component.find('.settings-page__content-row')).toHaveLength(15); expect( component @@ -116,9 +109,6 @@ describe('AdvancedTab Component', () => { setAutoLockTimeLimit={setAutoLockTimeLimitSpy} setIpfsGateway={() => undefined} setShowFiatConversionOnTestnetsPreference={() => undefined} - setThreeBoxSyncingPermission={() => undefined} - threeBoxDisabled - threeBoxSyncingAllowed={false} ledgerTransportType={LEDGER_TRANSPORT_TYPES.U2F} setLedgerTransportPreference={() => undefined} setDismissSeedBackUpReminder={() => undefined} @@ -161,11 +151,8 @@ describe('AdvancedTab Component', () => { setAutoLockTimeLimit={setAutoLockTimeLimitSpy} setIpfsGateway={() => undefined} setShowFiatConversionOnTestnetsPreference={() => undefined} - setThreeBoxSyncingPermission={() => undefined} setShowTestNetworks={toggleTestnet} showTestNetworks={false} - threeBoxDisabled - threeBoxSyncingAllowed={false} ledgerTransportType={LEDGER_TRANSPORT_TYPES.U2F} setLedgerTransportPreference={() => undefined} setDismissSeedBackUpReminder={() => undefined} diff --git a/ui/pages/settings/advanced-tab/advanced-tab.container.js b/ui/pages/settings/advanced-tab/advanced-tab.container.js index 6826ec272..347d9e438 100644 --- a/ui/pages/settings/advanced-tab/advanced-tab.container.js +++ b/ui/pages/settings/advanced-tab/advanced-tab.container.js @@ -8,8 +8,6 @@ import { setShowFiatConversionOnTestnetsPreference, setShowTestNetworks, setAutoLockTimeLimit, - setThreeBoxSyncingPermission, - turnThreeBoxSyncingOnAndInitialize, setUseNonceField, setIpfsGateway, setLedgerTransportPreference, @@ -29,8 +27,6 @@ export const mapStateToProps = (state) => { } = state; const { featureFlags: { sendHexData, advancedInlineGas } = {}, - threeBoxSyncingAllowed, - threeBoxDisabled, useNonceField, ipfsGateway, ledgerTransportType, @@ -52,8 +48,6 @@ export const mapStateToProps = (state) => { showFiatInTestnets, showTestNetworks, autoLockTimeLimit, - threeBoxSyncingAllowed, - threeBoxDisabled, useNonceField, ipfsGateway, ledgerTransportType, @@ -84,13 +78,6 @@ export const mapDispatchToProps = (dispatch) => { setAutoLockTimeLimit: (value) => { return dispatch(setAutoLockTimeLimit(value)); }, - setThreeBoxSyncingPermission: (newThreeBoxSyncingState) => { - if (newThreeBoxSyncingState) { - dispatch(turnThreeBoxSyncingOnAndInitialize()); - } else { - dispatch(setThreeBoxSyncingPermission(newThreeBoxSyncingState)); - } - }, setIpfsGateway: (value) => { return dispatch(setIpfsGateway(value)); }, diff --git a/ui/pages/settings/advanced-tab/advanced-tab.stories.js b/ui/pages/settings/advanced-tab/advanced-tab.stories.js index 259069686..ac8a7f1ad 100644 --- a/ui/pages/settings/advanced-tab/advanced-tab.stories.js +++ b/ui/pages/settings/advanced-tab/advanced-tab.stories.js @@ -11,8 +11,6 @@ export default { sendHexData: { control: 'boolean' }, advancedInlineGas: { control: 'boolean' }, showFiatInTestnets: { control: 'boolean' }, - threeBoxSyncingAllowed: { control: 'boolean' }, - threeBoxDisabled: { control: 'boolean' }, useLedgerLive: { control: 'boolean' }, dismissSeedBackUpReminder: { control: 'boolean' }, setAutoLockTimeLimit: { action: 'setAutoLockTimeLimit' }, @@ -20,7 +18,6 @@ export default { action: 'setShowFiatConversionOnTestnetsPreference', }, setShowTestNetworks: { action: 'setShowTestNetworks' }, - setThreeBoxSyncingPermission: { action: 'setThreeBoxSyncingPermission' }, setIpfsGateway: { action: 'setIpfsGateway' }, setLedgerTransportPreference: { action: 'setLedgerTransportPreference' }, setDismissSeedBackUpReminder: { action: 'setDismissSeedBackUpReminder' }, @@ -44,7 +41,6 @@ export const DefaultStory = (args) => { sendHexData, advancedInlineGas, showFiatInTestnets, - threeBoxSyncingAllowed, dismissSeedBackUpReminder, }, updateArgs, @@ -74,12 +70,6 @@ export const DefaultStory = (args) => { }); }; - const handleThreeBoxSyncingAllowed = () => { - updateArgs({ - threeBoxSyncingAllowed: !threeBoxSyncingAllowed, - }); - }; - const handleDismissSeedBackUpReminder = () => { updateArgs({ dismissSeedBackUpReminder: !dismissSeedBackUpReminder, @@ -97,8 +87,6 @@ export const DefaultStory = (args) => { setAdvancedInlineGasFeatureFlag={handleAdvancedInlineGas} showFiatInTestnets={showFiatInTestnets} setShowFiatConversionOnTestnetsPreference={handleShowFiatInTestnets} - threeBoxSyncingAllowed={threeBoxSyncingAllowed} - setThreeBoxSyncingPermission={handleThreeBoxSyncingAllowed} dismissSeedBackUpReminder={dismissSeedBackUpReminder} setDismissSeedBackUpReminder={handleDismissSeedBackUpReminder} ipfsGateway="ipfs-gateway" @@ -114,8 +102,6 @@ DefaultStory.args = { sendHexData: false, advancedInlineGas: false, showFiatInTestnets: false, - threeBoxSyncingAllowed: false, - threeBoxDisabled: false, useLedgerLive: false, dismissSeedBackUpReminder: false, }; diff --git a/ui/pages/settings/info-tab/index.scss b/ui/pages/settings/info-tab/index.scss index c2a08c1b8..066682cd1 100644 --- a/ui/pages/settings/info-tab/index.scss +++ b/ui/pages/settings/info-tab/index.scss @@ -53,4 +53,8 @@ color: var(--color-text-muted); margin-bottom: 15px; } + + &__tag { + margin-inline-start: 8px; + } } diff --git a/ui/pages/settings/info-tab/info-tab.component.js b/ui/pages/settings/info-tab/info-tab.component.js index 514030da8..5435576d5 100644 --- a/ui/pages/settings/info-tab/info-tab.component.js +++ b/ui/pages/settings/info-tab/info-tab.component.js @@ -2,6 +2,8 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import Button from '../../../components/ui/button'; +import { Tag } from '../../../components/component-library/tag'; + import { SUPPORT_REQUEST_LINK } from '../../../helpers/constants/common'; import { isBeta } from '../../../helpers/utils/build-types'; import { @@ -73,6 +75,20 @@ export default class InfoTab extends PureComponent { {t('terms')}
+ {isBeta() ? ( +
+ +
+ ) : null}
} primaryAction={ + /* istanbul ignore next */ verificationClicked ? null : { @@ -809,6 +813,7 @@ export default function BuildQuote({ className="build-quote__token-etherscan-link" key="build-quote-etherscan-link" onClick={() => { + /* istanbul ignore next */ trackEvent({ event: 'Clicked Block Explorer Link', category: EVENT.CATEGORIES.SWAPS, @@ -861,30 +866,33 @@ export default function BuildQuote({ )}
{ - // We need this to know how long it took to go from clicking on the Review swap button to rendered View Quote page. - dispatch(setReviewSwapClickedTimestamp(Date.now())); - // In case that quotes prefetching is waiting to be executed, but hasn't started yet, - // we want to cancel it and fetch quotes from here. - if (timeoutIdForQuotesPrefetching) { - clearTimeout(timeoutIdForQuotesPrefetching); - dispatch( - fetchQuotesAndSetQuoteState( - history, - fromTokenInputValue, - maxSlippage, - trackEvent, - ), - ); - } else if (areQuotesPresent) { - // If there are prefetched quotes already, go directly to the View Quote page. - history.push(VIEW_QUOTE_ROUTE); - } else { - // If the "Review swap" button was clicked while quotes are being fetched, go to the Loading Quotes page. - await dispatch(setBackgroundSwapRouteState('loading')); - history.push(LOADING_QUOTES_ROUTE); + onSubmit={ + /* istanbul ignore next */ + async () => { + // We need this to know how long it took to go from clicking on the Review swap button to rendered View Quote page. + dispatch(setReviewSwapClickedTimestamp(Date.now())); + // In case that quotes prefetching is waiting to be executed, but hasn't started yet, + // we want to cancel it and fetch quotes from here. + if (timeoutIdForQuotesPrefetching) { + clearTimeout(timeoutIdForQuotesPrefetching); + dispatch( + fetchQuotesAndSetQuoteState( + history, + fromTokenInputValue, + maxSlippage, + trackEvent, + ), + ); + } else if (areQuotesPresent) { + // If there are prefetched quotes already, go directly to the View Quote page. + history.push(VIEW_QUOTE_ROUTE); + } else { + // If the "Review swap" button was clicked while quotes are being fetched, go to the Loading Quotes page. + await dispatch(setBackgroundSwapRouteState('loading')); + history.push(LOADING_QUOTES_ROUTE); + } } - }} + } submitText={t('swapReviewSwap')} disabled={isReviewSwapButtonDisabled} hideCancel diff --git a/ui/pages/swaps/build-quote/build-quote.test.js b/ui/pages/swaps/build-quote/build-quote.test.js index 79b2584d9..8178566c9 100644 --- a/ui/pages/swaps/build-quote/build-quote.test.js +++ b/ui/pages/swaps/build-quote/build-quote.test.js @@ -6,7 +6,13 @@ import { renderWithProvider, createSwapsMockStore, setBackgroundConnection, + fireEvent, } from '../../../../test/jest'; +import { + setSwapsFromToken, + setSwapToToken, + setFromTokenInputValue, +} from '../../../ducks/swaps/swaps'; import BuildQuote from '.'; const middleware = [thunk]; @@ -27,16 +33,46 @@ setBackgroundConnection({ clearSwapsQuotes: jest.fn(), stopPollingForQuotes: jest.fn(), clearSmartTransactionFees: jest.fn(), + setSwapsFromToken: jest.fn(), + setSwapToToken: jest.fn(), + setFromTokenInputValue: jest.fn(), +}); + +jest.mock('../../../ducks/swaps/swaps', () => { + const actual = jest.requireActual('../../../ducks/swaps/swaps'); + return { + ...actual, + setSwapsFromToken: jest.fn(), + setSwapToToken: jest.fn(), + setFromTokenInputValue: jest.fn(() => { + return { + type: 'MOCK_ACTION', + }; + }), + }; +}); + +jest.mock('../swaps.util', () => { + const actual = jest.requireActual('../swaps.util'); + return { + ...actual, + fetchTokenBalance: jest.fn(() => Promise.resolve()), + fetchTokenPrice: jest.fn(() => Promise.resolve()), + }; }); describe('BuildQuote', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + it('renders the component with initial props', () => { const store = configureMockStore(middleware)(createSwapsMockStore()); const props = createProps(); const { getByText } = renderWithProvider(, store); expect(getByText('Swap from')).toBeInTheDocument(); expect(getByText('Swap to')).toBeInTheDocument(); - expect(getByText('ETH')).toBeInTheDocument(); + expect(getByText('Select')).toBeInTheDocument(); expect(getByText('Slippage tolerance')).toBeInTheDocument(); expect(getByText('2%')).toBeInTheDocument(); expect(getByText('3%')).toBeInTheDocument(); @@ -45,4 +81,86 @@ describe('BuildQuote', () => { document.querySelector('.slippage-buttons__button-group'), ).toMatchSnapshot(); }); + + it('switches swap from and to tokens', () => { + const setSwapFromTokenMock = jest.fn(() => { + return { + type: 'MOCK_ACTION', + }; + }); + setSwapsFromToken.mockImplementation(setSwapFromTokenMock); + const setSwapToTokenMock = jest.fn(() => { + return { + type: 'MOCK_ACTION', + }; + }); + setSwapToToken.mockImplementation(setSwapToTokenMock); + const mockStore = createSwapsMockStore(); + const store = configureMockStore(middleware)(mockStore); + const props = createProps(); + const { getByText, getByTestId } = renderWithProvider( + , + store, + ); + expect(getByText('Swap from')).toBeInTheDocument(); + fireEvent.click(getByTestId('build-quote__swap-arrows')); + expect(setSwapsFromToken).toHaveBeenCalledWith(mockStore.swaps.toToken); + expect(setSwapToToken).toHaveBeenCalled(); + }); + + it('renders the block explorer link, only 1 verified source', () => { + const mockStore = createSwapsMockStore(); + mockStore.swaps.toToken.occurances = 1; + const store = configureMockStore(middleware)(mockStore); + const props = createProps(); + const { getByText } = renderWithProvider(, store); + expect(getByText('Swap from')).toBeInTheDocument(); + expect(getByText('Only verified on 1 source.')).toBeInTheDocument(); + expect(getByText('Etherscan')).toBeInTheDocument(); + }); + + it('renders the block explorer link, 0 verified sources', () => { + const mockStore = createSwapsMockStore(); + mockStore.swaps.toToken.occurances = 0; + const store = configureMockStore(middleware)(mockStore); + const props = createProps(); + const { getByText } = renderWithProvider(, store); + expect(getByText('Swap from')).toBeInTheDocument(); + expect( + getByText('This token has been added manually.'), + ).toBeInTheDocument(); + expect(getByText('Etherscan')).toBeInTheDocument(); + }); + + it('clicks on a block explorer link', () => { + global.platform = { openTab: jest.fn() }; + const mockStore = createSwapsMockStore(); + mockStore.swaps.toToken.occurances = 1; + const store = configureMockStore(middleware)(mockStore); + const props = createProps(); + const { getByText } = renderWithProvider(, store); + const blockExplorer = getByText('Etherscan'); + expect(blockExplorer).toBeInTheDocument(); + fireEvent.click(blockExplorer); + expect(global.platform.openTab).toHaveBeenCalledWith({ + url: 'https://etherscan.io/token/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + }); + }); + + it('clicks on the "max" link', () => { + const setFromTokenInputValueMock = jest.fn(() => { + return { + type: 'MOCK_ACTION', + }; + }); + setFromTokenInputValue.mockImplementation(setFromTokenInputValueMock); + const mockStore = createSwapsMockStore(); + mockStore.swaps.fromToken = 'DAI'; + const store = configureMockStore(middleware)(mockStore); + const props = createProps(); + const { getByText } = renderWithProvider(, store); + const maxLink = getByText('Max'); + fireEvent.click(maxLink); + expect(setFromTokenInputValue).toHaveBeenCalled(); + }); }); diff --git a/ui/pages/swaps/create-new-swap/create-new-swap.test.js b/ui/pages/swaps/create-new-swap/create-new-swap.test.js index 53835efff..f0161a3c1 100644 --- a/ui/pages/swaps/create-new-swap/create-new-swap.test.js +++ b/ui/pages/swaps/create-new-swap/create-new-swap.test.js @@ -1,12 +1,20 @@ import React from 'react'; import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; import { renderWithProvider, createSwapsMockStore, + fireEvent, + setBackgroundConnection, } from '../../../../test/jest'; +import { + setSwapsFromToken, + navigateBackToBuildQuote, +} from '../../../ducks/swaps/swaps'; import CreateNewSwap from '.'; +const middleware = [thunk]; const createProps = (customProps = {}) => { return { sensitiveProperties: {}, @@ -14,7 +22,28 @@ const createProps = (customProps = {}) => { }; }; +const backgroundConnection = { + navigateBackToBuildQuote: jest.fn(), + setBackgroundSwapRouteState: jest.fn(), + navigatedBackToBuildQuote: jest.fn(), +}; + +setBackgroundConnection(backgroundConnection); + +jest.mock('../../../ducks/swaps/swaps', () => { + const actual = jest.requireActual('../../../ducks/swaps/swaps'); + return { + ...actual, + setSwapsFromToken: jest.fn(), + navigateBackToBuildQuote: jest.fn(), + }; +}); + describe('CreateNewSwap', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + it('renders the component with initial props', () => { const store = configureMockStore()(createSwapsMockStore()); const props = createProps(); @@ -24,4 +53,28 @@ describe('CreateNewSwap', () => { ); expect(getByText('Create a new swap')).toBeInTheDocument(); }); + + it('clicks on the Make another swap link', async () => { + const setSwapFromTokenMock = jest.fn(() => { + return { + type: 'MOCK_ACTION', + }; + }); + setSwapsFromToken.mockImplementation(setSwapFromTokenMock); + const navigateBackToBuildQuoteMock = jest.fn(() => { + return { + type: 'MOCK_ACTION', + }; + }); + navigateBackToBuildQuote.mockImplementation(navigateBackToBuildQuoteMock); + const store = configureMockStore(middleware)(createSwapsMockStore()); + const props = createProps(); + const { getByText } = renderWithProvider( + , + store, + ); + await fireEvent.click(getByText('Create a new swap')); + expect(setSwapFromTokenMock).toHaveBeenCalledTimes(1); + expect(navigateBackToBuildQuoteMock).toHaveBeenCalledTimes(1); + }); }); diff --git a/ui/pages/swaps/dropdown-input-pair/dropdown-input-pair.test.js b/ui/pages/swaps/dropdown-input-pair/dropdown-input-pair.test.js index 0f09cbf81..e9f319d25 100644 --- a/ui/pages/swaps/dropdown-input-pair/dropdown-input-pair.test.js +++ b/ui/pages/swaps/dropdown-input-pair/dropdown-input-pair.test.js @@ -4,11 +4,13 @@ import configureMockStore from 'redux-mock-store'; import { renderWithProvider, createSwapsMockStore, + fireEvent, } from '../../../../test/jest'; import DropdownInputPair from '.'; const createProps = (customProps = {}) => { return { + onInputChange: jest.fn(), ...customProps, }; }; @@ -26,4 +28,17 @@ describe('DropdownInputPair', () => { document.querySelector('.dropdown-input-pair__input'), ).toMatchSnapshot(); }); + + it('changes the input field', () => { + const store = configureMockStore()(createSwapsMockStore()); + const props = createProps(); + const { getByPlaceholderText } = renderWithProvider( + , + store, + ); + fireEvent.change(getByPlaceholderText('0'), { + target: { value: 1.1 }, + }); + expect(props.onInputChange).toHaveBeenCalledWith('1.1'); + }); }); diff --git a/ui/pages/swaps/dropdown-search-list/__snapshots__/dropdown-search-list.test.js.snap b/ui/pages/swaps/dropdown-search-list/__snapshots__/dropdown-search-list.test.js.snap index b9cd71bde..ee9809186 100644 --- a/ui/pages/swaps/dropdown-search-list/__snapshots__/dropdown-search-list.test.js.snap +++ b/ui/pages/swaps/dropdown-search-list/__snapshots__/dropdown-search-list.test.js.snap @@ -4,6 +4,7 @@ exports[`DropdownSearchList renders the component with initial props 1`] = `