1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Merge remote-tracking branch 'upstream/develop' into minimal

This commit is contained in:
Matthias Kretschmann 2023-04-04 14:42:21 +01:00
commit ac6f81d8da
Signed by: m
GPG Key ID: 606EEEF3C479A91F
193 changed files with 3050 additions and 1909 deletions

View File

@ -1097,12 +1097,6 @@ jobs:
- checkout
- attach_workspace:
at: .
- run:
name: Move beta build to dist
command: mv ./dist-beta ./dist
- run:
name: Move beta zips to builds
command: mv ./builds-beta ./builds
- run:
name: Validate source maps
command: |
@ -1157,14 +1151,9 @@ jobs:
- attach_workspace:
at: .
- run:
name: Move beta build to dist
command: mv ./dist-beta ./dist
- run:
name: Move beta zips to builds
command: mv ./builds-beta ./builds
- run:
name: test:mozilla-lint
command: NODE_OPTIONS=--max_old_space_size=3072 yarn mozilla-lint
name: Lint beta for firefox
command: |
.circleci/scripts/mozilla-lint-beta.sh
test-mozilla-lint-desktop:
executor: node-browsers

View File

@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -e
set -u
set -o pipefail
current_commit_msg=$(git show -s --format='%s' HEAD)
if [[ $current_commit_msg =~ Version[[:space:]](v[[:digit:]]+.[[:digit:]]+.[[:digit:]]+[-]beta.[[:digit:]]) ]]
then
# filter the commit message like Version v10.24.1-beta.1
printf '%s\n' "Linting beta builds for firefox"
# Move beta build to dist
mv ./dist-beta ./dist
# Move beta zips to builds
mv ./builds-beta ./builds
# test:mozilla-lint
export NODE_OPTIONS='--max_old_space_size=3072'
yarn mozilla-lint
else
printf '%s\n' 'Commit message does not match commit message for beta pattern; skipping linting for firefox'
mkdir dist
mkdir builds
exit 0
fi
exit 0

0
.circleci/scripts/validate-changelog-in-rc.sh Normal file → Executable file
View File

View File

@ -10,6 +10,8 @@ current_commit_msg=$(git show -s --format='%s' HEAD)
if [[ $current_commit_msg =~ Version[[:space:]](v[[:digit:]]+.[[:digit:]]+.[[:digit:]]+[-]beta.[[:digit:]]) ]]
then
# filter the commit message like Version v10.24.1-beta.1
mv ./dist-beta ./dist
mv ./builds-beta ./builds
printf '%s\n' "Validate source maps with beta version $current_commit_msg"
yarn validate-source-maps
else

View File

@ -6,6 +6,109 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [10.28.1]
### Changed
- Fix release automation ([#18427](https://github.com/MetaMask/metamask-extension/pull/18427))
## [10.28.0]
### Added
- Adding NFT autodetection to "What's New" Announcements ([#17653](https://github.com/MetaMask/metamask-extension/pull/17653))
- [FLASK] Add WebAssembly endowment ([#17694](https://github.com/MetaMask/metamask-extension/pull/17694))
- Bridge tokens by redirecting to Portfolio from wallet overview page ([#17952](https://github.com/MetaMask/metamask-extension/pull/17952))
- [MMI] Adds the MMI support link and the mmi_website link as well ([#17853](https://github.com/MetaMask/metamask-extension/pull/17853))
- What's new - OpenSea security provider ([#16831](https://github.com/MetaMask/metamask-extension/pull/16831))
- Open sea security provider warning message ([#17662](https://github.com/MetaMask/metamask-extension/pull/17662))
- SRP hold to reveal ([#17232](https://github.com/MetaMask/metamask-extension/pull/17232))
- Additional incoming transactions support ([#14219](https://github.com/MetaMask/metamask-extension/pull/14219))
### Changed
- UX: Loaclize the avatar-favicon description text ([#18132](https://github.com/MetaMask/metamask-extension/pull/18132))
- 17921 Update TransactionAlerts with BannerAlert ([#17940](https://github.com/MetaMask/metamask-extension/pull/17940))
- Part of 17670: Replace Typography with Text confirm-approve-content.component.js and home.component.js ([#18049](https://github.com/MetaMask/metamask-extension/pull/18049))
- UX: Icon: Update buy icon ([#18123](https://github.com/MetaMask/metamask-extension/pull/18123))
- Display internet protocol on the domain in SIWE screen ([#18052](https://github.com/MetaMask/metamask-extension/pull/18052))
- Wrap balance and portfolio button ([#18109](https://github.com/MetaMask/metamask-extension/pull/18109))
- UX Icon: Updated Icon for Disclosure ([#17877](https://github.com/MetaMask/metamask-extension/pull/17877))
- Updating AvatarWithBage to BadgeWrapper ([#17851](https://github.com/MetaMask/metamask-extension/pull/17851))
- [FLASK] BREAKING - snaps-monorepo@0.30.0 ([#17718](https://github.com/MetaMask/metamask-extension/pull/17718))
- increment keyring controller version ([#18036](https://github.com/MetaMask/metamask-extension/pull/18036))
- Bump Snow 1.5.0 ([#17985](https://github.com/MetaMask/metamask-extension/pull/17985))
- Avoid blob url for files downloads ([#17986](https://github.com/MetaMask/metamask-extension/pull/17986))
- Upgrading the Import Account modal ([#17763](https://github.com/MetaMask/metamask-extension/pull/17763))
- identify desktop is paired in the metrics event ([#17892](https://github.com/MetaMask/metamask-extension/pull/17892))
- [MMI] Conditional change title in home if buildType is MMI ([#17898](https://github.com/MetaMask/metamask-extension/pull/17898))
- [MMI] Prevent multiple instances of MM at the same browser ([#17856](https://github.com/MetaMask/metamask-extension/pull/17856))
- Buy crypto by redirecting to onramp experience on pdapp instead of deposit popover ([#17689](https://github.com/MetaMask/metamask-extension/pull/17689))
- Update snaps locale messages for casing and content ([#17915](https://github.com/MetaMask/metamask-extension/pull/17915))
- Ux: Icon: Update fa-eye with ICON_NAMES.EYE ([#17800](https://github.com/MetaMask/metamask-extension/pull/17800))
- UX: Icon: Stop using fa-times ([#17811](https://github.com/MetaMask/metamask-extension/pull/17811))
- Selector performance improvements ([#17410](https://github.com/MetaMask/metamask-extension/pull/17410))
- UX: Update Settings Icon ([#17561](https://github.com/MetaMask/metamask-extension/pull/17561))
- UX Icon: updated fa-exclamation-circle ([#17879](https://github.com/MetaMask/metamask-extension/pull/17879))
- Update minimum browser versions ([#12847](https://github.com/MetaMask/metamask-extension/pull/12847))
- UX: Icon: Remove fa-exclamation-triangle usages ([#17691](https://github.com/MetaMask/metamask-extension/pull/17691))
- UX: Icons: Remove icon-import ([#17816](https://github.com/MetaMask/metamask-extension/pull/17816))
- UX: Icons: Remove IconCheck and fa-check ([#17787](https://github.com/MetaMask/metamask-extension/pull/17787))
- UX Icon: updated fas-question icon ([#17828](https://github.com/MetaMask/metamask-extension/pull/17828))
- UX: Icons: Stop using FA in TransactionActivityLog ([#17667](https://github.com/MetaMask/metamask-extension/pull/17667))
- Ux: Icon: Improve alignment of asset list chevron ([#17791](https://github.com/MetaMask/metamask-extension/pull/17791))
- UX: Icons: Remove IconWithLabel ([#17815](https://github.com/MetaMask/metamask-extension/pull/17815))
- UX: Move Portfolio link to its own button ([#17722](https://github.com/MetaMask/metamask-extension/pull/17722))
- UX Icon: Replace fa-user ([#17809](https://github.com/MetaMask/metamask-extension/pull/17809))
- UX: Icons: Fix alignment of settings icons in full screen ([#17783](https://github.com/MetaMask/metamask-extension/pull/17783))
- Cleanup: clearTimeout on useEffect for gas estimation and prevent state update on unmounted ConfirmTransactionBase ([#17804](https://github.com/MetaMask/metamask-extension/pull/17804))
- Part of 17670: Replace Typography with Text approve-content-card ([#17753](https://github.com/MetaMask/metamask-extension/pull/17753))
- UX: Icons: Remove lock icon ([#17739](https://github.com/MetaMask/metamask-extension/pull/17739))
- Update HelpText component ([#17705](https://github.com/MetaMask/metamask-extension/pull/17705))
- Change transaction type for send with approve transaction ([#17777](https://github.com/MetaMask/metamask-extension/pull/17777))
- UX: Icon: Remove Plus icon ([#17666](https://github.com/MetaMask/metamask-extension/pull/17666))
- Updating TextField component ([#17732](https://github.com/MetaMask/metamask-extension/pull/17732))
- UX: Update three-dot icon for settings ([#17558](https://github.com/MetaMask/metamask-extension/pull/17558))
- Updating Label component ([#17731](https://github.com/MetaMask/metamask-extension/pull/17731))
- Pass `excludedPermissions` to `SnapController` ([#17321](https://github.com/MetaMask/metamask-extension/pull/17321))
- UX: Update fa-search icon ([#17527](https://github.com/MetaMask/metamask-extension/pull/17527))
- UX: Icons: Remove legacy connect icon ([#17673](https://github.com/MetaMask/metamask-extension/pull/17673))
- UX: Icons: Remove usage of pencil icon ([#17676](https://github.com/MetaMask/metamask-extension/pull/17676))
- Rename reset account settings ([#17457](https://github.com/MetaMask/metamask-extension/pull/17457))
- Make username mandatory in the edit contact screen ([#17425](https://github.com/MetaMask/metamask-extension/pull/17425))
- New Crowdin translations by Github Action ([#17082](https://github.com/MetaMask/metamask-extension/pull/17082))
### Removed
- NFTs: Remove feature flag for release ([#17401](https://github.com/MetaMask/metamask-extension/pull/17401))
- Removed a feature flag ([#17922](https://github.com/MetaMask/metamask-extension/pull/17922))
- UX: Remove legacy metametrics modal ([#17817](https://github.com/MetaMask/metamask-extension/pull/17817))
- UX: Icons: Remove unused overview icons ([#17671](https://github.com/MetaMask/metamask-extension/pull/17671))
- Remove CancelTransaction modal ([#17819](https://github.com/MetaMask/metamask-extension/pull/17819))
### Fixed
- Fix ThemeType casing issue ([#18039](https://github.com/MetaMask/metamask-extension/pull/18039))
- Fix #17948 - Allow editing of NFT sends ([#17970](https://github.com/MetaMask/metamask-extension/pull/17970))
- Fix #17848 - Ensure NFT collections toggle appropriately ([#17972](https://github.com/MetaMask/metamask-extension/pull/17972))
- Force update mock state and render nfts item test fix ([#18044](https://github.com/MetaMask/metamask-extension/pull/18044))
- fix network dropdown bug ([#18079](https://github.com/MetaMask/metamask-extension/pull/18079))
- Fix #17932 - Ensure NFT last sold price is formatted correctly ([#17983](https://github.com/MetaMask/metamask-extension/pull/17983))
- Use tokenList to get token details, when available, in getTokenStanda… ([#17891](https://github.com/MetaMask/metamask-extension/pull/17891))
- delay chain validation ([#17413](https://github.com/MetaMask/metamask-extension/pull/17413))
- fix(17542): fix fiat currency display in few txn actions ([#18011](https://github.com/MetaMask/metamask-extension/pull/18011))
- fix(17716): increase threshold to include all options for nonce search ([#17999](https://github.com/MetaMask/metamask-extension/pull/17999))
- fix issue with fragment messageIds ([#17949](https://github.com/MetaMask/metamask-extension/pull/17949))
- UX: Icons: Fix Chevrons in Settings Tabs ([#17971](https://github.com/MetaMask/metamask-extension/pull/17971))
- fix(17857): show correctly converted account balance in sign&encrypt windows ([#17973](https://github.com/MetaMask/metamask-extension/pull/17973))
- Edit Token Transfer displays mixed info with regular Send Tx (ETH) ([#17507](https://github.com/MetaMask/metamask-extension/pull/17507))
- fix(17855): persist popup when sw is restarted ([#17855](https://github.com/MetaMask/metamask-extension/pull/17855))
- Fix incorrect balance in signature request header ([#17829](https://github.com/MetaMask/metamask-extension/pull/17829))
- fix keeping the user login after the first login ([#17950](https://github.com/MetaMask/metamask-extension/pull/17950))
- Fixed accounts auto scrolling ([#17075](https://github.com/MetaMask/metamask-extension/pull/17075))
- Fix a bug where non-address types would be rendered as addresses in EIP-712 ([#17846](https://github.com/MetaMask/metamask-extension/pull/17846))
- Transaction-list-item-details pop up to display the correct token information on token approve item ([#17422](https://github.com/MetaMask/metamask-extension/pull/17422))
- ConfirmDecryptMessage: avoid mutation of state in decryptMsg/completedTx action ([#17895](https://github.com/MetaMask/metamask-extension/pull/17895))
- Fix GetEncryptionKey TypeError Cannot destructure property 'msgParams' of 'txData' ([#17808](https://github.com/MetaMask/metamask-extension/pull/17808))
- Fix state in confirm transaction ([#17838](https://github.com/MetaMask/metamask-extension/pull/17838))
- window open noopener ([#17882](https://github.com/MetaMask/metamask-extension/pull/17882))
- avoid mutation of state in signTransaction action ([#17772](https://github.com/MetaMask/metamask-extension/pull/17772))
- MenuItem: Fix layout of menu item with subtitle ([#17650](https://github.com/MetaMask/metamask-extension/pull/17650))
- fix: fix url for flask build ([#17784](https://github.com/MetaMask/metamask-extension/pull/17784))
## [10.27.0]
### Added
- feat: add the ConsenSys zkEVM (Linea) as a default network ([#17875](https://github.com/MetaMask/metamask-extension/pull/17875))
@ -227,7 +330,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [FLASK] **BREAKING**: Snap RPC methods now use `@metamask/key-tree@6.0.0` ([#16394](https://github.com/MetaMask/metamask-extension/pull/16394))
- In the new version, all hexadecimal values are prefixed with `0x`
- All fields containing the word `Buffer` has also been renamed to `Bytes`
- Please update your snap to use the latest version
- Please update your snap to use the latest version
### Fixed
- Fix Settings Search pointing into the incorrect row for Token Detection entry ([#16407](https://github.com/MetaMask/metamask-extension/pull/16407))
@ -3540,7 +3643,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Uncategorized
- Added the ability to restore accounts from seed words.
[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.27.0...HEAD
[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.28.1...HEAD
[10.28.1]: https://github.com/MetaMask/metamask-extension/compare/v10.28.0...v10.28.1
[10.28.0]: https://github.com/MetaMask/metamask-extension/compare/v10.27.0...v10.28.0
[10.27.0]: https://github.com/MetaMask/metamask-extension/compare/v10.26.2...v10.27.0
[10.26.2]: https://github.com/MetaMask/metamask-extension/compare/v10.26.1...v10.26.2
[10.26.1]: https://github.com/MetaMask/metamask-extension/compare/v10.26.0...v10.26.1

View File

@ -3355,10 +3355,6 @@
"snaps": {
"message": "Snaps"
},
"snapsInsightError": {
"message": "Ein Fehler ist mit $1: $2 aufgetreten",
"description": "This is shown when the insight snap throws an error. $1 is the snap name, $2 is the error message."
},
"snapsInsightLoading": {
"message": "Transaktions-Einsicht wird geladen ..."
},
@ -3375,7 +3371,8 @@
"message": "Ein Snap wird nur ausgeführt, wenn er aktiviert ist"
},
"snapsUIError": {
"message": "Die vom Snap spezifizierte UI ist ungültig."
"message": "Die vom Snap spezifizierte UI ist ungültig.",
"description": "This is shown when the insight snap throws an error. $1 is the snap name"
},
"someNetworksMayPoseSecurity": {
"message": "Einige Netzwerke können Sicherheits- und/oder Datenschutzrisiken bergen. Informieren Sie sich über die Risiken, bevor Sie ein Netzwerk hinzufügen und nutzen."

View File

@ -3355,10 +3355,6 @@
"snaps": {
"message": "Snaps"
},
"snapsInsightError": {
"message": "Παρουσιάστηκε ένα σφάλμα με $1: $2",
"description": "This is shown when the insight snap throws an error. $1 is the snap name, $2 is the error message."
},
"snapsInsightLoading": {
"message": "Φόρτωση πληροφοριών συναλλαγών..."
},
@ -3375,7 +3371,8 @@
"message": "Ένα snap θα εκτελεστεί μόνο εάν είναι ενεργοποιημένο"
},
"snapsUIError": {
"message": "Η Διεπαφή Χρήστη (UI) που καθορίζεται από το στιγμιότυπο δεν είναι έγκυρη."
"message": "Η Διεπαφή Χρήστη (UI) που καθορίζεται από το στιγμιότυπο δεν είναι έγκυρη.",
"description": "This is shown when the insight snap throws an error. $1 is the snap name"
},
"someNetworksMayPoseSecurity": {
"message": "Ορισμένα δίκτυα ενδέχεται να ενέχουν κινδύνους για την ασφάλεια ή/και το απόρρητο. Ενημερωθείτε για τους κινδύνους πριν προσθέσετε και χρησιμοποιήσετε ένα δίκτυο."

View File

@ -1374,6 +1374,10 @@
"errorWhileConnectingToRPC": {
"message": "Error while connecting to the custom network."
},
"errorWithSnap": {
"message": "Error with $1",
"description": "$1 represents the name of the snap"
},
"ethGasPriceFetchWarning": {
"message": "Backup gas price is provided as the main gas estimation service is unavailable right now."
},
@ -1801,6 +1805,10 @@
"inputLogicHigherNumber": {
"message": "This allows the contract to spend all your token balance until it reaches the cap or you revoke the spending cap. If this is not intended, consider setting a lower spending cap."
},
"insightsFromSnap": {
"message": "Insights from $1",
"description": "$1 represents the name of the snap"
},
"install": {
"message": "Install"
},
@ -2446,10 +2454,10 @@
"message": "The Ethereum Merge is here!"
},
"notifications16ActionText": {
"message": "Enable security provider"
"message": "Enable security alerts"
},
"notifications16DescriptionOne": {
"message": "Get warnings from OpenSea whenever you receive a known malicious request.",
"message": "Get alerts from third parties when you may have received a malicious request.",
"description": "Description of a notification in the 'See What's New' popup. Describes Opensea Security Provider feature."
},
"notifications16DescriptionThree": {
@ -2457,11 +2465,11 @@
"description": "Description of a notification in the 'See What's New' popup. Describes Opensea Security Provider feature."
},
"notifications16DescriptionTwo": {
"message": "OpenSea is the first security provider for this feature. More providers coming soon!",
"message": "OpenSea is the first provider for this feature. More providers coming soon!",
"description": "Description of a notification in the 'See What's New' popup. Describes Opensea Security Provider feature."
},
"notifications16Title": {
"message": "Stay safe with OpenSea"
"message": "Stay safe with security alerts"
},
"notifications17ActionText": {
"message": "Enable NFT autodetection"
@ -2919,7 +2927,7 @@
"description": "An extended description for the `snap_getBip32Entropy` permission. $1 is a derivation path (name)"
},
"permission_manageBip44Keys": {
"message": "Control your \"$1\" accounts and assets.",
"message": "Control your $1 accounts and assets.",
"description": "The description for the `snap_getBip44Entropy` permission. $1 is the name of a protocol, e.g. 'Filecoin'."
},
"permission_manageBip44KeysDescription": {
@ -3627,13 +3635,12 @@
"snaps": {
"message": "Snaps"
},
"snapsInsightError": {
"message": "An error occured with $1: $2",
"description": "This is shown when the insight snap throws an error. $1 is the snap name, $2 is the error message."
},
"snapsInsightLoading": {
"message": "Loading transaction insight..."
},
"snapsInvalidUIError": {
"message": "The UI specified by the snap is invalid."
},
"snapsNoInsight": {
"message": "The snap didn't return any insight"
},
@ -3647,7 +3654,8 @@
"message": "A snap will only run if it is enabled"
},
"snapsUIError": {
"message": "The UI specified by the snap is invalid."
"message": "Contact the creators of $1 for further support.",
"description": "This is shown when the insight snap throws an error. $1 is the snap name"
},
"someNetworksMayPoseSecurity": {
"message": "Some networks may pose security and/or privacy risks. Understand the risks before adding & using a network."

View File

@ -3355,10 +3355,6 @@
"snaps": {
"message": "Complementos"
},
"snapsInsightError": {
"message": "Ocurrió un error con $1: $2",
"description": "This is shown when the insight snap throws an error. $1 is the snap name, $2 is the error message."
},
"snapsInsightLoading": {
"message": "Cargando información de transacción..."
},
@ -3375,7 +3371,8 @@
"message": "Un complemento solo se ejecutará si está habilitado"
},
"snapsUIError": {
"message": "La IU especificada por el complemento no es válida."
"message": "La IU especificada por el complemento no es válida.",
"description": "This is shown when the insight snap throws an error. $1 is the snap name"
},
"someNetworksMayPoseSecurity": {
"message": "Algunas redes pueden presentar riesgos de seguridad y/o privacidad. Comprenda los riesgos antes de agregar y utilizar una red."

View File

@ -3355,10 +3355,6 @@
"snaps": {
"message": "Snaps"
},
"snapsInsightError": {
"message": "Une erreur sest produite avec $1: $2",
"description": "This is shown when the insight snap throws an error. $1 is the snap name, $2 is the error message."
},
"snapsInsightLoading": {
"message": "Chargement de laperçu de transaction…"
},
@ -3375,7 +3371,8 @@
"message": "Un snap ne sexécute que sil est activé"
},
"snapsUIError": {
"message": "Linterface utilisateur (IU) spécifiée par le snap nest pas valide."
"message": "Linterface utilisateur (IU) spécifiée par le snap nest pas valide.",
"description": "This is shown when the insight snap throws an error. $1 is the snap name"
},
"someNetworksMayPoseSecurity": {
"message": "Certains réseaux peuvent présenter des risques pour la sécurité et/ou la vie privée. Informez-vous sur les risques avant dajouter et dutiliser un réseau."

View File

@ -3355,10 +3355,6 @@
"snaps": {
"message": "स्नैप्स"
},
"snapsInsightError": {
"message": "$1: $2 के साथ त्रुटि हुई",
"description": "This is shown when the insight snap throws an error. $1 is the snap name, $2 is the error message."
},
"snapsInsightLoading": {
"message": "ट्रांजैक्शन इनसाइट लोड हो रही है..."
},
@ -3375,7 +3371,8 @@
"message": "कोई स्नैप तभी चलेगा जब उसे सक्षम किया गया हो"
},
"snapsUIError": {
"message": "स्नैप द्वारा विनिर्दिष्टत UI अमान्य है।"
"message": "स्नैप द्वारा विनिर्दिष्टत UI अमान्य है।",
"description": "This is shown when the insight snap throws an error. $1 is the snap name"
},
"someNetworksMayPoseSecurity": {
"message": "कुछ नेटवर्क सुरक्षा और/या गोपनीयता संबंधी जोखिम पैदा कर सकते हैं। नेटवर्क जोड़ने और उपयोग करने से पहले जोखिमों को समझें।"

View File

@ -3355,10 +3355,6 @@
"snaps": {
"message": "Snap"
},
"snapsInsightError": {
"message": "Terjadi kesalahan dengan $1: $2",
"description": "This is shown when the insight snap throws an error. $1 is the snap name, $2 is the error message."
},
"snapsInsightLoading": {
"message": "Memuat wawasan transaksi..."
},
@ -3375,7 +3371,8 @@
"message": "Snap hanya akan beroperasi jika diaktifkan"
},
"snapsUIError": {
"message": "UI yang ditentukan oleh snap tidak valid."
"message": "UI yang ditentukan oleh snap tidak valid.",
"description": "This is shown when the insight snap throws an error. $1 is the snap name"
},
"someNetworksMayPoseSecurity": {
"message": "Beberapa jaringan dapat menimbulkan risiko keamanan dan/atau privasi. Pahami risikonya sebelum menambahkan & menggunakan jaringan."

View File

@ -3355,10 +3355,6 @@
"snaps": {
"message": "スナップ"
},
"snapsInsightError": {
"message": "$1 でエラーが発生しました: $2",
"description": "This is shown when the insight snap throws an error. $1 is the snap name, $2 is the error message."
},
"snapsInsightLoading": {
"message": "トランザクションインサイトを読み込み中..."
},
@ -3375,7 +3371,8 @@
"message": "スナップは有効になっている場合にのみ実行されます"
},
"snapsUIError": {
"message": "スナップにより指定された UI が無効です。"
"message": "スナップにより指定された UI が無効です。",
"description": "This is shown when the insight snap throws an error. $1 is the snap name"
},
"someNetworksMayPoseSecurity": {
"message": "ネットワークによっては、セキュリティやプライバシーの面でリスクが伴う可能性があります。ネットワークを追加・使用する前にリスクを理解するようにしてください。"

View File

@ -3355,10 +3355,6 @@
"snaps": {
"message": "스냅"
},
"snapsInsightError": {
"message": "$1 관련 오류 발생: $2",
"description": "This is shown when the insight snap throws an error. $1 is the snap name, $2 is the error message."
},
"snapsInsightLoading": {
"message": "거래 인사이트를 가져오는 중..."
},
@ -3375,7 +3371,8 @@
"message": "스냅은 활성화된 상태에서만 작동합니다."
},
"snapsUIError": {
"message": "스냅에서 지정한 UI가 올바르지 않습니다."
"message": "스냅에서 지정한 UI가 올바르지 않습니다.",
"description": "This is shown when the insight snap throws an error. $1 is the snap name"
},
"someNetworksMayPoseSecurity": {
"message": "네트워크에 따라 보안이나 개인 정보 유출의 위험이 있을 수 있습니다. 네트워크 추가 및 사용 이전에 위험 요소를 파악하세요."

View File

@ -3355,10 +3355,6 @@
"snaps": {
"message": "Snaps"
},
"snapsInsightError": {
"message": "Ocorreu um erro com $1: $2",
"description": "This is shown when the insight snap throws an error. $1 is the snap name, $2 is the error message."
},
"snapsInsightLoading": {
"message": "Carregando insight da transação..."
},
@ -3375,7 +3371,8 @@
"message": "O snap só será executado se estiver ativado"
},
"snapsUIError": {
"message": "A IU especificada pelo snap é inválida."
"message": "A IU especificada pelo snap é inválida.",
"description": "This is shown when the insight snap throws an error. $1 is the snap name"
},
"someNetworksMayPoseSecurity": {
"message": "Algumas redes podem representar riscos de segurança e/ou privacidade. Tenha os riscos em mente antes de adicionar e usar uma rede."

View File

@ -3355,10 +3355,6 @@
"snaps": {
"message": "Снапы"
},
"snapsInsightError": {
"message": "Произошла ошибка с $1: $2",
"description": "This is shown when the insight snap throws an error. $1 is the snap name, $2 is the error message."
},
"snapsInsightLoading": {
"message": "Загрузка аналитики по транзакции..."
},
@ -3375,7 +3371,8 @@
"message": "Снап будет работать только в том случае, если он включен"
},
"snapsUIError": {
"message": "Пользовательский интерфейс, указанный привязкой, недействителен."
"message": "Пользовательский интерфейс, указанный привязкой, недействителен.",
"description": "This is shown when the insight snap throws an error. $1 is the snap name"
},
"someNetworksMayPoseSecurity": {
"message": "Некоторые сети могут представлять угрозу безопасности и/или конфиденциальности. Прежде чем добавлять и использовать сеть, ознакомьтесь с рисками."

View File

@ -3355,10 +3355,6 @@
"snaps": {
"message": "Mga Snap"
},
"snapsInsightError": {
"message": "Nagkaroon ng error sa $1: $2",
"description": "This is shown when the insight snap throws an error. $1 is the snap name, $2 is the error message."
},
"snapsInsightLoading": {
"message": "Naglo-load ng insight sa transaksyon..."
},
@ -3375,7 +3371,8 @@
"message": "Tatakbo lamang ang snap kapag pinagana ito"
},
"snapsUIError": {
"message": "Ang UI na tinukoy sa pamamagitan ng snap ay hindi wasto."
"message": "Ang UI na tinukoy sa pamamagitan ng snap ay hindi wasto.",
"description": "This is shown when the insight snap throws an error. $1 is the snap name"
},
"someNetworksMayPoseSecurity": {
"message": "Maaaring magdulot ang ilang network ng mga panganib sa seguridad at/o pagkapribado. Unawain ang mga panganib bago idagdag o gamitin ang isang network."

View File

@ -3355,10 +3355,6 @@
"snaps": {
"message": "Snap'ler"
},
"snapsInsightError": {
"message": "$1: $2 ile ilgili bir hata oldu",
"description": "This is shown when the insight snap throws an error. $1 is the snap name, $2 is the error message."
},
"snapsInsightLoading": {
"message": "İşlem ayrıntıları yükleniyor..."
},
@ -3375,7 +3371,8 @@
"message": "Bir snap yalnızca etkinleştirilmişse çalışır"
},
"snapsUIError": {
"message": "Snap tarafından belirtilen Kullanıcı Arayüzü geçersiz."
"message": "Snap tarafından belirtilen Kullanıcı Arayüzü geçersiz.",
"description": "This is shown when the insight snap throws an error. $1 is the snap name"
},
"someNetworksMayPoseSecurity": {
"message": "Bazı ağlar güvenlik ve/veya gizlilik riskleri teşkil edebilir. Bir ağ eklemeden ve kullanmadan önce riskleri anlayın."

View File

@ -3355,10 +3355,6 @@
"snaps": {
"message": "Snap"
},
"snapsInsightError": {
"message": "Đã xảy ra lỗi với $1: $2",
"description": "This is shown when the insight snap throws an error. $1 is the snap name, $2 is the error message."
},
"snapsInsightLoading": {
"message": "Đang tải thông tin chi tiết về giao dịch..."
},
@ -3375,7 +3371,8 @@
"message": "Snap chỉ hoạt động khi đã bật"
},
"snapsUIError": {
"message": "Giao diện người dùng được chỉ định bởi snap không hợp lệ."
"message": "Giao diện người dùng được chỉ định bởi snap không hợp lệ.",
"description": "This is shown when the insight snap throws an error. $1 is the snap name"
},
"someNetworksMayPoseSecurity": {
"message": "Một số mạng có thể gây ra rủi ro về bảo mật và/hoặc quyền riêng tư. Bạn cần hiểu rõ các rủi ro này trước khi thêm và sử dụng mạng."

View File

@ -3355,10 +3355,6 @@
"snaps": {
"message": "Snap"
},
"snapsInsightError": {
"message": "$1 发生错误:$2",
"description": "This is shown when the insight snap throws an error. $1 is the snap name, $2 is the error message."
},
"snapsInsightLoading": {
"message": "正在加载交易洞察……"
},
@ -3375,7 +3371,8 @@
"message": "Snap仅在启用后才会运行"
},
"snapsUIError": {
"message": "Snap指定的用户界面无效。"
"message": "Snap指定的用户界面无效。",
"description": "This is shown when the insight snap throws an error. $1 is the snap name"
},
"someNetworksMayPoseSecurity": {
"message": "某些网络可能会带来安全和/或隐私风险。在添加和使用网络之前,请先了解风险。"

View File

@ -24,11 +24,11 @@ import {
} from '../../shared/constants/app';
import { SECOND } from '../../shared/constants/time';
import {
REJECT_NOTFICIATION_CLOSE,
REJECT_NOTFICIATION_CLOSE_SIG,
EVENT,
EVENT_NAMES,
TRAITS,
REJECT_NOTIFICATION_CLOSE,
REJECT_NOTIFICATION_CLOSE_SIG,
MetaMetricsEventCategory,
MetaMetricsEventName,
MetaMetricsUserTrait,
} from '../../shared/constants/metametrics';
import { checkForLastErrorAndLog } from '../../shared/modules/browser-runtime.utils';
import { isManifestV3 } from '../../shared/modules/mv3.utils';
@ -738,13 +738,13 @@ export function setupController(initState, initLangCode, overrides) {
).forEach((txId) =>
controller.txController.txStateManager.setTxStatusRejected(txId),
);
controller.signController.rejectUnapproved(REJECT_NOTFICIATION_CLOSE_SIG);
controller.signController.rejectUnapproved(REJECT_NOTIFICATION_CLOSE_SIG);
controller.decryptMessageManager.messages
.filter((msg) => msg.status === 'unapproved')
.forEach((tx) =>
controller.decryptMessageManager.rejectMsg(
tx.id,
REJECT_NOTFICIATION_CLOSE,
REJECT_NOTIFICATION_CLOSE,
),
);
controller.encryptionPublicKeyManager.messages
@ -752,7 +752,7 @@ export function setupController(initState, initLangCode, overrides) {
.forEach((tx) =>
controller.encryptionPublicKeyManager.rejectMsg(
tx.id,
REJECT_NOTFICIATION_CLOSE,
REJECT_NOTIFICATION_CLOSE,
),
);
@ -848,11 +848,13 @@ async function openPopup() {
const addAppInstalledEvent = () => {
if (controller) {
controller.metaMetricsController.updateTraits({
[TRAITS.INSTALL_DATE_EXT]: new Date().toISOString().split('T')[0], // yyyy-mm-dd
[MetaMetricsUserTrait.InstallDateExt]: new Date()
.toISOString()
.split('T')[0], // yyyy-mm-dd
});
controller.metaMetricsController.addEventBeforeMetricsOptIn({
category: EVENT.CATEGORIES.APP,
event: EVENT_NAMES.APP_INSTALLED,
category: MetaMetricsEventCategory.App,
event: MetaMetricsEventName.AppInstalled,
properties: {},
});
return;

View File

@ -8,7 +8,10 @@ import {
AssetType,
TokenStandard,
} from '../../../shared/constants/transaction';
import { EVENT, EVENT_NAMES } from '../../../shared/constants/metametrics';
import {
MetaMetricsEventCategory,
MetaMetricsEventName,
} from '../../../shared/constants/metametrics';
// By default, poll every 3 minutes
const DEFAULT_INTERVAL = MINUTE * 3;
@ -167,8 +170,8 @@ export default class DetectTokensController {
if (tokensWithBalance.length > 0) {
this._trackMetaMetricsEvent({
event: EVENT_NAMES.TOKEN_DETECTED,
category: EVENT.CATEGORIES.WALLET,
event: MetaMetricsEventName.TokenDetected,
category: MetaMetricsEventCategory.Wallet,
properties: {
tokens: eventTokensDetails,
token_standard: TokenStandard.ERC20,

View File

@ -15,7 +15,7 @@ import { ENVIRONMENT_TYPE_BACKGROUND } from '../../../shared/constants/app';
import {
METAMETRICS_ANONYMOUS_ID,
METAMETRICS_BACKGROUND_PAGE_OBJECT,
TRAITS,
MetaMetricsUserTrait,
} from '../../../shared/constants/metametrics';
import { SECOND } from '../../../shared/constants/time';
import { isManifestV3 } from '../../../shared/modules/mv3.utils';
@ -692,38 +692,44 @@ export default class MetaMetricsController {
const { traits, previousUserTraits } = this.store.getState();
/** @type {MetaMetricsTraits} */
const currentTraits = {
[TRAITS.ADDRESS_BOOK_ENTRIES]: sum(
[MetaMetricsUserTrait.AddressBookEntries]: sum(
Object.values(metamaskState.addressBook).map(size),
),
[TRAITS.INSTALL_DATE_EXT]: traits[TRAITS.INSTALL_DATE_EXT] || '',
[TRAITS.LEDGER_CONNECTION_TYPE]: metamaskState.ledgerTransportType,
[TRAITS.NETWORKS_ADDED]: Object.values(
[MetaMetricsUserTrait.InstallDateExt]:
traits[MetaMetricsUserTrait.InstallDateExt] || '',
[MetaMetricsUserTrait.LedgerConnectionType]:
metamaskState.ledgerTransportType,
[MetaMetricsUserTrait.NetworksAdded]: Object.values(
metamaskState.networkConfigurations,
).map((networkConfiguration) => networkConfiguration.chainId),
[TRAITS.NETWORKS_WITHOUT_TICKER]: Object.values(
[MetaMetricsUserTrait.NetworksWithoutTicker]: Object.values(
metamaskState.networkConfigurations,
)
.filter(({ ticker }) => !ticker)
.map(({ chainId }) => chainId),
[TRAITS.NFT_AUTODETECTION_ENABLED]: metamaskState.useNftDetection,
[TRAITS.NUMBER_OF_ACCOUNTS]: Object.values(metamaskState.identities)
.length,
[TRAITS.NUMBER_OF_NFT_COLLECTIONS]: this._getAllUniqueNFTAddressesLength(
[MetaMetricsUserTrait.NftAutodetectionEnabled]:
metamaskState.useNftDetection,
[MetaMetricsUserTrait.NumberOfAccounts]: Object.values(
metamaskState.identities,
).length,
[MetaMetricsUserTrait.NumberOfNftCollections]:
this._getAllUniqueNFTAddressesLength(metamaskState.allNfts),
[MetaMetricsUserTrait.NumberOfNfts]: this._getAllNFTsFlattened(
metamaskState.allNfts,
),
[TRAITS.NUMBER_OF_NFTS]: this._getAllNFTsFlattened(metamaskState.allNfts)
.length,
[TRAITS.NUMBER_OF_TOKENS]: this._getNumberOfTokens(metamaskState),
[TRAITS.OPENSEA_API_ENABLED]: metamaskState.openSeaEnabled,
[TRAITS.THREE_BOX_ENABLED]: false, // deprecated, hard-coded as false
[TRAITS.THEME]: metamaskState.theme || 'default',
[TRAITS.TOKEN_DETECTION_ENABLED]: metamaskState.useTokenDetection,
).length,
[MetaMetricsUserTrait.NumberOfTokens]:
this._getNumberOfTokens(metamaskState),
[MetaMetricsUserTrait.OpenseaApiEnabled]: metamaskState.openSeaEnabled,
[MetaMetricsUserTrait.ThreeBoxEnabled]: false, // deprecated, hard-coded as false
[MetaMetricsUserTrait.Theme]: metamaskState.theme || 'default',
[MetaMetricsUserTrait.TokenDetectionEnabled]:
metamaskState.useTokenDetection,
///: BEGIN:ONLY_INCLUDE_IN(flask)
[TRAITS.DESKTOP_ENABLED]: metamaskState.desktopEnabled || false,
[MetaMetricsUserTrait.DesktopEnabled]:
metamaskState.desktopEnabled || false,
///: END:ONLY_INCLUDE_IN
[TRAITS.SECURITY_PROVIDERS]: metamaskState.transactionSecurityCheckEnabled
? ['opensea']
: [],
[MetaMetricsUserTrait.SecurityProviders]:
metamaskState.transactionSecurityCheckEnabled ? ['opensea'] : [],
};
if (!previousUserTraits) {

View File

@ -5,7 +5,7 @@ import { createSegmentMock } from '../lib/segment';
import {
METAMETRICS_ANONYMOUS_ID,
METAMETRICS_BACKGROUND_PAGE_OBJECT,
TRAITS,
MetaMetricsUserTrait,
} from '../../../shared/constants/metametrics';
import waitUntilCalled from '../../../test/lib/wait-until-called';
import {
@ -953,22 +953,26 @@ describe('MetaMetricsController', function () {
});
assert.deepEqual(traits, {
[TRAITS.ADDRESS_BOOK_ENTRIES]: 3,
[TRAITS.INSTALL_DATE_EXT]: '',
[TRAITS.LEDGER_CONNECTION_TYPE]: 'web-hid',
[TRAITS.NETWORKS_ADDED]: [CHAIN_IDS.MAINNET, CHAIN_IDS.GOERLI, '0xaf'],
[TRAITS.NETWORKS_WITHOUT_TICKER]: ['0xaf'],
[TRAITS.NFT_AUTODETECTION_ENABLED]: false,
[TRAITS.NUMBER_OF_ACCOUNTS]: 2,
[TRAITS.NUMBER_OF_NFT_COLLECTIONS]: 3,
[TRAITS.NUMBER_OF_NFTS]: 4,
[TRAITS.NUMBER_OF_TOKENS]: 5,
[TRAITS.OPENSEA_API_ENABLED]: true,
[TRAITS.THREE_BOX_ENABLED]: false,
[TRAITS.THEME]: 'default',
[TRAITS.TOKEN_DETECTION_ENABLED]: true,
[TRAITS.DESKTOP_ENABLED]: false,
[TRAITS.SECURITY_PROVIDERS]: [],
[MetaMetricsUserTrait.AddressBookEntries]: 3,
[MetaMetricsUserTrait.InstallDateExt]: '',
[MetaMetricsUserTrait.LedgerConnectionType]: 'web-hid',
[MetaMetricsUserTrait.NetworksAdded]: [
CHAIN_IDS.MAINNET,
CHAIN_IDS.GOERLI,
'0xaf',
],
[MetaMetricsUserTrait.NetworksWithoutTicker]: ['0xaf'],
[MetaMetricsUserTrait.NftAutodetectionEnabled]: false,
[MetaMetricsUserTrait.NumberOfAccounts]: 2,
[MetaMetricsUserTrait.NumberOfNftCollections]: 3,
[MetaMetricsUserTrait.NumberOfNfts]: 4,
[MetaMetricsUserTrait.NumberOfTokens]: 5,
[MetaMetricsUserTrait.OpenseaApiEnabled]: true,
[MetaMetricsUserTrait.ThreeBoxEnabled]: false,
[MetaMetricsUserTrait.Theme]: 'default',
[MetaMetricsUserTrait.TokenDetectionEnabled]: true,
[MetaMetricsUserTrait.DesktopEnabled]: false,
[MetaMetricsUserTrait.SecurityProviders]: [],
});
});
@ -1015,10 +1019,10 @@ describe('MetaMetricsController', function () {
});
assert.deepEqual(updatedTraits, {
[TRAITS.ADDRESS_BOOK_ENTRIES]: 4,
[TRAITS.NUMBER_OF_ACCOUNTS]: 3,
[TRAITS.NUMBER_OF_TOKENS]: 1,
[TRAITS.OPENSEA_API_ENABLED]: false,
[MetaMetricsUserTrait.AddressBookEntries]: 4,
[MetaMetricsUserTrait.NumberOfAccounts]: 3,
[MetaMetricsUserTrait.NumberOfTokens]: 1,
[MetaMetricsUserTrait.OpenseaApiEnabled]: false,
});
});

View File

@ -5,7 +5,7 @@ import log from 'loglevel';
import {
createSwappableProxy,
createEventEmitterProxy,
} from 'swappable-obj-proxy';
} from '@metamask/swappable-obj-proxy';
import EthQuery from 'eth-query';
// ControllerMessenger is referred to in the JSDocs
// eslint-disable-next-line no-unused-vars
@ -26,7 +26,7 @@ import {
isPrefixedFormattedHexString,
isSafeChainId,
} from '../../../../shared/modules/network.utils';
import { EVENT } from '../../../../shared/constants/metametrics';
import { MetaMetricsEventCategory } from '../../../../shared/constants/metametrics';
import { createNetworkClient } from './create-network-client';
/**
@ -645,7 +645,7 @@ export default class NetworkController extends EventEmitter {
if (!oldNetworkConfigurationId) {
this._trackMetaMetricsEvent({
event: 'Custom Network Added',
category: EVENT.CATEGORIES.NETWORK,
category: MetaMetricsEventCategory.Network,
referrer: {
url: referrer,
},

View File

@ -5,7 +5,7 @@ import nock from 'nock';
import sinon from 'sinon';
import { ControllerMessenger } from '@metamask/base-controller';
import { BUILT_IN_NETWORKS } from '../../../../shared/constants/network';
import { EVENT } from '../../../../shared/constants/metametrics';
import { MetaMetricsNetworkEventSource } from '../../../../shared/constants/metametrics';
import NetworkController from './network-controller';
jest.mock('uuid', () => {
@ -6991,7 +6991,7 @@ describe('NetworkController', () => {
},
{
referrer: 'https://test-dapp.com',
source: EVENT.SOURCE.NETWORK.DAPP,
source: MetaMetricsNetworkEventSource.Dapp,
},
),
).toThrow(
@ -7015,7 +7015,7 @@ describe('NetworkController', () => {
},
{
referrer: 'https://test-dapp.com',
source: EVENT.SOURCE.NETWORK.DAPP,
source: MetaMetricsNetworkEventSource.Dapp,
},
),
).toThrow(
@ -7038,7 +7038,7 @@ describe('NetworkController', () => {
},
{
referrer: 'https://test-dapp.com',
source: EVENT.SOURCE.NETWORK.DAPP,
source: MetaMetricsNetworkEventSource.Dapp,
},
),
).toThrow(
@ -7062,7 +7062,7 @@ describe('NetworkController', () => {
},
{
referrer: 'https://test-dapp.com',
source: EVENT.SOURCE.NETWORK.DAPP,
source: MetaMetricsNetworkEventSource.Dapp,
},
),
).toThrow(new Error('rpcUrl must be a valid URL'));
@ -7081,7 +7081,7 @@ describe('NetworkController', () => {
},
{
referrer: 'https://test-dapp.com',
source: EVENT.SOURCE.NETWORK.DAPP,
source: MetaMetricsNetworkEventSource.Dapp,
},
),
).toThrow(
@ -7126,7 +7126,7 @@ describe('NetworkController', () => {
controller.upsertNetworkConfiguration(rpcUrlNetwork, {
referrer: 'https://test-dapp.com',
source: EVENT.SOURCE.NETWORK.DAPP,
source: MetaMetricsNetworkEventSource.Dapp,
});
expect(
@ -7164,7 +7164,7 @@ describe('NetworkController', () => {
controller.upsertNetworkConfiguration(rpcUrlNetwork, {
referrer: 'https://test-dapp.com',
source: EVENT.SOURCE.NETWORK.DAPP,
source: MetaMetricsNetworkEventSource.Dapp,
});
expect(
@ -7213,7 +7213,7 @@ describe('NetworkController', () => {
controller.upsertNetworkConfiguration(rpcUrlNetwork, {
referrer: 'https://test-dapp.com',
source: EVENT.SOURCE.NETWORK.DAPP,
source: MetaMetricsNetworkEventSource.Dapp,
});
expect(
@ -7262,7 +7262,7 @@ describe('NetworkController', () => {
};
controller.upsertNetworkConfiguration(updatedConfiguration, {
referrer: 'https://test-dapp.com',
source: EVENT.SOURCE.NETWORK.DAPP,
source: MetaMetricsNetworkEventSource.Dapp,
});
expect(
Object.values(controller.store.getState().networkConfigurations),
@ -7315,7 +7315,7 @@ describe('NetworkController', () => {
},
{
referrer: 'https://test-dapp.com',
source: EVENT.SOURCE.NETWORK.DAPP,
source: MetaMetricsNetworkEventSource.Dapp,
},
);
@ -7375,7 +7375,7 @@ describe('NetworkController', () => {
controller.upsertNetworkConfiguration(rpcUrlNetwork, {
referrer: 'https://test-dapp.com',
source: EVENT.SOURCE.NETWORK.DAPP,
source: MetaMetricsNetworkEventSource.Dapp,
});
expect(controller.store.getState().provider).toStrictEqual(
@ -7424,7 +7424,7 @@ describe('NetworkController', () => {
controller.upsertNetworkConfiguration(rpcUrlNetwork, {
setActive: true,
referrer: 'https://test-dapp.com',
source: EVENT.SOURCE.NETWORK.DAPP,
source: MetaMetricsNetworkEventSource.Dapp,
});
expect(controller.store.getState().provider).toStrictEqual({
@ -7473,7 +7473,7 @@ describe('NetworkController', () => {
controller.upsertNetworkConfiguration(newNetworkConfiguration, {
referrer: 'https://test-dapp.com',
source: EVENT.SOURCE.NETWORK.DAPP,
source: MetaMetricsNetworkEventSource.Dapp,
});
expect(

View File

@ -7,7 +7,7 @@ import {
AbstractMessage,
OriginalRequest,
} from '@metamask/message-manager/dist/AbstractMessageManager';
import { EVENT } from '../../../shared/constants/metametrics';
import { MetaMetricsEventCategory } from '../../../shared/constants/metametrics';
import { detectSIWE } from '../../../shared/modules/siwe';
import SignController, {
SignControllerMessenger,
@ -270,7 +270,7 @@ describe('SignController', () => {
expect(metricsEventMock).toHaveBeenCalledTimes(6);
expect(metricsEventMock).toHaveBeenLastCalledWith({
event: 'Test Reason',
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
properties: {
action: 'Sign Request',
type: messageMock.type,

View File

@ -32,7 +32,7 @@ import {
AddApprovalRequest,
RejectRequest,
} from '@metamask/approval-controller';
import { EVENT } from '../../../shared/constants/metametrics';
import { MetaMetricsEventCategory } from '../../../shared/constants/metametrics';
import { detectSIWE } from '../../../shared/modules/siwe';
import PreferencesController from './preferences';
@ -510,7 +510,7 @@ export default class SignController extends BaseControllerV2<
this._metricsEvent({
event: reason,
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
properties: {
action: 'Sign Request',
type: message.type,

View File

@ -1,4 +1,4 @@
import EventEmitter from 'safe-event-emitter';
import EventEmitter from '@metamask/safe-event-emitter';
import { ObservableStore } from '@metamask/obs-store';
import { bufferToHex, keccak, toBuffer, isHexString } from 'ethereumjs-util';
import EthQuery from 'ethjs-query';
@ -39,7 +39,7 @@ import {
hexWEIToDecGWEI,
} from '../../../../shared/modules/conversion.utils';
import { isSwapsDefaultTokenAddress } from '../../../../shared/modules/swaps.utils';
import { EVENT } from '../../../../shared/constants/metametrics';
import { MetaMetricsEventCategory } from '../../../../shared/constants/metametrics';
import {
HARDFORKS,
CHAIN_ID_TO_GAS_LIMIT_BUFFER_MAP,
@ -2027,7 +2027,7 @@ export default class TransactionController extends EventEmitter {
this._trackMetaMetricsEvent({
event: 'Swap Failed',
sensitiveProperties: { ...txMeta.swapMetaData },
category: EVENT.CATEGORIES.SWAPS,
category: MetaMetricsEventCategory.Swaps,
});
} else {
const tokensReceived = getSwapsTokensReceivedFromTxMeta(
@ -2062,7 +2062,7 @@ export default class TransactionController extends EventEmitter {
this._trackMetaMetricsEvent({
event: 'Swap Completed',
category: EVENT.CATEGORIES.SWAPS,
category: MetaMetricsEventCategory.Swaps,
sensitiveProperties: {
...txMeta.swapMetaData,
token_to_amount_received: tokensReceived,
@ -2414,7 +2414,7 @@ export default class TransactionController extends EventEmitter {
// occur.
case TransactionMetaMetricsEvent.added:
this.createEventFragment({
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
initialEvent: TransactionMetaMetricsEvent.added,
successEvent: TransactionMetaMetricsEvent.approved,
failureEvent: TransactionMetaMetricsEvent.rejected,
@ -2436,7 +2436,7 @@ export default class TransactionController extends EventEmitter {
case TransactionMetaMetricsEvent.approved:
case TransactionMetaMetricsEvent.rejected:
this.createEventFragment({
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
successEvent: TransactionMetaMetricsEvent.approved,
failureEvent: TransactionMetaMetricsEvent.rejected,
properties,
@ -2458,7 +2458,7 @@ export default class TransactionController extends EventEmitter {
// properties to the transaction event.
case TransactionMetaMetricsEvent.submitted:
this.createEventFragment({
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
initialEvent: TransactionMetaMetricsEvent.submitted,
successEvent: TransactionMetaMetricsEvent.finalized,
properties,
@ -2478,7 +2478,7 @@ export default class TransactionController extends EventEmitter {
// fragment does not exist.
case TransactionMetaMetricsEvent.finalized:
this.createEventFragment({
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
successEvent: TransactionMetaMetricsEvent.finalized,
properties,
sensitiveProperties,

View File

@ -10,7 +10,10 @@ import {
getTestAccounts,
} from '../../../../test/stub/provider';
import mockEstimates from '../../../../test/data/mock-estimates.json';
import { EVENT } from '../../../../shared/constants/metametrics';
import {
MetaMetricsEventCategory,
MetaMetricsTransactionEventSource,
} from '../../../../shared/constants/metametrics';
import {
TransactionStatus,
TransactionType,
@ -1772,7 +1775,7 @@ describe('Transaction Controller', function () {
successEvent: 'Transaction Approved',
failureEvent: 'Transaction Rejected',
uniqueIdentifier: 'transaction-added-1',
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
persist: true,
properties: {
chain_id: '0x5',
@ -1781,7 +1784,7 @@ describe('Transaction Controller', function () {
gas_edit_type: 'none',
network: '5',
referrer: ORIGIN_METAMASK,
source: EVENT.SOURCE.TRANSACTION.USER,
source: MetaMetricsTransactionEventSource.User,
transaction_type: TransactionType.simpleSend,
account_type: 'MetaMask',
asset_type: AssetType.native,
@ -1859,7 +1862,7 @@ describe('Transaction Controller', function () {
initialEvent: 'Transaction Submitted',
successEvent: 'Transaction Finalized',
uniqueIdentifier: 'transaction-submitted-1',
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
persist: true,
properties: {
chain_id: '0x5',
@ -1868,7 +1871,7 @@ describe('Transaction Controller', function () {
gas_edit_type: 'none',
network: '5',
referrer: ORIGIN_METAMASK,
source: EVENT.SOURCE.TRANSACTION.USER,
source: MetaMetricsTransactionEventSource.User,
transaction_type: TransactionType.simpleSend,
account_type: 'MetaMask',
asset_type: AssetType.native,
@ -1958,7 +1961,7 @@ describe('Transaction Controller', function () {
successEvent: 'Transaction Approved',
failureEvent: 'Transaction Rejected',
uniqueIdentifier: 'transaction-added-1',
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
persist: true,
properties: {
chain_id: '0x5',
@ -1967,7 +1970,7 @@ describe('Transaction Controller', function () {
gas_edit_type: 'none',
network: '5',
referrer: 'other',
source: EVENT.SOURCE.TRANSACTION.DAPP,
source: MetaMetricsTransactionEventSource.Dapp,
transaction_type: TransactionType.simpleSend,
account_type: 'MetaMask',
asset_type: AssetType.native,
@ -2047,7 +2050,7 @@ describe('Transaction Controller', function () {
initialEvent: 'Transaction Submitted',
successEvent: 'Transaction Finalized',
uniqueIdentifier: 'transaction-submitted-1',
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
persist: true,
properties: {
chain_id: '0x5',
@ -2056,7 +2059,7 @@ describe('Transaction Controller', function () {
gas_edit_type: 'none',
network: '5',
referrer: 'other',
source: EVENT.SOURCE.TRANSACTION.DAPP,
source: MetaMetricsTransactionEventSource.Dapp,
transaction_type: TransactionType.simpleSend,
account_type: 'MetaMask',
asset_type: AssetType.native,
@ -2138,7 +2141,7 @@ describe('Transaction Controller', function () {
successEvent: 'Transaction Approved',
failureEvent: 'Transaction Rejected',
uniqueIdentifier: 'transaction-added-1',
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
persist: true,
properties: {
chain_id: '0x5',
@ -2147,7 +2150,7 @@ describe('Transaction Controller', function () {
gas_edit_type: 'none',
network: '5',
referrer: 'other',
source: EVENT.SOURCE.TRANSACTION.DAPP,
source: MetaMetricsTransactionEventSource.Dapp,
transaction_type: TransactionType.simpleSend,
account_type: 'MetaMask',
asset_type: AssetType.native,
@ -2211,11 +2214,11 @@ describe('Transaction Controller', function () {
failureEvent: 'Transaction Rejected',
uniqueIdentifier: 'transaction-added-1',
persist: true,
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
properties: {
network: '5',
referrer: 'other',
source: EVENT.SOURCE.TRANSACTION.DAPP,
source: MetaMetricsTransactionEventSource.Dapp,
transaction_type: TransactionType.simpleSend,
chain_id: '0x5',
eip_1559_version: '0',
@ -2285,11 +2288,11 @@ describe('Transaction Controller', function () {
failureEvent: 'Transaction Rejected',
uniqueIdentifier: 'transaction-added-1',
persist: true,
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
properties: {
network: '5',
referrer: 'other',
source: EVENT.SOURCE.TRANSACTION.DAPP,
source: MetaMetricsTransactionEventSource.Dapp,
transaction_type: TransactionType.simpleSend,
chain_id: '0x5',
eip_1559_version: '0',
@ -2359,11 +2362,11 @@ describe('Transaction Controller', function () {
failureEvent: 'Transaction Rejected',
uniqueIdentifier: 'transaction-added-1',
persist: true,
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
properties: {
network: '5',
referrer: 'other',
source: EVENT.SOURCE.TRANSACTION.DAPP,
source: MetaMetricsTransactionEventSource.Dapp,
transaction_type: TransactionType.simpleSend,
chain_id: '0x5',
eip_1559_version: '0',
@ -2441,7 +2444,7 @@ describe('Transaction Controller', function () {
failureEvent: 'Transaction Rejected',
uniqueIdentifier: 'transaction-added-1',
persist: true,
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
properties: {
chain_id: '0x5',
eip_1559_version: '2',
@ -2449,7 +2452,7 @@ describe('Transaction Controller', function () {
gas_edit_type: 'none',
network: '5',
referrer: 'other',
source: EVENT.SOURCE.TRANSACTION.DAPP,
source: MetaMetricsTransactionEventSource.Dapp,
transaction_type: TransactionType.simpleSend,
account_type: 'MetaMask',
asset_type: AssetType.native,

View File

@ -1,4 +1,4 @@
import EventEmitter from 'safe-event-emitter';
import EventEmitter from '@metamask/safe-event-emitter';
import log from 'loglevel';
import EthQuery from 'ethjs-query';
import { TransactionStatus } from '../../../../shared/constants/transaction';

View File

@ -1,4 +1,4 @@
import EventEmitter from 'safe-event-emitter';
import EventEmitter from '@metamask/safe-event-emitter';
import { ObservableStore } from '@metamask/obs-store';
import log from 'loglevel';
import { values, keyBy, mapValues, omitBy, pickBy, sortBy } from 'lodash';

View File

@ -4,9 +4,9 @@ import { TransactionStatus } from '../../../shared/constants/transaction';
import { SECOND } from '../../../shared/constants/time';
import { detectSIWE } from '../../../shared/modules/siwe';
import {
EVENT,
EVENT_NAMES,
METAMETRIC_KEY_OPT,
MetaMetricsEventCategory,
MetaMetricsEventName,
MetaMetricsEventUiCustomization,
} from '../../../shared/constants/metametrics';
/**
@ -46,50 +46,50 @@ const RATE_LIMIT_MAP = {
*/
const EVENT_NAME_MAP = {
[MESSAGE_TYPE.ETH_SIGN]: {
APPROVED: EVENT_NAMES.SIGNATURE_APPROVED,
FAILED: EVENT_NAMES.SIGNATURE_FAILED,
REJECTED: EVENT_NAMES.SIGNATURE_REJECTED,
REQUESTED: EVENT_NAMES.SIGNATURE_REQUESTED,
APPROVED: MetaMetricsEventName.SignatureApproved,
FAILED: MetaMetricsEventName.SignatureFailed,
REJECTED: MetaMetricsEventName.SignatureRejected,
REQUESTED: MetaMetricsEventName.SignatureRequested,
},
[MESSAGE_TYPE.ETH_SIGN_TYPED_DATA]: {
APPROVED: EVENT_NAMES.SIGNATURE_APPROVED,
REJECTED: EVENT_NAMES.SIGNATURE_REJECTED,
REQUESTED: EVENT_NAMES.SIGNATURE_REQUESTED,
APPROVED: MetaMetricsEventName.SignatureApproved,
REJECTED: MetaMetricsEventName.SignatureRejected,
REQUESTED: MetaMetricsEventName.SignatureRequested,
},
[MESSAGE_TYPE.ETH_SIGN_TYPED_DATA_V3]: {
APPROVED: EVENT_NAMES.SIGNATURE_APPROVED,
REJECTED: EVENT_NAMES.SIGNATURE_REJECTED,
REQUESTED: EVENT_NAMES.SIGNATURE_REQUESTED,
APPROVED: MetaMetricsEventName.SignatureApproved,
REJECTED: MetaMetricsEventName.SignatureRejected,
REQUESTED: MetaMetricsEventName.SignatureRequested,
},
[MESSAGE_TYPE.ETH_SIGN_TYPED_DATA_V4]: {
APPROVED: EVENT_NAMES.SIGNATURE_APPROVED,
REJECTED: EVENT_NAMES.SIGNATURE_REJECTED,
REQUESTED: EVENT_NAMES.SIGNATURE_REQUESTED,
APPROVED: MetaMetricsEventName.SignatureApproved,
REJECTED: MetaMetricsEventName.SignatureRejected,
REQUESTED: MetaMetricsEventName.SignatureRequested,
},
[MESSAGE_TYPE.PERSONAL_SIGN]: {
APPROVED: EVENT_NAMES.SIGNATURE_APPROVED,
REJECTED: EVENT_NAMES.SIGNATURE_REJECTED,
REQUESTED: EVENT_NAMES.SIGNATURE_REQUESTED,
APPROVED: MetaMetricsEventName.SignatureApproved,
REJECTED: MetaMetricsEventName.SignatureRejected,
REQUESTED: MetaMetricsEventName.SignatureRequested,
},
[MESSAGE_TYPE.ETH_DECRYPT]: {
APPROVED: EVENT_NAMES.DECRYPTION_APPROVED,
REJECTED: EVENT_NAMES.DECRYPTION_REJECTED,
REQUESTED: EVENT_NAMES.DECRYPTION_REQUESTED,
APPROVED: MetaMetricsEventName.DecryptionApproved,
REJECTED: MetaMetricsEventName.DecryptionRejected,
REQUESTED: MetaMetricsEventName.DecryptionRequested,
},
[MESSAGE_TYPE.ETH_GET_ENCRYPTION_PUBLIC_KEY]: {
APPROVED: EVENT_NAMES.ENCRYPTION_PUBLIC_KEY_APPROVED,
REJECTED: EVENT_NAMES.ENCRYPTION_PUBLIC_KEY_REJECTED,
REQUESTED: EVENT_NAMES.ENCRYPTION_PUBLIC_KEY_REQUESTED,
APPROVED: MetaMetricsEventName.EncryptionPublicKeyApproved,
REJECTED: MetaMetricsEventName.EncryptionPublicKeyRejected,
REQUESTED: MetaMetricsEventName.EncryptionPublicKeyRequested,
},
[MESSAGE_TYPE.ETH_REQUEST_ACCOUNTS]: {
APPROVED: EVENT_NAMES.PERMISSIONS_APPROVED,
REJECTED: EVENT_NAMES.PERMISSIONS_REJECTED,
REQUESTED: EVENT_NAMES.PERMISSIONS_REQUESTED,
APPROVED: MetaMetricsEventName.PermissionsApproved,
REJECTED: MetaMetricsEventName.PermissionsRejected,
REQUESTED: MetaMetricsEventName.PermissionsRequested,
},
[MESSAGE_TYPE.WALLET_REQUEST_PERMISSIONS]: {
APPROVED: EVENT_NAMES.PERMISSIONS_APPROVED,
REJECTED: EVENT_NAMES.PERMISSIONS_REJECTED,
REQUESTED: EVENT_NAMES.PERMISSIONS_REQUESTED,
APPROVED: MetaMetricsEventName.PermissionsApproved,
REJECTED: MetaMetricsEventName.PermissionsRejected,
REQUESTED: MetaMetricsEventName.PermissionsRequested,
},
};
@ -162,9 +162,9 @@ export default function createRPCMethodTrackingMiddleware({
// 'Provider Method Called'.
const event = eventType
? eventType.REQUESTED
: EVENT_NAMES.PROVIDER_METHOD_CALLED;
: MetaMetricsEventName.ProviderMethodCalled;
if (event === EVENT_NAMES.SIGNATURE_REQUESTED) {
if (event === MetaMetricsEventName.SignatureRequested) {
eventProperties.signature_type = method;
const data = req?.params?.[0];
@ -190,11 +190,11 @@ export default function createRPCMethodTrackingMiddleware({
if (securityProviderResponse?.flagAsDangerous === 1) {
eventProperties.ui_customizations = [
METAMETRIC_KEY_OPT.ui_customizations.flaggedAsMalicious,
MetaMetricsEventUiCustomization.FlaggedAsMalicious,
];
} else if (securityProviderResponse?.flagAsDangerous === 2) {
eventProperties.ui_customizations = [
METAMETRIC_KEY_OPT.ui_customizations.flaggedAsSafetyUnknown,
MetaMetricsEventUiCustomization.FlaggedAsSafetyUnknown,
];
}
@ -203,7 +203,7 @@ export default function createRPCMethodTrackingMiddleware({
if (isSIWEMessage) {
eventProperties.ui_customizations = (
eventProperties.ui_customizations || []
).concat(METAMETRIC_KEY_OPT.ui_customizations.SIWE);
).concat(MetaMetricsEventUiCustomization.Siwe);
}
}
} catch (e) {
@ -217,7 +217,7 @@ export default function createRPCMethodTrackingMiddleware({
trackEvent({
event,
category: EVENT.CATEGORIES.INPAGE_PROVIDER,
category: MetaMetricsEventCategory.InpageProvider,
referrer: {
url: origin,
},
@ -253,7 +253,7 @@ export default function createRPCMethodTrackingMiddleware({
trackEvent({
event,
category: EVENT.CATEGORIES.INPAGE_PROVIDER,
category: MetaMetricsEventCategory.InpageProvider,
referrer: {
url: origin,
},

View File

@ -1,8 +1,8 @@
import { errorCodes } from 'eth-rpc-errors';
import { MESSAGE_TYPE } from '../../../shared/constants/app';
import {
EVENT_NAMES,
METAMETRIC_KEY_OPT,
MetaMetricsEventName,
MetaMetricsEventUiCustomization,
} from '../../../shared/constants/metametrics';
import { SECOND } from '../../../shared/constants/time';
import { detectSIWE } from '../../../shared/modules/siwe';
@ -111,7 +111,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
metricsState.participateInMetaMetrics = true;
});
it(`should immediately track a ${EVENT_NAMES.SIGNATURE_REQUESTED} event`, async () => {
it(`should immediately track a ${MetaMetricsEventName.SignatureRequested} event`, async () => {
const req = {
method: MESSAGE_TYPE.ETH_SIGN,
origin: 'some.dapp',
@ -125,7 +125,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
expect(trackEvent).toHaveBeenCalledTimes(1);
expect(trackEvent.mock.calls[0][0]).toMatchObject({
category: 'inpage_provider',
event: EVENT_NAMES.SIGNATURE_REQUESTED,
event: MetaMetricsEventName.SignatureRequested,
properties: {
signature_type: MESSAGE_TYPE.ETH_SIGN,
},
@ -133,7 +133,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
});
});
it(`should track a ${EVENT_NAMES.SIGNATURE_APPROVED} event if the user approves`, async () => {
it(`should track a ${MetaMetricsEventName.SignatureApproved} event if the user approves`, async () => {
const req = {
method: MESSAGE_TYPE.ETH_SIGN_TYPED_DATA_V4,
origin: 'some.dapp',
@ -148,7 +148,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
expect(trackEvent).toHaveBeenCalledTimes(2);
expect(trackEvent.mock.calls[1][0]).toMatchObject({
category: 'inpage_provider',
event: EVENT_NAMES.SIGNATURE_APPROVED,
event: MetaMetricsEventName.SignatureApproved,
properties: {
signature_type: MESSAGE_TYPE.ETH_SIGN_TYPED_DATA_V4,
},
@ -156,7 +156,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
});
});
it(`should track a ${EVENT_NAMES.SIGNATURE_REJECTED} event if the user approves`, async () => {
it(`should track a ${MetaMetricsEventName.SignatureRejected} event if the user approves`, async () => {
const req = {
method: MESSAGE_TYPE.PERSONAL_SIGN,
origin: 'some.dapp',
@ -171,7 +171,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
expect(trackEvent).toHaveBeenCalledTimes(2);
expect(trackEvent.mock.calls[1][0]).toMatchObject({
category: 'inpage_provider',
event: EVENT_NAMES.SIGNATURE_REJECTED,
event: MetaMetricsEventName.SignatureRejected,
properties: {
signature_type: MESSAGE_TYPE.PERSONAL_SIGN,
},
@ -179,7 +179,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
});
});
it(`should track a ${EVENT_NAMES.PERMISSIONS_APPROVED} event if the user approves`, async () => {
it(`should track a ${MetaMetricsEventName.PermissionsApproved} event if the user approves`, async () => {
const req = {
method: MESSAGE_TYPE.ETH_REQUEST_ACCOUNTS,
origin: 'some.dapp',
@ -192,7 +192,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
expect(trackEvent).toHaveBeenCalledTimes(2);
expect(trackEvent.mock.calls[1][0]).toMatchObject({
category: 'inpage_provider',
event: EVENT_NAMES.PERMISSIONS_APPROVED,
event: MetaMetricsEventName.PermissionsApproved,
properties: { method: MESSAGE_TYPE.ETH_REQUEST_ACCOUNTS },
referrer: { url: 'some.dapp' },
});
@ -261,17 +261,17 @@ describe('createRPCMethodTrackingMiddleware', () => {
expect(trackEvent.mock.calls[1][0]).toMatchObject({
category: 'inpage_provider',
event: EVENT_NAMES.SIGNATURE_APPROVED,
event: MetaMetricsEventName.SignatureApproved,
properties: {
signature_type: MESSAGE_TYPE.PERSONAL_SIGN,
ui_customizations: [METAMETRIC_KEY_OPT.ui_customizations.SIWE],
ui_customizations: [MetaMetricsEventUiCustomization.Siwe],
},
referrer: { url: 'some.dapp' },
});
});
describe(`when '${MESSAGE_TYPE.ETH_SIGN}' is disabled in advanced settings`, () => {
it(`should track ${EVENT_NAMES.SIGNATURE_FAILED} and include error property`, async () => {
it(`should track ${MetaMetricsEventName.SignatureFailed} and include error property`, async () => {
const mockError = { code: errorCodes.rpc.methodNotFound };
const req = {
method: MESSAGE_TYPE.ETH_SIGN,
@ -289,7 +289,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
expect(trackEvent.mock.calls[1][0]).toMatchObject({
category: 'inpage_provider',
event: EVENT_NAMES.SIGNATURE_FAILED,
event: MetaMetricsEventName.SignatureFailed,
properties: {
signature_type: MESSAGE_TYPE.ETH_SIGN,
error: mockError,
@ -300,7 +300,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
});
describe('when request is flagged as safe by security provider', () => {
it(`should immediately track a ${EVENT_NAMES.SIGNATURE_REQUESTED} event`, async () => {
it(`should immediately track a ${MetaMetricsEventName.SignatureRequested} event`, async () => {
const req = {
method: MESSAGE_TYPE.ETH_SIGN,
origin: 'some.dapp',
@ -315,7 +315,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
expect(trackEvent).toHaveBeenCalledTimes(1);
expect(trackEvent.mock.calls[0][0]).toMatchObject({
category: 'inpage_provider',
event: EVENT_NAMES.SIGNATURE_REQUESTED,
event: MetaMetricsEventName.SignatureRequested,
properties: {
signature_type: MESSAGE_TYPE.ETH_SIGN,
},
@ -329,7 +329,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
flagAsDangerous = 1;
});
it(`should immediately track a ${EVENT_NAMES.SIGNATURE_REQUESTED} event which is flagged as malicious`, async () => {
it(`should immediately track a ${MetaMetricsEventName.SignatureRequested} event which is flagged as malicious`, async () => {
const req = {
method: MESSAGE_TYPE.ETH_SIGN,
origin: 'some.dapp',
@ -344,7 +344,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
expect(trackEvent).toHaveBeenCalledTimes(1);
expect(trackEvent.mock.calls[0][0]).toMatchObject({
category: 'inpage_provider',
event: EVENT_NAMES.SIGNATURE_REQUESTED,
event: MetaMetricsEventName.SignatureRequested,
properties: {
signature_type: MESSAGE_TYPE.ETH_SIGN,
ui_customizations: ['flagged_as_malicious'],
@ -359,7 +359,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
flagAsDangerous = 2;
});
it(`should immediately track a ${EVENT_NAMES.SIGNATURE_REQUESTED} event which is flagged as safety unknown`, async () => {
it(`should immediately track a ${MetaMetricsEventName.SignatureRequested} event which is flagged as safety unknown`, async () => {
const req = {
method: MESSAGE_TYPE.ETH_SIGN,
origin: 'some.dapp',
@ -374,7 +374,7 @@ describe('createRPCMethodTrackingMiddleware', () => {
expect(trackEvent).toHaveBeenCalledTimes(1);
expect(trackEvent.mock.calls[0][0]).toMatchObject({
category: 'inpage_provider',
event: EVENT_NAMES.SIGNATURE_REQUESTED,
event: MetaMetricsEventName.SignatureRequested,
properties: {
signature_type: MESSAGE_TYPE.ETH_SIGN,
ui_customizations: ['flagged_as_safety_unknown'],

View File

@ -4,7 +4,7 @@ import { bufferToHex } from 'ethereumjs-util';
import { ethErrors } from 'eth-rpc-errors';
import log from 'loglevel';
import { MESSAGE_TYPE } from '../../../shared/constants/app';
import { EVENT } from '../../../shared/constants/metametrics';
import { MetaMetricsEventCategory } from '../../../shared/constants/metametrics';
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
import createId from '../../../shared/modules/random-id';
import { stripHexPrefix } from '../../../shared/modules/hexstring-utils';
@ -237,7 +237,7 @@ export default class DecryptMessageManager extends EventEmitter {
if (reason) {
this.metricsEvent({
event: reason,
category: EVENT.CATEGORIES.MESSAGES,
category: MetaMetricsEventCategory.Messages,
properties: {
action: 'Decrypt Message Request',
},

View File

@ -3,7 +3,7 @@ import { ObservableStore } from '@metamask/obs-store';
import { ethErrors } from 'eth-rpc-errors';
import log from 'loglevel';
import { MESSAGE_TYPE } from '../../../shared/constants/app';
import { EVENT } from '../../../shared/constants/metametrics';
import { MetaMetricsEventCategory } from '../../../shared/constants/metametrics';
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
import createId from '../../../shared/modules/random-id';
@ -225,7 +225,7 @@ export default class EncryptionPublicKeyManager extends EventEmitter {
if (reason) {
this.metricsEvent({
event: reason,
category: EVENT.CATEGORIES.MESSAGES,
category: MetaMetricsEventCategory.Messages,
properties: {
action: 'Encryption public key Request',
},

View File

@ -1,5 +1,5 @@
import { EthereumRpcError } from 'eth-rpc-errors';
import SafeEventEmitter from 'safe-event-emitter';
import SafeEventEmitter from '@metamask/safe-event-emitter';
import createRandomId from '../../../shared/modules/random-id';
import { TEN_SECONDS_IN_MILLISECONDS } from '../../../shared/lib/transactions-controller-utils';

View File

@ -1,4 +1,4 @@
import EventEmitter from 'safe-event-emitter';
import EventEmitter from '@metamask/safe-event-emitter';
import ExtensionPlatform from '../platforms/extension';
const NOTIFICATION_HEIGHT = 620;

View File

@ -9,7 +9,7 @@ import {
isPrefixedFormattedHexString,
isSafeChainId,
} from '../../../../../shared/modules/network.utils';
import { EVENT } from '../../../../../shared/constants/metametrics';
import { MetaMetricsNetworkEventSource } from '../../../../../shared/constants/metametrics';
const addEthereumChain = {
methodNames: [MESSAGE_TYPE.ADD_ETHEREUM_CHAIN],
@ -262,7 +262,7 @@ async function addEthereumChainHandler(
rpcUrl: firstValidRPCUrl,
ticker,
},
{ source: EVENT.SOURCE.NETWORK.DAPP, referrer: origin },
{ source: MetaMetricsNetworkEventSource.Dapp, referrer: origin },
);
// Once the network has been added, the requested is considered successful

View File

@ -1,5 +1,5 @@
import { MESSAGE_TYPE } from '../../../../../shared/constants/app';
import { EVENT } from '../../../../../shared/constants/metametrics';
import { MetaMetricsEventCategory } from '../../../../../shared/constants/metametrics';
/**
* This RPC method is called by the inpage provider whenever it detects the
@ -49,7 +49,7 @@ function logWeb3ShimUsageHandler(
sendMetrics(
{
event: `Website Accessed window.web3 Shim`,
category: EVENT.CATEGORIES.INPAGE_PROVIDER,
category: MetaMetricsEventCategory.InpageProvider,
referrer: {
url: origin,
},

View File

@ -104,7 +104,10 @@ import {
///: END:ONLY_INCLUDE_IN
POLLING_TOKEN_ENVIRONMENT_TYPES,
} from '../../shared/constants/app';
import { EVENT, EVENT_NAMES } from '../../shared/constants/metametrics';
import {
MetaMetricsEventCategory,
MetaMetricsEventName,
} from '../../shared/constants/metametrics';
import {
getTokenIdParam,
@ -399,8 +402,8 @@ export default class MetamaskController extends EventEmitter {
),
onNftAdded: ({ address, symbol, tokenId, standard, source }) =>
this.metaMetricsController.trackEvent({
event: EVENT_NAMES.NFT_ADDED,
category: EVENT.CATEGORIES.WALLET,
event: MetaMetricsEventName.NftAdded,
category: MetaMetricsEventCategory.Wallet,
properties: {
token_contract_address: address,
token_symbol: symbol,
@ -1069,7 +1072,7 @@ export default class MetamaskController extends EventEmitter {
this.metaMetricsController.trackEvent(
{
event: 'Tx Status Update: On-Chain Failure',
category: EVENT.CATEGORIES.BACKGROUND,
category: MetaMetricsEventCategory.Background,
properties: {
action: 'Transactions',
errorMessage: txMeta.simulationFails?.reason,
@ -1196,8 +1199,8 @@ export default class MetamaskController extends EventEmitter {
const { serviceWorkerLastActiveTime } =
this.appStateController.store.getState();
const metametricsPayload = {
category: EVENT.SOURCE.SERVICE_WORKERS,
event: EVENT_NAMES.SERVICE_WORKER_RESTARTED,
category: MetaMetricsEventCategory.ServiceWorkers,
event: MetaMetricsEventName.ServiceWorkerRestarted,
properties: {
service_worker_restarted_time:
Date.now() - serviceWorkerLastActiveTime,
@ -1619,7 +1622,7 @@ export default class MetamaskController extends EventEmitter {
(truncatedSnap) => {
this.metaMetricsController.trackEvent({
event: 'Snap Installed',
category: EVENT.CATEGORIES.SNAPS,
category: MetaMetricsEventCategory.Snaps,
properties: {
snap_id: truncatedSnap.id,
version: truncatedSnap.version,
@ -1633,7 +1636,7 @@ export default class MetamaskController extends EventEmitter {
(newSnap, oldVersion) => {
this.metaMetricsController.trackEvent({
event: 'Snap Updated',
category: EVENT.CATEGORIES.SNAPS,
category: MetaMetricsEventCategory.Snaps,
properties: {
snap_id: newSnap.id,
old_version: oldVersion,
@ -3540,8 +3543,8 @@ export default class MetamaskController extends EventEmitter {
if (usePhishDetect && phishingTestResponse?.result) {
this.sendPhishingWarning(connectionStream, hostname);
this.metaMetricsController.trackEvent({
event: EVENT_NAMES.PHISHING_PAGE_DISPLAYED,
category: EVENT.CATEGORIES.PHISHING,
event: MetaMetricsEventName.PhishingPageDisplayed,
category: MetaMetricsEventCategory.Phishing,
properties: {
url: hostname,
},

View File

@ -4,6 +4,11 @@ const yargs = require('yargs/yargs');
const { hideBin } = require('yargs/helpers');
const { BuildType } = require('./lib/build-type');
const stableBuildTypes = Object.values(BuildType).filter(
// Skip generating policy for MMI until that build has stabilized
(buildType) => buildType !== BuildType.mmi,
);
start().catch((error) => {
console.error('Policy generation failed.', error);
process.exitCode = 1;
@ -20,7 +25,7 @@ async function start() {
.option('build-types', {
alias: ['t'],
choices: Object.values(BuildType),
default: Object.values(BuildType),
default: stableBuildTypes,
demandOption: true,
description: 'The build type(s) to generate policy files for.',
})

View File

@ -469,8 +469,8 @@
"@keystonehq/metamask-airgapped-keyring>@metamask/obs-store": {
"packages": {
"@keystonehq/metamask-airgapped-keyring>@metamask/obs-store>through2": true,
"browserify>stream-browserify": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
"@metamask/safe-event-emitter": true,
"browserify>stream-browserify": true
}
},
"@keystonehq/metamask-airgapped-keyring>@metamask/obs-store>through2": {
@ -874,10 +874,10 @@
"@metamask/eth-json-rpc-infura>@metamask/utils": true,
"@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>pify": true,
"@metamask/eth-keyring-controller>@metamask/eth-sig-util": true,
"@metamask/safe-event-emitter": true,
"browserify>browser-resolve": true,
"eth-rpc-errors": true,
"json-rpc-engine": true,
"json-rpc-engine>@metamask/safe-event-emitter": true,
"lavamoat>json-stable-stringify": true,
"vinyl>clone": true
}
@ -912,8 +912,8 @@
},
"@metamask/eth-json-rpc-provider": {
"packages": {
"json-rpc-engine": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
"@metamask/safe-event-emitter": true,
"json-rpc-engine": true
}
},
"@metamask/eth-keyring-controller": {
@ -968,7 +968,7 @@
},
"@metamask/eth-keyring-controller>obs-store": {
"packages": {
"safe-event-emitter": true,
"@metamask/eth-token-tracker>safe-event-emitter": true,
"watchify>xtend": true
}
},
@ -1056,9 +1056,9 @@
"@metamask/eth-token-tracker>eth-block-tracker": true,
"@metamask/eth-token-tracker>ethjs": true,
"@metamask/eth-token-tracker>human-standard-token-abi": true,
"@metamask/eth-token-tracker>safe-event-emitter": true,
"ethjs-contract": true,
"ethjs-query": true,
"safe-event-emitter": true
"ethjs-query": true
}
},
"@metamask/eth-token-tracker>deep-equal": {
@ -1090,8 +1090,8 @@
},
"packages": {
"@metamask/eth-token-tracker>eth-block-tracker>pify": true,
"eth-query": true,
"safe-event-emitter": true
"@metamask/eth-token-tracker>safe-event-emitter": true,
"eth-query": true
}
},
"@metamask/eth-token-tracker>ethjs": {
@ -1150,6 +1150,15 @@
"promise-to-callback": true
}
},
"@metamask/eth-token-tracker>safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"browserify>util": true,
"webpack>events": true
}
},
"@metamask/etherscan-link": {
"globals": {
"URL": true
@ -1327,13 +1336,10 @@
}
},
"@metamask/obs-store": {
"globals": {
"localStorage": true
},
"packages": {
"@metamask/obs-store>through2": true,
"browserify>stream-browserify": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
"@metamask/safe-event-emitter": true,
"browserify>stream-browserify": true
}
},
"@metamask/obs-store>through2": {
@ -1455,6 +1461,14 @@
"crypto.getRandomValues": true
}
},
"@metamask/safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"browserify>events": true
}
},
"@metamask/scure-bip39": {
"globals": {
"TextEncoder": true
@ -2726,10 +2740,10 @@
"setTimeout": true
},
"packages": {
"@metamask/safe-event-emitter": true,
"eth-block-tracker>@metamask/utils": true,
"eth-block-tracker>pify": true,
"eth-query>json-rpc-random-id": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
"eth-query>json-rpc-random-id": true
}
},
"eth-block-tracker>@metamask/utils": {
@ -2772,10 +2786,10 @@
"console.error": true
},
"packages": {
"@metamask/safe-event-emitter": true,
"eth-json-rpc-filters>async-mutex": true,
"eth-query": true,
"json-rpc-engine": true,
"json-rpc-engine>@metamask/safe-event-emitter": true,
"pify": true
}
},
@ -3614,16 +3628,8 @@
},
"json-rpc-engine": {
"packages": {
"eth-rpc-errors": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
}
},
"json-rpc-engine>@metamask/safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"browserify>events": true
"@metamask/safe-event-emitter": true,
"eth-rpc-errors": true
}
},
"json-rpc-middleware-stream": {
@ -3632,7 +3638,7 @@
"setTimeout": true
},
"packages": {
"json-rpc-engine>@metamask/safe-event-emitter": true,
"@metamask/safe-event-emitter": true,
"readable-stream": true
}
},
@ -4211,15 +4217,6 @@
"@babel/runtime": true
}
},
"safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"browserify>util": true,
"webpack>events": true
}
},
"semver": {
"globals": {
"console.error": true

View File

@ -469,8 +469,8 @@
"@keystonehq/metamask-airgapped-keyring>@metamask/obs-store": {
"packages": {
"@keystonehq/metamask-airgapped-keyring>@metamask/obs-store>through2": true,
"browserify>stream-browserify": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
"@metamask/safe-event-emitter": true,
"browserify>stream-browserify": true
}
},
"@keystonehq/metamask-airgapped-keyring>@metamask/obs-store>through2": {
@ -857,9 +857,9 @@
"setTimeout": true
},
"packages": {
"@metamask/desktop>@metamask/obs-store": true,
"@metamask/desktop>eciesjs": true,
"@metamask/desktop>otpauth": true,
"@metamask/obs-store": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
@ -872,6 +872,24 @@
"webextension-polyfill": true
}
},
"@metamask/desktop>@metamask/obs-store": {
"globals": {
"localStorage": true
},
"packages": {
"@metamask/desktop>@metamask/obs-store>through2": true,
"@metamask/safe-event-emitter": true,
"browserify>stream-browserify": true
}
},
"@metamask/desktop>@metamask/obs-store>through2": {
"packages": {
"browserify>process": true,
"browserify>util": true,
"readable-stream": true,
"watchify>xtend": true
}
},
"@metamask/desktop>eciesjs": {
"packages": {
"@metamask/desktop>eciesjs>futoin-hkdf": true,
@ -928,10 +946,10 @@
"@metamask/eth-json-rpc-infura>@metamask/utils": true,
"@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>pify": true,
"@metamask/eth-keyring-controller>@metamask/eth-sig-util": true,
"@metamask/safe-event-emitter": true,
"browserify>browser-resolve": true,
"eth-rpc-errors": true,
"json-rpc-engine": true,
"json-rpc-engine>@metamask/safe-event-emitter": true,
"lavamoat>json-stable-stringify": true,
"vinyl>clone": true
}
@ -966,8 +984,8 @@
},
"@metamask/eth-json-rpc-provider": {
"packages": {
"json-rpc-engine": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
"@metamask/safe-event-emitter": true,
"json-rpc-engine": true
}
},
"@metamask/eth-keyring-controller": {
@ -1022,7 +1040,7 @@
},
"@metamask/eth-keyring-controller>obs-store": {
"packages": {
"safe-event-emitter": true,
"@metamask/eth-token-tracker>safe-event-emitter": true,
"watchify>xtend": true
}
},
@ -1110,9 +1128,9 @@
"@metamask/eth-token-tracker>eth-block-tracker": true,
"@metamask/eth-token-tracker>ethjs": true,
"@metamask/eth-token-tracker>human-standard-token-abi": true,
"@metamask/eth-token-tracker>safe-event-emitter": true,
"ethjs-contract": true,
"ethjs-query": true,
"safe-event-emitter": true
"ethjs-query": true
}
},
"@metamask/eth-token-tracker>deep-equal": {
@ -1144,8 +1162,8 @@
},
"packages": {
"@metamask/eth-token-tracker>eth-block-tracker>pify": true,
"eth-query": true,
"safe-event-emitter": true
"@metamask/eth-token-tracker>safe-event-emitter": true,
"eth-query": true
}
},
"@metamask/eth-token-tracker>ethjs": {
@ -1204,6 +1222,15 @@
"promise-to-callback": true
}
},
"@metamask/eth-token-tracker>safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"browserify>util": true,
"webpack>events": true
}
},
"@metamask/etherscan-link": {
"globals": {
"URL": true
@ -1393,13 +1420,10 @@
}
},
"@metamask/obs-store": {
"globals": {
"localStorage": true
},
"packages": {
"@metamask/obs-store>through2": true,
"browserify>stream-browserify": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
"@metamask/safe-event-emitter": true,
"browserify>stream-browserify": true
}
},
"@metamask/obs-store>through2": {
@ -1610,6 +1634,14 @@
"crypto.getRandomValues": true
}
},
"@metamask/safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"browserify>events": true
}
},
"@metamask/scure-bip39": {
"globals": {
"TextEncoder": true
@ -3121,10 +3153,10 @@
"setTimeout": true
},
"packages": {
"@metamask/safe-event-emitter": true,
"eth-block-tracker>@metamask/utils": true,
"eth-block-tracker>pify": true,
"eth-query>json-rpc-random-id": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
"eth-query>json-rpc-random-id": true
}
},
"eth-block-tracker>@metamask/utils": {
@ -3167,10 +3199,10 @@
"console.error": true
},
"packages": {
"@metamask/safe-event-emitter": true,
"eth-json-rpc-filters>async-mutex": true,
"eth-query": true,
"json-rpc-engine": true,
"json-rpc-engine>@metamask/safe-event-emitter": true,
"pify": true
}
},
@ -4009,16 +4041,8 @@
},
"json-rpc-engine": {
"packages": {
"eth-rpc-errors": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
}
},
"json-rpc-engine>@metamask/safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"browserify>events": true
"@metamask/safe-event-emitter": true,
"eth-rpc-errors": true
}
},
"json-rpc-middleware-stream": {
@ -4027,7 +4051,7 @@
"setTimeout": true
},
"packages": {
"json-rpc-engine>@metamask/safe-event-emitter": true,
"@metamask/safe-event-emitter": true,
"readable-stream": true
}
},
@ -4738,15 +4762,6 @@
"@babel/runtime": true
}
},
"safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"browserify>util": true,
"webpack>events": true
}
},
"semver": {
"globals": {
"console.error": true

View File

@ -469,8 +469,8 @@
"@keystonehq/metamask-airgapped-keyring>@metamask/obs-store": {
"packages": {
"@keystonehq/metamask-airgapped-keyring>@metamask/obs-store>through2": true,
"browserify>stream-browserify": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
"@metamask/safe-event-emitter": true,
"browserify>stream-browserify": true
}
},
"@keystonehq/metamask-airgapped-keyring>@metamask/obs-store>through2": {
@ -857,9 +857,9 @@
"setTimeout": true
},
"packages": {
"@metamask/desktop>@metamask/obs-store": true,
"@metamask/desktop>eciesjs": true,
"@metamask/desktop>otpauth": true,
"@metamask/obs-store": true,
"browserify>buffer": true,
"browserify>events": true,
"browserify>process": true,
@ -872,6 +872,24 @@
"webextension-polyfill": true
}
},
"@metamask/desktop>@metamask/obs-store": {
"globals": {
"localStorage": true
},
"packages": {
"@metamask/desktop>@metamask/obs-store>through2": true,
"@metamask/safe-event-emitter": true,
"browserify>stream-browserify": true
}
},
"@metamask/desktop>@metamask/obs-store>through2": {
"packages": {
"browserify>process": true,
"browserify>util": true,
"readable-stream": true,
"watchify>xtend": true
}
},
"@metamask/desktop>eciesjs": {
"packages": {
"@metamask/desktop>eciesjs>futoin-hkdf": true,
@ -928,10 +946,10 @@
"@metamask/eth-json-rpc-infura>@metamask/utils": true,
"@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>pify": true,
"@metamask/eth-keyring-controller>@metamask/eth-sig-util": true,
"@metamask/safe-event-emitter": true,
"browserify>browser-resolve": true,
"eth-rpc-errors": true,
"json-rpc-engine": true,
"json-rpc-engine>@metamask/safe-event-emitter": true,
"lavamoat>json-stable-stringify": true,
"vinyl>clone": true
}
@ -966,8 +984,8 @@
},
"@metamask/eth-json-rpc-provider": {
"packages": {
"json-rpc-engine": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
"@metamask/safe-event-emitter": true,
"json-rpc-engine": true
}
},
"@metamask/eth-keyring-controller": {
@ -1022,7 +1040,7 @@
},
"@metamask/eth-keyring-controller>obs-store": {
"packages": {
"safe-event-emitter": true,
"@metamask/eth-token-tracker>safe-event-emitter": true,
"watchify>xtend": true
}
},
@ -1110,9 +1128,9 @@
"@metamask/eth-token-tracker>eth-block-tracker": true,
"@metamask/eth-token-tracker>ethjs": true,
"@metamask/eth-token-tracker>human-standard-token-abi": true,
"@metamask/eth-token-tracker>safe-event-emitter": true,
"ethjs-contract": true,
"ethjs-query": true,
"safe-event-emitter": true
"ethjs-query": true
}
},
"@metamask/eth-token-tracker>deep-equal": {
@ -1144,8 +1162,8 @@
},
"packages": {
"@metamask/eth-token-tracker>eth-block-tracker>pify": true,
"eth-query": true,
"safe-event-emitter": true
"@metamask/eth-token-tracker>safe-event-emitter": true,
"eth-query": true
}
},
"@metamask/eth-token-tracker>ethjs": {
@ -1204,6 +1222,15 @@
"promise-to-callback": true
}
},
"@metamask/eth-token-tracker>safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"browserify>util": true,
"webpack>events": true
}
},
"@metamask/etherscan-link": {
"globals": {
"URL": true
@ -1393,13 +1420,10 @@
}
},
"@metamask/obs-store": {
"globals": {
"localStorage": true
},
"packages": {
"@metamask/obs-store>through2": true,
"browserify>stream-browserify": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
"@metamask/safe-event-emitter": true,
"browserify>stream-browserify": true
}
},
"@metamask/obs-store>through2": {
@ -1610,6 +1634,14 @@
"crypto.getRandomValues": true
}
},
"@metamask/safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"browserify>events": true
}
},
"@metamask/scure-bip39": {
"globals": {
"TextEncoder": true
@ -3121,10 +3153,10 @@
"setTimeout": true
},
"packages": {
"@metamask/safe-event-emitter": true,
"eth-block-tracker>@metamask/utils": true,
"eth-block-tracker>pify": true,
"eth-query>json-rpc-random-id": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
"eth-query>json-rpc-random-id": true
}
},
"eth-block-tracker>@metamask/utils": {
@ -3167,10 +3199,10 @@
"console.error": true
},
"packages": {
"@metamask/safe-event-emitter": true,
"eth-json-rpc-filters>async-mutex": true,
"eth-query": true,
"json-rpc-engine": true,
"json-rpc-engine>@metamask/safe-event-emitter": true,
"pify": true
}
},
@ -4009,16 +4041,8 @@
},
"json-rpc-engine": {
"packages": {
"eth-rpc-errors": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
}
},
"json-rpc-engine>@metamask/safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"browserify>events": true
"@metamask/safe-event-emitter": true,
"eth-rpc-errors": true
}
},
"json-rpc-middleware-stream": {
@ -4027,7 +4051,7 @@
"setTimeout": true
},
"packages": {
"json-rpc-engine>@metamask/safe-event-emitter": true,
"@metamask/safe-event-emitter": true,
"readable-stream": true
}
},
@ -4738,15 +4762,6 @@
"@babel/runtime": true
}
},
"safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"browserify>util": true,
"webpack>events": true
}
},
"semver": {
"globals": {
"console.error": true

View File

@ -469,8 +469,8 @@
"@keystonehq/metamask-airgapped-keyring>@metamask/obs-store": {
"packages": {
"@keystonehq/metamask-airgapped-keyring>@metamask/obs-store>through2": true,
"browserify>stream-browserify": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
"@metamask/safe-event-emitter": true,
"browserify>stream-browserify": true
}
},
"@keystonehq/metamask-airgapped-keyring>@metamask/obs-store>through2": {
@ -874,10 +874,10 @@
"@metamask/eth-json-rpc-infura>@metamask/utils": true,
"@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>pify": true,
"@metamask/eth-keyring-controller>@metamask/eth-sig-util": true,
"@metamask/safe-event-emitter": true,
"browserify>browser-resolve": true,
"eth-rpc-errors": true,
"json-rpc-engine": true,
"json-rpc-engine>@metamask/safe-event-emitter": true,
"lavamoat>json-stable-stringify": true,
"vinyl>clone": true
}
@ -912,8 +912,8 @@
},
"@metamask/eth-json-rpc-provider": {
"packages": {
"json-rpc-engine": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
"@metamask/safe-event-emitter": true,
"json-rpc-engine": true
}
},
"@metamask/eth-keyring-controller": {
@ -968,7 +968,7 @@
},
"@metamask/eth-keyring-controller>obs-store": {
"packages": {
"safe-event-emitter": true,
"@metamask/eth-token-tracker>safe-event-emitter": true,
"watchify>xtend": true
}
},
@ -1056,9 +1056,9 @@
"@metamask/eth-token-tracker>eth-block-tracker": true,
"@metamask/eth-token-tracker>ethjs": true,
"@metamask/eth-token-tracker>human-standard-token-abi": true,
"@metamask/eth-token-tracker>safe-event-emitter": true,
"ethjs-contract": true,
"ethjs-query": true,
"safe-event-emitter": true
"ethjs-query": true
}
},
"@metamask/eth-token-tracker>deep-equal": {
@ -1090,8 +1090,8 @@
},
"packages": {
"@metamask/eth-token-tracker>eth-block-tracker>pify": true,
"eth-query": true,
"safe-event-emitter": true
"@metamask/eth-token-tracker>safe-event-emitter": true,
"eth-query": true
}
},
"@metamask/eth-token-tracker>ethjs": {
@ -1150,6 +1150,15 @@
"promise-to-callback": true
}
},
"@metamask/eth-token-tracker>safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"browserify>util": true,
"webpack>events": true
}
},
"@metamask/etherscan-link": {
"globals": {
"URL": true
@ -1327,13 +1336,10 @@
}
},
"@metamask/obs-store": {
"globals": {
"localStorage": true
},
"packages": {
"@metamask/obs-store>through2": true,
"browserify>stream-browserify": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
"@metamask/safe-event-emitter": true,
"browserify>stream-browserify": true
}
},
"@metamask/obs-store>through2": {
@ -1455,6 +1461,14 @@
"crypto.getRandomValues": true
}
},
"@metamask/safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"browserify>events": true
}
},
"@metamask/scure-bip39": {
"globals": {
"TextEncoder": true
@ -2726,10 +2740,10 @@
"setTimeout": true
},
"packages": {
"@metamask/safe-event-emitter": true,
"eth-block-tracker>@metamask/utils": true,
"eth-block-tracker>pify": true,
"eth-query>json-rpc-random-id": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
"eth-query>json-rpc-random-id": true
}
},
"eth-block-tracker>@metamask/utils": {
@ -2772,10 +2786,10 @@
"console.error": true
},
"packages": {
"@metamask/safe-event-emitter": true,
"eth-json-rpc-filters>async-mutex": true,
"eth-query": true,
"json-rpc-engine": true,
"json-rpc-engine>@metamask/safe-event-emitter": true,
"pify": true
}
},
@ -3614,16 +3628,8 @@
},
"json-rpc-engine": {
"packages": {
"eth-rpc-errors": true,
"json-rpc-engine>@metamask/safe-event-emitter": true
}
},
"json-rpc-engine>@metamask/safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"browserify>events": true
"@metamask/safe-event-emitter": true,
"eth-rpc-errors": true
}
},
"json-rpc-middleware-stream": {
@ -3632,7 +3638,7 @@
"setTimeout": true
},
"packages": {
"json-rpc-engine>@metamask/safe-event-emitter": true,
"@metamask/safe-event-emitter": true,
"readable-stream": true
}
},
@ -4211,15 +4217,6 @@
"@babel/runtime": true
}
},
"safe-event-emitter": {
"globals": {
"setTimeout": true
},
"packages": {
"browserify>util": true,
"webpack>events": true
}
},
"semver": {
"globals": {
"console.error": true

View File

@ -1,6 +1,6 @@
{
"name": "metamask-crx",
"version": "10.27.0",
"version": "10.28.1",
"private": true,
"repository": {
"type": "git",
@ -248,13 +248,14 @@
"@metamask/message-manager": "^2.0.0",
"@metamask/metamask-eth-abis": "^3.0.0",
"@metamask/notification-controller": "^1.0.0",
"@metamask/obs-store": "^5.0.0",
"@metamask/obs-store": "^8.0.0",
"@metamask/permission-controller": "^3.1.0",
"@metamask/phishing-controller": "^2.0.0",
"@metamask/post-message-stream": "^6.0.0",
"@metamask/providers": "^10.2.1",
"@metamask/rate-limit-controller": "^1.0.0",
"@metamask/rpc-methods": "^0.32.2",
"@metamask/safe-event-emitter": "^2.0.0",
"@metamask/scure-bip39": "^2.0.3",
"@metamask/slip44": "^2.1.0",
"@metamask/smart-transactions-controller": "^3.1.0",
@ -262,6 +263,7 @@
"@metamask/snaps-ui": "^0.32.2",
"@metamask/snaps-utils": "^0.32.2",
"@metamask/subject-metadata-controller": "^1.0.0",
"@metamask/swappable-obj-proxy": "^2.1.0",
"@metamask/utils": "^5.0.0",
"@ngraveio/bc-ur": "^1.1.6",
"@popperjs/core": "^2.4.0",
@ -348,10 +350,8 @@
"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",
"single-call-balance-checker-abi": "^1.0.0",
"swappable-obj-proxy": "^1.1.0",
"unicode-confusables": "^0.1.1",
"uuid": "^8.3.2",
"valid-url": "^1.0.9",

View File

@ -1,482 +0,0 @@
// Type Imports
/**
* @typedef {import('../../shared/constants/app').EnvironmentType} EnvironmentType
*/
// Type Declarations
/**
* Used to attach context of where the user was at in the application when the
* event was triggered. Also included as full details of the current page in
* page events.
*
* @typedef {object} MetaMetricsPageObject
* @property {string} [path] - the path of the current page (e.g /home)
* @property {string} [title] - the title of the current page (e.g 'home')
* @property {string} [url] - the fully qualified url of the current page
*/
/**
* For metamask, this is the dapp that triggered an interaction
*
* @typedef {object} MetaMetricsReferrerObject
* @property {string} [url] - the origin of the dapp issuing the
* notification
*/
/**
* We attach context to every meta metrics event that help to qualify our
* analytics. This type has all optional values because it represents a
* returned object from a method call. Ideally app and userAgent are
* defined on every event. This is confirmed in the getTrackMetaMetricsEvent
* function, but still provides the consumer a way to override these values if
* necessary.
*
* @typedef {object} MetaMetricsContext
* @property {object} app - Application metadata.
* @property {string} app.name - the name of the application tracking the event
* @property {string} app.version - the version of the application
* @property {string} userAgent - the useragent string of the user
* @property {MetaMetricsPageObject} [page] - an object representing details of
* the current page
* @property {MetaMetricsReferrerObject} [referrer] - for metamask, this is the
* dapp that triggered an interaction
*/
/**
* @typedef {object} MetaMetricsEventPayload
* @property {string} event - event name to track
* @property {string} category - category to associate event to
* @property {number} [actionId] - Action id to deduplicate event requests from
* the UI
* @property {string} [environmentType] - The type of environment this event
* occurred in. Defaults to the background process type
* @property {object} [properties] - object of custom values to track, keys
* in this object must be in snake_case
* @property {object} [sensitiveProperties] - Object of sensitive values to
* track. Keys in this object must be in snake_case. These properties will be
* sent in an additional event that excludes the user's metaMetricsId
* @property {number} [revenue] - amount of currency that event creates in
* revenue for MetaMask
* @property {string} [currency] - ISO 4127 format currency for events with
* revenue, defaults to US dollars
* @property {number} [value] - Abstract business "value" attributable to
* customers who trigger this event
* @property {MetaMetricsPageObject} [page] - the page/route that the event
* occurred on
* @property {MetaMetricsReferrerObject} [referrer] - the origin of the dapp
* that triggered the event
*/
/**
* @typedef {object} MetaMetricsEventOptions
* @property {boolean} [isOptIn] - happened during opt in/out workflow
* @property {boolean} [flushImmediately] - When true will automatically flush
* the segment queue after tracking the event. Recommended if the result of
* tracking the event must be known before UI transition or update
* @property {boolean} [excludeMetaMetricsId] - whether to exclude the user's
* metametrics id for anonymity
* @property {string} [metaMetricsId] - an override for the metaMetricsId in
* the event one is created as part of an asynchronous workflow, such as
* awaiting the result of the metametrics opt-in function that generates the
* user's metametrics id
* @property {boolean} [matomoEvent] - is this event a holdover from matomo
* that needs further migration? when true, sends the data to a special
* segment source that marks the event data as not conforming to our schema
*/
/**
* @typedef {object} MetaMetricsEventFragment
* @property {string} successEvent - The event name to fire when the fragment
* is closed in an affirmative action.
* @property {string} [failureEvent] - The event name to fire when the fragment
* is closed with a rejection.
* @property {string} [initialEvent] - An event name to fire immediately upon
* fragment creation. This is useful for building funnels in mixpanel and for
* reduction of code duplication.
* @property {string} category - the event category to use for both the success
* and failure events
* @property {boolean} [persist] - Should this fragment be persisted in
* state and progressed after the extension is locked and unlocked.
* @property {number} [timeout] - Time in seconds the event should be persisted
* for. After the timeout the fragment will be closed as abandoned. if not
* supplied the fragment is stored indefinitely.
* @property {number} [lastUpdated] - Date.now() when the fragment was last
* updated. Used to determine if the timeout has expired and the fragment
* should be closed.
* @property {object} [properties] - Object of custom values to track, keys in
* this object must be in snake_case.
* @property {object} [sensitiveProperties] - Object of sensitive values to
* track. Keys in this object must be in snake_case. These properties will be
* sent in an additional event that excludes the user's metaMetricsId
* @property {number} [revenue] - amount of currency that event creates in
* revenue for MetaMask if fragment is successful.
* @property {string} [currency] - ISO 4127 format currency for events with
* revenue, defaults to US dollars
* @property {number} [value] - Abstract business "value" attributable to
* customers who successfully complete this fragment
* @property {MetaMetricsPageObject} [page] - the page/route that the event
* occurred on
* @property {MetaMetricsReferrerObject} [referrer] - the origin of the dapp
* that initiated the event fragment.
* @property {string} [uniqueIdentifier] - optional argument to override the
* automatic generation of UUID for the event fragment. This is useful when
* tracking events for subsystems that already generate UUIDs so to avoid
* unnecessary lookups and reduce accidental duplication.
*/
/**
* Represents the shape of data sent to the segment.track method.
*
* @typedef {object} SegmentEventPayload
* @property {string} [userId] - The metametrics id for the user
* @property {string} [anonymousId] - An anonymousId that is used to track
* sensitive data while preserving anonymity.
* @property {string} event - name of the event to track
* @property {object} properties - properties to attach to the event
* @property {MetaMetricsContext} context - the context the event occurred in
*/
/**
* @typedef {object} MetaMetricsPagePayload
* @property {string} name - The name of the page that was viewed
* @property {object} [params] - The variadic parts of the page url
* example (route: `/asset/:asset`, path: `/asset/ETH`)
* params: { asset: 'ETH' }
* @property {EnvironmentType} environmentType - the environment type that the
* page was viewed in
* @property {MetaMetricsPageObject} [page] - the details of the page
* @property {MetaMetricsReferrerObject} [referrer] - dapp that triggered the page
* view
*/
/**
* @typedef {object} MetaMetricsPageOptions
* @property {boolean} [isOptInPath] - is the current path one of the pages in
* the onboarding workflow? If true and participateInMetaMetrics is null track
* the page view
*/
/**
* @typedef {object} Traits
* @property {'address_book_entries'} ADDRESS_BOOK_ENTRIES - When the user
* adds or modifies addresses in address book the address_book_entries trait
* is identified.
* @property {'ledger_connection_type'} LEDGER_CONNECTION_TYPE - when ledger
* live connnection type is changed we identify the ledger_connection_type
* trait
* @property {'networks_added'} NETWORKS_ADDED - when user modifies networks
* we identify the networks_added trait
* @property {'networks_without_ticker'} NETWORKS_WITHOUT_TICKER - when user
* modifies networks we identify the networks_without_ticker trait for
* networks without a ticker.
* @property {'nft_autodetection_enabled'} NFT_AUTODETECTION_ENABLED - when Autodetect NFTs
* feature is toggled we identify the nft_autodetection_enabled trait
* @property {'number_of_accounts'} NUMBER_OF_ACCOUNTS - when identities
* change, we identify the new number_of_accounts trait
* @property {'number_of_nft_collections'} NUMBER_OF_NFT_COLLECTIONS - user
* trait for number of unique NFT addresses
* @property {'number_of_nfts'} NUMBER_OF_NFTS - user trait for number of all NFT addresses
* @property {'number_of_tokens'} NUMBER_OF_TOKENS - when the number of tokens change, we
* 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. 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
* @property {'install_date_ext'} INSTALL_DATE_EXT - when the user installed the extension
* @property {'desktop_enabled'} [DESKTOP_ENABLED] - optional / does the user have desktop enabled?
* @property {'security_providers'} SECURITY_PROVIDERS - when security provider feature is toggled we
* identify the security_providers trait
*/
/**
*
* @type {Traits}
*/
export const TRAITS = {
ADDRESS_BOOK_ENTRIES: 'address_book_entries',
INSTALL_DATE_EXT: 'install_date_ext',
LEDGER_CONNECTION_TYPE: 'ledger_connection_type',
NETWORKS_ADDED: 'networks_added',
NETWORKS_WITHOUT_TICKER: 'networks_without_ticker',
NFT_AUTODETECTION_ENABLED: 'nft_autodetection_enabled',
NUMBER_OF_ACCOUNTS: 'number_of_accounts',
NUMBER_OF_NFT_COLLECTIONS: 'number_of_nft_collections',
NUMBER_OF_NFTS: 'number_of_nfts',
NUMBER_OF_TOKENS: 'number_of_tokens',
OPENSEA_API_ENABLED: 'opensea_api_enabled',
THEME: 'theme',
THREE_BOX_ENABLED: 'three_box_enabled',
TOKEN_DETECTION_ENABLED: 'token_detection_enabled',
DESKTOP_ENABLED: 'desktop_enabled',
SECURITY_PROVIDERS: 'security_providers',
};
/**
* @typedef {object} MetaMetricsTraits
* @property {number} [address_book_entries] - The number of entries in the
* user's address book.
* @property {'ledgerLive' | 'webhid' | 'u2f'} [ledger_connection_type] - the
* type of ledger connection set by user preference.
* @property {Array<string>} [networks_added] - An array consisting of chainIds
* that indicate the networks a user has added to their MetaMask.
* @property {Array<string>} [networks_without_ticker] - An array consisting of
* chainIds that indicate the networks added by the user that do not have a
* ticker.
* @property {number} [nft_autodetection_enabled] - does the user have the
* use collection/nft detection enabled?
* @property {number} [number_of_accounts] - A number representing the number
* of identities(accounts) added to the user's MetaMask.
* @property {number} [number_of_nft_collections] - A number representing the
* amount of different NFT collections the user possesses an NFT from.
* @property {number} [number_of_nfts] - A number representing the
* amount of all NFTs the user possesses across all networks and accounts.
* @property {number} [number_of_tokens] - The total number of token contracts
* 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? (deprecated)
* @property {string} [theme] - which theme the user has selected
* @property {boolean} [token_detection_enabled] - does the user have token detection is enabled?
* @property {boolean} [desktop_enabled] - optional / does the user have desktop enabled?
* @property {Array<string>} [security_providers] - whether security provider feature toggle is on or off
*/
// Mixpanel converts the zero address value to a truly anonymous event, which
// speeds up reporting
export const METAMETRICS_ANONYMOUS_ID = '0x0000000000000000';
/**
* This object is used to identify events that are triggered by the background
* process.
*
* @type {MetaMetricsPageObject}
*/
export const METAMETRICS_BACKGROUND_PAGE_OBJECT = {
path: '/background-process',
title: 'Background Process',
url: '/background-process',
};
/**
* @typedef {object} SegmentInterface
* @property {SegmentEventPayload[]} queue - A queue of events to be sent when
* the flushAt limit has been reached, or flushInterval occurs
* @property {() => void} flush - Immediately flush the queue, resetting it to
* an empty array and sending the pending events to Segment
* @property {(
* payload: SegmentEventPayload,
* callback: (err?: Error) => void
* ) => void} track - Track an event with Segment, using the internal batching
* mechanism to optimize network requests
* @property {(payload: object) => void} page - Track a page view with Segment
* @property {() => void} identify - Identify an anonymous user. We do not
* currently use this method.
*/
export const REJECT_NOTFICIATION_CLOSE = 'Cancel Via Notification Close';
export const REJECT_NOTFICIATION_CLOSE_SIG =
'Cancel Sig Request Via Notification Close';
/**
* EVENTS
*/
export const EVENT_NAMES = {
ACCOUNT_ADDED: 'Account Added',
ACCOUNT_ADD_SELECTED: 'Account Add Selected',
ACCOUNT_ADD_FAILED: 'Account Add Failed',
ACCOUNT_PASSWORD_CREATED: 'Account Password Created',
ACCOUNT_RESET: 'Account Reset',
APP_INSTALLED: 'App Installed',
APP_UNLOCKED: 'App Unlocked',
APP_UNLOCKED_FAILED: 'App Unlocked Failed',
APP_WINDOW_EXPANDED: 'App Window Expanded',
BRIDGE_LINK_CLICKED: 'Bridge Link Clicked',
DECRYPTION_APPROVED: 'Decryption Approved',
DECRYPTION_REJECTED: 'Decryption Rejected',
DECRYPTION_REQUESTED: 'Decryption Requested',
ENCRYPTION_PUBLIC_KEY_APPROVED: 'Encryption Approved',
ENCRYPTION_PUBLIC_KEY_REJECTED: 'Encryption Rejected',
ENCRYPTION_PUBLIC_KEY_REQUESTED: 'Encryption Requested',
EXTERNAL_LINK_CLICKED: 'External Link Clicked',
KEY_EXPORT_SELECTED: 'Key Export Selected',
KEY_EXPORT_REQUESTED: 'Key Export Requested',
KEY_EXPORT_FAILED: 'Key Export Failed',
KEY_EXPORT_CANCELED: 'Key Export Canceled',
KEY_EXPORT_REVEALED: 'Key Material Revealed',
KEY_EXPORT_COPIED: 'Key Material Copied',
KEY_TOKEN_DETECTION_SELECTED: 'Key Token Detection Selected',
KEY_GLOBAL_SECURITY_TOGGLE_SELECTED: 'Key Global Security/Privacy Settings',
KEY_BALANCE_TOKEN_PRICE_CHECKER:
'Key Show Balance and Token Price Checker Settings',
KEY_GAS_FEE_ESTIMATION_BUY_SWAP_TOKENS:
'Key Show Gas Fee Estimation, Buy Crypto and Swap Tokens',
KEY_AUTO_DETECT_TOKENS: 'Key Autodetect tokens',
KEY_BATCH_ACCOUNT_BALANCE_REQUESTS: 'Key Batch account balance requests',
METRICS_OPT_IN: 'Metrics Opt In',
METRICS_OPT_OUT: 'Metrics Opt Out',
NAV_ACCOUNT_MENU_OPENED: 'Account Menu Opened',
NAV_ACCOUNT_DETAILS_OPENED: 'Account Details Opened',
NAV_CONNECTED_SITES_OPENED: 'Connected Sites Opened',
NAV_MAIN_MENU_OPENED: 'Main Menu Opened',
NAV_NETWORK_MENU_OPENED: 'Network Menu Opened',
NAV_SETTINGS_OPENED: 'Settings Opened',
NAV_ACCOUNT_SWITCHED: 'Account Switched',
NAV_NETWORK_SWITCHED: 'Network Switched',
NAV_BUY_BUTTON_CLICKED: 'Buy Button Clicked',
NAV_SEND_BUTTON_CLICKED: 'Send Button Clicked',
NAV_SWAP_BUTTON_CLICKED: 'Swap Button Clicked',
SRP_TO_CONFIRM_BACKUP: 'SRP Backup Confirm Displayed',
WALLET_SETUP_STARTED: 'Wallet Setup Selected',
WALLET_SETUP_CANCELED: 'Wallet Setup Canceled',
WALLET_SETUP_FAILED: 'Wallet Setup Failed',
WALLET_CREATED: 'Wallet Created',
NFT_ADDED: 'NFT Added',
ONRAMP_PROVIDER_SELECTED: 'On-ramp Provider Selected',
PERMISSIONS_APPROVED: 'Permissions Approved',
PERMISSIONS_REJECTED: 'Permissions Rejected',
PERMISSIONS_REQUESTED: 'Permissions Requested',
PHISHING_PAGE_DISPLAYED: 'Phishing Page Displayed',
PORTFOLIO_LINK_CLICKED: 'Portfolio Link Clicked',
PUBLIC_ADDRESS_COPIED: 'Public Address Copied',
PROVIDER_METHOD_CALLED: 'Provider Method Called',
SIGNATURE_APPROVED: 'Signature Approved',
SIGNATURE_FAILED: 'Signature Failed',
SIGNATURE_REJECTED: 'Signature Rejected',
SIGNATURE_REQUESTED: 'Signature Requested',
TOKEN_IMPORT_BUTTON_CLICKED: 'Import Token Button Clicked',
TOKEN_SCREEN_OPENED: 'Token Screen Opened',
SUPPORT_LINK_CLICKED: 'Support Link Clicked',
TOKEN_ADDED: 'Token Added',
TOKEN_DETECTED: 'Token Detected',
TOKEN_HIDDEN: 'Token Hidden',
TOKEN_IMPORT_CANCELED: 'Token Import Canceled',
TOKEN_IMPORT_CLICKED: 'Token Import Clicked',
ONBOARDING_WELCOME: 'App Installed',
ONBOARDING_WALLET_CREATION_STARTED: 'Wallet Setup Selected',
ONBOARDING_WALLET_IMPORT_STARTED: 'Wallet Import Started',
ONBOARDING_WALLET_CREATION_ATTEMPTED: 'Wallet Password Created',
ONBOARDING_WALLET_SECURITY_STARTED: 'SRP Backup Selected',
ONBOARDING_WALLET_SECURITY_SKIP_INITIATED: 'SRP Skip Backup Selected',
ONBOARDING_WALLET_SECURITY_SKIP_CONFIRMED: 'SRP Backup Skipped',
ONBOARDING_WALLET_SECURITY_SKIP_CANCELED: 'SRP Skip Backup Canceled',
ONBOARDING_WALLET_SECURITY_PHRASE_REVEALED: 'SRP Revealed',
ONBOARDING_WALLET_SECURITY_PHRASE_WRITTEN_DOWN: 'SRP Backup Confirm Display',
ONBOARDING_WALLET_SECURITY_PHRASE_CONFIRMED: 'SRP Backup Confirmed',
ONBOARDING_WALLET_CREATION_COMPLETE: 'Wallet Created',
ONBOARDING_WALLET_SETUP_COMPLETE: 'Application Opened',
ONBOARDING_WALLET_ADVANCED_SETTINGS: 'Settings Updated',
ONBOARDING_WALLET_IMPORT_ATTEMPTED: 'Wallet Import Attempted',
ONBOARDING_WALLET_VIDEO_PLAY: 'SRP Intro Video Played',
ONBOARDING_TWITTER_CLICK: 'External Link Clicked',
SERVICE_WORKER_RESTARTED: 'Service Worker Restarted',
};
export const EVENT = {
ACCOUNT_TYPES: {
DEFAULT: 'metamask',
IMPORTED: 'imported',
HARDWARE: 'hardware',
},
ACCOUNT_IMPORT_TYPES: {
JSON: 'json',
PRIVATE_KEY: 'private_key',
SRP: 'srp',
},
CATEGORIES: {
ACCOUNTS: 'Accounts',
APP: 'App',
AUTH: 'Auth',
BACKGROUND: 'Background',
ERROR: 'Error',
FOOTER: 'Footer',
HOME: 'Home',
INPAGE_PROVIDER: 'inpage_provider',
KEYS: 'Keys',
MESSAGES: 'Messages',
NAVIGATION: 'Navigation',
NETWORK: 'Network',
ONBOARDING: 'Onboarding',
PHISHING: 'Phishing',
RETENTION: 'Retention',
SETTINGS: 'Settings',
SNAPS: 'Snaps',
SWAPS: 'Swaps',
TRANSACTIONS: 'Transactions',
WALLET: 'Wallet',
DESKTOP: 'Desktop',
},
EXTERNAL_LINK_TYPES: {
TRANSACTION_BLOCK_EXPLORER: 'Transaction Block Explorer',
BLOCK_EXPLORER: 'Block Explorer',
ACCOUNT_TRACKER: 'Account Tracker',
TOKEN_TRACKER: 'Token Tracker',
},
KEY_TYPES: {
PKEY: 'private_key',
SRP: 'srp',
},
ONRAMP_PROVIDER_TYPES: {
COINBASE: 'coinbase',
MOONPAY: 'moonpay',
WYRE: 'wyre',
TRANSAK: 'transak',
SELF_DEPOSIT: 'direct_deposit',
},
SOURCE: {
NETWORK: {
CUSTOM_NETWORK_FORM: 'custom_network_form',
POPULAR_NETWORK_LIST: 'popular_network_list',
DAPP: 'dapp',
},
SWAPS: {
MAIN_VIEW: 'Main View',
TOKEN_VIEW: 'Token View',
},
TOKEN: {
CUSTOM: 'custom',
DAPP: 'dapp',
DETECTED: 'detected',
LIST: 'list',
},
TRANSACTION: {
DAPP: 'dapp',
USER: 'user',
},
SERVICE_WORKERS: 'service_workers',
},
LOCATION: {
TOKEN_DETAILS: 'token_details',
TOKEN_DETECTION: 'token_detection',
TOKEN_MENU: 'token_menu',
},
};
// Values below (e.g. 'location') can be used in the "properties"
// tracking object as keys, e.g. { location: 'Home' }
export const CONTEXT_PROPS = {
PAGE_TITLE: 'location',
};
/**
* These types correspond to the keys in the METAMETRIC_KEY_OPT object
*/
export const METAMETRIC_KEY = {
UI_CUSTOMIZATIONS: `ui_customizations`,
};
/**
* This object maps a METAMETRIC_KEY to an object of possible options
*/
export const METAMETRIC_KEY_OPT = {
[METAMETRIC_KEY.UI_CUSTOMIZATIONS]: {
flaggedAsMalicious: 'flagged_as_malicious',
flaggedAsSafetyUnknown: 'flagged_as_safety_unknown',
SIWE: 'sign_in_with_ethereum',
},
};

View File

@ -0,0 +1,642 @@
import type { EnvironmentType } from './app';
import { LedgerTransportTypes } from './hardware-wallets';
/**
* Used to attach context of where the user was at in the application when the
* event was triggered. Also included as full details of the current page in
* page events.
*/
export type MetaMetricsPageObject = {
/**
* The path of the current page (e.g. "/home").
*/
path?: string;
/**
* The title of the current page (e.g. "home").
*/
title?: string;
/**
* The fully qualified URL of the current page.
*/
url?: string;
};
/**
* The dapp that triggered an interaction (MetaMask only).
*/
export type MetaMetricsReferrerObject = {
/**
* The origin of the dapp issuing the notification.
*/
url?: string;
};
/**
* We attach context to every meta metrics event that help to qualify our
* analytics. This type has all optional values because it represents a
* returned object from a method call. Ideally app and userAgent are
* defined on every event. This is confirmed in the getTrackMetaMetricsEvent
* function, but still provides the consumer a way to override these values if
* necessary.
*/
type MetaMetricsContext = {
/**
* Application metadata.
*/
app: {
/**
* The name of the application tracking the event.
*/
name: string;
/**
* The version of the application.
*/
version: string;
};
/**
* The user agent of the application.
*/
userAgent: string;
/**
* An object representing details of the current page.
*/
page?: MetaMetricsPageObject;
/**
* The dapp that triggered an interaction (MetaMask only).
*/
referrer?: MetaMetricsReferrerObject;
};
export type MetaMetricsEventPayload = {
/**
* The event name to track.
*/
event: string;
/**
* The category to associate the event to.
*/
category: string;
/**
* The action ID to deduplicate event requests from the UI.
*/
actionId?: number;
/**
* The type of environment this event occurred in. Defaults to the background
* process type.
*/
environmentType?: string;
/**
* Custom values to track. Keys in this object must be `snake_case`.
*/
properties?: object;
/**
* Sensitive values to track. These properties will be sent in an additional
* event that excludes the user's `metaMetricsId`. Keys in this object must be
* in `snake_case`.
*/
sensitiveProperties?: object;
/**
* Amount of currency that the event creates in revenue for MetaMask.
*/
revenue?: number;
/**
* ISO-4127-formatted currency for events with revenue. Defaults to US
* dollars.
*/
currency?: string;
/**
* Abstract business "value" attributable to customers who trigger this event.
*/
value?: number;
/**
* The page/route that the event occurred on.
*/
page?: MetaMetricsPageObject;
/**
* The origin of the dapp that triggered this event.
*/
referrer?: MetaMetricsReferrerObject;
};
export type MetaMetricsEventOptions = {
/**
* Whether or not the event happened during the opt-in workflow.
*/
isOptIn?: boolean;
/**
* Whether the segment queue should be flushed after tracking the event.
* Recommended if the result of tracking the event must be known before UI
* transition or update.
*/
flushImmediately?: boolean;
/**
* Whether to exclude the user's `metaMetricsId` for anonymity.
*/
excludeMetaMetricsId?: boolean;
/**
* An override for the `metaMetricsId` in the event (no pun intended) one is
* created as a part of an asynchronous workflow, such as awaiting the result
* of the MetaMetrics opt-in function that generates the user's
* `metaMetricsId`.
*/
metaMetricsId?: string;
/**
* Is this event a holdover from Matomo that needs further migration? When
* true, sends the data to a special Segment source that marks the event data
* as not conforming to our schema.
*/
matomoEvent?: boolean;
};
export type MetaMetricsEventFragment = {
/**
* The event name to fire when the fragment is closed in an affirmative action.
*/
successEvent: string;
/**
* The event name to fire when the fragment is closed with a rejection.
*/
failureEvent?: string;
/**
* An event name to fire immediately upon fragment creation. This is useful
* for building funnels in mixpanel and for reduction of code duplication.
*/
initialEvent?: string;
/**
* The event category to use for both the success and failure events.
*/
category: string;
/**
* Should this fragment be persisted in state and progressed after the
* extension is locked and unlocked.
*/
persist?: boolean;
/**
* Time in seconds the event should be persisted for. After the timeout the
* fragment will be closed as abandoned. If not supplied the fragment is
* stored indefinitely.
*/
timeout?: number;
/**
* `Date.now()` when the fragment was last updated. Used to determine if the
* timeout has expired and the fragment should be closed.
*/
lastUpdated?: number;
/**
* Custom values to track. Keys in this object must be `snake_case`.
*/
properties?: object;
/**
* Sensitive values to track. These properties will be sent in an additional
* event that excludes the user's `metaMetricsId`. Keys in this object must be
* in `snake_case`.
*/
sensitiveProperties?: object;
/**
* Amount of currency that the event creates in revenue for MetaMask.
*/
revenue?: number;
/**
* ISO-4127-formatted currency for events with revenue. Defaults to US
* dollars.
*/
currency?: string;
/**
* Abstract business "value" attributable to customers who trigger this event.
*/
value?: number;
/**
* The page/route that the event occurred on.
*/
page?: MetaMetricsPageObject;
/**
* The origin of the dapp that triggered this event.
*/
referrer?: MetaMetricsReferrerObject;
/**
* Overrides the automatic generation of UUID for the event fragment. This is
* useful when tracking events for subsystems that already generate UUIDs so
* to avoid unnecessary lookups and reduce accidental duplication.
*/
uniqueIdentifier?: string;
};
/**
* Data sent to the `segment.track` method.
*/
export type SegmentEventPayload = {
/**
* The MetaMetrics id for the user.
*/
userId?: string;
/**
* An anonymous ID that is used to track sensitive data while preserving
* anonymity.
*/
anonymousId?: string;
/**
* The name of the event to track.
*/
event: string;
/**
* Properties to attach to the event.
*/
properties: object;
/**
* The context the event occurred in.
*/
context: MetaMetricsContext;
};
/**
* Data sent to MetaMetrics for page views.
*/
export type MetaMetricsPagePayload = {
/**
* The name of the page that was viewed.
*/
name: string;
/**
* The variadic parts of the page URL.
*
* Example: If the route is `/asset/:asset` and the path is `/asset/ETH`,
* the `params` property would be `{ asset: 'ETH' }`.
*/
params?: object;
/**
* The environment type that the page was viewed in.
*/
environmentType: EnvironmentType;
/**
* The details of the page.
*/
page?: MetaMetricsPageObject;
/**
* The dapp that triggered the page view.
*/
referrer?: MetaMetricsReferrerObject;
};
export type MetaMetricsPageOptions = {
/**
* Is the current path one of the pages in the onboarding workflow? (If this
* is true and participateInMetaMetrics is null, then the page view will be
* tracked.)
*/
isOptInPath?: boolean;
};
/**
* Data sent to MetaMetrics for user traits.
*/
export type MetaMetricsUserTraits = {
/**
* The number of entries in the user's address book.
*/
address_book_entries?: number;
/**
* The type of ledger connection set by user preference.
*/
ledger_connection_type?: LedgerTransportTypes;
/**
* An array consisting of chain IDs that represent the networks added by the
* user.
*/
networks_added?: string[];
/**
* An array consisting of chain IDs that represent the networks added by the
* user that do not have a ticker.
*/
networks_without_ticker?: string[];
/**
* Does the user have the Autodetect NFTs feature enabled?
*/
nft_autodetection_enabled?: number;
/**
* A number representing the number of identities (accounts) added to the
* user's wallet.
*/
number_of_accounts?: number;
/**
* A number representing the amount of NFT collections from which the user
* possesses NFTs.
*/
number_of_nft_collections?: number;
/**
* A number representing the amount of all NFTs the user possesses across all
* networks and accounts.
*/
number_of_nfts?: number;
/**
* The total number of token contracts the user has across all networks and
* accounts.
*/
number_of_tokens?: number;
/**
* Does the user have the OpenSea API enabled?
*/
opensea_api_enabled?: boolean;
/**
* Does the user have 3Box sync enabled?
*
* @deprecated
*/
three_box_enabled?: boolean;
/**
* Which theme the user has selected.
*/
theme?: string;
/**
* Does the user have token detection enabled?
*/
token_detection_enabled?: boolean;
/**
* Does the user have desktop enabled?
*/
desktop_enabled?: boolean;
/**
* Whether the security provider feature has been enabled.
*/
security_providers?: string[];
};
export enum MetaMetricsUserTrait {
/**
* Identified when the user adds or modifies addresses in the address book.
*/
AddressBookEntries = 'address_book_entries',
/**
* Identified when the user installed the extension.
*/
InstallDateExt = 'install_date_ext',
/**
* Identified when the Ledger Live connection type is changed.
*/
LedgerConnectionType = 'ledger_connection_type',
/**
* Identified when the user modifies networks.
*/
NetworksAdded = 'networks_added',
/**
* Identified when the user modifies networks that lack a ticker.
*/
NetworksWithoutTicker = 'networks_without_ticker',
/**
* Identified when the "Autodetect NFTs" feature is toggled.
*/
NftAutodetectionEnabled = 'nft_autodetection_enabled',
/**
* Identified when identities change.
*/
NumberOfAccounts = 'number_of_accounts',
/**
* The number of unique NFT addresses.
*/
NumberOfNftCollections = 'number_of_nft_collections',
/**
* Identified when the number of NFTs owned by the user changes.
*/
NumberOfNfts = 'number_of_nfts',
/**
* Identified when the number of tokens change.
*/
NumberOfTokens = 'number_of_tokens',
/**
* Identified when the OpenSea API is enabled.
*/
OpenSeaApiEnabled = 'opensea_api_enabled',
/**
* Identified when the user's theme changes.
*/
Theme = 'theme',
/**
* Identified when the 3Box feature is toggled.
*
* @deprecated
*/
ThreeBoxEnabled = 'three_box_enabled',
/**
* Identified when the token detection feature is toggled.
*/
TokenDetectionEnabled = 'token_detection_enabled',
/**
* Identified when the user enables desktop.
*/
DesktopEnabled = 'desktop_enabled',
/**
* Identified when the security provider feature is enabled.
*/
SecurityProviders = 'security_providers',
}
/**
* Mixpanel converts the zero address value to a truly anonymous event, which
* speeds up reporting
*/
export const METAMETRICS_ANONYMOUS_ID = '0x0000000000000000';
/**
* Used to identify events that are triggered by the background process.
*/
export const METAMETRICS_BACKGROUND_PAGE_OBJECT: MetaMetricsPageObject = {
path: '/background-process',
title: 'Background Process',
url: '/background-process',
};
export const REJECT_NOTIFICATION_CLOSE = 'Cancel Via Notification Close';
export const REJECT_NOTIFICATION_CLOSE_SIG =
'Cancel Sig Request Via Notification Close';
export enum MetaMetricsEventName {
AccountAdded = 'Account Added',
AccountAddSelected = 'Account Add Selected',
AccountAddFailed = 'Account Add Failed',
AccountPasswordCreated = 'Account Password Created',
AccountReset = 'Account Reset',
AppInstalled = 'App Installed',
AppUnlocked = 'App Unlocked',
AppUnlockedFailed = 'App Unlocked Failed',
AppWindowExpanded = 'App Window Expanded',
BridgeLinkClicked = 'Bridge Link Clicked',
DecryptionApproved = 'Decryption Approved',
DecryptionRejected = 'Decryption Rejected',
DecryptionRequested = 'Decryption Requested',
EncryptionPublicKeyApproved = 'Encryption Approved',
EncryptionPublicKeyRejected = 'Encryption Rejected',
EncryptionPublicKeyRequested = 'Encryption Requested',
ExternalLinkClicked = 'External Link Clicked',
KeyExportSelected = 'Key Export Selected',
KeyExportRequested = 'Key Export Requested',
KeyExportFailed = 'Key Export Failed',
KeyExportCanceled = 'Key Export Canceled',
KeyExportRevealed = 'Key Material Revealed',
KeyExportCopied = 'Key Material Copied',
KeyTokenDetectionSelected = 'Key Token Detection Selected',
KeyGlobalSecurityToggleSelected = 'Key Global Security/Privacy Settings',
KeyBalanceTokenPriceChecker = 'Key Show Balance and Token Price Checker Settings',
KeyGasFeeEstimationBuySwapTokens = 'Key Show Gas Fee Estimation, Buy Crypto and Swap Tokens',
KeyAutoDetectTokens = 'Key Autodetect tokens',
KeyBatchAccountBalanceRequests = 'Key Batch account balance requests',
MetricsOptIn = 'Metrics Opt In',
MetricsOptOut = 'Metrics Opt Out',
NavAccountMenuOpened = 'Account Menu Opened',
NavAccountDetailsOpened = 'Account Details Opened',
NavConnectedSitesOpened = 'Connected Sites Opened',
NavMainMenuOpened = 'Main Menu Opened',
NavNetworkMenuOpened = 'Network Menu Opened',
NavSettingsOpened = 'Settings Opened',
NavAccountSwitched = 'Account Switched',
NavNetworkSwitched = 'Network Switched',
NavBuyButtonClicked = 'Buy Button Clicked',
NavSendButtonClicked = 'Send Button Clicked',
NavSwapButtonClicked = 'Swap Button Clicked',
SrpToConfirmBackup = 'SRP Backup Confirm Displayed',
WalletSetupStarted = 'Wallet Setup Selected',
WalletSetupCanceled = 'Wallet Setup Canceled',
WalletSetupFailed = 'Wallet Setup Failed',
WalletCreated = 'Wallet Created',
NftAdded = 'NFT Added',
OnrampProviderSelected = 'On-ramp Provider Selected',
PermissionsApproved = 'Permissions Approved',
PermissionsRejected = 'Permissions Rejected',
PermissionsRequested = 'Permissions Requested',
PhishingPageDisplayed = 'Phishing Page Displayed',
PortfolioLinkClicked = 'Portfolio Link Clicked',
PublicAddressCopied = 'Public Address Copied',
ProviderMethodCalled = 'Provider Method Called',
SignatureApproved = 'Signature Approved',
SignatureFailed = 'Signature Failed',
SignatureRejected = 'Signature Rejected',
SignatureRequested = 'Signature Requested',
TokenImportButtonClicked = 'Import Token Button Clicked',
TokenScreenOpened = 'Token Screen Opened',
SupportLinkClicked = 'Support Link Clicked',
TokenAdded = 'Token Added',
TokenDetected = 'Token Detected',
TokenHidden = 'Token Hidden',
TokenImportCanceled = 'Token Import Canceled',
TokenImportClicked = 'Token Import Clicked',
OnboardingWelcome = 'App Installed',
OnboardingWalletCreationStarted = 'Wallet Setup Selected',
OnboardingWalletImportStarted = 'Wallet Import Started',
OnboardingWalletCreationAttempted = 'Wallet Password Created',
OnboardingWalletSecurityStarted = 'SRP Backup Selected',
OnboardingWalletSecuritySkipInitiated = 'SRP Skip Backup Selected',
OnboardingWalletSecuritySkipConfirmed = 'SRP Backup Skipped',
OnboardingWalletSecuritySkipCanceled = 'SRP Skip Backup Canceled',
OnboardingWalletSecurityPhraseRevealed = 'SRP Revealed',
OnboardingWalletSecurityPhraseWrittenDown = 'SRP Backup Confirm Display',
OnboardingWalletSecurityPhraseConfirmed = 'SRP Backup Confirmed',
OnboardingWalletCreationComplete = 'Wallet Created',
OnboardingWalletSetupComplete = 'Application Opened',
OnboardingWalletAdvancedSettings = 'Settings Updated',
OnboardingWalletImportAttempted = 'Wallet Import Attempted',
OnboardingWalletVideoPlay = 'SRP Intro Video Played',
OnboardingTwitterClick = 'External Link Clicked',
ServiceWorkerRestarted = 'Service Worker Restarted',
}
export enum MetaMetricsEventAccountType {
Default = 'metamask',
Imported = 'imported',
Hardware = 'hardware',
}
export enum MetaMetricsEventAccountImportType {
Json = 'json',
PrivateKey = 'private_key',
Srp = 'srp',
}
export enum MetaMetricsEventCategory {
Accounts = 'Accounts',
App = 'App',
Auth = 'Auth',
Background = 'Background',
// The TypeScript ESLint rule is incorrectly marking this line.
/* eslint-disable-next-line @typescript-eslint/no-shadow */
Error = 'Error',
Footer = 'Footer',
Home = 'Home',
InpageProvider = 'inpage_provider',
Keys = 'Keys',
Messages = 'Messages',
Navigation = 'Navigation',
Network = 'Network',
Onboarding = 'Onboarding',
Phishing = 'Phishing',
Retention = 'Retention',
Settings = 'Settings',
Snaps = 'Snaps',
Swaps = 'Swaps',
Transactions = 'Transactions',
Wallet = 'Wallet',
Desktop = 'Desktop',
ServiceWorkers = 'service_workers',
}
export enum MetaMetricsEventLinkType {
TransactionBlockExplorer = 'Transaction Block Explorer',
BlockExplorer = 'Block Explorer',
AccountTracker = 'Account Tracker',
TokenTracker = 'Token Tracker',
}
export enum MetaMetricsEventKeyType {
Pkey = 'private_key',
Srp = 'srp',
}
// NOTE: This doesn't seem to be used at all
export enum MetaMetricsEventOnrampProviderType {
Coinbase = 'coinbase',
Moonpay = 'moonpay',
Wyre = 'wyre',
Transak = 'transak',
SelfDeposit = 'direct_deposit',
}
export enum MetaMetricsNetworkEventSource {
CustomNetworkForm = 'custom_network_form',
PopularNetworkList = 'popular_network_list',
Dapp = 'dapp',
}
export enum MetaMetricsSwapsEventSource {
MainView = 'Main View',
TokenView = 'Token View',
}
export enum MetaMetricsTokenEventSource {
Custom = 'custom',
Dapp = 'dapp',
Detected = 'detected',
List = 'list',
}
export enum MetaMetricsTransactionEventSource {
Dapp = 'dapp',
User = 'user',
}
export enum MetaMetricsEventLocation {
TokenDetails = 'token_details',
TokenDetection = 'token_detection',
TokenMenu = 'token_menu',
}
export enum MetaMetricsEventUiCustomization {
FlaggedAsMalicious = 'flagged_as_malicious',
FlaggedAsSafetyUnknown = 'flagged_as_safety_unknown',
Siwe = 'sign_in_with_ethereum',
}
/**
* Values that can used in the "properties" tracking object as keys, e.g. `{
* location: 'Home' }`.
*/
export enum MetaMetricsContextProp {
PageTitle = 'location',
}

View File

@ -6,9 +6,10 @@ import InputAdornment from '@material-ui/core/InputAdornment';
import classnames from 'classnames';
import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app';
import {
EVENT,
EVENT_NAMES,
CONTEXT_PROPS,
MetaMetricsContextProp,
MetaMetricsEventAccountType,
MetaMetricsEventCategory,
MetaMetricsEventName,
} from '../../../../shared/constants/metametrics';
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
import Identicon from '../../ui/identicon';
@ -209,8 +210,8 @@ export default class AccountMenu extends Component {
className="account-menu__account account-menu__item--clickable"
onClick={() => {
this.context.trackEvent({
category: EVENT.CATEGORIES.NAVIGATION,
event: EVENT_NAMES.NAV_ACCOUNT_SWITCHED,
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.NavAccountSwitched,
properties: {
location: 'Main Menu',
},
@ -360,10 +361,10 @@ export default class AccountMenu extends Component {
onClick={() => {
toggleAccountMenu();
trackEvent({
category: EVENT.CATEGORIES.NAVIGATION,
event: EVENT_NAMES.ACCOUNT_ADD_SELECTED,
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.AccountAddSelected,
properties: {
account_type: EVENT.ACCOUNT_TYPES.DEFAULT,
account_type: MetaMetricsEventAccountType.Default,
location: 'Main Menu',
},
});
@ -378,10 +379,10 @@ export default class AccountMenu extends Component {
onClick={() => {
toggleAccountMenu();
trackEvent({
category: EVENT.CATEGORIES.NAVIGATION,
event: EVENT_NAMES.ACCOUNT_ADD_SELECTED,
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.AccountAddSelected,
properties: {
account_type: EVENT.ACCOUNT_TYPES.IMPORTED,
account_type: MetaMetricsEventAccountType.Imported,
location: 'Main Menu',
},
});
@ -396,10 +397,10 @@ export default class AccountMenu extends Component {
onClick={() => {
toggleAccountMenu();
trackEvent({
category: EVENT.CATEGORIES.NAVIGATION,
event: EVENT_NAMES.ACCOUNT_ADD_SELECTED,
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.AccountAddSelected,
properties: {
account_type: EVENT.ACCOUNT_TYPES.HARDWARE,
account_type: MetaMetricsEventAccountType.Hardware,
location: 'Main Menu',
},
});
@ -446,14 +447,16 @@ export default class AccountMenu extends Component {
onClick={() => {
trackEvent(
{
category: EVENT.CATEGORIES.NAVIGATION,
event: EVENT_NAMES.SUPPORT_LINK_CLICKED,
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.SupportLinkClicked,
properties: {
url: supportLink,
},
},
{
contextPropsIntoEventProperties: [CONTEXT_PROPS.PAGE_TITLE],
contextPropsIntoEventProperties: [
MetaMetricsContextProp.PageTitle,
],
},
);
global.platform.openTab({ url: supportLink });
@ -472,8 +475,8 @@ export default class AccountMenu extends Component {
toggleAccountMenu();
history.push(SETTINGS_ROUTE);
this.context.trackEvent({
category: EVENT.CATEGORIES.NAVIGATION,
event: EVENT_NAMES.NAV_SETTINGS_OPENED,
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.NavSettingsOpened,
properties: {
location: 'Main Menu',
},

View File

@ -37,7 +37,7 @@ import { ADD_NETWORK_ROUTE } from '../../../helpers/constants/routes';
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
import ZENDESK_URLS from '../../../helpers/constants/zendesk-url';
import { Icon, ICON_NAMES, ICON_SIZES, Text } from '../../component-library';
import { EVENT } from '../../../../shared/constants/metametrics';
import { MetaMetricsNetworkEventSource } from '../../../../shared/constants/metametrics';
const AddNetwork = () => {
const t = useContext(I18nContext);
@ -267,7 +267,8 @@ const AddNetwork = () => {
imageUrl: item.rpcPrefs?.imageUrl,
chainName: item.nickname,
referrer: ORIGIN_METAMASK,
source: EVENT.SOURCE.NETWORK.POPULAR_NETWORK_LIST,
source:
MetaMetricsNetworkEventSource.PopularNetworkList,
},
}),
);

View File

@ -59,6 +59,7 @@
@import 'permissions-connect-footer/index';
@import 'permissions-connect-header/index';
@import 'permissions-connect-permission-list/index';
@import 'permission-cell/index';
@import 'recovery-phrase-reminder/index';
@import 'set-approval-for-all-warning/index';
@import 'step-progress-bar/index.scss';

View File

@ -4,7 +4,10 @@ import classnames from 'classnames';
import Identicon from '../../ui/identicon';
import MetaFoxLogo from '../../ui/metafox-logo';
import { DEFAULT_ROUTE } from '../../../helpers/constants/routes';
import { EVENT, EVENT_NAMES } from '../../../../shared/constants/metametrics';
import {
MetaMetricsEventCategory,
MetaMetricsEventName,
} from '../../../../shared/constants/metametrics';
import NetworkDisplay from '../network-display';
///: BEGIN:ONLY_INCLUDE_IN(beta)
@ -57,8 +60,8 @@ export default class AppHeader extends PureComponent {
if (networkDropdownOpen === false) {
this.context.trackEvent({
category: EVENT.CATEGORIES.NAVIGATION,
event: EVENT_NAMES.NAV_NETWORK_MENU_OPENED,
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.NavNetworkMenuOpened,
properties: {},
});
showNetworkDropdown();
@ -90,8 +93,8 @@ export default class AppHeader extends PureComponent {
if (!disabled) {
!isAccountMenuOpen &&
this.context.trackEvent({
category: EVENT.CATEGORIES.NAVIGATION,
event: EVENT_NAMES.NAV_MAIN_MENU_OPENED,
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.NavMainMenuOpened,
properties: {},
});
toggleAccountMenu();

View File

@ -13,7 +13,7 @@ import { startNewDraftTransaction } from '../../../ducks/send';
import { SEND_ROUTE } from '../../../helpers/constants/routes';
import { Color, SEVERITIES } from '../../../helpers/constants/design-system';
import { INVALID_ASSET_TYPE } from '../../../helpers/constants/error-keys';
import { EVENT } from '../../../../shared/constants/metametrics';
import { MetaMetricsEventCategory } from '../../../../shared/constants/metametrics';
import { AssetType } from '../../../../shared/constants/transaction';
import { MetaMetricsContext } from '../../../contexts/metametrics';
import { Icon, ICON_NAMES, ICON_SIZES } from '../../component-library';
@ -68,7 +68,7 @@ const AssetListItem = ({
e.stopPropagation();
trackEvent({
event: 'Clicked Send: Token',
category: EVENT.CATEGORIES.NAVIGATION,
category: MetaMetricsEventCategory.Navigation,
properties: {
action: 'Home',
legacy_event: true,

View File

@ -24,7 +24,10 @@ import {
} from '../../../helpers/constants/design-system';
import { useI18nContext } from '../../../hooks/useI18nContext';
import { MetaMetricsContext } from '../../../contexts/metametrics';
import { EVENT, EVENT_NAMES } from '../../../../shared/constants/metametrics';
import {
MetaMetricsEventCategory,
MetaMetricsEventName,
} from '../../../../shared/constants/metametrics';
import DetectedToken from '../detected-token/detected-token';
import {
DetectedTokensBanner,
@ -110,8 +113,8 @@ const AssetList = ({ onClickAsset }) => {
onTokenClick={(tokenAddress) => {
onClickAsset(tokenAddress);
trackEvent({
event: EVENT_NAMES.TOKEN_SCREEN_OPENED,
category: EVENT.CATEGORIES.NAVIGATION,
event: MetaMetricsEventName.TokenScreenOpened,
category: MetaMetricsEventCategory.Navigation,
properties: {
token_symbol: primaryCurrencyProperties.suffix,
location: 'Home',

View File

@ -9,8 +9,9 @@ import { useI18nContext } from '../../../../hooks/useI18nContext';
import { getDetectedTokensInCurrentNetwork } from '../../../../selectors';
import { MetaMetricsContext } from '../../../../contexts/metametrics';
import {
EVENT,
EVENT_NAMES,
MetaMetricsEventCategory,
MetaMetricsEventName,
MetaMetricsTokenEventSource,
} from '../../../../../shared/constants/metametrics';
const DetectedTokensLink = ({ className = '', setShowDetectedTokens }) => {
@ -25,10 +26,10 @@ const DetectedTokensLink = ({ className = '', setShowDetectedTokens }) => {
const onClick = () => {
setShowDetectedTokens(true);
trackEvent({
event: EVENT_NAMES.TOKEN_IMPORT_CLICKED,
category: EVENT.CATEGORIES.WALLET,
event: MetaMetricsEventName.TokenImportClicked,
category: MetaMetricsEventCategory.Wallet,
properties: {
source: EVENT.SOURCE.TOKEN.DETECTED,
source: MetaMetricsTokenEventSource.Detected,
tokens: detectedTokensDetails,
},
});

View File

@ -44,7 +44,10 @@ import {
} from '../../../selectors';
import useRamps from '../../../hooks/experiences/useRamps';
import { MetaMetricsContext } from '../../../contexts/metametrics';
import { EVENT, EVENT_NAMES } from '../../../../shared/constants/metametrics';
import {
MetaMetricsEventCategory,
MetaMetricsEventName,
} from '../../../../shared/constants/metametrics';
import {
ConfirmPageContainerHeader,
ConfirmPageContainerContent,
@ -250,8 +253,8 @@ const ConfirmPageContainer = (props) => {
onClick={() => {
openBuyCryptoInPdapp();
trackEvent({
event: EVENT_NAMES.NAV_BUY_BUTTON_CLICKED,
category: EVENT.CATEGORIES.NAVIGATION,
event: MetaMetricsEventName.NavBuyButtonClicked,
category: MetaMetricsEventCategory.Navigation,
properties: {
location: 'Transaction Confirmation',
text: 'Buy',

View File

@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import Preloader from '../../../ui/icon/preloader/preloader-icon.component';
import { Text } from '../../../component-library';
import {
@ -14,8 +15,12 @@ import {
import { useI18nContext } from '../../../../hooks/useI18nContext';
import { useTransactionInsightSnap } from '../../../../hooks/flask/useTransactionInsightSnap';
import Box from '../../../ui/box/box';
import ActionableMessage from '../../../ui/actionable-message/actionable-message';
import { SnapUIRenderer } from '../../flask/snap-ui-renderer';
import { SnapDelineator } from '../../flask/snap-delineator';
import { DelineatorType } from '../../../../helpers/constants/flask';
import { getSnapName } from '../../../../helpers/utils/util';
import { Copyable } from '../../flask/copyable';
import { getTargetSubjectMetadata } from '../../../../selectors';
export const SnapInsight = ({ transaction, origin, chainId, selectedSnap }) => {
const t = useI18nContext();
@ -30,6 +35,12 @@ export const SnapInsight = ({ transaction, origin, chainId, selectedSnap }) => {
snapId: selectedSnap.id,
});
const targetSubjectMetadata = useSelector((state) =>
getTargetSubjectMetadata(state, selectedSnap.id),
);
const snapName = getSnapName(selectedSnap.id, targetSubjectMetadata);
const data = response?.content;
const hasNoData =
@ -52,7 +63,11 @@ export const SnapInsight = ({ transaction, origin, chainId, selectedSnap }) => {
className="snap-insight__container"
>
{data && Object.keys(data).length > 0 ? (
<SnapUIRenderer snapId={selectedSnap.id} data={data} />
<SnapUIRenderer
snapId={selectedSnap.id}
data={data}
delineatorType={DelineatorType.Insights}
/>
) : (
<Text
color={TextColor.textAlternative}
@ -66,22 +81,13 @@ export const SnapInsight = ({ transaction, origin, chainId, selectedSnap }) => {
)}
{!loading && error && (
<Box
paddingTop={0}
paddingRight={6}
paddingBottom={3}
paddingLeft={6}
className="snap-insight__container__error"
>
<ActionableMessage
message={t('snapsInsightError', [
selectedSnap.manifest.proposedName,
error.message,
])}
type="danger"
useIcon
iconFillColor="var(--color-error-default)"
/>
<Box padding={4} className="snap-insight__container__error">
<SnapDelineator snapName={snapName} type={DelineatorType.Error}>
<Text variant={TextVariant.bodySm} marginBottom={4}>
{t('snapsUIError', [<b key="0">{snapName}</b>])}
</Text>
<Copyable text={error.message} />
</SnapDelineator>
</Box>
)}

View File

@ -20,7 +20,7 @@ import {
} from '../../../store/actions';
import { SECOND } from '../../../../shared/constants/time';
import { MetaMetricsContext } from '../../../contexts/metametrics';
import { EVENT } from '../../../../shared/constants/metametrics';
import { MetaMetricsEventCategory } from '../../../../shared/constants/metametrics';
const DESKTOP_ERROR_DESKTOP_OUTDATED_ROUTE = `${DESKTOP_ERROR_ROUTE}/${EXTENSION_ERROR_PAGE_TYPES.DESKTOP_OUTDATED}`;
const DESKTOP_ERROR_EXTENSION_OUTDATED_ROUTE = `${DESKTOP_ERROR_ROUTE}/${EXTENSION_ERROR_PAGE_TYPES.EXTENSION_OUTDATED}`;
@ -45,7 +45,7 @@ export default function DesktopEnableButton() {
await disableDesktop();
setDesktopEnabled(false);
trackEvent({
category: EVENT.CATEGORIES.DESKTOP,
category: MetaMetricsEventCategory.Desktop,
event: DESKTOP_UPDATE_SETTINGS_EVENT,
properties: {
desktop_enabled: false,
@ -90,7 +90,7 @@ export default function DesktopEnableButton() {
}
trackEvent({
category: EVENT.CATEGORIES.DESKTOP,
category: MetaMetricsEventCategory.Desktop,
event: 'Desktop Button Clicked',
properties: {
button_action: 'Enable MetaMask Desktop',

View File

@ -5,8 +5,9 @@ import { useSelector } from 'react-redux';
import { useI18nContext } from '../../../../hooks/useI18nContext';
import { MetaMetricsContext } from '../../../../contexts/metametrics';
import {
EVENT,
EVENT_NAMES,
MetaMetricsEventCategory,
MetaMetricsEventName,
MetaMetricsTokenEventSource,
} from '../../../../../shared/constants/metametrics';
import { getDetectedTokensInCurrentNetwork } from '../../../../selectors';
@ -40,10 +41,10 @@ const DetectedTokenSelectionPopover = ({
({ address, symbol }) => `${symbol} - ${address}`,
);
trackEvent({
event: EVENT_NAMES.TOKEN_IMPORT_CANCELED,
category: EVENT.CATEGORIES.WALLET,
event: MetaMetricsEventName.TokenImportCanceled,
category: MetaMetricsEventCategory.Wallet,
properties: {
source: EVENT.SOURCE.TOKEN.DETECTED,
source: MetaMetricsTokenEventSource.Detected,
tokens: eventTokensDetails,
},
});
@ -62,6 +63,7 @@ const DetectedTokenSelectionPopover = ({
className="detected-token-selection-popover__import-button"
type="primary"
onClick={onImport}
disabled={selectedTokens.length === 0}
>
{t('importWithCount', [numOfTokensImporting])}
</Button>

View File

@ -15,7 +15,12 @@ import {
AssetType,
TokenStandard,
} from '../../../../shared/constants/transaction';
import { EVENT, EVENT_NAMES } from '../../../../shared/constants/metametrics';
import {
MetaMetricsEventCategory,
MetaMetricsEventLocation,
MetaMetricsEventName,
MetaMetricsTokenEventSource,
} from '../../../../shared/constants/metametrics';
import DetectedTokenSelectionPopover from './detected-token-selection-popover/detected-token-selection-popover';
import DetectedTokenIgnoredPopover from './detected-token-ignored-popover/detected-token-ignored-popover';
@ -58,13 +63,13 @@ const DetectedToken = ({ setShowDetectedTokens }) => {
const importSelectedTokens = async (selectedTokens) => {
selectedTokens.forEach((importedToken) => {
trackEvent({
event: EVENT_NAMES.TOKEN_ADDED,
category: EVENT.CATEGORIES.WALLET,
event: MetaMetricsEventName.TokenAdded,
category: MetaMetricsEventCategory.Wallet,
sensitiveProperties: {
token_symbol: importedToken.symbol,
token_contract_address: importedToken.address,
token_decimal_precision: importedToken.decimals,
source: EVENT.SOURCE.TOKEN.DETECTED,
source: MetaMetricsTokenEventSource.Detected,
token_standard: TokenStandard.ERC20,
asset_type: AssetType.token,
},
@ -86,11 +91,11 @@ const DetectedToken = ({ setShowDetectedTokens }) => {
({ symbol, address }) => `${symbol} - ${address}`,
);
trackEvent({
event: EVENT_NAMES.TOKEN_HIDDEN,
category: EVENT.CATEGORIES.WALLET,
event: MetaMetricsEventName.TokenHidden,
category: MetaMetricsEventCategory.Wallet,
sensitiveProperties: {
tokens: tokensDetailsList,
location: EVENT.LOCATION.TOKEN_DETECTION,
location: MetaMetricsEventLocation.TokenDetection,
token_standard: TokenStandard.ERC20,
asset_type: AssetType.token,
},

View File

@ -23,7 +23,11 @@ import { IconColor, Size } from '../../../helpers/constants/design-system';
import { getShowTestNetworks } from '../../../selectors';
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app';
import { EVENT, EVENT_NAMES } from '../../../../shared/constants/metametrics';
import {
MetaMetricsEventCategory,
MetaMetricsEventName,
MetaMetricsNetworkEventSource,
} from '../../../../shared/constants/metametrics';
import {
ADD_POPULAR_CUSTOM_NETWORK,
ADVANCED_ROUTE,
@ -127,8 +131,8 @@ class NetworkDropdown extends Component {
const { trackEvent } = this.context;
trackEvent({
category: EVENT.CATEGORIES.NAVIGATION,
event: EVENT_NAMES.NAV_NETWORK_SWITCHED,
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.NavNetworkSwitched,
properties: {
from_network: providerType,
to_network: newProviderType,
@ -305,7 +309,7 @@ class NetworkDropdown extends Component {
},
{
setActive: true,
source: EVENT.SOURCE.NETWORK.CUSTOM_NETWORK_FORM,
source: MetaMetricsNetworkEventSource.CustomNetworkForm,
},
);
}

View File

@ -14,6 +14,7 @@ import {
AlignItems,
DISPLAY,
BorderRadius,
BLOCK_SIZES,
} from '../../../../helpers/constants/design-system';
import {
getSnapName,
@ -59,7 +60,7 @@ const SnapAuthorship = ({ snapId, className }) => {
paddingRight={4}
borderRadius={BorderRadius.pill}
display={DISPLAY.FLEX}
style={{ maxWidth: 'fit-content', width: '100%' }}
width={BLOCK_SIZES.FULL}
>
<Box>
<SnapAvatar snapId={snapId} />
@ -87,6 +88,7 @@ const SnapAuthorship = ({ snapId, className }) => {
iconName={ICON_NAMES.EXPORT}
color={IconColor.infoDefault}
size={ICON_SIZES.MD}
style={{ marginLeft: 'auto' }}
/>
</Box>
);

View File

@ -1,7 +1,7 @@
.snap-delineator {
&__header {
border-bottom-width: 1px;
border-color: var(--color-border-muted);
border-color: var(--color-border-default);
border-style: solid;
border-radius: 8px 8px 0 0;

View File

@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
import { useI18nContext } from '../../../../hooks/useI18nContext';
import {
BorderStyle,
Size,
BorderColor,
BorderRadius,
AlignItems,
@ -13,37 +12,60 @@ import {
TextColor,
} from '../../../../helpers/constants/design-system';
import Box from '../../../ui/box';
import { Icon, Text } from '../../../component-library';
import {
AvatarIcon,
ICON_NAMES,
ICON_SIZES,
Text,
} from '../../../component-library';
import {
DelineatorType,
getDelineatorTitle,
} from '../../../../helpers/constants/flask';
export const SnapDelineator = ({ snapName, children }) => {
export const SnapDelineator = ({
snapName,
type = DelineatorType.default,
children,
}) => {
const t = useI18nContext();
const isError = type === DelineatorType.Error;
return (
<Box
className="snap-delineator__wrapper"
borderStyle={BorderStyle.solid}
borderColor={BorderColor.borderMuted}
borderColor={BorderColor.borderDefault}
borderRadius={BorderRadius.LG}
backgroundColor={
isError ? BackgroundColor.errorMuted : BackgroundColor.backgroundDefault
}
>
<Box
className="snap-delineator__header"
alignItems={AlignItems.center}
backgroundColor={BackgroundColor.infoMuted}
paddingLeft={2}
paddingRight={2}
paddingTop={1}
paddingBottom={1}
padding={1}
>
<Icon name="snaps" color={IconColor.infoDefault} size={Size.SM} />
<AvatarIcon
iconName={ICON_NAMES.SNAPS}
size={ICON_SIZES.XS}
backgroundColor={
isError ? IconColor.errorDefault : IconColor.infoDefault
}
margin={1}
iconProps={{
size: ICON_SIZES.XS,
color: IconColor.infoInverse,
}}
/>
<Text
variant={TextVariant.bodySm}
color={TextColor.infoDefault}
color={isError ? TextColor.errorDefault : TextColor.default}
className="snap-delineator__header__text"
marginLeft={1}
marginTop={0}
marginBottom={0}
>
{t('contentFromSnap', [snapName])}
{t(getDelineatorTitle(type), [snapName])}
</Text>
</Box>
<Box className="snap-delineator__content" padding={4}>
@ -55,5 +77,6 @@ export const SnapDelineator = ({ snapName, children }) => {
SnapDelineator.propTypes = {
snapName: PropTypes.string,
type: PropTypes.string,
children: PropTypes.ReactNode,
};

View File

@ -6,5 +6,5 @@ export default {
};
export const DefaultStory = () => (
<SnapDelineator snapId="foo">Children</SnapDelineator>
<SnapDelineator snapName="foo">Children</SnapDelineator>
);

View File

@ -0,0 +1,35 @@
import React from 'react';
import { DelineatorType } from '../../../../helpers/constants/flask';
import { renderWithLocalization } from '../../../../../test/lib/render-helpers';
import { SnapDelineator } from './snap-delineator';
describe('SnapDelineator', () => {
const args = {
snapName: 'Test Snap',
type: DelineatorType.Content,
children: 'This is some test content',
};
it('should render the SnapDelineator with content inside', () => {
const { getByText } = renderWithLocalization(<SnapDelineator {...args} />);
expect(getByText(/Content from Test Snap/u)).toBeDefined();
expect(getByText(args.children)).toBeDefined();
});
it('should render an insight title', () => {
args.type = DelineatorType.Insights;
const { getByText } = renderWithLocalization(<SnapDelineator {...args} />);
expect(getByText(/Insights from Test Snap/u)).toBeDefined();
});
it('should render an error title', () => {
args.type = DelineatorType.Error;
const { getByText } = renderWithLocalization(<SnapDelineator {...args} />);
expect(getByText(/Error with Test Snap/u)).toBeDefined();
});
});

View File

@ -1,8 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import nanoid from 'nanoid';
import { isComponent } from '@metamask/snaps-ui';
import { useSelector } from 'react-redux';
import MetaMaskTemplateRenderer from '../../metamask-template-renderer/metamask-template-renderer';
import {
TypographyVariant,
@ -10,12 +10,16 @@ import {
DISPLAY,
FLEX_DIRECTION,
OVERFLOW_WRAP,
TextVariant,
} from '../../../../helpers/constants/design-system';
import { SnapDelineator } from '../snap-delineator';
import { useI18nContext } from '../../../../hooks/useI18nContext';
import ActionableMessage from '../../../ui/actionable-message/actionable-message';
import Box from '../../../ui/box';
import { getSnap } from '../../../../selectors';
import { getSnapName } from '../../../../helpers/utils/util';
import { getTargetSubjectMetadata } from '../../../../selectors';
import { Text } from '../../../component-library';
import { Copyable } from '../copyable';
import { DelineatorType } from '../../../../helpers/constants/flask';
export const UI_MAPPING = {
panel: (props) => ({
@ -70,22 +74,25 @@ export const mapToTemplate = (data) => {
};
// Component that maps Snaps UI JSON format to MetaMask Template Renderer format
export const SnapUIRenderer = ({ snapId, data }) => {
export const SnapUIRenderer = ({
snapId,
delineatorType = DelineatorType.Content,
data,
}) => {
const t = useI18nContext();
const snap = useSelector((state) => getSnap(state, snapId));
const targetSubjectMetadata = useSelector((state) =>
getTargetSubjectMetadata(state, snapId),
);
const snapName = snap.manifest.proposedName;
const snapName = getSnapName(snapId, targetSubjectMetadata);
if (!isComponent(data)) {
return (
<SnapDelineator snapName={snapName}>
<ActionableMessage
className="snap-ui-renderer__error"
message={t('snapsUIError')}
type="danger"
useIcon
iconFillColor="var(--color-error-default)"
/>
<SnapDelineator snapName={snapName} type={DelineatorType.Error}>
<Text variant={TextVariant.bodySm} marginBottom={4}>
{t('snapsUIError', [<b key="0">{snapName}</b>])}
</Text>
<Copyable text={t('snapsInvalidUIError')} />
</SnapDelineator>
);
}
@ -93,7 +100,7 @@ export const SnapUIRenderer = ({ snapId, data }) => {
const sections = mapToTemplate(data);
return (
<SnapDelineator snapName={snapName}>
<SnapDelineator snapName={snapName} type={delineatorType}>
<Box className="snap-ui-renderer__content">
<MetaMaskTemplateRenderer sections={sections} />
</Box>
@ -103,5 +110,6 @@ export const SnapUIRenderer = ({ snapId, data }) => {
SnapUIRenderer.propTypes = {
snapId: PropTypes.string,
delineatorType: PropTypes.string,
data: PropTypes.object,
};

View File

@ -1,14 +1,9 @@
import React from 'react';
import PropTypes from 'prop-types';
import { isFunction } from 'lodash';
import {
getRightIcon,
getWeightedPermissions,
} from '../../../../helpers/utils/permission';
import { getWeightedPermissions } from '../../../../helpers/utils/permission';
import { useI18nContext } from '../../../../hooks/useI18nContext';
import { formatDate } from '../../../../helpers/utils/util';
import Typography from '../../../ui/typography/typography';
import { TextColor } from '../../../../helpers/constants/design-system';
import PermissionCell from '../../permission-cell';
import Box from '../../../ui/box';
export default function UpdateSnapPermissionList({
approvedPermissions,
@ -17,52 +12,50 @@ export default function UpdateSnapPermissionList({
}) {
const t = useI18nContext();
const Permissions = ({ className, permissions, subText }) => {
return getWeightedPermissions(t, permissions).map((permission) => {
const { label, permissionName, permissionValue } = permission;
return (
<div className={className} key={permissionName}>
<i className="fas fa-x" />
<div className="permission-description">
{label}
<Typography
color={TextColor.textAlternative}
boxProps={{ paddingTop: 1 }}
className="permission-description-subtext"
>
{isFunction(subText)
? subText(permissionName, permissionValue)
: subText}
</Typography>
</div>
{getRightIcon(permission)}
</div>
);
});
};
return (
<div className="update-snap-permission-list">
<Permissions
className="new-permission"
permissions={newPermissions}
subText={t('permissionRequested')}
/>
<Permissions
className="approved-permission"
permissions={approvedPermissions}
subText={(_, permissionValue) => {
const { date } = permissionValue;
const formattedDate = formatDate(date, 'yyyy-MM-dd');
return t('approvedOn', [formattedDate]);
}}
/>
<Permissions
className="revoked-permission"
permissions={revokedPermissions}
subText={t('permissionRevoked')}
/>
</div>
<Box paddingTop={1}>
{getWeightedPermissions(t, newPermissions).map((permission, index) => {
return (
<PermissionCell
title={permission.label}
description={permission.description}
weight={permission.weight}
avatarIcon={permission.leftIcon}
dateApproved={permission?.permissionValue?.date}
key={`${permission.permissionName}-${index}`}
/>
);
})}
{getWeightedPermissions(t, approvedPermissions).map(
(permission, index) => {
return (
<PermissionCell
title={permission.label}
description={permission.description}
weight={permission.weight}
avatarIcon={permission.leftIcon}
dateApproved={permission?.permissionValue?.date}
key={`${permission.permissionName}-${index}`}
/>
);
},
)}
{getWeightedPermissions(t, revokedPermissions).map(
(permission, index) => {
return (
<PermissionCell
title={permission.label}
description={permission.description}
weight={permission.weight}
avatarIcon={permission.leftIcon}
dateApproved={permission?.permissionValue?.date}
key={`${permission.permissionName}-${index}`}
revoked
/>
);
},
)}
</Box>
);
}

View File

@ -8,7 +8,10 @@ import Box from '../../ui/box/box';
import { TEXT_ALIGN } from '../../../helpers/constants/design-system';
import { detectNewTokens } from '../../../store/actions';
import { MetaMetricsContext } from '../../../contexts/metametrics';
import { EVENT, EVENT_NAMES } from '../../../../shared/constants/metametrics';
import {
MetaMetricsEventCategory,
MetaMetricsEventName,
} from '../../../../shared/constants/metametrics';
import {
getIsTokenDetectionSupported,
getIsTokenDetectionInactiveOnMainnet,
@ -51,8 +54,8 @@ export default function ImportTokenLink() {
onClick={() => {
history.push(IMPORT_TOKEN_ROUTE);
trackEvent({
event: EVENT_NAMES.TOKEN_IMPORT_BUTTON_CLICKED,
category: EVENT.CATEGORIES.NAVIGATION,
event: MetaMetricsEventName.TokenImportButtonClicked,
category: MetaMetricsEventCategory.Navigation,
properties: {
location: 'Home',
},

View File

@ -22,7 +22,11 @@ import { useI18nContext } from '../../../hooks/useI18nContext';
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../shared/constants/app';
import { KeyringType } from '../../../../shared/constants/keyring';
import { EVENT, EVENT_NAMES } from '../../../../shared/constants/metametrics';
import {
MetaMetricsEventCategory,
MetaMetricsEventLinkType,
MetaMetricsEventName,
} from '../../../../shared/constants/metametrics';
import { MetaMetricsContext } from '../../../contexts/metametrics';
import { ICON_NAMES } from '../../component-library';
@ -50,10 +54,10 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) {
const openBlockExplorer = () => {
trackEvent({
event: EVENT_NAMES.EXTERNAL_LINK_CLICKED,
category: EVENT.CATEGORIES.NAVIGATION,
event: MetaMetricsEventName.ExternalLinkClicked,
category: MetaMetricsEventCategory.Navigation,
properties: {
link_type: EVENT.EXTERNAL_LINK_TYPES.ACCOUNT_TRACKER,
link_type: MetaMetricsEventLinkType.AccountTracker,
location: 'Account Options',
url_domain: getURLHostName(addressLink),
},
@ -96,8 +100,8 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) {
<MenuItem
onClick={() => {
trackEvent({
event: EVENT_NAMES.APP_WINDOW_EXPANDED,
category: EVENT.CATEGORIES.NAVIGATION,
event: MetaMetricsEventName.AppWindowExpanded,
category: MetaMetricsEventCategory.Navigation,
properties: {
location: 'Account Options',
},
@ -115,8 +119,8 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) {
onClick={() => {
dispatch(showModal({ name: 'ACCOUNT_DETAILS' }));
trackEvent({
event: EVENT_NAMES.NAV_ACCOUNT_DETAILS_OPENED,
category: EVENT.CATEGORIES.NAVIGATION,
event: MetaMetricsEventName.NavAccountDetailsOpened,
category: MetaMetricsEventCategory.Navigation,
properties: {
location: 'Account Options',
},
@ -131,8 +135,8 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) {
data-testid="account-options-menu__connected-sites"
onClick={() => {
trackEvent({
event: EVENT_NAMES.NAV_CONNECTED_SITES_OPENED,
category: EVENT.CATEGORIES.NAVIGATION,
event: MetaMetricsEventName.NavConnectedSitesOpened,
category: MetaMetricsEventCategory.Navigation,
properties: {
location: 'Account Options',
},

View File

@ -6,7 +6,10 @@ import SelectedAccount from '../selected-account';
import ConnectedStatusIndicator from '../connected-status-indicator';
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app';
import { EVENT, EVENT_NAMES } from '../../../../shared/constants/metametrics';
import {
MetaMetricsEventCategory,
MetaMetricsEventName,
} from '../../../../shared/constants/metametrics';
import { CONNECTED_ACCOUNTS_ROUTE } from '../../../helpers/constants/routes';
import { useI18nContext } from '../../../hooks/useI18nContext';
import { getOriginOfCurrentTab } from '../../../selectors';
@ -44,8 +47,8 @@ export default function MenuBar() {
ariaLabel={t('accountOptions')}
onClick={() => {
trackEvent({
event: EVENT_NAMES.NAV_ACCOUNT_MENU_OPENED,
category: EVENT.CATEGORIES.NAVIGATION,
event: MetaMetricsEventName.NavAccountMenuOpened,
category: MetaMetricsEventCategory.Navigation,
properties: {
location: 'Home',
},

View File

@ -9,8 +9,10 @@ import Button from '../../../ui/button';
import { getURLHostName } from '../../../../helpers/utils/util';
import { isHardwareKeyring } from '../../../../helpers/utils/hardware';
import {
EVENT,
EVENT_NAMES,
MetaMetricsEventCategory,
MetaMetricsEventLinkType,
MetaMetricsEventKeyType,
MetaMetricsEventName,
} from '../../../../../shared/constants/metametrics';
import { NETWORKS_ROUTE } from '../../../../helpers/constants/routes';
@ -65,10 +67,10 @@ export default class AccountDetailsModal extends Component {
const openBlockExplorer = () => {
const accountLink = getAccountLink(address, chainId, rpcPrefs);
this.context.trackEvent({
category: EVENT.CATEGORIES.NAVIGATION,
event: EVENT_NAMES.EXTERNAL_LINK_CLICKED,
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.ExternalLinkClicked,
properties: {
link_type: EVENT.EXTERNAL_LINK_TYPES.ACCOUNT_TRACKER,
link_type: MetaMetricsEventLinkType.AccountTracker,
location: 'Account Details Modal',
url_domain: getURLHostName(accountLink),
},
@ -115,10 +117,10 @@ export default class AccountDetailsModal extends Component {
className="account-details-modal__button"
onClick={() => {
this.context.trackEvent({
category: EVENT.CATEGORIES.ACCOUNTS,
event: EVENT_NAMES.KEY_EXPORT_SELECTED,
category: MetaMetricsEventCategory.Accounts,
event: MetaMetricsEventName.KeyExportSelected,
properties: {
key_type: EVENT.KEY_TYPES.PKEY,
key_type: MetaMetricsEventKeyType.Pkey,
location: 'Account Details Modal',
},
});

View File

@ -4,7 +4,7 @@ import { getAccountLink } from '@metamask/etherscan-link';
import Modal from '../../modal';
import { addressSummary, getURLHostName } from '../../../../helpers/utils/util';
import Identicon from '../../../ui/identicon';
import { EVENT } from '../../../../../shared/constants/metametrics';
import { MetaMetricsEventCategory } from '../../../../../shared/constants/metametrics';
import ZENDESK_URLS from '../../../../helpers/constants/zendesk-url';
export default class ConfirmRemoveAccount extends Component {
@ -62,7 +62,7 @@ export default class ConfirmRemoveAccount extends Component {
rpcPrefs,
);
this.context.trackEvent({
category: EVENT.CATEGORIES.ACCOUNTS,
category: MetaMetricsEventCategory.Accounts,
event: 'Clicked Block Explorer Link',
properties: {
link_type: 'Account Tracker',

View File

@ -10,8 +10,9 @@ import {
stripHexPrefix,
} from '../../../../../shared/modules/hexstring-utils';
import {
EVENT,
EVENT_NAMES,
MetaMetricsEventCategory,
MetaMetricsEventKeyType,
MetaMetricsEventName,
} from '../../../../../shared/constants/metametrics';
export default class ExportPrivateKeyModal extends Component {
@ -53,10 +54,10 @@ export default class ExportPrivateKeyModal extends Component {
exportAccount(password, address)
.then((privateKey) => {
this.context.trackEvent({
category: EVENT.CATEGORIES.KEYS,
event: EVENT_NAMES.KEY_EXPORT_REVEALED,
category: MetaMetricsEventCategory.Keys,
event: MetaMetricsEventName.KeyExportRevealed,
properties: {
key_type: EVENT.KEY_TYPES.PKEY,
key_type: MetaMetricsEventKeyType.Pkey,
},
});
@ -67,10 +68,10 @@ export default class ExportPrivateKeyModal extends Component {
})
.catch((e) => {
this.context.trackEvent({
category: EVENT.CATEGORIES.KEYS,
event: EVENT_NAMES.KEY_EXPORT_FAILED,
category: MetaMetricsEventCategory.Keys,
event: MetaMetricsEventName.KeyExportFailed,
properties: {
key_type: EVENT.KEY_TYPES.PKEY,
key_type: MetaMetricsEventKeyType.Pkey,
reason: 'incorrect_password',
},
});
@ -108,10 +109,10 @@ export default class ExportPrivateKeyModal extends Component {
onClick={() => {
copyToClipboard(plainKey);
this.context.trackEvent({
category: EVENT.CATEGORIES.KEYS,
event: EVENT_NAMES.KEY_EXPORT_COPIED,
category: MetaMetricsEventCategory.Keys,
event: MetaMetricsEventName.KeyExportCopied,
properties: {
key_type: EVENT.KEY_TYPES.PKEY,
key_type: MetaMetricsEventKeyType.Pkey,
copy_method: 'clipboard',
},
});
@ -132,10 +133,10 @@ export default class ExportPrivateKeyModal extends Component {
className="export-private-key-modal__button export-private-key-modal__button--cancel"
onClick={() => {
this.context.trackEvent({
category: EVENT.CATEGORIES.KEYS,
event: EVENT_NAMES.KEY_EXPORT_CANCELED,
category: MetaMetricsEventCategory.Keys,
event: MetaMetricsEventName.KeyExportCanceled,
properties: {
key_type: EVENT.KEY_TYPES.PKEY,
key_type: MetaMetricsEventKeyType.Pkey,
},
});
hideModal();
@ -159,10 +160,10 @@ export default class ExportPrivateKeyModal extends Component {
<Button
onClick={() => {
this.context.trackEvent({
category: EVENT.CATEGORIES.KEYS,
event: EVENT_NAMES.KEY_EXPORT_REQUESTED,
category: MetaMetricsEventCategory.Keys,
event: MetaMetricsEventName.KeyExportRequested,
properties: {
key_type: EVENT.KEY_TYPES.PKEY,
key_type: MetaMetricsEventKeyType.Pkey,
},
});

View File

@ -0,0 +1 @@
export { default } from './permission-cell';

View File

@ -0,0 +1,5 @@
.permission-cell {
&__title-revoked {
text-decoration: line-through;
}
}

View File

@ -0,0 +1,126 @@
import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import Box from '../../ui/box';
import {
AlignItems,
Color,
IconColor,
JustifyContent,
Size,
TextColor,
TextVariant,
} from '../../../helpers/constants/design-system';
import {
AvatarIcon,
Icon,
ICON_NAMES,
ICON_SIZES,
Text,
} from '../../component-library';
import { formatDate } from '../../../helpers/utils/util';
import { useI18nContext } from '../../../hooks/useI18nContext';
import Tooltip from '../../ui/tooltip';
const PermissionCell = ({
title,
description,
weight,
avatarIcon,
dateApproved,
revoked,
}) => {
const t = useI18nContext();
let infoIconColor = IconColor.iconMuted;
let infoIcon = ICON_NAMES.INFO;
let iconColor = Color.primaryDefault;
let iconBackgroundColor = Color.primaryMuted;
if (!revoked && weight === 1) {
iconColor = Color.warningDefault;
iconBackgroundColor = Color.warningMuted;
infoIconColor = IconColor.warningDefault;
infoIcon = ICON_NAMES.DANGER;
}
if (dateApproved) {
iconColor = Color.iconMuted;
iconBackgroundColor = Color.backgroundAlternative;
}
if (revoked) {
iconColor = Color.iconMuted;
iconBackgroundColor = Color.backgroundAlternative;
}
return (
<Box
className="permission-cell"
justifyContent={JustifyContent.center}
alignItems={AlignItems.flexStart}
marginLeft={4}
marginRight={4}
paddingTop={2}
paddingBottom={2}
>
<Box>
{typeof avatarIcon === 'string' ? (
<AvatarIcon
iconName={avatarIcon}
size={ICON_SIZES.MD}
iconProps={{
size: ICON_SIZES.SM,
}}
color={iconColor}
backgroundColor={iconBackgroundColor}
/>
) : (
avatarIcon
)}
</Box>
<Box width="full" marginLeft={4} marginRight={4}>
<Text
size={Size.MD}
variant={TextVariant.bodyMd}
className={classnames('permission-cell__title', {
'permission-cell__title-revoked': revoked,
})}
>
{title}
</Text>
<Text
size={Size.XS}
className="permission-cell__status"
variant={TextVariant.bodyXs}
color={TextColor.textAlternative}
>
{!revoked &&
(dateApproved
? t('approvedOn', [formatDate(dateApproved, 'yyyy-MM-dd')])
: t('permissionRequested'))}
{revoked ? t('permissionRevoked') : ''}
</Text>
</Box>
<Box>
<Tooltip html={<div>{description}</div>} position="bottom">
<Icon color={infoIconColor} name={infoIcon} size={ICON_SIZES.SM} />
</Tooltip>
</Box>
</Box>
);
};
PermissionCell.propTypes = {
title: PropTypes.oneOfType([
PropTypes.string.isRequired,
PropTypes.object.isRequired,
]),
description: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
weight: PropTypes.number,
avatarIcon: PropTypes.any.isRequired,
dateApproved: PropTypes.number,
revoked: PropTypes.bool,
};
export default PermissionCell;

View File

@ -0,0 +1,22 @@
import React from 'react';
import PermissionCell from '.';
export default {
title: 'Components/App/PermissionCell',
component: PermissionCell,
};
export const DefaultStory = (args) => <PermissionCell {...args} />;
DefaultStory.storyName = 'Default';
DefaultStory.args = {
title: 'Access the Ethereum provider.',
description:
'Allow the snap to communicate with MetaMask direct…blockchain and suggest messages and transactions.',
weight: 1,
avatarIcon: 'ethereum',
dateApproved: 1680185432326,
revoked: false,
};

View File

@ -0,0 +1,69 @@
import React from 'react';
import { screen } from '@testing-library/react';
import { renderWithProvider } from '../../../../test/jest';
import PermissionCell from './permission-cell';
describe('Permission Cell', () => {
const mockPermissionData = {
label: 'Access the Ethereum provider.',
description:
'Allow the snap to communicate with MetaMask direct…blockchain and suggest messages and transactions.',
weight: 1,
leftIcon: 'ethereum',
permissionValue: {
date: 1680185432326,
},
permissionName: 'ethereum-provider',
};
it('renders approved permission cell', () => {
renderWithProvider(
<PermissionCell
title={mockPermissionData.label}
description={mockPermissionData.description}
weight={mockPermissionData.weight}
avatarIcon={mockPermissionData.leftIcon}
dateApproved={mockPermissionData?.permissionValue?.date}
key={`${mockPermissionData.permissionName}-${1}`}
/>,
);
expect(
screen.getByText('Access the Ethereum provider.'),
).toBeInTheDocument();
expect(screen.getByText('Approved on 2023-03-30')).toBeInTheDocument();
});
it('renders revoked permission cell', () => {
renderWithProvider(
<PermissionCell
title={mockPermissionData.label}
description={mockPermissionData.description}
weight={mockPermissionData.weight}
avatarIcon={mockPermissionData.leftIcon}
dateApproved={mockPermissionData?.permissionValue?.date}
key={`${mockPermissionData.permissionName}-${1}`}
revoked
/>,
);
expect(
screen.getByText('Access the Ethereum provider.'),
).toBeInTheDocument();
expect(screen.getByText('Revoked in this update')).toBeInTheDocument();
});
it('renders requested permission cell', () => {
renderWithProvider(
<PermissionCell
title={mockPermissionData.label}
description={mockPermissionData.description}
weight={mockPermissionData.weight}
avatarIcon={mockPermissionData.leftIcon}
key={`${mockPermissionData.permissionName}-${1}`}
/>,
);
expect(
screen.getByText('Access the Ethereum provider.'),
).toBeInTheDocument();
expect(screen.getByText('Requested now')).toBeInTheDocument();
});
});

View File

@ -8,7 +8,7 @@ import {
WALLET_SNAP_PERMISSION_KEY,
} from '@metamask/rpc-methods';
///: END:ONLY_INCLUDE_IN
import { EVENT } from '../../../../shared/constants/metametrics';
import { MetaMetricsEventCategory } from '../../../../shared/constants/metametrics';
import { PageContainerFooter } from '../../ui/page-container';
import PermissionsConnectFooter from '../permissions-connect-footer';
///: BEGIN:ONLY_INCLUDE_IN(flask)
@ -116,7 +116,7 @@ export default class PermissionPageContainer extends Component {
componentDidMount() {
this.context.trackEvent({
category: EVENT.CATEGORIES.AUTH,
category: MetaMetricsEventCategory.Auth,
event: 'Tab Opened',
properties: {
action: 'Connect',

View File

@ -1,37 +1,28 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
getRightIcon,
getWeightedPermissions,
} from '../../../helpers/utils/permission';
import { getWeightedPermissions } from '../../../helpers/utils/permission';
import { useI18nContext } from '../../../hooks/useI18nContext';
/**
* Get one or more permission descriptions for a permission name.
*
* @param permission - The permission to render.
* @param index - The index of the permission.
* @returns {JSX.Element} A permission description node.
*/
function getDescriptionNode(permission, index) {
const { label, leftIcon, permissionName } = permission;
return (
<div className="permission" key={`${permissionName}-${index}`}>
{typeof leftIcon === 'string' ? <i className={leftIcon} /> : leftIcon}
{label}
{getRightIcon(permission)}
</div>
);
}
import PermissionCell from '../permission-cell';
import Box from '../../ui/box';
export default function PermissionsConnectPermissionList({ permissions }) {
const t = useI18nContext();
return (
<div className="permissions-connect-permission-list">
{getWeightedPermissions(t, permissions).map(getDescriptionNode)}
</div>
<Box paddingTop={2} paddingBottom={2}>
{getWeightedPermissions(t, permissions).map((permission, index) => {
return (
<PermissionCell
title={permission.label}
description={permission.description}
weight={permission.weight}
avatarIcon={permission.leftIcon}
dateApproved={permission?.permissionValue?.date}
key={`${permission.permissionName}-${index}`}
/>
);
})}
</Box>
);
}

View File

@ -3,7 +3,7 @@ import { memoize } from 'lodash';
import PropTypes from 'prop-types';
// import LedgerInstructionField from '../ledger-instruction-field';
import { sanitizeMessage, getURLHostName } from '../../../helpers/utils/util';
import { EVENT } from '../../../../shared/constants/metametrics';
import { MetaMetricsEventCategory } from '../../../../shared/constants/metametrics';
import SiteOrigin from '../../ui/site-origin';
import Button from '../../ui/button';
import Typography from '../../ui/typography/typography';
@ -196,7 +196,7 @@ export default class SignatureRequest extends PureComponent {
const onSign = (event) => {
sign(event);
trackEvent({
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
event: 'Confirm',
properties: {
action: 'Sign Request',
@ -210,7 +210,7 @@ export default class SignatureRequest extends PureComponent {
const onCancel = (event) => {
cancel(event);
trackEvent({
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
event: 'Cancel',
properties: {
action: 'Sign Request',

View File

@ -4,7 +4,7 @@ import classnames from 'classnames';
import { getBlockExplorerLink } from '@metamask/etherscan-link';
import { formatDate, getURLHostName } from '../../../helpers/utils/util';
import { EVENT } from '../../../../shared/constants/metametrics';
import { MetaMetricsEventCategory } from '../../../../shared/constants/metametrics';
import { getValueFromWeiHex } from '../../../../shared/modules/conversion.utils';
import TransactionActivityLogIcon from './transaction-activity-log-icon';
import { CONFIRMED_STATUS } from './transaction-activity-log.constants';
@ -34,7 +34,7 @@ export default class TransactionActivityLog extends PureComponent {
const etherscanUrl = getBlockExplorerLink(activity, rpcPrefs);
this.context.trackEvent({
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
event: 'Clicked Block Explorer Link',
properties: {
link_type: 'Transaction Block Explorer',

View File

@ -12,7 +12,7 @@ import Tooltip from '../../ui/tooltip';
import CancelButton from '../cancel-button';
import Popover from '../../ui/popover';
import { SECOND } from '../../../../shared/constants/time';
import { EVENT } from '../../../../shared/constants/metametrics';
import { MetaMetricsEventCategory } from '../../../../shared/constants/metametrics';
import { TransactionType } from '../../../../shared/constants/transaction';
import { getURLHostName } from '../../../helpers/utils/util';
import TransactionDecoding from '../transaction-decoding';
@ -76,7 +76,7 @@ export default class TransactionListItemDetails extends PureComponent {
history.push(`${NETWORKS_ROUTE}#blockExplorerUrl`);
} else {
this.context.trackEvent({
category: EVENT.CATEGORIES.TRANSACTIONS,
category: MetaMetricsEventCategory.Transactions,
event: 'Clicked Block Explorer Link',
properties: {
link_type: 'Transaction Block Explorer',
@ -109,7 +109,7 @@ export default class TransactionListItemDetails extends PureComponent {
const { hash } = transaction;
this.context.trackEvent({
category: EVENT.CATEGORIES.NAVIGATION,
category: MetaMetricsEventCategory.Navigation,
event: 'Copied Transaction ID',
properties: {
action: 'Activity Log',
@ -250,7 +250,7 @@ export default class TransactionListItemDetails extends PureComponent {
senderAddress={senderAddress}
onRecipientClick={() => {
this.context.trackEvent({
category: EVENT.CATEGORIES.NAVIGATION,
category: MetaMetricsEventCategory.Navigation,
event: 'Copied "To" Address',
properties: {
action: 'Activity Log',
@ -260,7 +260,7 @@ export default class TransactionListItemDetails extends PureComponent {
}}
onSenderClick={() => {
this.context.trackEvent({
category: EVENT.CATEGORIES.NAVIGATION,
category: MetaMetricsEventCategory.Navigation,
event: 'Copied "From" Address',
properties: {
action: 'Activity Log',

View File

@ -13,7 +13,7 @@ import { CONFIRM_TRANSACTION_ROUTE } from '../../../helpers/constants/routes';
import { useShouldShowSpeedUp } from '../../../hooks/useShouldShowSpeedUp';
import TransactionStatusLabel from '../transaction-status-label/transaction-status-label';
import TransactionIcon from '../transaction-icon';
import { EVENT } from '../../../../shared/constants/metametrics';
import { MetaMetricsEventCategory } from '../../../../shared/constants/metametrics';
import {
TransactionGroupCategory,
TransactionStatus,
@ -65,7 +65,7 @@ function TransactionListItemInner({
event.stopPropagation();
trackEvent({
event: 'Clicked "Speed Up"',
category: EVENT.CATEGORIES.NAVIGATION,
category: MetaMetricsEventCategory.Navigation,
properties: {
action: 'Activity Log',
legacy_event: true,
@ -86,7 +86,7 @@ function TransactionListItemInner({
event.stopPropagation();
trackEvent({
event: 'Clicked "Cancel"',
category: EVENT.CATEGORIES.NAVIGATION,
category: MetaMetricsEventCategory.Navigation,
properties: {
action: 'Activity Log',
legacy_event: true,

View File

@ -17,12 +17,6 @@ import {
getSelectedAccountCachedBalance,
} from '../../../selectors';
import IconButton from '../../ui/icon-button';
import { MetaMetricsContext } from '../../../contexts/metametrics';
import {
EVENT,
EVENT_NAMES,
// CONTEXT_PROPS,
} from '../../../../shared/constants/metametrics';
import Spinner from '../../ui/spinner';
import { startNewDraftTransaction } from '../../../ducks/send';
import { AssetType } from '../../../../shared/constants/transaction';
@ -31,7 +25,6 @@ import WalletOverview from './wallet-overview';
const EthOverview = ({ className }) => {
const dispatch = useDispatch();
const t = useContext(I18nContext);
const trackEvent = useContext(MetaMetricsContext);
const history = useHistory();
const balanceIsCached = useSelector(isBalanceCached);
const showFiat = useSelector(getShouldShowFiat);
@ -93,15 +86,6 @@ const EthOverview = ({ className }) => {
data-testid="eth-overview-send"
label={t('send')}
onClick={() => {
trackEvent({
event: EVENT_NAMES.NAV_SEND_BUTTON_CLICKED,
category: EVENT.CATEGORIES.NAVIGATION,
properties: {
token_symbol: 'ETH',
location: 'Home',
text: 'Send',
},
});
dispatch(startNewDraftTransaction({ type: AssetType.native })).then(
() => {
history.push(SEND_ROUTE);

View File

@ -14,15 +14,12 @@ import { startNewDraftTransaction } from '../../../ducks/send';
import IconButton from '../../ui/icon-button';
import { INVALID_ASSET_TYPE } from '../../../helpers/constants/error-keys';
import { showModal } from '../../../store/actions';
import { MetaMetricsContext } from '../../../contexts/metametrics';
import { EVENT, EVENT_NAMES } from '../../../../shared/constants/metametrics';
import { AssetType } from '../../../../shared/constants/transaction';
import WalletOverview from './wallet-overview';
const TokenOverview = ({ className, token }) => {
const dispatch = useDispatch();
const t = useContext(I18nContext);
const trackEvent = useContext(MetaMetricsContext);
const history = useHistory();
const { tokensWithBalances } = useTokenTracker([token]);
const balanceToRender = tokensWithBalances[0]?.string;
@ -66,15 +63,6 @@ const TokenOverview = ({ className, token }) => {
<IconButton
className="token-overview__button"
onClick={async () => {
trackEvent({
event: EVENT_NAMES.NAV_SEND_BUTTON_CLICKED,
category: EVENT.CATEGORIES.NAVIGATION,
properties: {
token_symbol: token.symbol,
location: EVENT.SOURCE.SWAPS.TOKEN_VIEW,
text: 'Send',
},
});
try {
await dispatch(
startNewDraftTransaction({

View File

@ -177,7 +177,7 @@ For RTL language support use the `textDirection` prop.
</Canvas>
```jsx
import { ButtonBase, ICON_NAMES } from '../../component-library';
import { ButtonBase, ICON_NAMES, TextDirection } from '../../component-library';
<>
<ButtonBase
@ -189,7 +189,7 @@ import { ButtonBase, ICON_NAMES } from '../../component-library';
<ButtonBase
startIconName={ICON_NAMES.ADD_SQUARE}
endIconName={ICON_NAMES.ARROW_2_RIGHT}
textDirection={TEXT_DIRECTIONS.RIGHT_TO_LEFT}
textDirection={TextDirection.RightToLeft}
>
Button Demo
</ButtonBase>

View File

@ -7,7 +7,7 @@ import {
Size,
} from '../../../helpers/constants/design-system';
import Box from '../../ui/box/box';
import { ICON_NAMES, TEXT_DIRECTIONS } from '..';
import { ICON_NAMES, TextDirection } from '..';
import { BUTTON_BASE_SIZES } from './button-base.constants';
import { ButtonBase } from './button-base';
import README from './README.mdx';
@ -200,7 +200,7 @@ export const Rtl = (args) => (
{...args}
startIconName={ICON_NAMES.ADD_SQUARE}
endIconName={ICON_NAMES.ARROW_2_RIGHT}
textDirection={TEXT_DIRECTIONS.RIGHT_TO_LEFT}
textDirection={TextDirection.RightToLeft}
>
Button Demo
</ButtonBase>

View File

@ -28,7 +28,7 @@ export { Label } from './label';
export { PickerNetwork } from './picker-network';
export { Tag } from './tag';
export { TagUrl } from './tag-url';
export { Text, TEXT_DIRECTIONS, INVISIBLE_CHARACTER } from './text';
export { Text, ValidTag, TextDirection, InvisibleCharacter } from './text';
export { Input, INPUT_TYPES } from './input';
export { TextField, TEXT_FIELD_TYPES, TEXT_FIELD_SIZES } from './text-field';
export { TextFieldSearch } from './text-field-search';

View File

@ -59,7 +59,7 @@ import { TextVariant } from '../../../helpers/constants/design-system';
### Color
Use the `color` prop and the `TextColor` object from `./ui/helpers/constants/design-system.js` to change the color of the `Text` component.
Use the `color` prop and the `TextColor` enum from `./ui/helpers/constants/design-system.js` to change the color of the `Text` component.
<Canvas>
<Story id="components-componentlibrary-text--color-story" />
@ -267,6 +267,8 @@ import { Text } from '../../component-library';
Use the `as` prop to change the root html element of the `Text` component
You can also utilize the `ValidTag` enum from `./text.types` to ensure that you are using a valid html element
<Canvas>
<Story id="components-componentlibrary-text--as" />
</Canvas>
@ -313,22 +315,22 @@ Renders the html:
### Text Direction
Use the `textDirection` prop and the `TEXT_DIRECTIONS` object from `./text.constants.js` to change the text direction of `Text`
Use the `textDirection` prop and the `TextDirection` enum from `./text.types` to change the text direction of `Text`
<Canvas>
<Story id="components-componentlibrary-text--text-direction" />
<Story id="components-componentlibrary-text--text-direction-story" />
</Canvas>
```jsx
import { Text, TEXT_DIRECTIONS } from '../../component-library';
import { Text, TextDirection } from '../../component-library';
<Text textDirection={TEXT_DIRECTIONS.LEFT_TO_RIGHT}>
<Text textDirection={TextDirection.LeftToRight}>
This is left to right (ltr) for English and most languages
</Text>
<Text textDirection={TEXT_DIRECTIONS.RIGHT_TO_LEFT}>
<Text textDirection={TextDirection.RightToLeft}>
This is right to left (rtl) for use with other laguanges such as Arabic. This Enlgish example is incorrect usage.
</Text>
<Text textDirection={TEXT_DIRECTIONS.AUTO}>
<Text textDirection={TextDirection.Auto}>
Let the user agent decide with the auto option
</Text>
```

View File

@ -0,0 +1,56 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Text should render the Text with proper variant class name 1`] = `
<div>
<h1
class="box mm-text mm-text--display-md box--flex-direction-row box--color-text-default"
>
display-md
</h1>
<h2
class="box mm-text mm-text--heading-lg box--flex-direction-row box--color-text-default"
>
heading-lg
</h2>
<h3
class="box mm-text mm-text--heading-md box--flex-direction-row box--color-text-default"
>
heading-md
</h3>
<h4
class="box mm-text mm-text--heading-sm box--flex-direction-row box--color-text-default"
>
heading-sm
</h4>
<p
class="box mm-text mm-text--body-lg-medium box--flex-direction-row box--color-text-default"
>
body-lg-medium
</p>
<p
class="box mm-text mm-text--body-md box--flex-direction-row box--color-text-default"
>
body-md
</p>
<p
class="box mm-text mm-text--body-md-bold box--flex-direction-row box--color-text-default"
>
body-md-bold
</p>
<p
class="box mm-text mm-text--body-sm box--flex-direction-row box--color-text-default"
>
body-sm
</p>
<p
class="box mm-text mm-text--body-sm-bold box--flex-direction-row box--color-text-default"
>
body-sm-bold
</p>
<p
class="box mm-text mm-text--body-xs box--flex-direction-row box--color-text-default"
>
body-xs
</p>
</div>
`;

View File

@ -1,7 +1,7 @@
import React from 'react';
import classnames from 'classnames';
import PropTypes from 'prop-types';
import Box from '../../ui/box';
import Box from '../../../ui/box';
import {
FONT_WEIGHT,
FONT_STYLE,
@ -10,7 +10,7 @@ import {
TEXT_TRANSFORM,
OVERFLOW_WRAP,
TextColor,
} from '../../../helpers/constants/design-system';
} from '../../../../helpers/constants/design-system';
import { TEXT_DIRECTIONS } from './text.constants';
export const ValidTags = [

View File

@ -9,7 +9,7 @@ import {
TEXT_TRANSFORM,
TextVariant,
Color,
} from '../../../helpers/constants/design-system';
} from '../../../../helpers/constants/design-system';
import { Text, TEXT_DIRECTIONS } from '.';
describe('Text', () => {

View File

@ -0,0 +1,3 @@
export { Text } from './text';
export { ValidTag, TextDirection, InvisibleCharacter } from './text.types';
export type { TextProps } from './text.types';

View File

@ -1,4 +1,5 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import {
DISPLAY,
BackgroundColor,
@ -16,115 +17,20 @@ import {
} from '../../../helpers/constants/design-system';
import Box from '../../ui/box';
import { ValidTags, Text } from './text';
import { TEXT_DIRECTIONS } from './text.constants';
import README from './README.mdx';
const sizeKnobOptions = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
const marginSizeKnobOptions = [...sizeKnobOptions, 'auto'];
import { Text } from './text';
import { ValidTag, TextDirection } from './text.types';
export default {
title: 'Components/ComponentLibrary/Text',
component: Text,
parameters: {
docs: {
page: README,
},
},
argTypes: {
variant: {
control: { type: 'select' },
options: Object.values(TextVariant),
},
color: {
control: { type: 'select' },
options: Object.values(TextColor),
},
fontWeight: {
control: { type: 'select' },
options: Object.values(FONT_WEIGHT),
},
fontStyle: {
control: { type: 'select' },
options: Object.values(FONT_STYLE),
},
textTransform: {
control: { type: 'select' },
options: Object.values(TEXT_TRANSFORM),
},
align: {
control: { type: 'select' },
options: Object.values(TEXT_ALIGN),
},
overflowWrap: {
control: { type: 'select' },
options: Object.values(OVERFLOW_WRAP),
},
ellipsis: {
control: { type: 'boolean' },
},
as: {
control: { type: 'select' },
options: ValidTags,
},
textDirection: {
control: { type: 'select' },
options: Object.values(TEXT_DIRECTIONS),
},
className: {
control: { type: 'text' },
},
children: {
control: { type: 'text' },
},
display: {
options: Object.values(DISPLAY),
control: 'select',
table: { category: 'box props' },
},
backgroundColor: {
options: Object.values(BackgroundColor),
control: 'select',
table: { category: 'box props' },
},
borderColor: {
options: Object.values(BorderColor),
control: 'select',
table: { category: 'box props' },
},
padding: {
options: sizeKnobOptions,
control: 'select',
table: { category: 'box props' },
},
margin: {
options: marginSizeKnobOptions,
control: 'select',
table: { category: 'box props' },
},
marginTop: {
options: marginSizeKnobOptions,
control: 'select',
table: { category: 'box props' },
},
marginRight: {
options: marginSizeKnobOptions,
control: 'select',
table: { category: 'box props' },
},
marginBottom: {
options: marginSizeKnobOptions,
control: 'select',
table: { category: 'box props' },
},
marginLeft: {
options: marginSizeKnobOptions,
control: 'select',
table: { category: 'box props' },
},
},
};
} as ComponentMeta<typeof Text>;
function renderBackgroundColor(color) {
let bgColor;
@ -164,14 +70,18 @@ function renderBackgroundColor(color) {
return bgColor;
}
export const DefaultStory = (args) => <Text {...args}>{args.children}</Text>;
const Template: ComponentStory<typeof Text> = (args) => (
<Text {...args}>{args.children}</Text>
);
DefaultStory.storyName = 'Default';
export const DefaultStory = Template.bind({});
DefaultStory.args = {
children: 'The quick orange fox jumped over the lazy dog.',
};
DefaultStory.storyName = 'Default';
export const Variant = (args) => (
<>
{Object.values(TextVariant).map((variant) => (
@ -182,7 +92,7 @@ export const Variant = (args) => (
</>
);
export const ColorStory = (args) => {
export const ColorStory: ComponentStory<typeof Text> = (args) => {
// Index of last valid color in TextColor array
return (
<>
@ -203,7 +113,7 @@ export const ColorStory = (args) => {
};
ColorStory.storyName = 'Color';
export const FontWeight = (args) => (
export const FontWeight: ComponentStory<typeof Text> = (args) => (
<>
{Object.values(FONT_WEIGHT).map((weight) => (
<Text {...args} fontWeight={weight} key={weight}>
@ -213,7 +123,7 @@ export const FontWeight = (args) => (
</>
);
export const FontStyle = (args) => (
export const FontStyle: ComponentStory<typeof Text> = (args) => (
<>
{Object.values(FONT_STYLE).map((style) => (
<Text {...args} fontStyle={style} key={style}>
@ -223,7 +133,7 @@ export const FontStyle = (args) => (
</>
);
export const TextTransform = (args) => (
export const TextTransform: ComponentStory<typeof Text> = (args) => (
<>
{Object.values(TEXT_TRANSFORM).map((transform) => (
<Text {...args} textTransform={transform} key={transform}>
@ -233,7 +143,7 @@ export const TextTransform = (args) => (
</>
);
export const TextAlign = (args) => (
export const TextAlign: ComponentStory<typeof Text> = (args) => (
<>
{Object.values(TEXT_ALIGN).map((align) => (
<Text {...args} textAlign={align} key={align}>
@ -243,11 +153,11 @@ export const TextAlign = (args) => (
</>
);
export const OverflowWrap = (args) => (
export const OverflowWrap: ComponentStory<typeof Text> = (args) => (
<Box
borderColor={BorderColor.warningDefault}
display={DISPLAY.BLOCK}
width={FRACTIONS.ONE_THIRD}
style={{ width: 200 }}
>
<Text {...args} overflowWrap={OVERFLOW_WRAP.NORMAL}>
{OVERFLOW_WRAP.NORMAL}: 0x39013f961c378f02c2b82a6e1d31e9812786fd9d
@ -258,7 +168,7 @@ export const OverflowWrap = (args) => (
</Box>
);
export const Ellipsis = (args) => (
export const Ellipsis: ComponentStory<typeof Text> = (args) => (
<Box
borderColor={BorderColor.primaryDefault}
display={DISPLAY.BLOCK}
@ -273,16 +183,23 @@ export const Ellipsis = (args) => (
</Box>
);
export const As = (args) => (
export const As: ComponentStory<typeof Text> = (args) => (
<>
{ValidTags.map((tag) => {
if (tag === 'input') {
return <Text key={tag} {...args} as={tag} placeholder={tag} />;
{Object.keys(ValidTag).map((tag) => {
if (ValidTag[tag] === ValidTag.Input) {
return (
<Text
key={ValidTag[tag]}
{...args}
as={ValidTag[tag]}
placeholder={ValidTag[tag]}
/>
);
}
return (
<div key={tag}>
<Text {...args} as={tag}>
{tag}
<div key={ValidTag[tag]}>
<Text {...args} as={ValidTag[tag]}>
{ValidTag[tag]}
</Text>
</div>
);
@ -290,21 +207,21 @@ export const As = (args) => (
</>
);
export const TextDirection = (args) => (
export const TextDirectionStory: ComponentStory<typeof Text> = (args) => (
<Box
style={{ maxWidth: 300 }}
display={DISPLAY.FLEX}
flexDirection={FLEX_DIRECTION.COLUMN}
gap={4}
>
<Text {...args} textDirection={TEXT_DIRECTIONS.LEFT_TO_RIGHT}>
<Text {...args} textDirection={TextDirection.LeftToRight}>
This is left to right (ltr) for English and most languages
</Text>
<Text {...args} textDirection={TEXT_DIRECTIONS.RIGHT_TO_LEFT}>
<Text {...args} textDirection={TextDirection.RightToLeft}>
This is right to left (rtl) for use with other laguanges such as Arabic.
This Enlgish example is incorrect usage.
</Text>
<Text {...args} textDirection={TEXT_DIRECTIONS.AUTO}>
<Text {...args} textDirection={TextDirection.Auto}>
Let the user agent decide with the auto option
</Text>
</Box>

Some files were not shown because too many files have changed in this diff Show More