From 22e44c2db847f8cc430bc4763a7bdc51d576a7e3 Mon Sep 17 00:00:00 2001 From: metamaskbot Date: Fri, 4 Oct 2024 02:29:34 +0000 Subject: [PATCH 01/45] 7.33.0 --- android/app/build.gradle | 4 ++-- bitrise.yml | 8 ++++---- ios/MetaMask.xcodeproj/project.pbxproj | 24 ++++++++++++------------ package.json | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 7ff5e6cd321..9e4a5e4ede9 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -173,8 +173,8 @@ android { applicationId "io.metamask" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1444 - versionName "7.32.0" + versionCode 1445 + versionName "7.33.0" testBuildType System.getProperty('testBuildType', 'debug') missingDimensionStrategy 'react-native-camera', 'general' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/bitrise.yml b/bitrise.yml index 58d92813187..82771ddecef 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -1497,16 +1497,16 @@ app: PROJECT_LOCATION_IOS: ios - opts: is_expand: false - VERSION_NAME: 7.32.0 + VERSION_NAME: 7.33.0 - opts: is_expand: false - VERSION_NUMBER: 1444 + VERSION_NUMBER: 1445 - opts: is_expand: false - FLASK_VERSION_NAME: 7.32.0 + FLASK_VERSION_NAME: 7.33.0 - opts: is_expand: false - FLASK_VERSION_NUMBER: 1444 + FLASK_VERSION_NUMBER: 1445 - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index d8054141512..5e73fc0a9d9 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -1273,7 +1273,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1444; + CURRENT_PROJECT_VERSION = 1445; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1310,7 +1310,7 @@ "${inherited}", ); LLVM_LTO = YES; - MARKETING_VERSION = 7.32.0; + MARKETING_VERSION = 7.33.0; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = ( @@ -1338,7 +1338,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1444; + CURRENT_PROJECT_VERSION = 1445; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1373,7 +1373,7 @@ "${inherited}", ); LLVM_LTO = YES; - MARKETING_VERSION = 7.32.0; + MARKETING_VERSION = 7.33.0; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = ( @@ -1401,7 +1401,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1444; + CURRENT_PROJECT_VERSION = 1445; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1434,7 +1434,7 @@ ); LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)"; LLVM_LTO = YES; - MARKETING_VERSION = 7.32.0; + MARKETING_VERSION = 7.33.0; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = ( @@ -1462,7 +1462,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1444; + CURRENT_PROJECT_VERSION = 1445; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1493,7 +1493,7 @@ ); LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)"; LLVM_LTO = YES; - MARKETING_VERSION = 7.32.0; + MARKETING_VERSION = 7.33.0; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = ( @@ -1616,7 +1616,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1444; + CURRENT_PROJECT_VERSION = 1445; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1653,7 +1653,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 7.32.0; + MARKETING_VERSION = 7.33.0; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "$(inherited)", @@ -1684,7 +1684,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1444; + CURRENT_PROJECT_VERSION = 1445; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1719,7 +1719,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 7.32.0; + MARKETING_VERSION = 7.33.0; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = ( "$(inherited)", diff --git a/package.json b/package.json index 99a3ed5a51c..4c0e6d25fda 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "metamask", - "version": "7.32.0", + "version": "7.33.0", "private": true, "scripts": { "audit:ci": "./scripts/yarn-audit.sh", From f178cd0c9f2c4f88d5d9d2bf94511dd19d174c59 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 4 Oct 2024 09:42:31 -0700 Subject: [PATCH 02/45] chore: chore/7.33.0-Changelog (#11617) This is PR updateds the change log for 7.33.0 and generates the test plan here [commit.csv](https://github.com/MetaMask/metamask-mobile/blob/release/7.33.0/commits.csv) --------- Co-authored-by: metamaskbot Co-authored-by: Cal-L --- CHANGELOG.md | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97b9b7095f6..3e501b25217 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,115 @@ ## Current Main Branch +## 7.33.0 - Oct 3, 2024 + +### Added +- [#11507](https://github.com/MetaMask/metamask-mobile/pull/11507): feat: 10550 Re-introduce test for measuring cold app start + JS bundle load time (#11507) +- [#11347](https://github.com/MetaMask/metamask-mobile/pull/11347): "chore: revert ""feat: react native fast crypto for notifications"" (#11347)" +- [#11318](https://github.com/MetaMask/metamask-mobile/pull/11318): feat: app event manager and attribution id parameters (#11318) +- [#11445](https://github.com/MetaMask/metamask-mobile/pull/11445): feat: add the abilty to hide the disconnect all button as well as showing and hiding the accounts row when necessary (#11445) +- [#11386](https://github.com/MetaMask/metamask-mobile/pull/11386): feat(3299): add tracking to network switching and confirmation (#11386) +- [#11379](https://github.com/MetaMask/metamask-mobile/pull/11379): refactor: rename the feature flag since it had a typo (#11379) +- [#11239](https://github.com/MetaMask/metamask-mobile/pull/11239): feat(2739): permission summary view gets the ability to disconnect all (#11239) +- [#11382](https://github.com/MetaMask/metamask-mobile/pull/11382): chore(runway): cherry-pick feat: app event manager and attribution id parameters (#11382) +- [#11497](https://github.com/MetaMask/metamask-mobile/pull/11497): feat: simple key-> value component for text value type (#11497) +- [#11478](https://github.com/MetaMask/metamask-mobile/pull/11478): feat: adding title to confirmation page (#11478) +- [#11477](https://github.com/MetaMask/metamask-mobile/pull/11477): feat: adding footer section to confirmation page (#11477) +- [#11454](https://github.com/MetaMask/metamask-mobile/pull/11454): feat: adding very basic confirmation page hidden behind env var (#11454) +- [#11083](https://github.com/MetaMask/metamask-mobile/pull/11083): feat: bundle size check (#11083) +- [#11452](https://github.com/MetaMask/metamask-mobile/pull/11452): feat(ds): add ListItem top and bottom accessories (#11452) +- [#11387](https://github.com/MetaMask/metamask-mobile/pull/11387): feat: 10550 Re-introduce test for measuring cold app start + JS bundle load time (#11387) +- [#11464](https://github.com/MetaMask/metamask-mobile/pull/11464): feat: STAKE-804: build pooled staking empty state component (#11464) +- [#11399](https://github.com/MetaMask/metamask-mobile/pull/11399): feat: add learn more modal component for staking (#11399) +- [#11261](https://github.com/MetaMask/metamask-mobile/pull/11261): feat: STAKE-822 build your balance component (#11261) +- [#11294](https://github.com/MetaMask/metamask-mobile/pull/11294): feat: added KeyValueRow to component-library/components-temp (#11294) +- [#11185](https://github.com/MetaMask/metamask-mobile/pull/11185): "feat: display ""Snaps (Beta)"" decorator tag in accounts list (#11185)" +- [#10829](https://github.com/MetaMask/metamask-mobile/pull/10829): feat: Eth snap keyring (#10829) +- [#11455](https://github.com/MetaMask/metamask-mobile/pull/11455): feat: bootstrap a reset notifications feat (#11455) +- [#11466](https://github.com/MetaMask/metamask-mobile/pull/11466): feat: add support for external links (#11466) +- [#11429](https://github.com/MetaMask/metamask-mobile/pull/11429): feat: add timeout handler (#11429) +- [#11427](https://github.com/MetaMask/metamask-mobile/pull/11427): feat: add feature announcements channel for android (#11427) +- [#11250](https://github.com/MetaMask/metamask-mobile/pull/11250): fix: push notifications (#11250) +- [#11069](https://github.com/MetaMask/metamask-mobile/pull/11069): feat: react native fast crypto for notifications (#11069) + +### Changed +- [#11615](https://github.com/MetaMask/metamask-mobile/pull/11615): chore: exclude temporarily sentry SDK advisory (#11615) +- [#11577](https://github.com/MetaMask/metamask-mobile/pull/11577): ci: disable swaps e2e workflow (#11577) +- [#11350](https://github.com/MetaMask/metamask-mobile/pull/11350): chore: replace Segment patch by plugin (#11350) +- [#11287](https://github.com/MetaMask/metamask-mobile/pull/11287): chore: remove unused events (#11287) +- [#11512](https://github.com/MetaMask/metamask-mobile/pull/11512): fix: android firebase docs template (#11512) +- [#11517](https://github.com/MetaMask/metamask-mobile/pull/11517): chore: delete swaps token charts test (#11517) +- [#11515](https://github.com/MetaMask/metamask-mobile/pull/11515): test: disable swaps token charts regression tests (#11515) +- [#11504](https://github.com/MetaMask/metamask-mobile/pull/11504): chore: revert measuring with react native performance (#11504) +- [#11458](https://github.com/MetaMask/metamask-mobile/pull/11458): test: Merge Import Token flow methods and ids in just one folder and files (#11458) +- [#11492](https://github.com/MetaMask/metamask-mobile/pull/11492): chore(revert): Prevent redundant Sentry sourcemap uploads (#11492) +- [#11469](https://github.com/MetaMask/metamask-mobile/pull/11469): test: Remove E2E Tests for Features No Longer Present in the App (#11469) +- [#11425](https://github.com/MetaMask/metamask-mobile/pull/11425): chore: Add skip label to bypass sonarcloud (#11425) +- [#11275](https://github.com/MetaMask/metamask-mobile/pull/11275): chore(js-ts): Convert app/util/bytes.js to TypeScript (#11275) +- [#11418](https://github.com/MetaMask/metamask-mobile/pull/11418): chore: revert chore(js-ts): Migrate 37 0-error js files (#11418) +- [#10880](https://github.com/MetaMask/metamask-mobile/pull/10880): chore: Enable linting Pods and re-organize setup.mjs file (#10880) +- [#11311](https://github.com/MetaMask/metamask-mobile/pull/11311): chore(js-ts): Convert app/components/UI/Swaps/components/Ratio.js to TypeScript (#11311) +- [#11357](https://github.com/MetaMask/metamask-mobile/pull/11357): chore(js-ts): Convert app/components/Views/PickComponent/index.js to TypeScript (#11357) +- [#11446](https://github.com/MetaMask/metamask-mobile/pull/11446): chore(js-ts): Convert app/components/Views/MediaPlayer/Loader.js to TypeScript (#11446) +- [#11473](https://github.com/MetaMask/metamask-mobile/pull/11473): chore(js-ts): Convert app/components/Base/ModalHandler.js to TypeScript (#11473) +- [#11601](https://github.com/MetaMask/metamask-mobile/pull/11601): chore(js-ts): Convert app/components/Base/ListItem.js to TypeScript (#11601) +- [#11407](https://github.com/MetaMask/metamask-mobile/pull/11407): chore(js-ts): Convert app/util/jsonRpcRequest.js to TypeScript (#11407) +- [#11594](https://github.com/MetaMask/metamask-mobile/pull/11594): chore(js-ts): Convert app/component-library/components/Icons/Icon/scripts/generate-assets.js to TypeScript (#11594) +- [#11523](https://github.com/MetaMask/metamask-mobile/pull/11523): chore(js-ts): Convert app/components/UI/GenericButton/index.ios.js to TypeScript (#11523) +- [#11472](https://github.com/MetaMask/metamask-mobile/pull/11472): chore(js-ts): Convert app/components/UI/FadeView/index.js to TypeScript (#11472) +- [#11476](https://github.com/MetaMask/metamask-mobile/pull/11476): chore(js-ts): Convert app/components/UI/OnboardingProgress/index.js to TypeScript (#11476) +- [#11405](https://github.com/MetaMask/metamask-mobile/pull/11405): chore(js-ts): Convert app/util/browserScripts.js to TypeScript (#11405) +- [#11214](https://github.com/MetaMask/metamask-mobile/pull/11214): chore(js-ts): Migrate 37 0-error js files (#11214) +- [#11271](https://github.com/MetaMask/metamask-mobile/pull/11271): chore(js-ts): Convert app/components/UI/ComponentErrorBoundary/index.js to TypeScript (#11271) +- [#11299](https://github.com/MetaMask/metamask-mobile/pull/11299): chore(js-ts): Convert app/util/validators/index.js to TypeScript (#11299) +- [#11303](https://github.com/MetaMask/metamask-mobile/pull/11303): chore(js-ts): Convert app/components/Base/SelectorButton.js to TypeScript (#11303) +- [#11280](https://github.com/MetaMask/metamask-mobile/pull/11280): chore(js-ts): Convert app/components/UI/GenericButton/index.android.js to TypeScript (#11280) +- [#11273](https://github.com/MetaMask/metamask-mobile/pull/11273): chore(js-ts): Convert app/components/UI/OnboardingScreenWithBg/index.js to TypeScript (#11273) +- [#11272](https://github.com/MetaMask/metamask-mobile/pull/11272): chore(js-ts): Convert app/components/Base/ModalDragger.js to TypeScript (#11272) +- [#11308](https://github.com/MetaMask/metamask-mobile/pull/11308): chore(js-ts): Convert app/components/UI/BlockingActionModal/index.js to TypeScript (#11308) +- [#11305](https://github.com/MetaMask/metamask-mobile/pull/11305): chore(js-ts): Convert app/components/Base/Summary.js to TypeScript (#11305) +- [#11274](https://github.com/MetaMask/metamask-mobile/pull/11274): chore(js-ts): Convert app/components/UI/ConnectHeader/index.js to TypeScript (#11274) +- [#11334](https://github.com/MetaMask/metamask-mobile/pull/11334): chore: chore/7.32.0-Changelog (#11334) +- [#11483](https://github.com/MetaMask/metamask-mobile/pull/11483): chore: refactor e2e (#11483) +- [#11491](https://github.com/MetaMask/metamask-mobile/pull/11491): chore: Add UX CodeOwners responsibilities (#11491) +- [#11364](https://github.com/MetaMask/metamask-mobile/pull/11364): refactor(1702-2): auto detect nft component (#11364) +- [#11363](https://github.com/MetaMask/metamask-mobile/pull/11363): refactor(1702-1): auto detect tokens component (#11363) +- [#11329](https://github.com/MetaMask/metamask-mobile/pull/11329): chore: Add `@MetaMask/metamask-assets` to `CODEOWNERS` (#11329) +- [#10449](https://github.com/MetaMask/metamask-mobile/pull/10449): chore: remove installation of redundant detox-cli in bitrise (#10449) +- [#11111](https://github.com/MetaMask/metamask-mobile/pull/11111): chore(deps): Bump `@metamask/phishing-controller` from `^9.0.0` to `^12.0.1` (#11111) +- [#11375](https://github.com/MetaMask/metamask-mobile/pull/11375): chore(deps): Bump `@metamask/controller-utils` from `^10.0.0` to `^11.3.0` (#11375) +- [#11140](https://github.com/MetaMask/metamask-mobile/pull/11140): chore(deps): Bump `@metamask/smart-transactions-controller` from `11.0.0` to `^13.0.0` (#11140) +- [#11351](https://github.com/MetaMask/metamask-mobile/pull/11351): chore(deps): Bump `@metamask/keyring-controller` from `^16.1.0` to `^17.2.1` (#11351) +- [#11104](https://github.com/MetaMask/metamask-mobile/pull/11104): chore(deps): Bump `@metamask/address-book-controller` from `^4.0.1` to `^6.0.1` (#11104) +- [#10917](https://github.com/MetaMask/metamask-mobile/pull/10917): chore(ci): split out ci scripts and devDeps into separate project (#10917) +- [#11081](https://github.com/MetaMask/metamask-mobile/pull/11081): chore: Prevent redundant Sentry sourcemap uploads (#11081) +- [#11430](https://github.com/MetaMask/metamask-mobile/pull/11430): fix: refactor Logger usage (#11430) +- [#11470](https://github.com/MetaMask/metamask-mobile/pull/11470): chore: [Design quality] Update token details (#11470) +- [#11439](https://github.com/MetaMask/metamask-mobile/pull/11439): "chore: cherry-pick fix: ""chore(deps): Bump @metamask/base-controller from ^6.0.0 to ^7.0.0 (#11207)"" (#11439)" +- [#11169](https://github.com/MetaMask/metamask-mobile/pull/11169): "chore(deps): Bump `@metamask/signature-controller` from `^17.0.0` to `^19.1.0` +- [#11352](https://github.com/MetaMask/metamask-mobile/pull/11352): "chore(deps): Bump `@metamask/accounts-controller` to `^18.2.1` + +### Fixed +- [#11581](https://github.com/MetaMask/metamask-mobile/pull/11581): fix: Fix invalid browser url crash (#11581) +- [#11467](https://github.com/MetaMask/metamask-mobile/pull/11467): fix: Reorder prep_environment (#11467) +- [#11367](https://github.com/MetaMask/metamask-mobile/pull/11367): fix: Update steps of the methods that are no longer valid (#11367) +- [#11400](https://github.com/MetaMask/metamask-mobile/pull/11400): fix: Stop crowdin action from creating branches (#11400) +- [#11348](https://github.com/MetaMask/metamask-mobile/pull/11348): fix: splash screen image on android (#11348) +- [#11346](https://github.com/MetaMask/metamask-mobile/pull/11346): fix: splash screen image on android (#11346) +- [#11554](https://github.com/MetaMask/metamask-mobile/pull/11554): fix: Fix/use portfolio home page (#11554) +- [#11443](https://github.com/MetaMask/metamask-mobile/pull/11443): fix: react native quick crypto ios build bug (#11443) +- [#11325](https://github.com/MetaMask/metamask-mobile/pull/11325): fix: loader can display on top of login screen (#11325) +- [#11372](https://github.com/MetaMask/metamask-mobile/pull/11372): fix: origin spoofing vulnerability in signature prompts on iOS (#11372) +- [#11076](https://github.com/MetaMask/metamask-mobile/pull/11076): fix(2453): adjust UI details for account cell on wallet screen (#11076) +- [#11524](https://github.com/MetaMask/metamask-mobile/pull/11524): fix: fix duplicated network select (#11524) +- [#11411](https://github.com/MetaMask/metamask-mobile/pull/11411): fix: fix fixture builder network state (#11411) +- [#11380](https://github.com/MetaMask/metamask-mobile/pull/11380): fix: Unreadable Asset options (#11380) +- [#11321](https://github.com/MetaMask/metamask-mobile/pull/11321): fix: fix detect tokens performance (#11321) +- [#11401](https://github.com/MetaMask/metamask-mobile/pull/11401): fix: replace decomissioned cloudflare-ipfs.com with gateway.pinata.cloud (#11401) +- [#11552](https://github.com/MetaMask/metamask-mobile/pull/11552): fix(11481): android system alert respects dark mode themes (#11552) +- [#11518](https://github.com/MetaMask/metamask-mobile/pull/11518): fix(11482): incorrect QR code error (#11518) + + ## 7.32.0 - Sep 19, 2024 ### Added From 22d1a595ccd1b585e28041ffc04f2922eed696bb Mon Sep 17 00:00:00 2001 From: Nico MASSART Date: Tue, 8 Oct 2024 15:34:25 +0200 Subject: [PATCH 03/45] chore: merge 7.32.0 in 7.33.0 and bump build (#11677) Merge 7.32.0 back in 7.33.0 bump build to 1451 --------- Co-authored-by: Cal Leung Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- CHANGELOG.md | 8 ++++---- android/app/build.gradle | 2 +- bitrise.yml | 4 ++-- ios/MetaMask.xcodeproj/project.pbxproj | 12 ++++++------ 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e501b25217..1afbe7ca333 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,6 @@ ## Current Main Branch ## 7.33.0 - Oct 3, 2024 - ### Added - [#11507](https://github.com/MetaMask/metamask-mobile/pull/11507): feat: 10550 Re-introduce test for measuring cold app start + JS bundle load time (#11507) - [#11347](https://github.com/MetaMask/metamask-mobile/pull/11347): "chore: revert ""feat: react native fast crypto for notifications"" (#11347)" @@ -110,9 +109,7 @@ - [#11552](https://github.com/MetaMask/metamask-mobile/pull/11552): fix(11481): android system alert respects dark mode themes (#11552) - [#11518](https://github.com/MetaMask/metamask-mobile/pull/11518): fix(11482): incorrect QR code error (#11518) - -## 7.32.0 - Sep 19, 2024 - +## 7.32.0 - Oct 7, 2024 ### Added - [#10294](https://github.com/MetaMask/metamask-mobile/pull/10294): feat: create redux slice for featureFlags (#10294) @@ -200,6 +197,9 @@ - [#11193](https://github.com/MetaMask/metamask-mobile/pull/11193): fix: ItemMenu crash using dayjs (#11193) - [#11098](https://github.com/MetaMask/metamask-mobile/pull/11098): fix: badge count and ui polishing (#11098) +## 7.31.1 - Oct 4, 2024 +### Fixed +- [#11631](https://github.com/MetaMask/metamask-mobile/pull/11631): fix: Fixes UI issue in token details (#11631) ## 7.31.0 - Sep 6, 2024 ### Added diff --git a/android/app/build.gradle b/android/app/build.gradle index 9e4a5e4ede9..28619afb4a0 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -173,8 +173,8 @@ android { applicationId "io.metamask" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1445 versionName "7.33.0" + versionCode 1451 testBuildType System.getProperty('testBuildType', 'debug') missingDimensionStrategy 'react-native-camera', 'general' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/bitrise.yml b/bitrise.yml index 82771ddecef..1edda496c87 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -1500,13 +1500,13 @@ app: VERSION_NAME: 7.33.0 - opts: is_expand: false - VERSION_NUMBER: 1445 + VERSION_NUMBER: 1451 - opts: is_expand: false FLASK_VERSION_NAME: 7.33.0 - opts: is_expand: false - FLASK_VERSION_NUMBER: 1445 + FLASK_VERSION_NUMBER: 1451 - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index 5e73fc0a9d9..e6a283bc115 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -1273,7 +1273,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1445; + CURRENT_PROJECT_VERSION = 1451; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1338,7 +1338,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1445; + CURRENT_PROJECT_VERSION = 1451; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1401,7 +1401,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1445; + CURRENT_PROJECT_VERSION = 1451; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1462,7 +1462,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1445; + CURRENT_PROJECT_VERSION = 1451; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1616,7 +1616,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1445; + CURRENT_PROJECT_VERSION = 1451; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1684,7 +1684,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1445; + CURRENT_PROJECT_VERSION = 1451; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; From 06cf1b673be082a49eba366a8220ef68dfd47471 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 8 Oct 2024 16:08:21 +0200 Subject: [PATCH 04/45] chore: cherry-pick #11595 (#11683) This PR cherry-picks #11595 Co-authored-by: Mpendulo Ndlovu Co-authored-by: Nico MASSART --- .../components/SignatureRequest/index.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/app/components/Views/confirmations/components/SignatureRequest/index.js b/app/components/Views/confirmations/components/SignatureRequest/index.js index 869e2752ed0..aa1fb6c3db3 100644 --- a/app/components/Views/confirmations/components/SignatureRequest/index.js +++ b/app/components/Views/confirmations/components/SignatureRequest/index.js @@ -214,6 +214,21 @@ class SignatureRequest extends PureComponent { return createStyles(colors); }; + componentDidMount = () => { + const { currentPageInformation, type, fromAddress } = this.props; + + this.props.metrics.trackEvent( + MetaMetricsEvents.SIGNATURE_REQUESTED, + getAnalyticsParams( + { + currentPageInformation, + from: fromAddress, + }, + type, + ), + ); + }; + renderActionViewChildren = () => { const { children, From 8bc683c13ad754103d3c5d62b362eac2b7f917eb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 8 Oct 2024 16:45:50 +0200 Subject: [PATCH 05/45] chore: cherry-pick #11603 (#11682) This PR cherry-picks #11603 Co-authored-by: Mpendulo Ndlovu Co-authored-by: Nico MASSART --- app/components/Views/confirmations/Approval/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/components/Views/confirmations/Approval/index.js b/app/components/Views/confirmations/Approval/index.js index c35246ee8c9..27de9a65448 100644 --- a/app/components/Views/confirmations/Approval/index.js +++ b/app/components/Views/confirmations/Approval/index.js @@ -247,9 +247,12 @@ class Approval extends PureComponent { ); navigation && navigation.setParams({ mode: REVIEW, dispatch: this.onModeChange }); + this.initialise(); + }; + initialise = async () => { // Detect origin: WalletConnect / SDK / InAppBrowser - this.detectOrigin(); + await this.detectOrigin(); // Ensure detectOrigin finishes before proceeding this.props.metrics.trackEvent( MetaMetricsEvents.DAPP_TRANSACTION_STARTED, From 57d3a57c1214eaca5f5b5c2932ec7cc4eaeaadb2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:00:53 +0200 Subject: [PATCH 06/45] chore: cherry-pick #11592 (#11684) This PR cherry-picks #11592 Co-authored-by: Mpendulo Ndlovu Co-authored-by: Nico MASSART --- .../Views/confirmations/Approval/index.js | 15 +++++++++++---- .../components/ApproveTransactionReview/index.js | 7 ++++++- app/core/AppConstants.ts | 2 -- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/app/components/Views/confirmations/Approval/index.js b/app/components/Views/confirmations/Approval/index.js index 27de9a65448..5edfc96d87f 100644 --- a/app/components/Views/confirmations/Approval/index.js +++ b/app/components/Views/confirmations/Approval/index.js @@ -274,10 +274,17 @@ class Approval extends PureComponent { const wc2Manager = await WC2Manager.getInstance(); const sessions = wc2Manager.getSessions(); this.originIsWalletConnect = sessions.some((session) => { - DevLogger.log( - `Approval::detectOrigin Comparing session URL ${session.peer.metadata.url} with origin ${origin}`, - ); - return session.peer.metadata.url === origin; + // Otherwise, compare the origin with the metadata URL + if ( + session.peer.metadata.url === origin || + origin.startsWith(WALLET_CONNECT_ORIGIN) + ) { + DevLogger.log( + `Approval::detectOrigin Comparing session URL ${session.peer.metadata.url} with origin ${origin}`, + ); + return true; + } + return false; }); } DevLogger.log( diff --git a/app/components/Views/confirmations/components/ApproveTransactionReview/index.js b/app/components/Views/confirmations/components/ApproveTransactionReview/index.js index 193f019f22c..5814390edb8 100644 --- a/app/components/Views/confirmations/components/ApproveTransactionReview/index.js +++ b/app/components/Views/confirmations/components/ApproveTransactionReview/index.js @@ -104,6 +104,7 @@ import { createBuyNavigationDetails } from '../../../../UI/Ramp/routes/utils'; import SDKConnect from '../../../../../core/SDKConnect/SDKConnect'; import DevLogger from '../../../../../core/SDKConnect/utils/DevLogger'; import { WC2Manager } from '../../../../../core/WalletConnect/WalletConnectV2'; +import { WALLET_CONNECT_ORIGIN } from '../../../../../util/walletconnect'; const { ORIGIN_DEEPLINK, ORIGIN_QR_CODE } = AppConstants.DEEPLINKS; const POLLING_INTERVAL_ESTIMATED_L1_FEE = 30000; @@ -362,7 +363,11 @@ class ApproveTransactionReview extends PureComponent { // Check if it is walletConnect origin WC2Manager.getInstance().then((wc2) => { this.originIsWalletConnect = wc2.getSessions().some((session) => { - if (session.peer.metadata.url === origin) { + // Otherwise, compare the origin with the metadata URL + if ( + session.peer.metadata.url === origin || + origin.startsWith(WALLET_CONNECT_ORIGIN) + ) { DevLogger.log( `ApproveTransactionReview::componentDidMount Found matching session for origin ${origin}`, ); diff --git a/app/core/AppConstants.ts b/app/core/AppConstants.ts index 798e07e00b8..080f41edd90 100644 --- a/app/core/AppConstants.ts +++ b/app/core/AppConstants.ts @@ -171,8 +171,6 @@ export default { WC: 'WalletConnect', WC2: 'WalletConnectV2', IN_APP_BROWSER: 'In-App-Browser', - SDK_ANDROID: 'MetaMask-SDK-Android', - SDK_IOS: 'MetaMask-SDK-IOS', }, MM_SDK: { SDK_CONNECTIONS: 'sdkConnections', From 58d08f1161b17f9c7ca6e6183aa28982be5fa2d1 Mon Sep 17 00:00:00 2001 From: sahar-fehri Date: Wed, 9 Oct 2024 14:02:51 +0200 Subject: [PATCH 07/45] chore: cherry-pick #11631 (#11702) This PR cherry-picks https://github.com/MetaMask/metamask-mobile/pull/11631 Co-authored-by: Nick Gambino <35090461+gambinish@users.noreply.github.com> --- .../UI/AssetOverview/TokenDetails/TokenDetails.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/components/UI/AssetOverview/TokenDetails/TokenDetails.tsx b/app/components/UI/AssetOverview/TokenDetails/TokenDetails.tsx index fef37630508..8864c78c35c 100644 --- a/app/components/UI/AssetOverview/TokenDetails/TokenDetails.tsx +++ b/app/components/UI/AssetOverview/TokenDetails/TokenDetails.tsx @@ -59,10 +59,10 @@ const TokenDetails: React.FC = ({ asset }) => { let marketData; if (asset.isETH) { - marketData = tokenExchangeRates[zeroAddress() as `0x${string}`]; + marketData = tokenExchangeRates?.[zeroAddress() as `0x${string}`]; } else if (!asset.isETH && tokenContractAddress) { - tokenMetadata = tokenList[tokenContractAddress.toLowerCase()]; - marketData = tokenExchangeRates[tokenContractAddress]; + tokenMetadata = tokenList?.[tokenContractAddress.toLowerCase()]; + marketData = tokenExchangeRates?.[tokenContractAddress]; } else { Logger.log('cannot find contract address'); return null; From c132256e9950b4c145ff769c57f910ad0f526dbe Mon Sep 17 00:00:00 2001 From: Nico MASSART Date: Thu, 10 Oct 2024 17:05:10 +0200 Subject: [PATCH 08/45] chore: bump to version 1454 (#11738) Bump version to 1454 for 7.33.0 RC-3 --- android/app/build.gradle | 2 +- bitrise.yml | 4 ++-- ios/MetaMask.xcodeproj/project.pbxproj | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 28619afb4a0..3844583ba8a 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -174,7 +174,7 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionName "7.33.0" - versionCode 1451 + versionCode 1454 testBuildType System.getProperty('testBuildType', 'debug') missingDimensionStrategy 'react-native-camera', 'general' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/bitrise.yml b/bitrise.yml index 1edda496c87..1edf9023ba1 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -1500,13 +1500,13 @@ app: VERSION_NAME: 7.33.0 - opts: is_expand: false - VERSION_NUMBER: 1451 + VERSION_NUMBER: 1454 - opts: is_expand: false FLASK_VERSION_NAME: 7.33.0 - opts: is_expand: false - FLASK_VERSION_NUMBER: 1451 + FLASK_VERSION_NUMBER: 1454 - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index e6a283bc115..49b2812b936 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -1273,7 +1273,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1451; + CURRENT_PROJECT_VERSION = 1454; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1338,7 +1338,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1451; + CURRENT_PROJECT_VERSION = 1454; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1401,7 +1401,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1451; + CURRENT_PROJECT_VERSION = 1454; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1462,7 +1462,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1451; + CURRENT_PROJECT_VERSION = 1454; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1616,7 +1616,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1451; + CURRENT_PROJECT_VERSION = 1454; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1684,7 +1684,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1451; + CURRENT_PROJECT_VERSION = 1454; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; From db2d2c671bcc278304720b0e80617b39c35743e1 Mon Sep 17 00:00:00 2001 From: Nico MASSART Date: Thu, 10 Oct 2024 19:20:08 +0200 Subject: [PATCH 09/45] chore: cherry-pick #11718 (#11739) This PR cherry-picks #11718 Co-authored-by: Brian Bergeron --- app/core/Engine.ts | 2 +- .../@metamask+assets-controllers+30.0.0.patch | 58 +++++++++++++------ 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/app/core/Engine.ts b/app/core/Engine.ts index 0c9901b42a5..d6ef156d0af 100644 --- a/app/core/Engine.ts +++ b/app/core/Engine.ts @@ -700,7 +700,7 @@ class Engine { // @ts-expect-error TODO: Resolve mismatch between base-controller versions. messenger: this.controllerMessenger.getRestricted({ name: 'TokenListController', - allowedActions: [], + allowedActions: [`${networkController.name}:getNetworkClientById`], allowedEvents: [`${networkController.name}:stateChange`], }), }); diff --git a/patches/@metamask+assets-controllers+30.0.0.patch b/patches/@metamask+assets-controllers+30.0.0.patch index a9f3c0d37f5..985cb9387e8 100644 --- a/patches/@metamask+assets-controllers+30.0.0.patch +++ b/patches/@metamask+assets-controllers+30.0.0.patch @@ -15,6 +15,28 @@ index 542e3f6..af49a85 100644 }); } }); +diff --git a/node_modules/@metamask/assets-controllers/dist/chunk-5F5EQAX5.js b/node_modules/@metamask/assets-controllers/dist/chunk-5F5EQAX5.js +index 6d1492c..2ac3275 100644 +--- a/node_modules/@metamask/assets-controllers/dist/chunk-5F5EQAX5.js ++++ b/node_modules/@metamask/assets-controllers/dist/chunk-5F5EQAX5.js +@@ -247,10 +247,15 @@ var TokenListController = class extends _pollingcontroller.StaticIntervalPolling + }; + _onNetworkControllerStateChange = new WeakSet(); + onNetworkControllerStateChange_fn = async function(networkControllerState) { +- if (this.chainId !== networkControllerState.providerConfig.chainId) { ++ const selectedNetworkClient = this.messagingSystem.call( ++ "NetworkController:getNetworkClientById", ++ networkControllerState.selectedNetworkClientId ++ ); ++ const { chainId } = selectedNetworkClient.configuration; ++ if (this.chainId !== chainId) { + this.abortController.abort(); + this.abortController = new AbortController(); +- this.chainId = networkControllerState.providerConfig.chainId; ++ this.chainId = chainId; + if (this.state.preventPollingOnNetworkRestart) { + this.clearingTokenListData(); + } else { diff --git a/node_modules/@metamask/assets-controllers/dist/chunk-6W5EQ3JQ.js b/node_modules/@metamask/assets-controllers/dist/chunk-6W5EQ3JQ.js index 0dc70ec..461a210 100644 --- a/node_modules/@metamask/assets-controllers/dist/chunk-6W5EQ3JQ.js @@ -99,14 +121,14 @@ index ee6155c..06a3a04 100644 +++ b/node_modules/@metamask/assets-controllers/dist/chunk-FMZML3V5.js @@ -1,12 +1,16 @@ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/NftDetectionController.ts - + +var utils_1 = require('@metamask/utils'); - + - +var _chunkNEXY7SE2js = require('./chunk-NEXY7SE2.js'); +var MAX_GET_COLLECTION_BATCH_SIZE = 20; - - + + var _controllerutils = require('@metamask/controller-utils'); var _pollingcontroller = require('@metamask/polling-controller'); var DEFAULT_INTERVAL = 18e4; @@ -245,7 +267,7 @@ index ee6155c..06a3a04 100644 + resolve: updateSucceeded, + reject: updateFailed + } = utils_1.createDeferredPromise.call(void 0, { suppressUnhandledRejection: true }); -+ ++ + this.inProcessNftFetchingUpdates[updateKey] = inProgressUpdate; + let next; + let apiNfts= []; @@ -278,7 +300,7 @@ index ee6155c..06a3a04 100644 + batch.map((s) => ["contract", s]) + ); + params.append("chainId", "1"); -+ const collectionResponseForBatch = await _controllerutils.fetchWithErrorHandling.call(void 0, ++ const collectionResponseForBatch = await _controllerutils.fetchWithErrorHandling.call(void 0, + { + url: `${_controllerutils.NFT_API_BASE_URL}/collections?${params.toString()}`, + options: { @@ -611,8 +633,8 @@ index d429be1..6fef22b 100644 networkClientId ) ), -- this.config.openSeaEnabled && chainId === "0x1" ? _controllerutils.safelyExecute.call(void 0, -+ this.config.displayNftMedia && chainId === "0x1" ? _controllerutils.safelyExecute.call(void 0, +- this.config.openSeaEnabled && chainId === "0x1" ? _controllerutils.safelyExecute.call(void 0, ++ this.config.displayNftMedia && chainId === "0x1" ? _controllerutils.safelyExecute.call(void 0, () => this.getNftInformationFromApi(contractAddress, tokenId) ) : void 0 ]); @@ -712,7 +734,7 @@ index d429be1..6fef22b 100644 + (nft) => nft.address.toLowerCase() === singleNft.nft.address.toLowerCase() && nft.tokenId === singleNft.nft.tokenId ); if (existingEntry) { - const differentMetadata = _chunkNEXY7SE2js.compareNftMetadata.call(void 0, + const differentMetadata = _chunkNEXY7SE2js.compareNftMetadata.call(void 0, - singleNft.value.newMetadata, + singleNft.newMetadata, existingEntry @@ -812,7 +834,7 @@ index cd8f792..b20db8a 100644 "PreferencesController:getState" ); - try { -- newContractBalances[address] = _controllerutils.toHex.call(void 0, +- newContractBalances[address] = _controllerutils.toHex.call(void 0, - await _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getERC20BalanceOf).call(this, address, selectedAddress) - ); + return _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getERC20BalanceOf).call(this, address, selectedAddress).then((balance) => { @@ -849,8 +871,8 @@ index cd8f792..b20db8a 100644 _disabled = new WeakMap(); +_updateInProgress = new WeakMap(); var TokenBalancesController_default = TokenBalancesController; - - + + diff --git a/node_modules/@metamask/assets-controllers/dist/chunk-MBCN3MNX.js b/node_modules/@metamask/assets-controllers/dist/chunk-MBCN3MNX.js index b8722af..dbff48b 100644 --- a/node_modules/@metamask/assets-controllers/dist/chunk-MBCN3MNX.js @@ -904,9 +926,9 @@ index 8c506d9..bd798ec 100644 }, {} @@ -205,5 +216,5 @@ async function fetchTokenContractExchangeRates({ - - - + + + -exports.TOKEN_PRICES_BATCH_SIZE = TOKEN_PRICES_BATCH_SIZE; exports.compareNftMetadata = compareNftMetadata; exports.formatAggregatorNames = formatAggregatorNames; exports.formatIconUrlWithProxy = formatIconUrlWithProxy; exports.SupportedTokenDetectionNetworks = SupportedTokenDetectionNetworks; exports.isTokenDetectionSupportedForNetwork = isTokenDetectionSupportedForNetwork; exports.isTokenListSupportedForNetwork = isTokenListSupportedForNetwork; exports.removeIpfsProtocolPrefix = removeIpfsProtocolPrefix; exports.getIpfsCIDv1AndPath = getIpfsCIDv1AndPath; exports.getFormattedIpfsUrl = getFormattedIpfsUrl; exports.addUrlProtocolPrefix = addUrlProtocolPrefix; exports.ethersBigNumberToBN = ethersBigNumberToBN; exports.divideIntoBatches = divideIntoBatches; exports.reduceInBatchesSerially = reduceInBatchesSerially; exports.fetchTokenContractExchangeRates = fetchTokenContractExchangeRates; +exports.TOKEN_PRICES_BATCH_SIZE = TOKEN_PRICES_BATCH_SIZE; exports.compareNftMetadata = compareNftMetadata; exports.hasNewCollectionFields = hasNewCollectionFields; exports.formatAggregatorNames = formatAggregatorNames; exports.formatIconUrlWithProxy = formatIconUrlWithProxy; exports.SupportedTokenDetectionNetworks = SupportedTokenDetectionNetworks; exports.isTokenDetectionSupportedForNetwork = isTokenDetectionSupportedForNetwork; exports.isTokenListSupportedForNetwork = isTokenListSupportedForNetwork; exports.removeIpfsProtocolPrefix = removeIpfsProtocolPrefix; exports.getIpfsCIDv1AndPath = getIpfsCIDv1AndPath; exports.getFormattedIpfsUrl = getFormattedIpfsUrl; exports.addUrlProtocolPrefix = addUrlProtocolPrefix; exports.ethersBigNumberToBN = ethersBigNumberToBN; exports.divideIntoBatches = divideIntoBatches; exports.reduceInBatchesSerially = reduceInBatchesSerially; exports.fetchTokenContractExchangeRates = fetchTokenContractExchangeRates; //# sourceMappingURL=chunk-NEXY7SE2.js.map @@ -1016,7 +1038,7 @@ index 9016c5f..a24805e 100644 +export type GetCollectionsResponse = { + collections: CollectionResponse[]; + }; -+ ++ +export type CollectionResponse = { + id?: string; + openseaVerificationStatus?: string; @@ -1039,7 +1061,7 @@ index 9016c5f..a24805e 100644 + rawData?: Metadata; + isNativeOffChainCancellable?: boolean; +}; -+ ++ +export type SourceCollection = { + id: string; + domain: string; @@ -1059,7 +1081,7 @@ index 9016c5f..a24805e 100644 -}; + floorAsk?: FloorAskCollection; + }; -+ ++ +export type Collection = TokenCollection & CollectionResponse; + export type Royalties = { From c774787a2da9e90d2b08135dc931168842d64761 Mon Sep 17 00:00:00 2001 From: Nico MASSART Date: Mon, 14 Oct 2024 19:24:10 +0200 Subject: [PATCH 10/45] Bump version to 1456 for 7.33.0 RC-4 (#11784) Bump version to 1456 for 7.33.0 RC-4 --- android/app/build.gradle | 2 +- bitrise.yml | 4 ++-- ios/MetaMask.xcodeproj/project.pbxproj | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 3844583ba8a..6a40a9f84ba 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -174,7 +174,7 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionName "7.33.0" - versionCode 1454 + versionCode 1456 testBuildType System.getProperty('testBuildType', 'debug') missingDimensionStrategy 'react-native-camera', 'general' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/bitrise.yml b/bitrise.yml index 1edf9023ba1..4e2a46785ea 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -1500,13 +1500,13 @@ app: VERSION_NAME: 7.33.0 - opts: is_expand: false - VERSION_NUMBER: 1454 + VERSION_NUMBER: 1456 - opts: is_expand: false FLASK_VERSION_NAME: 7.33.0 - opts: is_expand: false - FLASK_VERSION_NUMBER: 1454 + FLASK_VERSION_NUMBER: 1456 - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index 49b2812b936..e47cd61c2e0 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -1273,7 +1273,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1454; + CURRENT_PROJECT_VERSION = 1456; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1338,7 +1338,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1454; + CURRENT_PROJECT_VERSION = 1456; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1401,7 +1401,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1454; + CURRENT_PROJECT_VERSION = 1456; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1462,7 +1462,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1454; + CURRENT_PROJECT_VERSION = 1456; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1616,7 +1616,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1454; + CURRENT_PROJECT_VERSION = 1456; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1684,7 +1684,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1454; + CURRENT_PROJECT_VERSION = 1456; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; From 3e564e19c884ecce895000e86552a2e148b08e46 Mon Sep 17 00:00:00 2001 From: "runway-github[bot]" <73448015+runway-github[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:40:50 -0600 Subject: [PATCH 11/45] chore(runway): cherry-pick chore(ramp): upgrade sdk to 1.28.5 (#11790) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - chore(ramp): upgrade sdk to 1.28.5 (#11788) ## **Description** - update on-ramp-sdk to version 1.28.5, which removes a unused dependency ## **Related issues** Fixes: [dependency issue](https://github.com/MetaMask/metamask-mobile/actions/runs/11332800511/job/31515686025?pr=11787) ## **Manual testing steps** - go to buy crypto - request a quote - quote should be provided ## **Screenshots/Recordings** N/A ### **Before** N/A ### **After** N/A ## **Pre-merge author checklist** - [x] I’ve followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. [4f8f66c](https://github.com/MetaMask/metamask-mobile/commit/4f8f66c2e2e74b787876e88c51edb351b671a25e) Co-authored-by: Pedro Pablo Aste Kompen --- package.json | 2 +- yarn.lock | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 4c0e6d25fda..85f1fdb46ab 100644 --- a/package.json +++ b/package.json @@ -136,7 +136,7 @@ "send": "0.19.0" }, "dependencies": { - "@consensys/on-ramp-sdk": "1.28.3", + "@consensys/on-ramp-sdk": "1.28.5", "@ethersproject/abi": "^5.7.0", "@keystonehq/bc-ur-registry-eth": "^0.19.1", "@keystonehq/metamask-airgapped-keyring": "^0.13.1", diff --git a/yarn.lock b/yarn.lock index f5cafcca92f..bbfd2eca5e9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1288,16 +1288,15 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0" integrity sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA== -"@consensys/on-ramp-sdk@1.28.3": - version "1.28.3" - resolved "https://registry.yarnpkg.com/@consensys/on-ramp-sdk/-/on-ramp-sdk-1.28.3.tgz#5c7c9293f6ee83e1a681a6a76f982e801d3e75ec" - integrity sha512-QwWBFFqP3NMOhcJmcfmFd6fpEU3iXI/tYdWXM8u679/mY1/2rnRKUc3RnuWGFgs3qESZ5sUG2Xc7cp5OrmnDgA== +"@consensys/on-ramp-sdk@1.28.5": + version "1.28.5" + resolved "https://registry.yarnpkg.com/@consensys/on-ramp-sdk/-/on-ramp-sdk-1.28.5.tgz#b9ff6c2b0f46abef30bd32a720f34d963aa76491" + integrity sha512-tBZ2ZsEz+du/vHF4NChTTvcdYddoJCtNZDZj5lry8/TeNxctnYiZGx2tHtw2GJHfYa9Uuux2hwtdhubcR//ZeA== dependencies: async "^3.2.3" axios "^0.28.0" axios-retry "^3.1.2" crypto-js "^4.2.0" - jsonpath-plus "^7.2.0" reflect-metadata "^0.1.13" uuid "^9.0.0" From 93ec320491560ef671ab4031c8fe910e22a0031d Mon Sep 17 00:00:00 2001 From: sethkfman <10342624+sethkfman@users.noreply.github.com> Date: Mon, 14 Oct 2024 15:16:51 -0600 Subject: [PATCH 12/45] chore: cherry pick 6db794f7dc4799918dc83c97211db25d5a6542e2 (#11791) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** Cherry pick for #11785 ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. Co-authored-by: Nico MASSART --- .../UI/Notification/NotificationMenuItem/Content.test.tsx | 5 +++-- .../NotificationMenuItem/__snapshots__/Content.test.tsx.snap | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/components/UI/Notification/NotificationMenuItem/Content.test.tsx b/app/components/UI/Notification/NotificationMenuItem/Content.test.tsx index 1a65102a1ad..c227b206ec5 100644 --- a/app/components/UI/Notification/NotificationMenuItem/Content.test.tsx +++ b/app/components/UI/Notification/NotificationMenuItem/Content.test.tsx @@ -5,14 +5,15 @@ import NotificationContent from './Content'; describe('NotificationContent', () => { const title = 'Welcome to the new Test!'; - const createdAt = '2024-04-26T16:35:03.147606Z'; + const yesterday = new Date().setDate(new Date().getDate() - 1); + const createdAt = new Date(yesterday).toISOString(); // Relative date: one day before current date const description = { start: 'We are excited to announce the launch of our brand new website and app!', end: 'Ethereum', }; - it('renders correctly', () => { + it('render matches snapshot', () => { const { toJSON } = renderWithProvider( - 5 months ago + Yesterday Date: Mon, 14 Oct 2024 15:46:47 -0600 Subject: [PATCH 13/45] chore: cherry-pick #11760 (#11773) This PR cherry-picks #11760 Co-authored-by: Nico MASSART Co-authored-by: sethkfman <10342624+sethkfman@users.noreply.github.com> --- app/components/Nav/Main/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/components/Nav/Main/index.js b/app/components/Nav/Main/index.js index d800e78ce30..ebb19b219c8 100644 --- a/app/components/Nav/Main/index.js +++ b/app/components/Nav/Main/index.js @@ -458,7 +458,6 @@ const MainFlow = () => ( mode={'modal'} screenOptions={{ headerShown: false, - cardStyle: { backgroundColor: importedColors.transparent }, }} > From e7ae6953c76be388263cb15f0efc2786dd11ebd5 Mon Sep 17 00:00:00 2001 From: sethkfman Date: Mon, 14 Oct 2024 16:25:38 -0600 Subject: [PATCH 14/45] bump version 1458 --- android/app/build.gradle | 2 +- bitrise.yml | 4 ++-- ios/MetaMask.xcodeproj/project.pbxproj | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 6a40a9f84ba..f5591a45d27 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -174,7 +174,7 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionName "7.33.0" - versionCode 1456 + versionCode 1458 testBuildType System.getProperty('testBuildType', 'debug') missingDimensionStrategy 'react-native-camera', 'general' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/bitrise.yml b/bitrise.yml index 4e2a46785ea..f58ba65ebc0 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -1500,13 +1500,13 @@ app: VERSION_NAME: 7.33.0 - opts: is_expand: false - VERSION_NUMBER: 1456 + VERSION_NUMBER: 1458 - opts: is_expand: false FLASK_VERSION_NAME: 7.33.0 - opts: is_expand: false - FLASK_VERSION_NUMBER: 1456 + FLASK_VERSION_NUMBER: 1458 - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index e47cd61c2e0..d51d4be4a9a 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -1273,7 +1273,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1456; + CURRENT_PROJECT_VERSION = 1458; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1338,7 +1338,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1456; + CURRENT_PROJECT_VERSION = 1458; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1401,7 +1401,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1456; + CURRENT_PROJECT_VERSION = 1458; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1462,7 +1462,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1456; + CURRENT_PROJECT_VERSION = 1458; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1616,7 +1616,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1456; + CURRENT_PROJECT_VERSION = 1458; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1684,7 +1684,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1456; + CURRENT_PROJECT_VERSION = 1458; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; From 165846c7d6a11c58ab898ba6c214d101345d9687 Mon Sep 17 00:00:00 2001 From: "runway-github[bot]" <73448015+runway-github[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2024 18:10:19 +0200 Subject: [PATCH 15/45] chore(runway): cherry-pick chore: Update Sentry Performance Sampling utils.js (#11806) cherry-pick chore: Update Sentry Performance Sampling utils.js (#11806) --- app/util/sentry/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/util/sentry/utils.js b/app/util/sentry/utils.js index 26448b31041..024422616a6 100644 --- a/app/util/sentry/utils.js +++ b/app/util/sentry/utils.js @@ -503,7 +503,7 @@ export function setupSentry() { ] : integrations, // Set tracesSampleRate to 1.0, as that ensures that every transaction will be sent to Sentry for development builds. - tracesSampleRate: __DEV__ ? 1.0 : 0.08, + tracesSampleRate: __DEV__ ? 1.0 : 0.04, beforeSend: (report) => rewriteReport(report), beforeBreadcrumb: (breadcrumb) => rewriteBreadcrumb(breadcrumb), beforeSendTransaction: (event) => excludeEvents(event), From 8581bbc170f54ea890525572f5376c82230e76a4 Mon Sep 17 00:00:00 2001 From: "runway-github[bot]" <73448015+runway-github[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2024 09:47:58 -0700 Subject: [PATCH 16/45] chore(runway): cherry-pick fix: persist token and phishing list (#11807) cherry-pick fix: persist token and phishing list #11802 Co-authored-by: tommasini <46944231+tommasini@users.noreply.github.com> Co-authored-by: Aslau Mario-Daniel Co-authored-by: Nico MASSART --- app/core/EngineService/EngineService.ts | 2 +- app/store/persistConfig.ts | 16 +++------------- wdio/step-definitions/common-steps.js | 1 - 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/app/core/EngineService/EngineService.ts b/app/core/EngineService/EngineService.ts index 7f5334a80f0..755beffa084 100644 --- a/app/core/EngineService/EngineService.ts +++ b/app/core/EngineService/EngineService.ts @@ -74,7 +74,7 @@ class EngineService { }, { name: 'PhishingController', - key: `${engine.context.PhishingController.name}:maybeUpdateState`, + key: `${engine.context.PhishingController.name}:stateChange`, }, { name: 'PreferencesController', diff --git a/app/store/persistConfig.ts b/app/store/persistConfig.ts index 2cd7477a432..bab5f5d74fe 100644 --- a/app/store/persistConfig.ts +++ b/app/store/persistConfig.ts @@ -68,14 +68,9 @@ const persistTransform = createTransform( return inboundState; } - const { - TokenListController, - SwapsController, - PhishingController, - ...controllers - } = inboundState.backgroundState || {}; - const { tokenList, tokensChainsCache, ...persistedTokenListController } = - TokenListController; + const { SwapsController, ...controllers } = + inboundState.backgroundState || {}; + const { aggregatorMetadata, aggregatorMetadataLastFetched, @@ -87,16 +82,11 @@ const persistTransform = createTransform( ...persistedSwapsController } = SwapsController; - const { phishingLists, whitelist, ...persistedPhishingController } = - PhishingController; - // Reconstruct data to persist const newState = { backgroundState: { ...controllers, - TokenListController: persistedTokenListController, SwapsController: persistedSwapsController, - PhishingController: persistedPhishingController, }, }; return newState; diff --git a/wdio/step-definitions/common-steps.js b/wdio/step-definitions/common-steps.js index 39f06270b6d..69da7223da4 100644 --- a/wdio/step-definitions/common-steps.js +++ b/wdio/step-definitions/common-steps.js @@ -54,7 +54,6 @@ Given(/^I have imported my wallet$/, async () => { await MetaMetricsScreen.isScreenTitleVisible(); await MetaMetricsScreen.tapIAgreeButton(); await TermOfUseScreen.isDisplayed(); - await TermOfUseScreen.textIsDisplayed(); await TermOfUseScreen.tapAgreeCheckBox(); await TermOfUseScreen.tapScrollEndButton(); if (!(await TermOfUseScreen.isCheckBoxChecked())) { From 0556903235b858b59a264b764eb1a0a8733b7bdf Mon Sep 17 00:00:00 2001 From: sethkfman <10342624+sethkfman@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:12:45 -0600 Subject: [PATCH 17/45] chore: cherry pick 9ac1488 (#11822) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** cherry pick 9ac1488 ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. Co-authored-by: Aslau Mario-Daniel --- app/components/Nav/App/index.js | 11 ++++- app/components/Views/LockScreen/index.js | 18 ++++++-- app/components/Views/Login/index.js | 31 ++++++++++++- app/components/Views/Onboarding/index.js | 38 ++++++++++------ app/components/Views/Wallet/index.tsx | 1 + app/store/index.ts | 58 ++++++++++++++++++++++-- app/util/trace.ts | 38 +++++++++++++++- 7 files changed, 168 insertions(+), 27 deletions(-) diff --git a/app/components/Nav/App/index.js b/app/components/Nav/App/index.js index 27bc4c34d8d..1b33dc8a4f5 100644 --- a/app/components/Nav/App/index.js +++ b/app/components/Nav/App/index.js @@ -127,6 +127,7 @@ import { SnapsExecutionWebView } from '../../../lib/snaps'; import OptionsSheet from '../../UI/SelectOptionSheet/OptionsSheet'; import FoxLoader from '../../../components/UI/FoxLoader'; import { AppStateEventProcessor } from '../../../core/AppStateEventListener'; +import { trace, TraceName, TraceOperation } from '../../../util/trace'; const clearStackNavigatorOptions = { headerShown: false, @@ -335,7 +336,15 @@ const App = (props) => { setOnboarded(!!existingUser); try { if (existingUser) { - await Authentication.appTriggeredAuth(); + await trace( + { + name: TraceName.BiometricAuthentication, + op: TraceOperation.BiometricAuthentication, + }, + async () => { + await Authentication.appTriggeredAuth(); + }, + ); // we need to reset the navigator here so that the user cannot go back to the login screen navigator.reset({ routes: [{ name: Routes.ONBOARDING.HOME_NAV }] }); } else { diff --git a/app/components/Views/LockScreen/index.js b/app/components/Views/LockScreen/index.js index 92f04193389..030bc9ace1d 100644 --- a/app/components/Views/LockScreen/index.js +++ b/app/components/Views/LockScreen/index.js @@ -22,6 +22,7 @@ import { import Routes from '../../../constants/navigation/Routes'; import { CommonActions } from '@react-navigation/native'; import trackErrorAsAnalytics from '../../../util/metrics/TrackError/trackErrorAsAnalytics'; +import { trace, TraceName, TraceOperation } from '../../../util/trace'; const LOGO_SIZE = 175; const createStyles = (colors) => @@ -134,10 +135,19 @@ class LockScreen extends PureComponent { // Retrieve the credentials Logger.log('Lockscreen::unlockKeychain - getting credentials'); - await Authentication.appTriggeredAuth({ - bioStateMachineId, - disableAutoLogout: true, - }); + await trace( + { + name: TraceName.BiometricAuthentication, + op: TraceOperation.BiometricAuthentication, + }, + async () => { + await Authentication.appTriggeredAuth({ + bioStateMachineId, + disableAutoLogout: true, + }); + }, + ); + this.setState({ ready: true }); Logger.log('Lockscreen::unlockKeychain - state: ready'); } catch (error) { diff --git a/app/components/Views/Login/index.js b/app/components/Views/Login/index.js index 7820e848bb5..4c1473a8090 100644 --- a/app/components/Views/Login/index.js +++ b/app/components/Views/Login/index.js @@ -59,6 +59,12 @@ import { LoginViewSelectors } from '../../../../e2e/selectors/LoginView.selector import { withMetricsAwareness } from '../../../components/hooks/useMetrics'; import trackErrorAsAnalytics from '../../../util/metrics/TrackError/trackErrorAsAnalytics'; import { downloadStateLogs } from '../../../util/logs'; +import { + trace, + endTrace, + TraceName, + TraceOperation, +} from '../../../util/trace'; const deviceHeight = Device.getDeviceHeight(); const breakPoint = deviceHeight < 700; @@ -245,6 +251,10 @@ class Login extends PureComponent { fieldRef = React.createRef(); async componentDidMount() { + trace({ + name: TraceName.LoginToPasswordEntry, + op: TraceOperation.LoginToPasswordEntry, + }); this.props.metrics.trackEvent(MetaMetricsEvents.LOGIN_SCREEN_VIEWED); BackHandler.addEventListener('hardwareBackPress', this.handleBackPress); @@ -368,7 +378,15 @@ class Login extends PureComponent { ); try { - await Authentication.userEntryAuth(password, authType); + await trace( + { + name: TraceName.AuthenticateUser, + op: TraceOperation.AuthenticateUser, + }, + async () => { + await Authentication.userEntryAuth(password, authType); + }, + ); Keyboard.dismiss(); @@ -436,7 +454,15 @@ class Login extends PureComponent { const { current: field } = this.fieldRef; field?.blur(); try { - await Authentication.appTriggeredAuth(); + await trace( + { + name: TraceName.BiometricAuthentication, + op: TraceOperation.BiometricAuthentication, + }, + async () => { + await Authentication.appTriggeredAuth(); + }, + ); const onboardingWizard = await StorageWrapper.getItem(ONBOARDING_WIZARD); if (!onboardingWizard) this.props.setOnboardingWizardStep(1); this.props.navigation.replace(Routes.ONBOARDING.HOME_NAV); @@ -455,6 +481,7 @@ class Login extends PureComponent { }; triggerLogIn = () => { + endTrace({ name: TraceName.LoginToPasswordEntry }); this.onLogin(); }; diff --git a/app/components/Views/Onboarding/index.js b/app/components/Views/Onboarding/index.js index f15aa33c3c5..52ea24f6192 100644 --- a/app/components/Views/Onboarding/index.js +++ b/app/components/Views/Onboarding/index.js @@ -49,6 +49,7 @@ import { OnboardingSelectorIDs } from '../../../../e2e/selectors/Onboarding/Onbo import Routes from '../../../constants/navigation/Routes'; import { selectAccounts } from '../../../selectors/accountTrackerController'; import trackOnboarding from '../../../util/metrics/TrackOnboarding/trackOnboarding'; +import { trace, TraceName, TraceOperation } from '../../../util/trace'; const createStyles = (colors) => StyleSheet.create({ @@ -275,24 +276,33 @@ class Onboarding extends PureComponent { }; onPressCreate = () => { - const action = async () => { - const { metrics } = this.props; - if (metrics.isEnabled()) { - this.props.navigation.navigate('ChoosePassword', { - [PREVIOUS_SCREEN]: ONBOARDING, - }); - this.track(MetaMetricsEvents.WALLET_SETUP_STARTED); - } else { - this.props.navigation.navigate('OptinMetrics', { - onContinue: () => { - this.props.navigation.replace('ChoosePassword', { + const action = () => { + trace( + { + name: TraceName.CreateNewWalletToChoosePassword, + op: TraceOperation.CreateNewWalletToChoosePassword, + }, + () => { + const { metrics } = this.props; + if (metrics.isEnabled()) { + this.props.navigation.navigate('ChoosePassword', { [PREVIOUS_SCREEN]: ONBOARDING, }); this.track(MetaMetricsEvents.WALLET_SETUP_STARTED); - }, - }); - } + } else { + this.props.navigation.navigate('OptinMetrics', { + onContinue: () => { + this.props.navigation.replace('ChoosePassword', { + [PREVIOUS_SCREEN]: ONBOARDING, + }); + this.track(MetaMetricsEvents.WALLET_SETUP_STARTED); + }, + }); + } + }, + ); }; + this.handleExistingUser(action); }; diff --git a/app/components/Views/Wallet/index.tsx b/app/components/Views/Wallet/index.tsx index 886a36d645a..2a6da7d8581 100644 --- a/app/components/Views/Wallet/index.tsx +++ b/app/components/Views/Wallet/index.tsx @@ -96,6 +96,7 @@ import { } from '../../../selectors/notifications'; import { ButtonVariants } from '../../../component-library/components/Buttons/Button'; import { useListNotifications } from '../../../util/notifications/hooks/useNotifications'; + const createStyles = ({ colors, typography }: Theme) => StyleSheet.create({ base: { diff --git a/app/store/index.ts b/app/store/index.ts index aa7a4df512f..84a500f8784 100644 --- a/app/store/index.ts +++ b/app/store/index.ts @@ -9,6 +9,9 @@ import { Authentication } from '../core'; import LockManagerService from '../core/LockManagerService'; import ReadOnlyNetworkStore from '../util/test/network-store'; import { isE2E } from '../util/test/utils'; +import { trace, endTrace, TraceName, TraceOperation } from '../util/trace'; +import StorageWrapper from './storage-wrapper'; + import thunk from 'redux-thunk'; import persistConfig from './persistConfig'; @@ -24,7 +27,7 @@ const pReducer = persistReducer(persistConfig, rootReducer); // TODO: Replace "any" with type // eslint-disable-next-line @typescript-eslint/no-explicit-any, import/no-mutable-exports let store: Store, persistor; -const createStoreAndPersistor = async () => { +const createStoreAndPersistor = async (appStartTime: number) => { // Obtain the initial state from ReadOnlyNetworkStore for E2E tests. const initialState = isE2E ? await ReadOnlyNetworkStore.getState() @@ -46,6 +49,24 @@ const createStoreAndPersistor = async () => { middlewares.push(createReduxFlipperDebugger()); } + const jsStartTime = performance.now(); + + trace({ + name: TraceName.LoadScripts, + op: TraceOperation.LoadScripts, + startTime: appStartTime, + }); + + endTrace({ + name: TraceName.LoadScripts, + timestamp: appStartTime + jsStartTime, + }); + + trace({ + name: TraceName.CreateStore, + op: TraceOperation.CreateStore, + }); + store = configureStore({ reducer: pReducer, middleware: middlewares, @@ -54,10 +75,19 @@ const createStoreAndPersistor = async () => { sagaMiddleware.run(rootSaga); + endTrace({ name: TraceName.CreateStore }); + + trace({ + name: TraceName.StorageRehydration, + op: TraceOperation.StorageRehydration, + }); + /** * Initialize services after persist is completed */ - const onPersistComplete = () => { + const onPersistComplete = async () => { + endTrace({ name: TraceName.StorageRehydration }); + /** * EngineService.initalizeEngine(store) with SES/lockdown: * Requires ethjs nested patches (lib->src) @@ -73,6 +103,7 @@ const createStoreAndPersistor = async () => { * - TypeError: undefined is not an object (evaluating 'TokenListController.tokenList') * - V8: SES_UNHANDLED_REJECTION */ + store.dispatch({ type: 'TOGGLE_BASIC_FUNCTIONALITY', basicFunctionalityEnabled: @@ -83,7 +114,17 @@ const createStoreAndPersistor = async () => { store.dispatch({ type: 'FETCH_FEATURE_FLAGS', }); - EngineService.initalizeEngine(store); + + await trace( + { + name: TraceName.EngineInitialization, + op: TraceOperation.EngineInitialization, + }, + () => { + EngineService.initalizeEngine(store); + }, + ); + Authentication.init(store); AppStateEventProcessor.init(store); LockManagerService.init(store); @@ -93,7 +134,16 @@ const createStoreAndPersistor = async () => { }; (async () => { - await createStoreAndPersistor(); + const appStartTime = await StorageWrapper.getItem('appStartTime'); + + await trace( + { + name: TraceName.UIStartup, + op: TraceOperation.UIStartup, + startTime: appStartTime, + }, + async () => await createStoreAndPersistor(appStartTime), + ); })(); export { store, persistor }; diff --git a/app/util/trace.ts b/app/util/trace.ts index d74ca003249..fd6b4c9dfb3 100644 --- a/app/util/trace.ts +++ b/app/util/trace.ts @@ -16,6 +16,32 @@ export enum TraceName { Middleware = 'Middleware', NestedTest1 = 'Nested Test 1', NestedTest2 = 'Nested Test 2', + NotificationDisplay = 'Notification Display', + PPOMValidation = 'PPOM Validation', + Signature = 'Signature', + LoadScripts = 'Load Scripts', + SetupStore = 'Setup Store', + LoginToPasswordEntry = 'Login to Password Entry', + AuthenticateUser = 'Authenticate User', + BiometricAuthentication = 'Biometrics Authentication', + EngineInitialization = 'Engine Initialization', + CreateStore = 'Create Store', + CreateNewWalletToChoosePassword = 'Create New Wallet to Choose Password', + StorageRehydration = 'Storage Rehydration', + UIStartup = 'Custom UIStartup', +} + +export enum TraceOperation { + LoadScripts = 'custom.load.scripts', + SetupStore = 'custom.setup.store', + LoginToPasswordEntry = 'custom.login.to.password.entry', + BiometricAuthentication = 'biometrics.authentication', + AuthenticateUser = 'custom.authenticate.user', + EngineInitialization = 'custom.engine.initialization', + CreateStore = 'custom.create.store', + CreateNewWalletToChoosePassword = 'custom.create.new.wallet', + StorageRehydration = 'custom.storage.rehydration', + UIStartup = 'custom.ui.startup', } const ID_DEFAULT = 'default'; @@ -42,6 +68,7 @@ export interface TraceRequest { parentContext?: TraceContext; startTime?: number; tags?: Record; + op?: string; } export interface EndTraceRequest { @@ -151,13 +178,20 @@ function startSpan( request: TraceRequest, callback: (spanOptions: StartSpanOptions) => T, ) { - const { data: attributes, name, parentContext, startTime, tags } = request; + const { + data: attributes, + name, + parentContext, + startTime, + tags, + op, + } = request; const parentSpan = (parentContext ?? null) as Span | null; const spanOptions: StartSpanOptions = { attributes, name, - op: OP_DEFAULT, + op: op || OP_DEFAULT, // This needs to be parentSpan once we have the withIsolatedScope implementation in place in the Sentry SDK for React Native // Reference PR that updates @sentry/react-native: https://github.com/getsentry/sentry-react-native/pull/3895 parentSpanId: parentSpan?.spanId, From 97d464094a3df09e44b8f7fe16047979c1ca8340 Mon Sep 17 00:00:00 2001 From: tommasini <46944231+tommasini@users.noreply.github.com> Date: Wed, 16 Oct 2024 20:02:00 +0100 Subject: [PATCH 18/45] chore: cherry pick tags for custom instrumentation (#11826) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --------- Co-authored-by: Cal Leung Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> ## **Description** cherry pick tags [PR](https://github.com/MetaMask/metamask-mobile/pull/11623) to the 7.33.0 ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- app/selectors/nftController.ts | 13 +- app/selectors/tokensController.ts | 20 +++ app/store/index.ts | 2 + app/util/sentry/tags/index.test.ts | 229 +++++++++++++++++++++++++++++ app/util/sentry/tags/index.ts | 30 ++++ app/util/trace.test.ts | 54 +++++-- app/util/trace.ts | 141 ++++++++++++++++-- e2e/fixtures/fixture-builder.js | 12 ++ 8 files changed, 469 insertions(+), 32 deletions(-) create mode 100644 app/util/sentry/tags/index.test.ts create mode 100644 app/util/sentry/tags/index.ts diff --git a/app/selectors/nftController.ts b/app/selectors/nftController.ts index 5d6a0239ee7..a56b5e9afed 100644 --- a/app/selectors/nftController.ts +++ b/app/selectors/nftController.ts @@ -1,5 +1,5 @@ import { createSelector } from 'reselect'; -import { NftState } from '@metamask/assets-controllers'; +import { Nft, NftState } from '@metamask/assets-controllers'; import { RootState } from '../reducers'; const selectNftControllerState = (state: RootState) => @@ -14,3 +14,14 @@ export const selectAllNfts = createSelector( selectNftControllerState, (nftControllerState: NftState) => nftControllerState.allNfts, ); + +export const selectAllNftsFlat = createSelector( + selectAllNfts, + (nftsByChainByAccount) => { + const nftsByChainArray = Object.values(nftsByChainByAccount); + return nftsByChainArray.reduce((acc, nftsByChain) => { + const nftsArrays = Object.values(nftsByChain); + return acc.concat(...nftsArrays); + }, [] as Nft[]); + }, +); diff --git a/app/selectors/tokensController.ts b/app/selectors/tokensController.ts index 9ff4b872e3c..3d91c000eef 100644 --- a/app/selectors/tokensController.ts +++ b/app/selectors/tokensController.ts @@ -34,3 +34,23 @@ export const selectDetectedTokens = createSelector( selectTokensControllerState, (tokensControllerState: TokensState) => tokensControllerState?.detectedTokens, ); + +const selectAllTokens = createSelector( + selectTokensControllerState, + (tokensControllerState: TokensState) => tokensControllerState?.allTokens, +); + +export const selectAllTokensFlat = createSelector( + selectAllTokens, + (tokensByAccountByChain) => { + if (Object.values(tokensByAccountByChain).length === 0) { + return []; + } + const tokensByAccountArray = Object.values(tokensByAccountByChain); + + return tokensByAccountArray.reduce((acc, tokensByAccount) => { + const tokensArray = Object.values(tokensByAccount); + return acc.concat(...tokensArray); + }, [] as Token[]); + }, +); diff --git a/app/store/index.ts b/app/store/index.ts index 84a500f8784..9cc858e9ac0 100644 --- a/app/store/index.ts +++ b/app/store/index.ts @@ -16,6 +16,7 @@ import thunk from 'redux-thunk'; import persistConfig from './persistConfig'; import { AppStateEventProcessor } from '../core/AppStateEventListener'; +import { getTraceTags } from '../util/sentry/tags'; // TODO: Improve type safety by using real Action types instead of `any` // TODO: Replace "any" with type @@ -119,6 +120,7 @@ const createStoreAndPersistor = async (appStartTime: number) => { { name: TraceName.EngineInitialization, op: TraceOperation.EngineInitialization, + tags: getTraceTags(store.getState?.()), }, () => { EngineService.initalizeEngine(store); diff --git a/app/util/sentry/tags/index.test.ts b/app/util/sentry/tags/index.test.ts new file mode 100644 index 00000000000..5511ab7cf92 --- /dev/null +++ b/app/util/sentry/tags/index.test.ts @@ -0,0 +1,229 @@ +import { RootState } from '../../../reducers'; +import { getTraceTags } from './'; +import initialRootState, { + backgroundState, +} from '../../../util/test/initial-root-state'; +import { userInitialState } from '../../../reducers/user'; +import { createMockAccountsControllerState } from '../../../util/test/accountsControllerTestUtils'; + +describe('Tags Utils', () => { + beforeEach(() => { + jest.resetAllMocks(); + }); + + describe('getTraceTags', () => { + it('includes if unlocked', () => { + const state = { + ...initialRootState, + user: { ...userInitialState, userLoggedIn: true }, + }; + + const tags = getTraceTags(state); + + expect(tags?.['wallet.unlocked']).toStrictEqual(true); + }); + + it('includes if not unlocked', () => { + const state = { + ...initialRootState, + user: { ...userInitialState, userLoggedIn: false }, + }; + + const tags = getTraceTags(state); + + expect(tags?.['wallet.unlocked']).toStrictEqual(false); + }); + + it('includes pending approval type', () => { + const state = { + ...initialRootState, + engine: { + backgroundState: { + ...backgroundState, + ApprovalController: { + ...backgroundState.ApprovalController, + pendingApprovals: { + 1: { + type: 'eth_sendTransaction', + }, + }, + }, + }, + }, + } as unknown as RootState; + + const tags = getTraceTags(state); + + expect(tags?.['wallet.pending_approval']).toStrictEqual( + 'eth_sendTransaction', + ); + }); + + it('includes first pending approval type if multiple', () => { + const state = { + ...initialRootState, + engine: { + backgroundState: { + ...backgroundState, + + ApprovalController: { + ...backgroundState.ApprovalController, + pendingApprovals: { + 1: { + type: 'eth_sendTransaction', + }, + 2: { + type: 'personal_sign', + }, + }, + }, + }, + }, + } as unknown as RootState; + + const tags = getTraceTags(state); + + expect(tags?.['wallet.pending_approval']).toStrictEqual( + 'eth_sendTransaction', + ); + }); + + it('includes account count', () => { + const state = { + ...initialRootState, + engine: { + backgroundState: { + ...backgroundState, + AccountsController: createMockAccountsControllerState([ + '0x1234', + '0x4321', + ]), + }, + }, + } as unknown as RootState; + + const tags = getTraceTags(state); + + expect(tags?.['wallet.account_count']).toStrictEqual(2); + }); + + it('includes nft count', () => { + const state = { + ...initialRootState, + engine: { + backgroundState: { + ...backgroundState, + NftController: { + ...backgroundState.NftController, + allNfts: { + '0x1234': { + '0x1': [ + { + tokenId: '1', + }, + { + tokenId: '2', + }, + ], + '0x2': [ + { + tokenId: '3', + }, + { + tokenId: '4', + }, + ], + }, + '0x4321': { + '0x3': [ + { + tokenId: '5', + }, + ], + }, + }, + }, + }, + }, + } as unknown as RootState; + + const tags = getTraceTags(state); + + expect(tags?.['wallet.nft_count']).toStrictEqual(5); + }); + + it('includes notification count', () => { + const state = { + ...initialRootState, + engine: { + backgroundState: { + ...backgroundState, + NotificationServicesController: { + metamaskNotificationsList: [{}, {}, {}], + }, + }, + }, + } as unknown as RootState; + + const tags = getTraceTags(state); + + expect(tags?.['wallet.notification_count']).toStrictEqual(3); + }); + + it('includes token count', () => { + const state = { + ...initialRootState, + engine: { + backgroundState: { + ...backgroundState, + TokensController: { + allTokens: { + '0x1': { + '0x1234': [{}, {}], + '0x4321': [{}], + }, + '0x2': { + '0x5678': [{}], + }, + }, + }, + }, + }, + } as unknown as RootState; + + const tags = getTraceTags(state); + + expect(tags?.['wallet.token_count']).toStrictEqual(4); + }); + + it('includes transaction count', () => { + const state = { + ...initialRootState, + engine: { + backgroundState: { + ...backgroundState, + TransactionController: { + transactions: [ + { + id: 1, + chainId: '0x1', + }, + { + id: 2, + chainId: '0x1', + }, + { + id: 3, + chainId: '0x2', + }, + ], + }, + }, + }, + } as unknown as RootState; + const tags = getTraceTags(state); + + expect(tags?.['wallet.transaction_count']).toStrictEqual(3); + }); + }); +}); diff --git a/app/util/sentry/tags/index.ts b/app/util/sentry/tags/index.ts new file mode 100644 index 00000000000..796bb9212fe --- /dev/null +++ b/app/util/sentry/tags/index.ts @@ -0,0 +1,30 @@ +import { RootState } from '../../../reducers'; +import { selectAllNftsFlat } from '../../../selectors/nftController'; +import { selectInternalAccounts } from '../../../selectors/accountsController'; +import { selectAllTokensFlat } from '../../../selectors/tokensController'; +import { getNotificationsList } from '../../../selectors/notifications'; +import { selectTransactions } from '../../../selectors/transactionController'; +import { selectPendingApprovals } from '../../../selectors/approvalController'; + +export function getTraceTags(state: RootState) { + if (!Object.keys(state?.engine?.backgroundState).length) return; + const unlocked = state.user.userLoggedIn; + const accountCount = selectInternalAccounts(state).length; + const nftCount = selectAllNftsFlat(state).length; + const notificationCount = getNotificationsList(state).length; + const tokenCount = selectAllTokensFlat(state).length; + const transactionCount = selectTransactions(state).length; + const pendingApprovals = Object.values(selectPendingApprovals(state)); + + const firstApprovalType = pendingApprovals?.[0]?.type; + + return { + 'wallet.account_count': accountCount, + 'wallet.nft_count': nftCount, + 'wallet.notification_count': notificationCount, + 'wallet.pending_approval': firstApprovalType, + 'wallet.token_count': tokenCount, + 'wallet.transaction_count': transactionCount, + 'wallet.unlocked': unlocked, + }; +} diff --git a/app/util/trace.test.ts b/app/util/trace.test.ts index cb90722c9cb..b9e541ebdc5 100644 --- a/app/util/trace.test.ts +++ b/app/util/trace.test.ts @@ -1,17 +1,19 @@ -import { startSpan, startSpanManual, withScope } from '@sentry/react-native'; +import { + Scope, + setMeasurement, + startSpan, + startSpanManual, + withScope, +} from '@sentry/react-native'; import { Span } from '@sentry/types'; -import { - endTrace, - trace, - TraceName, - TRACES_CLEANUP_INTERVAL, -} from './trace'; +import { endTrace, trace, TraceName, TRACES_CLEANUP_INTERVAL } from './trace'; jest.mock('@sentry/react-native', () => ({ withScope: jest.fn(), startSpan: jest.fn(), startSpanManual: jest.fn(), + setMeasurement: jest.fn(), })); const NAME_MOCK = TraceName.Middleware; @@ -36,15 +38,23 @@ describe('Trace', () => { const startSpanMock = jest.mocked(startSpan); const startSpanManualMock = jest.mocked(startSpanManual); const withScopeMock = jest.mocked(withScope); - const setTagsMock = jest.fn(); + const setMeasurementMock = jest.mocked(setMeasurement); + const setTagMock = jest.fn(); beforeEach(() => { jest.resetAllMocks(); startSpanMock.mockImplementation((_, fn) => fn({} as Span)); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - withScopeMock.mockImplementation((fn: any) => fn({ setTags: setTagsMock })); + startSpanManualMock.mockImplementation((_, fn) => + fn({} as Span, () => { + // Intentionally empty + }), + ); + + withScopeMock.mockImplementation((fn: (arg: Scope) => unknown) => + fn({ setTag: setTagMock } as unknown as Scope), + ); }); describe('trace', () => { @@ -87,8 +97,12 @@ describe('Trace', () => { expect.any(Function), ); - expect(setTagsMock).toHaveBeenCalledTimes(1); - expect(setTagsMock).toHaveBeenCalledWith(TAGS_MOCK); + expect(setTagMock).toHaveBeenCalledTimes(2); + expect(setTagMock).toHaveBeenCalledWith('tag1', 'value1'); + expect(setTagMock).toHaveBeenCalledWith('tag2', true); + + expect(setMeasurementMock).toHaveBeenCalledTimes(1); + expect(setMeasurementMock).toHaveBeenCalledWith('tag3', 123, 'none'); }); it('invokes Sentry if no callback provided', () => { @@ -113,8 +127,12 @@ describe('Trace', () => { expect.any(Function), ); - expect(setTagsMock).toHaveBeenCalledTimes(1); - expect(setTagsMock).toHaveBeenCalledWith(TAGS_MOCK); + expect(setTagMock).toHaveBeenCalledTimes(2); + expect(setTagMock).toHaveBeenCalledWith('tag1', 'value1'); + expect(setTagMock).toHaveBeenCalledWith('tag2', true); + + expect(setMeasurementMock).toHaveBeenCalledTimes(1); + expect(setMeasurementMock).toHaveBeenCalledWith('tag3', 123, 'none'); }); it('invokes Sentry if no callback provided with custom start time', () => { @@ -141,8 +159,12 @@ describe('Trace', () => { expect.any(Function), ); - expect(setTagsMock).toHaveBeenCalledTimes(1); - expect(setTagsMock).toHaveBeenCalledWith(TAGS_MOCK); + expect(setTagMock).toHaveBeenCalledTimes(2); + expect(setTagMock).toHaveBeenCalledWith('tag1', 'value1'); + expect(setTagMock).toHaveBeenCalledWith('tag2', true); + + expect(setMeasurementMock).toHaveBeenCalledTimes(1); + expect(setMeasurementMock).toHaveBeenCalledWith('tag3', 123, 'none'); }); }); diff --git a/app/util/trace.ts b/app/util/trace.ts index fd6b4c9dfb3..05ad23d9dd8 100644 --- a/app/util/trace.ts +++ b/app/util/trace.ts @@ -2,15 +2,19 @@ import { startSpan as sentryStartSpan, startSpanManual, withScope, + setMeasurement, + Scope, } from '@sentry/react-native'; import performance from 'react-native-performance'; -import type { Primitive, Span, StartSpanOptions } from '@sentry/types'; +import type { Span, StartSpanOptions, MeasurementUnit } from '@sentry/types'; import { createModuleLogger, createProjectLogger } from '@metamask/utils'; // Cannot create this 'sentry' logger in Sentry util file because of circular dependency const projectLogger = createProjectLogger('sentry'); const log = createModuleLogger(projectLogger, 'trace'); - +/** + * The supported trace names. + */ export enum TraceName { DeveloperTest = 'Developer Test', Middleware = 'Middleware', @@ -56,24 +60,72 @@ export interface PendingTrace { startTime: number; timeoutId: NodeJS.Timeout; } - +/** + * A context object to associate traces with each other and generate nested traces. + */ export type TraceContext = unknown; - +/** + * A callback function that can be traced. + */ export type TraceCallback = (context?: TraceContext) => T; - +/** + * A request to create a new trace. + */ export interface TraceRequest { + /** + * Custom data to associate with the trace. + */ data?: Record; + + /** + * A unique identifier when not tracing a callback. + * Defaults to 'default' if not provided. + */ id?: string; + + /** + * The name of the trace. + */ name: TraceName; + + /** + * The parent context of the trace. + * If provided, the trace will be nested under the parent trace. + */ parentContext?: TraceContext; + + /** + * Override the start time of the trace. + */ startTime?: number; + + /** + * Custom tags to associate with the trace. + */ tags?: Record; + /** + * Custom operation name to associate with the trace. + */ op?: string; } - +/** + * A request to end a pending trace. + */ export interface EndTraceRequest { + /** + * The unique identifier of the trace. + * Defaults to 'default' if not provided. + */ id?: string; + + /** + * The name of the trace. + */ name: TraceName; + + /** + * Override the end time of the trace. + */ timestamp?: number; } @@ -81,6 +133,16 @@ export function trace(request: TraceRequest, fn: TraceCallback): T; export function trace(request: TraceRequest): TraceContext; +/** + * Create a Sentry transaction to analyse the duration of a code flow. + * If a callback is provided, the transaction will be automatically ended when the callback completes. + * If the callback returns a promise, the transaction will be ended when the promise resolves or rejects. + * If no callback is provided, the transaction must be manually ended using `endTrace`. + * + * @param request - The data associated with the trace, such as the name and tags. + * @param fn - The optional callback to record the duration of. + * @returns The context of the trace, or the result of the callback if provided. + */ export function trace( request: TraceRequest, fn?: TraceCallback, @@ -92,6 +154,12 @@ export function trace( return traceCallback(request, fn); } +/** + * End a pending trace that was started without a callback. + * Does nothing if the pending trace cannot be found. + * + * @param request - The data necessary to identify and end the pending trace. + */ export function endTrace(request: EndTraceRequest) { const { name, timestamp } = request; const id = getTraceId(request); @@ -124,6 +192,10 @@ function traceCallback(request: TraceRequest, fn: TraceCallback): T { const start = Date.now(); let error: unknown; + if (span) { + initSpan(span, request); + } + return tryCatchMaybePromise( () => fn(span), (currentError) => { @@ -154,6 +226,10 @@ function startTrace(request: TraceRequest): TraceContext { span?.end(timestamp); }; + if (span) { + initSpan(span, request); + } + const timeoutId = setTimeout(() => { log('Trace cleanup due to timeout', name, id); end(); @@ -178,14 +254,7 @@ function startSpan( request: TraceRequest, callback: (spanOptions: StartSpanOptions) => T, ) { - const { - data: attributes, - name, - parentContext, - startTime, - tags, - op, - } = request; + const { data: attributes, name, parentContext, startTime, op } = request; const parentSpan = (parentContext ?? null) as Span | null; const spanOptions: StartSpanOptions = { @@ -199,7 +268,7 @@ function startSpan( }; return withScope((scope) => { - scope.setTags(tags as Record); + initScope(scope, request); return callback(spanOptions); }) as T; @@ -216,6 +285,40 @@ function getTraceKey(request: TraceRequest) { return [name, id].join(':'); } +/** + * Initialise the isolated Sentry scope created for each trace. + * Includes setting all non-numeric tags. + * + * @param scope - The Sentry scope to initialise. + * @param request - The trace request. + */ +function initScope(scope: Scope, request: TraceRequest) { + const tags = request.tags ?? {}; + + for (const [key, value] of Object.entries(tags)) { + if (typeof value !== 'number') { + scope.setTag(key, value); + } + } +} + +/** + * Initialise the Sentry span created for each trace. + * Includes setting all numeric tags as measurements so they can be queried numerically in Sentry. + * + * @param _span - The Sentry span to initialise. + * @param request - The trace request. + */ +function initSpan(_span: Span, request: TraceRequest) { + const tags = request.tags ?? {}; + + for (const [key, value] of Object.entries(tags)) { + if (typeof value === 'number') { + sentrySetMeasurement(key, value, 'none'); + } + } +} + function getPerformanceTimestamp(): number { return performance.timeOrigin + performance.now(); } @@ -248,3 +351,11 @@ function tryCatchMaybePromise( return undefined; } + +function sentrySetMeasurement( + key: string, + value: number, + unit: MeasurementUnit, +) { + setMeasurement(key, value, unit); +} diff --git a/e2e/fixtures/fixture-builder.js b/e2e/fixtures/fixture-builder.js index 76ac9c29eec..9e42459a051 100644 --- a/e2e/fixtures/fixture-builder.js +++ b/e2e/fixtures/fixture-builder.js @@ -368,6 +368,18 @@ class FixtureBuilder { pendingApprovalCount: 0, approvalFlows: [], }, + NotificationServicesController: { + subscriptionAccountsSeen: [], + isMetamaskNotificationsFeatureSeen: false, + isNotificationServicesEnabled: false, + isFeatureAnnouncementsEnabled: false, + metamaskNotificationsList: [], + metamaskNotificationsReadList: [], + isUpdatingMetamaskNotifications: false, + isFetchingMetamaskNotifications: false, + isUpdatingMetamaskNotificationsAccount: [], + isCheckingAccountsPresence: false, + }, }, }, privacy: { From 9d54b088ac2991eba09c8f90704b6b532873c111 Mon Sep 17 00:00:00 2001 From: sethkfman Date: Wed, 16 Oct 2024 13:04:17 -0600 Subject: [PATCH 19/45] Bump build version 1459 RC - 6 --- android/app/build.gradle | 2 +- bitrise.yml | 4 ++-- ios/MetaMask.xcodeproj/project.pbxproj | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index f5591a45d27..0a24cd66e97 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -174,7 +174,7 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionName "7.33.0" - versionCode 1458 + versionCode 1459 testBuildType System.getProperty('testBuildType', 'debug') missingDimensionStrategy 'react-native-camera', 'general' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/bitrise.yml b/bitrise.yml index f58ba65ebc0..7ed046ae3de 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -1500,13 +1500,13 @@ app: VERSION_NAME: 7.33.0 - opts: is_expand: false - VERSION_NUMBER: 1458 + VERSION_NUMBER: 1459 - opts: is_expand: false FLASK_VERSION_NAME: 7.33.0 - opts: is_expand: false - FLASK_VERSION_NUMBER: 1458 + FLASK_VERSION_NUMBER: 1459 - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index d51d4be4a9a..dadaf4aee2b 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -1273,7 +1273,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1458; + CURRENT_PROJECT_VERSION = 1459; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1338,7 +1338,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1458; + CURRENT_PROJECT_VERSION = 1459; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1401,7 +1401,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1458; + CURRENT_PROJECT_VERSION = 1459; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1462,7 +1462,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1458; + CURRENT_PROJECT_VERSION = 1459; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1616,7 +1616,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1458; + CURRENT_PROJECT_VERSION = 1459; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1684,7 +1684,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1458; + CURRENT_PROJECT_VERSION = 1459; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; From 392f8d0cc2a1ca8e5cbbe173dd4f3df57f7c562e Mon Sep 17 00:00:00 2001 From: tommasini <46944231+tommasini@users.noreply.github.com> Date: Thu, 17 Oct 2024 19:20:01 +0100 Subject: [PATCH 20/45] chore: Revert custom span (#11839) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** Revert this [PR](https://github.com/MetaMask/metamask-mobile/pull/11822) ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- app/components/Nav/App/index.js | 11 +- app/components/Views/LockScreen/index.js | 18 +- app/components/Views/Login/index.js | 31 +-- app/components/Views/Onboarding/index.js | 38 ++-- app/components/Views/Wallet/index.tsx | 1 - app/selectors/nftController.ts | 13 +- app/selectors/tokensController.ts | 20 -- app/store/index.ts | 60 +----- app/util/sentry/tags/index.test.ts | 229 ----------------------- app/util/sentry/tags/index.ts | 30 --- app/util/trace.test.ts | 54 ++---- app/util/trace.ts | 163 +--------------- e2e/fixtures/fixture-builder.js | 12 -- 13 files changed, 51 insertions(+), 629 deletions(-) delete mode 100644 app/util/sentry/tags/index.test.ts delete mode 100644 app/util/sentry/tags/index.ts diff --git a/app/components/Nav/App/index.js b/app/components/Nav/App/index.js index 1b33dc8a4f5..27bc4c34d8d 100644 --- a/app/components/Nav/App/index.js +++ b/app/components/Nav/App/index.js @@ -127,7 +127,6 @@ import { SnapsExecutionWebView } from '../../../lib/snaps'; import OptionsSheet from '../../UI/SelectOptionSheet/OptionsSheet'; import FoxLoader from '../../../components/UI/FoxLoader'; import { AppStateEventProcessor } from '../../../core/AppStateEventListener'; -import { trace, TraceName, TraceOperation } from '../../../util/trace'; const clearStackNavigatorOptions = { headerShown: false, @@ -336,15 +335,7 @@ const App = (props) => { setOnboarded(!!existingUser); try { if (existingUser) { - await trace( - { - name: TraceName.BiometricAuthentication, - op: TraceOperation.BiometricAuthentication, - }, - async () => { - await Authentication.appTriggeredAuth(); - }, - ); + await Authentication.appTriggeredAuth(); // we need to reset the navigator here so that the user cannot go back to the login screen navigator.reset({ routes: [{ name: Routes.ONBOARDING.HOME_NAV }] }); } else { diff --git a/app/components/Views/LockScreen/index.js b/app/components/Views/LockScreen/index.js index 030bc9ace1d..92f04193389 100644 --- a/app/components/Views/LockScreen/index.js +++ b/app/components/Views/LockScreen/index.js @@ -22,7 +22,6 @@ import { import Routes from '../../../constants/navigation/Routes'; import { CommonActions } from '@react-navigation/native'; import trackErrorAsAnalytics from '../../../util/metrics/TrackError/trackErrorAsAnalytics'; -import { trace, TraceName, TraceOperation } from '../../../util/trace'; const LOGO_SIZE = 175; const createStyles = (colors) => @@ -135,19 +134,10 @@ class LockScreen extends PureComponent { // Retrieve the credentials Logger.log('Lockscreen::unlockKeychain - getting credentials'); - await trace( - { - name: TraceName.BiometricAuthentication, - op: TraceOperation.BiometricAuthentication, - }, - async () => { - await Authentication.appTriggeredAuth({ - bioStateMachineId, - disableAutoLogout: true, - }); - }, - ); - + await Authentication.appTriggeredAuth({ + bioStateMachineId, + disableAutoLogout: true, + }); this.setState({ ready: true }); Logger.log('Lockscreen::unlockKeychain - state: ready'); } catch (error) { diff --git a/app/components/Views/Login/index.js b/app/components/Views/Login/index.js index 4c1473a8090..7820e848bb5 100644 --- a/app/components/Views/Login/index.js +++ b/app/components/Views/Login/index.js @@ -59,12 +59,6 @@ import { LoginViewSelectors } from '../../../../e2e/selectors/LoginView.selector import { withMetricsAwareness } from '../../../components/hooks/useMetrics'; import trackErrorAsAnalytics from '../../../util/metrics/TrackError/trackErrorAsAnalytics'; import { downloadStateLogs } from '../../../util/logs'; -import { - trace, - endTrace, - TraceName, - TraceOperation, -} from '../../../util/trace'; const deviceHeight = Device.getDeviceHeight(); const breakPoint = deviceHeight < 700; @@ -251,10 +245,6 @@ class Login extends PureComponent { fieldRef = React.createRef(); async componentDidMount() { - trace({ - name: TraceName.LoginToPasswordEntry, - op: TraceOperation.LoginToPasswordEntry, - }); this.props.metrics.trackEvent(MetaMetricsEvents.LOGIN_SCREEN_VIEWED); BackHandler.addEventListener('hardwareBackPress', this.handleBackPress); @@ -378,15 +368,7 @@ class Login extends PureComponent { ); try { - await trace( - { - name: TraceName.AuthenticateUser, - op: TraceOperation.AuthenticateUser, - }, - async () => { - await Authentication.userEntryAuth(password, authType); - }, - ); + await Authentication.userEntryAuth(password, authType); Keyboard.dismiss(); @@ -454,15 +436,7 @@ class Login extends PureComponent { const { current: field } = this.fieldRef; field?.blur(); try { - await trace( - { - name: TraceName.BiometricAuthentication, - op: TraceOperation.BiometricAuthentication, - }, - async () => { - await Authentication.appTriggeredAuth(); - }, - ); + await Authentication.appTriggeredAuth(); const onboardingWizard = await StorageWrapper.getItem(ONBOARDING_WIZARD); if (!onboardingWizard) this.props.setOnboardingWizardStep(1); this.props.navigation.replace(Routes.ONBOARDING.HOME_NAV); @@ -481,7 +455,6 @@ class Login extends PureComponent { }; triggerLogIn = () => { - endTrace({ name: TraceName.LoginToPasswordEntry }); this.onLogin(); }; diff --git a/app/components/Views/Onboarding/index.js b/app/components/Views/Onboarding/index.js index 52ea24f6192..f15aa33c3c5 100644 --- a/app/components/Views/Onboarding/index.js +++ b/app/components/Views/Onboarding/index.js @@ -49,7 +49,6 @@ import { OnboardingSelectorIDs } from '../../../../e2e/selectors/Onboarding/Onbo import Routes from '../../../constants/navigation/Routes'; import { selectAccounts } from '../../../selectors/accountTrackerController'; import trackOnboarding from '../../../util/metrics/TrackOnboarding/trackOnboarding'; -import { trace, TraceName, TraceOperation } from '../../../util/trace'; const createStyles = (colors) => StyleSheet.create({ @@ -276,33 +275,24 @@ class Onboarding extends PureComponent { }; onPressCreate = () => { - const action = () => { - trace( - { - name: TraceName.CreateNewWalletToChoosePassword, - op: TraceOperation.CreateNewWalletToChoosePassword, - }, - () => { - const { metrics } = this.props; - if (metrics.isEnabled()) { - this.props.navigation.navigate('ChoosePassword', { + const action = async () => { + const { metrics } = this.props; + if (metrics.isEnabled()) { + this.props.navigation.navigate('ChoosePassword', { + [PREVIOUS_SCREEN]: ONBOARDING, + }); + this.track(MetaMetricsEvents.WALLET_SETUP_STARTED); + } else { + this.props.navigation.navigate('OptinMetrics', { + onContinue: () => { + this.props.navigation.replace('ChoosePassword', { [PREVIOUS_SCREEN]: ONBOARDING, }); this.track(MetaMetricsEvents.WALLET_SETUP_STARTED); - } else { - this.props.navigation.navigate('OptinMetrics', { - onContinue: () => { - this.props.navigation.replace('ChoosePassword', { - [PREVIOUS_SCREEN]: ONBOARDING, - }); - this.track(MetaMetricsEvents.WALLET_SETUP_STARTED); - }, - }); - } - }, - ); + }, + }); + } }; - this.handleExistingUser(action); }; diff --git a/app/components/Views/Wallet/index.tsx b/app/components/Views/Wallet/index.tsx index 2a6da7d8581..886a36d645a 100644 --- a/app/components/Views/Wallet/index.tsx +++ b/app/components/Views/Wallet/index.tsx @@ -96,7 +96,6 @@ import { } from '../../../selectors/notifications'; import { ButtonVariants } from '../../../component-library/components/Buttons/Button'; import { useListNotifications } from '../../../util/notifications/hooks/useNotifications'; - const createStyles = ({ colors, typography }: Theme) => StyleSheet.create({ base: { diff --git a/app/selectors/nftController.ts b/app/selectors/nftController.ts index a56b5e9afed..5d6a0239ee7 100644 --- a/app/selectors/nftController.ts +++ b/app/selectors/nftController.ts @@ -1,5 +1,5 @@ import { createSelector } from 'reselect'; -import { Nft, NftState } from '@metamask/assets-controllers'; +import { NftState } from '@metamask/assets-controllers'; import { RootState } from '../reducers'; const selectNftControllerState = (state: RootState) => @@ -14,14 +14,3 @@ export const selectAllNfts = createSelector( selectNftControllerState, (nftControllerState: NftState) => nftControllerState.allNfts, ); - -export const selectAllNftsFlat = createSelector( - selectAllNfts, - (nftsByChainByAccount) => { - const nftsByChainArray = Object.values(nftsByChainByAccount); - return nftsByChainArray.reduce((acc, nftsByChain) => { - const nftsArrays = Object.values(nftsByChain); - return acc.concat(...nftsArrays); - }, [] as Nft[]); - }, -); diff --git a/app/selectors/tokensController.ts b/app/selectors/tokensController.ts index 3d91c000eef..9ff4b872e3c 100644 --- a/app/selectors/tokensController.ts +++ b/app/selectors/tokensController.ts @@ -34,23 +34,3 @@ export const selectDetectedTokens = createSelector( selectTokensControllerState, (tokensControllerState: TokensState) => tokensControllerState?.detectedTokens, ); - -const selectAllTokens = createSelector( - selectTokensControllerState, - (tokensControllerState: TokensState) => tokensControllerState?.allTokens, -); - -export const selectAllTokensFlat = createSelector( - selectAllTokens, - (tokensByAccountByChain) => { - if (Object.values(tokensByAccountByChain).length === 0) { - return []; - } - const tokensByAccountArray = Object.values(tokensByAccountByChain); - - return tokensByAccountArray.reduce((acc, tokensByAccount) => { - const tokensArray = Object.values(tokensByAccount); - return acc.concat(...tokensArray); - }, [] as Token[]); - }, -); diff --git a/app/store/index.ts b/app/store/index.ts index 9cc858e9ac0..aa7a4df512f 100644 --- a/app/store/index.ts +++ b/app/store/index.ts @@ -9,14 +9,10 @@ import { Authentication } from '../core'; import LockManagerService from '../core/LockManagerService'; import ReadOnlyNetworkStore from '../util/test/network-store'; import { isE2E } from '../util/test/utils'; -import { trace, endTrace, TraceName, TraceOperation } from '../util/trace'; -import StorageWrapper from './storage-wrapper'; - import thunk from 'redux-thunk'; import persistConfig from './persistConfig'; import { AppStateEventProcessor } from '../core/AppStateEventListener'; -import { getTraceTags } from '../util/sentry/tags'; // TODO: Improve type safety by using real Action types instead of `any` // TODO: Replace "any" with type @@ -28,7 +24,7 @@ const pReducer = persistReducer(persistConfig, rootReducer); // TODO: Replace "any" with type // eslint-disable-next-line @typescript-eslint/no-explicit-any, import/no-mutable-exports let store: Store, persistor; -const createStoreAndPersistor = async (appStartTime: number) => { +const createStoreAndPersistor = async () => { // Obtain the initial state from ReadOnlyNetworkStore for E2E tests. const initialState = isE2E ? await ReadOnlyNetworkStore.getState() @@ -50,24 +46,6 @@ const createStoreAndPersistor = async (appStartTime: number) => { middlewares.push(createReduxFlipperDebugger()); } - const jsStartTime = performance.now(); - - trace({ - name: TraceName.LoadScripts, - op: TraceOperation.LoadScripts, - startTime: appStartTime, - }); - - endTrace({ - name: TraceName.LoadScripts, - timestamp: appStartTime + jsStartTime, - }); - - trace({ - name: TraceName.CreateStore, - op: TraceOperation.CreateStore, - }); - store = configureStore({ reducer: pReducer, middleware: middlewares, @@ -76,19 +54,10 @@ const createStoreAndPersistor = async (appStartTime: number) => { sagaMiddleware.run(rootSaga); - endTrace({ name: TraceName.CreateStore }); - - trace({ - name: TraceName.StorageRehydration, - op: TraceOperation.StorageRehydration, - }); - /** * Initialize services after persist is completed */ - const onPersistComplete = async () => { - endTrace({ name: TraceName.StorageRehydration }); - + const onPersistComplete = () => { /** * EngineService.initalizeEngine(store) with SES/lockdown: * Requires ethjs nested patches (lib->src) @@ -104,7 +73,6 @@ const createStoreAndPersistor = async (appStartTime: number) => { * - TypeError: undefined is not an object (evaluating 'TokenListController.tokenList') * - V8: SES_UNHANDLED_REJECTION */ - store.dispatch({ type: 'TOGGLE_BASIC_FUNCTIONALITY', basicFunctionalityEnabled: @@ -115,18 +83,7 @@ const createStoreAndPersistor = async (appStartTime: number) => { store.dispatch({ type: 'FETCH_FEATURE_FLAGS', }); - - await trace( - { - name: TraceName.EngineInitialization, - op: TraceOperation.EngineInitialization, - tags: getTraceTags(store.getState?.()), - }, - () => { - EngineService.initalizeEngine(store); - }, - ); - + EngineService.initalizeEngine(store); Authentication.init(store); AppStateEventProcessor.init(store); LockManagerService.init(store); @@ -136,16 +93,7 @@ const createStoreAndPersistor = async (appStartTime: number) => { }; (async () => { - const appStartTime = await StorageWrapper.getItem('appStartTime'); - - await trace( - { - name: TraceName.UIStartup, - op: TraceOperation.UIStartup, - startTime: appStartTime, - }, - async () => await createStoreAndPersistor(appStartTime), - ); + await createStoreAndPersistor(); })(); export { store, persistor }; diff --git a/app/util/sentry/tags/index.test.ts b/app/util/sentry/tags/index.test.ts deleted file mode 100644 index 5511ab7cf92..00000000000 --- a/app/util/sentry/tags/index.test.ts +++ /dev/null @@ -1,229 +0,0 @@ -import { RootState } from '../../../reducers'; -import { getTraceTags } from './'; -import initialRootState, { - backgroundState, -} from '../../../util/test/initial-root-state'; -import { userInitialState } from '../../../reducers/user'; -import { createMockAccountsControllerState } from '../../../util/test/accountsControllerTestUtils'; - -describe('Tags Utils', () => { - beforeEach(() => { - jest.resetAllMocks(); - }); - - describe('getTraceTags', () => { - it('includes if unlocked', () => { - const state = { - ...initialRootState, - user: { ...userInitialState, userLoggedIn: true }, - }; - - const tags = getTraceTags(state); - - expect(tags?.['wallet.unlocked']).toStrictEqual(true); - }); - - it('includes if not unlocked', () => { - const state = { - ...initialRootState, - user: { ...userInitialState, userLoggedIn: false }, - }; - - const tags = getTraceTags(state); - - expect(tags?.['wallet.unlocked']).toStrictEqual(false); - }); - - it('includes pending approval type', () => { - const state = { - ...initialRootState, - engine: { - backgroundState: { - ...backgroundState, - ApprovalController: { - ...backgroundState.ApprovalController, - pendingApprovals: { - 1: { - type: 'eth_sendTransaction', - }, - }, - }, - }, - }, - } as unknown as RootState; - - const tags = getTraceTags(state); - - expect(tags?.['wallet.pending_approval']).toStrictEqual( - 'eth_sendTransaction', - ); - }); - - it('includes first pending approval type if multiple', () => { - const state = { - ...initialRootState, - engine: { - backgroundState: { - ...backgroundState, - - ApprovalController: { - ...backgroundState.ApprovalController, - pendingApprovals: { - 1: { - type: 'eth_sendTransaction', - }, - 2: { - type: 'personal_sign', - }, - }, - }, - }, - }, - } as unknown as RootState; - - const tags = getTraceTags(state); - - expect(tags?.['wallet.pending_approval']).toStrictEqual( - 'eth_sendTransaction', - ); - }); - - it('includes account count', () => { - const state = { - ...initialRootState, - engine: { - backgroundState: { - ...backgroundState, - AccountsController: createMockAccountsControllerState([ - '0x1234', - '0x4321', - ]), - }, - }, - } as unknown as RootState; - - const tags = getTraceTags(state); - - expect(tags?.['wallet.account_count']).toStrictEqual(2); - }); - - it('includes nft count', () => { - const state = { - ...initialRootState, - engine: { - backgroundState: { - ...backgroundState, - NftController: { - ...backgroundState.NftController, - allNfts: { - '0x1234': { - '0x1': [ - { - tokenId: '1', - }, - { - tokenId: '2', - }, - ], - '0x2': [ - { - tokenId: '3', - }, - { - tokenId: '4', - }, - ], - }, - '0x4321': { - '0x3': [ - { - tokenId: '5', - }, - ], - }, - }, - }, - }, - }, - } as unknown as RootState; - - const tags = getTraceTags(state); - - expect(tags?.['wallet.nft_count']).toStrictEqual(5); - }); - - it('includes notification count', () => { - const state = { - ...initialRootState, - engine: { - backgroundState: { - ...backgroundState, - NotificationServicesController: { - metamaskNotificationsList: [{}, {}, {}], - }, - }, - }, - } as unknown as RootState; - - const tags = getTraceTags(state); - - expect(tags?.['wallet.notification_count']).toStrictEqual(3); - }); - - it('includes token count', () => { - const state = { - ...initialRootState, - engine: { - backgroundState: { - ...backgroundState, - TokensController: { - allTokens: { - '0x1': { - '0x1234': [{}, {}], - '0x4321': [{}], - }, - '0x2': { - '0x5678': [{}], - }, - }, - }, - }, - }, - } as unknown as RootState; - - const tags = getTraceTags(state); - - expect(tags?.['wallet.token_count']).toStrictEqual(4); - }); - - it('includes transaction count', () => { - const state = { - ...initialRootState, - engine: { - backgroundState: { - ...backgroundState, - TransactionController: { - transactions: [ - { - id: 1, - chainId: '0x1', - }, - { - id: 2, - chainId: '0x1', - }, - { - id: 3, - chainId: '0x2', - }, - ], - }, - }, - }, - } as unknown as RootState; - const tags = getTraceTags(state); - - expect(tags?.['wallet.transaction_count']).toStrictEqual(3); - }); - }); -}); diff --git a/app/util/sentry/tags/index.ts b/app/util/sentry/tags/index.ts deleted file mode 100644 index 796bb9212fe..00000000000 --- a/app/util/sentry/tags/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { RootState } from '../../../reducers'; -import { selectAllNftsFlat } from '../../../selectors/nftController'; -import { selectInternalAccounts } from '../../../selectors/accountsController'; -import { selectAllTokensFlat } from '../../../selectors/tokensController'; -import { getNotificationsList } from '../../../selectors/notifications'; -import { selectTransactions } from '../../../selectors/transactionController'; -import { selectPendingApprovals } from '../../../selectors/approvalController'; - -export function getTraceTags(state: RootState) { - if (!Object.keys(state?.engine?.backgroundState).length) return; - const unlocked = state.user.userLoggedIn; - const accountCount = selectInternalAccounts(state).length; - const nftCount = selectAllNftsFlat(state).length; - const notificationCount = getNotificationsList(state).length; - const tokenCount = selectAllTokensFlat(state).length; - const transactionCount = selectTransactions(state).length; - const pendingApprovals = Object.values(selectPendingApprovals(state)); - - const firstApprovalType = pendingApprovals?.[0]?.type; - - return { - 'wallet.account_count': accountCount, - 'wallet.nft_count': nftCount, - 'wallet.notification_count': notificationCount, - 'wallet.pending_approval': firstApprovalType, - 'wallet.token_count': tokenCount, - 'wallet.transaction_count': transactionCount, - 'wallet.unlocked': unlocked, - }; -} diff --git a/app/util/trace.test.ts b/app/util/trace.test.ts index b9e541ebdc5..cb90722c9cb 100644 --- a/app/util/trace.test.ts +++ b/app/util/trace.test.ts @@ -1,19 +1,17 @@ -import { - Scope, - setMeasurement, - startSpan, - startSpanManual, - withScope, -} from '@sentry/react-native'; +import { startSpan, startSpanManual, withScope } from '@sentry/react-native'; import { Span } from '@sentry/types'; -import { endTrace, trace, TraceName, TRACES_CLEANUP_INTERVAL } from './trace'; +import { + endTrace, + trace, + TraceName, + TRACES_CLEANUP_INTERVAL, +} from './trace'; jest.mock('@sentry/react-native', () => ({ withScope: jest.fn(), startSpan: jest.fn(), startSpanManual: jest.fn(), - setMeasurement: jest.fn(), })); const NAME_MOCK = TraceName.Middleware; @@ -38,23 +36,15 @@ describe('Trace', () => { const startSpanMock = jest.mocked(startSpan); const startSpanManualMock = jest.mocked(startSpanManual); const withScopeMock = jest.mocked(withScope); - const setMeasurementMock = jest.mocked(setMeasurement); - const setTagMock = jest.fn(); + const setTagsMock = jest.fn(); beforeEach(() => { jest.resetAllMocks(); startSpanMock.mockImplementation((_, fn) => fn({} as Span)); - startSpanManualMock.mockImplementation((_, fn) => - fn({} as Span, () => { - // Intentionally empty - }), - ); - - withScopeMock.mockImplementation((fn: (arg: Scope) => unknown) => - fn({ setTag: setTagMock } as unknown as Scope), - ); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + withScopeMock.mockImplementation((fn: any) => fn({ setTags: setTagsMock })); }); describe('trace', () => { @@ -97,12 +87,8 @@ describe('Trace', () => { expect.any(Function), ); - expect(setTagMock).toHaveBeenCalledTimes(2); - expect(setTagMock).toHaveBeenCalledWith('tag1', 'value1'); - expect(setTagMock).toHaveBeenCalledWith('tag2', true); - - expect(setMeasurementMock).toHaveBeenCalledTimes(1); - expect(setMeasurementMock).toHaveBeenCalledWith('tag3', 123, 'none'); + expect(setTagsMock).toHaveBeenCalledTimes(1); + expect(setTagsMock).toHaveBeenCalledWith(TAGS_MOCK); }); it('invokes Sentry if no callback provided', () => { @@ -127,12 +113,8 @@ describe('Trace', () => { expect.any(Function), ); - expect(setTagMock).toHaveBeenCalledTimes(2); - expect(setTagMock).toHaveBeenCalledWith('tag1', 'value1'); - expect(setTagMock).toHaveBeenCalledWith('tag2', true); - - expect(setMeasurementMock).toHaveBeenCalledTimes(1); - expect(setMeasurementMock).toHaveBeenCalledWith('tag3', 123, 'none'); + expect(setTagsMock).toHaveBeenCalledTimes(1); + expect(setTagsMock).toHaveBeenCalledWith(TAGS_MOCK); }); it('invokes Sentry if no callback provided with custom start time', () => { @@ -159,12 +141,8 @@ describe('Trace', () => { expect.any(Function), ); - expect(setTagMock).toHaveBeenCalledTimes(2); - expect(setTagMock).toHaveBeenCalledWith('tag1', 'value1'); - expect(setTagMock).toHaveBeenCalledWith('tag2', true); - - expect(setMeasurementMock).toHaveBeenCalledTimes(1); - expect(setMeasurementMock).toHaveBeenCalledWith('tag3', 123, 'none'); + expect(setTagsMock).toHaveBeenCalledTimes(1); + expect(setTagsMock).toHaveBeenCalledWith(TAGS_MOCK); }); }); diff --git a/app/util/trace.ts b/app/util/trace.ts index 05ad23d9dd8..d74ca003249 100644 --- a/app/util/trace.ts +++ b/app/util/trace.ts @@ -2,50 +2,20 @@ import { startSpan as sentryStartSpan, startSpanManual, withScope, - setMeasurement, - Scope, } from '@sentry/react-native'; import performance from 'react-native-performance'; -import type { Span, StartSpanOptions, MeasurementUnit } from '@sentry/types'; +import type { Primitive, Span, StartSpanOptions } from '@sentry/types'; import { createModuleLogger, createProjectLogger } from '@metamask/utils'; // Cannot create this 'sentry' logger in Sentry util file because of circular dependency const projectLogger = createProjectLogger('sentry'); const log = createModuleLogger(projectLogger, 'trace'); -/** - * The supported trace names. - */ + export enum TraceName { DeveloperTest = 'Developer Test', Middleware = 'Middleware', NestedTest1 = 'Nested Test 1', NestedTest2 = 'Nested Test 2', - NotificationDisplay = 'Notification Display', - PPOMValidation = 'PPOM Validation', - Signature = 'Signature', - LoadScripts = 'Load Scripts', - SetupStore = 'Setup Store', - LoginToPasswordEntry = 'Login to Password Entry', - AuthenticateUser = 'Authenticate User', - BiometricAuthentication = 'Biometrics Authentication', - EngineInitialization = 'Engine Initialization', - CreateStore = 'Create Store', - CreateNewWalletToChoosePassword = 'Create New Wallet to Choose Password', - StorageRehydration = 'Storage Rehydration', - UIStartup = 'Custom UIStartup', -} - -export enum TraceOperation { - LoadScripts = 'custom.load.scripts', - SetupStore = 'custom.setup.store', - LoginToPasswordEntry = 'custom.login.to.password.entry', - BiometricAuthentication = 'biometrics.authentication', - AuthenticateUser = 'custom.authenticate.user', - EngineInitialization = 'custom.engine.initialization', - CreateStore = 'custom.create.store', - CreateNewWalletToChoosePassword = 'custom.create.new.wallet', - StorageRehydration = 'custom.storage.rehydration', - UIStartup = 'custom.ui.startup', } const ID_DEFAULT = 'default'; @@ -60,72 +30,23 @@ export interface PendingTrace { startTime: number; timeoutId: NodeJS.Timeout; } -/** - * A context object to associate traces with each other and generate nested traces. - */ + export type TraceContext = unknown; -/** - * A callback function that can be traced. - */ + export type TraceCallback = (context?: TraceContext) => T; -/** - * A request to create a new trace. - */ + export interface TraceRequest { - /** - * Custom data to associate with the trace. - */ data?: Record; - - /** - * A unique identifier when not tracing a callback. - * Defaults to 'default' if not provided. - */ id?: string; - - /** - * The name of the trace. - */ name: TraceName; - - /** - * The parent context of the trace. - * If provided, the trace will be nested under the parent trace. - */ parentContext?: TraceContext; - - /** - * Override the start time of the trace. - */ startTime?: number; - - /** - * Custom tags to associate with the trace. - */ tags?: Record; - /** - * Custom operation name to associate with the trace. - */ - op?: string; } -/** - * A request to end a pending trace. - */ + export interface EndTraceRequest { - /** - * The unique identifier of the trace. - * Defaults to 'default' if not provided. - */ id?: string; - - /** - * The name of the trace. - */ name: TraceName; - - /** - * Override the end time of the trace. - */ timestamp?: number; } @@ -133,16 +54,6 @@ export function trace(request: TraceRequest, fn: TraceCallback): T; export function trace(request: TraceRequest): TraceContext; -/** - * Create a Sentry transaction to analyse the duration of a code flow. - * If a callback is provided, the transaction will be automatically ended when the callback completes. - * If the callback returns a promise, the transaction will be ended when the promise resolves or rejects. - * If no callback is provided, the transaction must be manually ended using `endTrace`. - * - * @param request - The data associated with the trace, such as the name and tags. - * @param fn - The optional callback to record the duration of. - * @returns The context of the trace, or the result of the callback if provided. - */ export function trace( request: TraceRequest, fn?: TraceCallback, @@ -154,12 +65,6 @@ export function trace( return traceCallback(request, fn); } -/** - * End a pending trace that was started without a callback. - * Does nothing if the pending trace cannot be found. - * - * @param request - The data necessary to identify and end the pending trace. - */ export function endTrace(request: EndTraceRequest) { const { name, timestamp } = request; const id = getTraceId(request); @@ -192,10 +97,6 @@ function traceCallback(request: TraceRequest, fn: TraceCallback): T { const start = Date.now(); let error: unknown; - if (span) { - initSpan(span, request); - } - return tryCatchMaybePromise( () => fn(span), (currentError) => { @@ -226,10 +127,6 @@ function startTrace(request: TraceRequest): TraceContext { span?.end(timestamp); }; - if (span) { - initSpan(span, request); - } - const timeoutId = setTimeout(() => { log('Trace cleanup due to timeout', name, id); end(); @@ -254,13 +151,13 @@ function startSpan( request: TraceRequest, callback: (spanOptions: StartSpanOptions) => T, ) { - const { data: attributes, name, parentContext, startTime, op } = request; + const { data: attributes, name, parentContext, startTime, tags } = request; const parentSpan = (parentContext ?? null) as Span | null; const spanOptions: StartSpanOptions = { attributes, name, - op: op || OP_DEFAULT, + op: OP_DEFAULT, // This needs to be parentSpan once we have the withIsolatedScope implementation in place in the Sentry SDK for React Native // Reference PR that updates @sentry/react-native: https://github.com/getsentry/sentry-react-native/pull/3895 parentSpanId: parentSpan?.spanId, @@ -268,7 +165,7 @@ function startSpan( }; return withScope((scope) => { - initScope(scope, request); + scope.setTags(tags as Record); return callback(spanOptions); }) as T; @@ -285,40 +182,6 @@ function getTraceKey(request: TraceRequest) { return [name, id].join(':'); } -/** - * Initialise the isolated Sentry scope created for each trace. - * Includes setting all non-numeric tags. - * - * @param scope - The Sentry scope to initialise. - * @param request - The trace request. - */ -function initScope(scope: Scope, request: TraceRequest) { - const tags = request.tags ?? {}; - - for (const [key, value] of Object.entries(tags)) { - if (typeof value !== 'number') { - scope.setTag(key, value); - } - } -} - -/** - * Initialise the Sentry span created for each trace. - * Includes setting all numeric tags as measurements so they can be queried numerically in Sentry. - * - * @param _span - The Sentry span to initialise. - * @param request - The trace request. - */ -function initSpan(_span: Span, request: TraceRequest) { - const tags = request.tags ?? {}; - - for (const [key, value] of Object.entries(tags)) { - if (typeof value === 'number') { - sentrySetMeasurement(key, value, 'none'); - } - } -} - function getPerformanceTimestamp(): number { return performance.timeOrigin + performance.now(); } @@ -351,11 +214,3 @@ function tryCatchMaybePromise( return undefined; } - -function sentrySetMeasurement( - key: string, - value: number, - unit: MeasurementUnit, -) { - setMeasurement(key, value, unit); -} diff --git a/e2e/fixtures/fixture-builder.js b/e2e/fixtures/fixture-builder.js index 9e42459a051..76ac9c29eec 100644 --- a/e2e/fixtures/fixture-builder.js +++ b/e2e/fixtures/fixture-builder.js @@ -368,18 +368,6 @@ class FixtureBuilder { pendingApprovalCount: 0, approvalFlows: [], }, - NotificationServicesController: { - subscriptionAccountsSeen: [], - isMetamaskNotificationsFeatureSeen: false, - isNotificationServicesEnabled: false, - isFeatureAnnouncementsEnabled: false, - metamaskNotificationsList: [], - metamaskNotificationsReadList: [], - isUpdatingMetamaskNotifications: false, - isFetchingMetamaskNotifications: false, - isUpdatingMetamaskNotificationsAccount: [], - isCheckingAccountsPresence: false, - }, }, }, privacy: { From 498e8a20af0296b9911468b063b585902327dcc7 Mon Sep 17 00:00:00 2001 From: tommasini <46944231+tommasini@users.noreply.github.com> Date: Thu, 17 Oct 2024 19:33:27 +0100 Subject: [PATCH 21/45] chore: revert tags commit (#11838) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** Revert this PR: https://github.com/MetaMask/metamask-mobile/pull/11826 ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. Co-authored-by: sethkfman <10342624+sethkfman@users.noreply.github.com> From 3481ea8e5a084551c7cbff1a1667a155b02137ae Mon Sep 17 00:00:00 2001 From: sethkfman Date: Thu, 17 Oct 2024 12:55:26 -0600 Subject: [PATCH 22/45] bump build number 1460 RC-7 --- android/app/build.gradle | 2 +- bitrise.yml | 4 ++-- ios/MetaMask.xcodeproj/project.pbxproj | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 0a24cd66e97..d406752ae5a 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -174,7 +174,7 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionName "7.33.0" - versionCode 1459 + versionCode 1460 testBuildType System.getProperty('testBuildType', 'debug') missingDimensionStrategy 'react-native-camera', 'general' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/bitrise.yml b/bitrise.yml index 7ed046ae3de..fe4f6a61cc2 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -1500,13 +1500,13 @@ app: VERSION_NAME: 7.33.0 - opts: is_expand: false - VERSION_NUMBER: 1459 + VERSION_NUMBER: 1460 - opts: is_expand: false FLASK_VERSION_NAME: 7.33.0 - opts: is_expand: false - FLASK_VERSION_NUMBER: 1459 + FLASK_VERSION_NUMBER: 1460 - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index dadaf4aee2b..43068635fab 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -1273,7 +1273,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1459; + CURRENT_PROJECT_VERSION = 1460; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1338,7 +1338,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1459; + CURRENT_PROJECT_VERSION = 1460; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1401,7 +1401,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1459; + CURRENT_PROJECT_VERSION = 1460; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1462,7 +1462,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1459; + CURRENT_PROJECT_VERSION = 1460; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; @@ -1616,7 +1616,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1459; + CURRENT_PROJECT_VERSION = 1460; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1684,7 +1684,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1459; + CURRENT_PROJECT_VERSION = 1460; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 48XVW22RCG; From f895d7a7dd4f66cf1ea987c9b34662bbb7faea10 Mon Sep 17 00:00:00 2001 From: "runway-github[bot]" <73448015+runway-github[bot]@users.noreply.github.com> Date: Thu, 17 Oct 2024 12:56:17 -0600 Subject: [PATCH 23/45] chore(runway): cherry-pick chore: bump ruby version to 3.1.6 (#11848) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - chore: bump ruby version to 3.1.6 (#11846) ## **Description** Our CI platform updated VM images which replaced ruby `3.1.5` with `3.1.6` ## **Related issues** Fixes: https://github.com/MetaMask/metamask-mobile/issues/11843 ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. [c0edf60](https://github.com/MetaMask/metamask-mobile/commit/c0edf60592bf7e95f5d68f5b354a376154f1802f) Co-authored-by: João Loureiro <175489935+joaoloureirop@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .ruby-version | 2 +- ios/Gemfile | 2 +- ios/Gemfile.lock | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e1b92a4d58d..5864ba001ec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: cache: yarn - uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 #v1 with: - ruby-version: '3.1.5' + ruby-version: '3.1.6' bundler-cache: true env: BUNDLE_GEMFILE: ios/Gemfile diff --git a/.ruby-version b/.ruby-version index 3ad0595adcc..9cec7165ab0 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.1.5 +3.1.6 diff --git a/ios/Gemfile b/ios/Gemfile index 3c02108f3ce..4d245c9f943 100644 --- a/ios/Gemfile +++ b/ios/Gemfile @@ -1,7 +1,7 @@ source 'https://rubygems.org' # Recommended to use http://rbenv.org/ to install and use this version -ruby '>= 3.1.5' +ruby '>= 3.1.6' # Allow minor version updates up to but excluding 2.0.0 gem 'cocoapods', '~> 1.12' diff --git a/ios/Gemfile.lock b/ios/Gemfile.lock index 8450432ac95..ed3f678b6d1 100644 --- a/ios/Gemfile.lock +++ b/ios/Gemfile.lock @@ -101,7 +101,7 @@ DEPENDENCIES cocoapods (~> 1.12) RUBY VERSION - ruby 3.1.5p252 + ruby 3.1.6p260 BUNDLED WITH 2.5.8 From 801d609d6fa5e6a0306ba8f05acb183fad6e5e1e Mon Sep 17 00:00:00 2001 From: sethkfman <10342624+sethkfman@users.noreply.github.com> Date: Fri, 18 Oct 2024 10:16:42 -0600 Subject: [PATCH 24/45] chore: merge main 7.33.0 (#11850) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This PR merges main into the release branch and resolved conflicts. ## **Related issues** Fixes: NA ## **Manual testing steps** 1. NA 2. 3. ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --------- Co-authored-by: Brendan Kirby <124314512+bkirb@users.noreply.github.com> Co-authored-by: legobeat <109787230+legobeat@users.noreply.github.com> Co-authored-by: Curtis David Co-authored-by: Nick Gambino <35090461+gambinish@users.noreply.github.com> Co-authored-by: Nico MASSART Co-authored-by: Jyoti Puri Co-authored-by: OGPoyraz Co-authored-by: EtherWizard33 <165834542+EtherWizard33@users.noreply.github.com> Co-authored-by: Vince Howard Co-authored-by: SamuelSalas Co-authored-by: tommasini <46944231+tommasini@users.noreply.github.com> Co-authored-by: Mpendulo Ndlovu Co-authored-by: cryptodev-2s <109512101+cryptodev-2s@users.noreply.github.com> Co-authored-by: Pedro Pablo Aste Kompen Co-authored-by: Matthew Grainger <46547583+Matt561@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: metamaskbot Co-authored-by: runway-github[bot] <73448015+runway-github[bot]@users.noreply.github.com> Co-authored-by: Xiaoming Wang <7315988+dawnseeker8@users.noreply.github.com> Co-authored-by: Vivek <106310394+vivek-consensys@users.noreply.github.com> Co-authored-by: Xiaoming Wang Co-authored-by: Aslau Mario-Daniel Co-authored-by: Matthew Walsh Co-authored-by: sahar-fehri Co-authored-by: Frank von Hoven <141057783+frankvonhoven@users.noreply.github.com> Co-authored-by: Cal Leung Co-authored-by: Cal-L Co-authored-by: MetaMask Bot <37885440+metamaskbot@users.noreply.github.com> Co-authored-by: abretonc7s <107169956+abretonc7s@users.noreply.github.com> Co-authored-by: Jonathan Ferreira <44679989+Jonathansoufer@users.noreply.github.com> Co-authored-by: Salim TOUBAL Co-authored-by: Daniel Cross Co-authored-by: Jongsun Suh Co-authored-by: Michele Esposito Co-authored-by: Michele Esposito <34438276+mikesposito@users.noreply.github.com> Co-authored-by: Christopher Ferreira <104831203+christopherferreira9@users.noreply.github.com> Co-authored-by: João Loureiro <175489935+joaoloureirop@users.noreply.github.com> Co-authored-by: AxelGes <34173844+AxelGes@users.noreply.github.com> Co-authored-by: Brian Nguyen Co-authored-by: Amitabh Aggarwal Co-authored-by: George Marshall Co-authored-by: Brian Bergeron Co-authored-by: Frederik Bolding Co-authored-by: JSoufer Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Kylan Hurt Co-authored-by: Vinicius Stevam <45455812+vinistevam@users.noreply.github.com> Co-authored-by: Mark Stacey Co-authored-by: Gauthier Petetin --- .depcheckrc.yml | 2 +- .detoxrc.js | 28 +- .git-blame-ignore-revs | 2 + .github/CODEOWNERS | 31 +- .../scripts}/get-next-semver-version.sh | 2 +- .github/workflows/add-release-label.yml | 2 +- .github/workflows/ci.yml | 16 +- .iyarc | 4 - .storybook/storybook.requires.js | 5 +- CHANGELOG.md | 23 +- android/app/build.gradle | 2 +- app/actions/notification/constants/index.ts | 1 + app/actions/notification/helpers/index.ts | 17 + app/actions/security/index.ts | 16 +- .../AccountBase/AccountBase.styles.ts | 1 - .../Accounts/AccountBase/AccountBase.tsx | 8 +- .../CellSelectWithMenu/CellSelectWithMenu.tsx | 16 +- .../CellSelectWithMenu.test.tsx.snap | 12 +- .../KeyValueLabel/KeyValueLabel.tsx | 34 +- .../KeyValueRow/KeyValueRow.stories.tsx | 67 +- .../KeyValueRow/KeyValueRow.test.tsx | 24 +- .../KeyValueRow/KeyValueRow.tsx | 17 +- .../KeyValueRow/KeyValueRow.types.ts | 39 +- .../KeyValueRow/KeyValueRow.utils.ts | 15 +- .../__snapshots__/KeyValueRow.test.tsx.snap | 16 +- .../ListItemMultiSelectButton.constants.ts | 1 + .../ListItemMultiSelectButton.styles.ts | 7 +- .../ListItemMultiSelectButton.test.tsx | 8 +- .../ListItemMultiSelectButton.tsx | 40 +- .../ListItemMultiSelectButton.types.ts | 24 +- .../ListItemMultiSelectButton.test.tsx.snap | 12 +- .../PermissionApproval.test.tsx | 1 + .../SignatureApproval/SignatureApproval.tsx | 11 +- .../{index.js => index.tsx} | 160 +- app/components/Base/Title/Title.tsx | 15 +- app/components/Nav/App/index.js | 38 +- app/components/Nav/Main/index.js | 42 +- .../UI/AccountInfoCard/index.test.tsx | 23 +- .../UI/ApprovalTagUrl/ApprovalTagUrl.test.tsx | 34 + .../UI/ApprovalTagUrl/ApprovalTagUrl.tsx | 6 +- .../ApprovalTagUrl.test.tsx.snap | 69 + app/components/UI/AssetElement/index.test.tsx | 2 +- app/components/UI/AssetElement/index.tsx | 2 +- app/components/UI/AssetIcon/index.test.tsx | 1 + .../UI/AssetOverview/AssetOverview.test.tsx | 2 +- .../UI/AssetOverview/AssetOverview.tsx | 2 +- .../UI/AssetOverview/AssetOverview.types.ts | 2 +- .../UI/AssetOverview/Balance/index.test.tsx | 2 +- .../TokenDetails/TokenDetails.test.tsx | 2 +- app/components/UI/Fox/{index.js => index.tsx} | 29 +- app/components/UI/InfoRow/InfoRow.tsx | 30 - .../UI/InfoRow/InfoSection/InfoSection.tsx | 18 - app/components/UI/InfoRow/style.ts | 31 - .../LoginOptionsSwitch/LoginOptionsSwitch.tsx | 7 +- .../__snapshots__/ManageNetworks.test.js.snap | 2 +- app/components/UI/Name/Name.tsx | 14 +- app/components/UI/Name/Name.types.ts | 3 + app/components/UI/Navbar/index.js | 117 +- .../UI/NetworkCell/NetworkCell.styles.ts | 11 + .../UI/NetworkCell/NetworkCell.test.tsx | 68 + app/components/UI/NetworkCell/NetworkCell.tsx | 72 + .../__snapshots__/NetworkCell.test.tsx.snap | 146 + .../UI/NetworkModal/NetworkAdded/index.tsx | 5 +- app/components/UI/NetworkModal/index.tsx | 220 +- .../ResetNotificationsModal.test.tsx.snap | 2 +- .../ResetNotificationsModal/index.tsx | 31 +- app/components/UI/OptinMetrics/index.test.tsx | 2 - .../UI/Ramp/Views/BuildQuote/BuildQuote.tsx | 71 +- .../__snapshots__/BuildQuote.test.tsx.snap | 3958 ++--- .../__snapshots__/GetStarted.test.tsx.snap | 57 +- .../LoadingNetworksSkeleton.tsx | 32 +- .../NetworkSwitcher/NetworkSwitcher.test.tsx | 2 +- .../Views/NetworkSwitcher/NetworkSwitcher.tsx | 18 +- .../NetworkSwitcher.test.tsx.snap | 2427 +-- .../__snapshots__/OrderDetails.test.tsx.snap | 13244 ++++++---------- .../__snapshots__/OrdersList.test.tsx.snap | 3584 ++--- .../PaymentMethods.test.tsx.snap | 9818 ++++-------- .../Quotes/__snapshots__/Quotes.test.tsx.snap | 2429 ++- .../UI/Ramp/Views/Regions/Regions.tsx | 31 +- .../__snapshots__/Regions.test.tsx.snap | 1110 +- .../Views/SendTransaction/SendTransaction.tsx | 63 +- .../SendTransaction.test.tsx.snap | 3 + .../UI/Ramp/Views/Settings/Settings.tsx | 32 +- .../__snapshots__/Settings.test.tsx.snap | 318 +- .../UI/Ramp/components/AmountInput.tsx | 38 +- .../Ramp/components/AssetSelectorButton.tsx | 56 +- app/components/UI/Ramp/components/Box.tsx | 14 +- .../UI/Ramp/components/ListItemColumnEnd.tsx | 25 + .../UI/Ramp/components/OrderDetails.tsx | 288 +- .../OrderListItem/OrderListItem.tsx | 98 +- .../__snapshots__/OrderListItem.test.tsx.snap | 2200 +-- .../UI/Ramp/components/PaymentMethod.tsx | 98 +- .../Ramp/components/PaymentMethodSelector.tsx | 39 +- .../UI/Ramp/components/Quote/Quote.tsx | 240 +- .../UI/Ramp/components/RegionModal.tsx | 65 +- .../SkeletonPaymentMethod.tsx | 47 +- .../SkeletonQuote/SkeletonQuote.tsx | 45 +- .../UI/Ramp/components/TokenSelectModal.tsx | 70 +- .../components/modals/FiatSelectModal.tsx | 33 +- .../UI/ReceiveRequest/index.test.tsx | 20 +- .../SimulationDetails/AssetPill/AssetPill.tsx | 3 +- .../UI/SimulationDetails/useBalanceChanges.ts | 5 +- .../Stake/Views/InputView/StakeInputView.tsx | 264 - .../StakeConfirmationView.styles.ts | 23 + .../StakeConfirmationView.test.tsx | 74 + .../StakeConfirmationView.tsx | 60 + .../StakeConfirmationView.types.ts | 10 + .../StakeConfirmationView.test.tsx.snap | 1424 ++ .../StakeInputView.styles.ts | 17 - .../StakeInputView.test.tsx | 2 +- .../Views/StakeInputView/StakeInputView.tsx | 132 + .../StakeInputView.test.tsx.snap | 101 +- .../Views/UnstakeInputView/UnstakeBanner.tsx | 25 + .../UnstakeInputView.styles.ts | 31 + .../UnstakeInputView.test.tsx | 109 + .../UnstakeInputView/UnstakeInputView.tsx | 112 + .../UnstakeInputView.test.tsx.snap | 1577 ++ .../UI/Stake/components/InputDisplay.tsx | 93 + .../StakingBalance/StakingBalance.test.tsx | 56 +- .../StakingButtons/StakingButtons.tsx | 12 +- .../StakingBalance/StakingCta/StakingCta.tsx | 6 +- .../__snapshots__/StakingCta.test.tsx.snap | 2 +- .../StakingBalance.test.tsx.snap | 1385 +- .../AccountHeaderCard.styles.ts | 40 + .../AccountHeaderCard.test.tsx | 72 + .../AccountHeaderCard/AccountHeaderCard.tsx | 74 + .../AccountHeaderCard.types.ts | 3 + .../AccountHeaderCard.test.tsx.snap | 623 + .../AccountTag/AccountTag.test.tsx | 31 + .../AccountTag/AccountTag.tsx | 38 + .../AccountTag/AccountTag.types.ts | 5 + .../__snapshots__/AccountTag.test.tsx.snap | 395 + .../ConfirmationFooter.styles.ts | 114 + .../ConfirmationFooter.test.tsx | 19 + .../ConfirmationFooter/ConfirmationFooter.tsx | 19 + .../FooterButtonGroup.styles.ts | 18 + .../FooterButtonGroup.test.tsx | 49 + .../FooterButtonGroup/FooterButtonGroup.tsx | 59 + .../FooterButtonGroup.test.tsx.snap | 189 + .../LegalLinks/LegalLinks.styles.ts | 14 + .../LegalLinks/LegalLinks.test.tsx | 61 + .../LegalLinks/LegalLinks.tsx | 52 + .../__snapshots__/LegalLinks.test.tsx.snap | 187 + .../ConfirmationFooter.test.tsx.snap | 162 + .../ContractTag/ContractTag.test.tsx | 17 + .../ContractTag/ContractTag.tsx | 23 + .../ContractTag/ContractTag.types.ts | 3 + .../__snapshots__/ContractTag.test.tsx.snap | 69 + .../EstimatedGasCard.styles.ts | 39 + .../EstimatedGasCard.test.tsx | 67 + .../EstimatedGasCard/EstimatedGasCard.tsx | 69 + .../EstimatedGasCard.types.ts | 4 + .../EstimatedGasCard.test.tsx.snap | 419 + .../EstimatedGasFeeTooltipContent.styles.ts | 13 + .../EstimatedGasFeeTooltipContent.test.tsx | 53 + .../EstimatedGasFeeTooltipContent.tsx | 43 + ...stimatedGasFeeTooltipContent.test.tsx.snap | 67 + .../RewardsCard/RewardsCard.styles.ts | 16 + .../RewardsCard/RewardsCard.test.tsx | 98 + .../RewardsCard/RewardsCard.tsx | 74 + .../RewardsCard/RewardsCard.types.ts | 5 + .../__snapshots__/RewardsCard.test.tsx.snap | 1255 ++ .../TokenValueStack/TokenValueStack.styles.ts | 23 + .../TokenValueStack/TokenValueStack.test.tsx | 33 + .../TokenValueStack/TokenValueStack.tsx | 54 + .../TokenValueStack/TokenValueStack.types.ts | 7 + .../TokenValueStack.test.tsx.snap | 212 + app/components/UI/Stake/hooks/useBalance.ts | 14 +- .../UI/Stake/hooks/useStakingInput.ts | 159 + app/components/UI/Stake/routes/index.tsx | 9 +- ...dButtonStyles.js => styledButtonStyles.ts} | 5 +- .../{InfoModal.js => InfoModal.tsx} | 114 +- .../TokenList/PortfolioBalance/index.tsx | 140 + .../TokenList/ScamWarningIcon/index.tsx | 48 + .../TokenList/ScamWarningModal/index.tsx | 81 + .../UI/Tokens/TokenList/StakeButton/index.tsx | 95 + .../TokenList/TokenListFooter/index.tsx | 121 + .../Tokens/TokenList/TokenListItem/index.tsx | 230 + app/components/UI/Tokens/TokenList/index.tsx | 113 + .../Tokens/__snapshots__/index.test.tsx.snap | 218 +- app/components/UI/Tokens/index.tsx | 688 +- app/components/UI/Tokens/styles.ts | 3 +- app/components/UI/Tokens/types.ts | 2 +- ...eriveBalanceFromAssetMarketDetails.test.ts | 157 + .../deriveBalanceFromAssetMarketDetails.ts | 71 + app/components/UI/Tokens/util/index.ts | 2 + .../UI/Tokens/util/sortAssets.test.ts | 263 + app/components/UI/Tokens/util/sortAssets.ts | 81 + .../Views/AccountConnect/AccountConnect.tsx | 24 +- .../{index.js => index.tsx} | 27 +- app/components/Views/AssetDetails/index.tsx | 4 +- .../Views/ImportPrivateKey/index.tsx | 10 +- app/components/Views/LockScreen/index.js | 18 +- app/components/Views/Login/index.js | 39 +- .../MultiRpcModal/MultiRpcModal.constants.ts | 30 + .../MultiRpcModal/MultiRpcModal.styles.ts | 40 + .../MultiRpcModal/MultiRpcModal.test.tsx | 61 + .../Views/MultiRpcModal/MultiRpcModal.tsx | 146 + .../__snapshots__/MultiRpcModal.test.tsx.snap | 595 + app/components/Views/MultiRpcModal/index.ts | 1 + .../NetworkSelector/NetworkSelector.styles.ts | 2 +- .../NetworkSelector/NetworkSelector.test.tsx | 254 +- .../Views/NetworkSelector/NetworkSelector.tsx | 371 +- .../Details/Footers/BlockExplorerFooter.tsx | 2 +- app/components/Views/Onboarding/index.js | 38 +- .../__snapshots__/index.test.tsx.snap | 330 + .../DefaultSettings/index.styles.ts | 43 +- .../DefaultSettings/index.test.tsx | 76 + .../DefaultSettings/index.tsx | 110 +- .../__snapshots__/index.test.tsx.snap | 1682 ++ .../OnboardingAssetsSettings/index.styles.ts | 16 + .../OnboardingAssetsSettings/index.test.tsx | 55 + .../OnboardingAssetsSettings/index.tsx | 33 + .../__snapshots__/index.test.tsx.snap} | 36 +- .../index.test.tsx} | 16 +- .../OnboardingGeneralSettings/index.tsx | 73 + .../__snapshots__/index.test.tsx.snap | 120 + .../OnboardingSecuritySettings/index.test.tsx | 42 + .../OnboardingSecuritySettings/index.tsx | 19 + .../__snapshots__/index.test.tsx.snap | 90 + .../index.constants.ts | 3 + .../index.styles.ts | 26 + .../index.test.tsx | 120 + .../BatchAccountBalanceSettings/index.tsx | 74 + .../__snapshots__/index.test.tsx.snap | 89 + .../index.constants.ts | 1 + .../DisplayNFTMediaSettings/index.styles.ts | 26 + .../DisplayNFTMediaSettings/index.test.tsx | 74 + .../DisplayNFTMediaSettings/index.tsx | 61 + .../__snapshots__/index.test.tsx.snap | 129 + .../IPFSGatewaySettings/index.constants.ts | 4 + .../IPFSGatewaySettings/index.styles.ts | 42 + .../IPFSGatewaySettings/index.test.tsx | 120 + .../Settings/IPFSGatewaySettings/index.tsx | 138 + .../IPFSGatewaySettings/index.types.ts | 12 + .../__snapshots__/index.test.tsx.snap | 1196 ++ .../index.constants.ts | 5 + .../index.styles.ts | 18 + .../index.test.tsx | 131 + .../IncomingTransactionsSettings/index.tsx | 154 + .../index.types.ts | 13 + .../__snapshots__/index.test.tsx.snap | 108 + .../index.constants.ts | 3 + .../index.styles.ts | 26 + .../index.test.tsx | 90 + .../NetworkDetailsCheckSettings/index.tsx | 63 + .../NetworksSettings/NetworkSettings/index.js | 1072 +- .../NetworkSettings/index.test.tsx | 167 +- .../__snapshots__/index.test.tsx.snap | 22 +- .../Views/Settings/NetworksSettings/index.js | 53 +- .../NotificationsSettings.styles.ts | 1 + .../__snapshots__/index.test.tsx.snap | 2 +- .../NotificationsSettings/index.test.tsx | 150 +- .../Settings/NotificationsSettings/index.tsx | 47 +- .../useToggleNotifications.test.tsx | 125 + .../useToggleNotifications.ts | 70 + ...taMetricsAndDataCollectionSection.test.tsx | 4 - .../SecuritySettings.constants.ts | 10 - .../SecuritySettings.styles.ts | 5 - .../SecuritySettings.test.tsx | 11 - .../SecuritySettings/SecuritySettings.tsx | 499 +- .../SecuritySettings.types.ts | 19 - .../SecuritySettings.test.tsx.snap | 865 +- .../Views/TooltipModal/ToolTipModal.styles.ts | 6 +- .../Views/TooltipModal/ToolTipModal.types.ts | 4 +- app/components/Views/TooltipModal/index.tsx | 10 +- app/components/Views/Wallet/index.tsx | 36 +- .../confirmations/Confirm/Confirm.styles.ts | 23 + .../Views/confirmations/Confirm/Confirm.tsx | 18 +- .../__snapshots__/Confirm.test.tsx.snap | 561 +- .../Views/confirmations/Confirm/style.ts | 19 - .../Send/__snapshots__/index.test.tsx.snap | 4 +- .../SendFlow/Amount/index.test.tsx | 31 +- .../Confirm/__snapshots__/index.test.tsx.snap | 2 +- .../confirmations/SendFlow/Confirm/index.js | 58 +- .../SendFlow/Confirm/index.test.tsx | 80 +- .../SendFlow/Confirm/validation.test.ts | 48 +- .../SendFlow/Confirm/validation.ts | 30 +- .../ApproveTransactionHeader.tsx | 9 +- .../ApproveTransactionHeader.test.tsx.snap | 8 +- .../AddNickname/types.ts | 2 +- .../ShowBlockExplorer/index.tsx | 6 +- .../VerifyContractDetails.types.ts | 2 +- .../__snapshots__/index.test.tsx.snap | 2 +- .../ApproveTransactionReview/index.js | 16 +- .../ApproveTransactionReview/index.test.tsx | 142 + .../AccountNetworkInfo.test.tsx | 14 + .../AccountNetworkInfo/AccountNetworkInfo.tsx | 25 + .../AccountNetworkInfoCollapsed.styles.ts | 33 + .../AccountNetworkInfoCollapsed.test.tsx | 14 + .../AccountNetworkInfoCollapsed.tsx | 64 + .../AccountNetworkInfoCollapsed.test.tsx.snap | 161 + .../AccountNetworkInfoCollapsed/index.ts | 1 + .../AccountNetworkInfoExpanded.test.tsx | 14 + .../AccountNetworkInfoExpanded.tsx | 50 + .../AccountNetworkInfoExpanded.test.tsx.snap | 334 + .../AccountNetworkInfoExpanded/index.ts | 1 + .../AccountNetworkInfo.test.tsx.snap | 198 + .../Confirm/AccountNetworkInfo/index.ts | 1 + .../Confirm/Footer/Footer.styles.ts | 30 + .../components/Confirm/Footer/Footer.tsx | 8 +- .../components/Confirm/Footer/style.ts | 27 - .../components/Confirm/Info/Info.test.tsx | 14 + .../components/Confirm/Info/Info.tsx | 26 + .../PersonalSign/Message/Message.styles.ts | 46 + .../PersonalSign/Message/Message.test.tsx | 30 + .../Info/PersonalSign/Message/Message.tsx | 45 + .../__snapshots__/Message.test.tsx.snap | 75 + .../Info/PersonalSign/Message/index.ts | 1 + .../Info/PersonalSign/PersonalSign.test.tsx | 14 + .../Info/PersonalSign/PersonalSign.tsx | 34 + .../Simulation/Simulation.test.tsx | 32 + .../PersonalSign/Simulation/Simulation.tsx | 30 + .../__snapshots__/Simulation.test.tsx.snap | 131 + .../Info/PersonalSign/Simulation/index.ts | 1 + .../__snapshots__/PersonalSign.test.tsx.snap | 337 + .../Confirm/Info/PersonalSign/index.ts | 1 + .../Info/__snapshots__/Info.test.tsx.snap | 337 + .../components/Confirm/Info/index.ts | 1 + .../components/Confirm/Title/Title.styles.ts | 23 + .../components/Confirm/Title/Title.test.tsx | 2 +- .../components/Confirm/Title/Title.tsx | 7 +- .../Title/__snapshots__/Title.test.tsx.snap | 3 +- .../components/Confirm/Title/style.ts | 19 - .../components/PersonalSign/index.test.tsx | 4 +- .../components/SignatureRequest/Root/Root.tsx | 2 +- .../components/TransactionReview/index.js | 2 +- .../components/TypedSign/index.test.tsx | 4 +- .../UI/BottomModal/BottomModal.test.tsx | 2 +- .../UI/BottomModal/BottomModal.tsx | 8 +- .../__snapshots__/BottomModal.test.tsx.snap | 0 .../components}/UI/BottomModal/index.tsx | 0 .../UI/CopyButton/CopyButton.stories.tsx | 8 + .../UI/CopyButton/CopyButton.test.tsx | 20 + .../components/UI/CopyButton/CopyButton.tsx | 36 + .../__snapshots__/CopyButton.test.tsx.snap | 36 + .../components/UI/CopyButton/index.tsx | 1 + .../ExpandableSection.stories.tsx | 25 + .../ExpandableSection.styles.ts | 47 + .../ExpandableSection.test.tsx | 70 + .../ExpandableSection/ExpandableSection.tsx | 73 + .../ExpandableSection.test.tsx.snap | 46 + .../components/UI/ExpandableSection/index.ts | 1 + .../UI/InfoRow/InfoRow.stories.tsx | 12 +- .../components/UI/InfoRow/InfoRow.styles.ts | 39 + .../components}/UI/InfoRow/InfoRow.test.tsx | 0 .../components/UI/InfoRow/InfoRow.tsx | 32 + .../InfoRow/InfoSection/InfoSection.styles.ts | 20 + .../InfoRow/InfoSection/InfoSection.test.tsx | 0 .../UI/InfoRow/InfoSection/InfoSection.tsx | 17 + .../__snapshots__/InfoSection.test.tsx.snap | 1 + .../UI/InfoRow/InfoSection/index.ts | 0 .../UI/InfoRow/InfoSection/style.ts | 4 +- .../InfoValue/Address/Address.test.tsx | 30 + .../UI/InfoRow/InfoValue/Address/Address.tsx | 14 + .../__snapshots__/Address.test.tsx.snap | 50 + .../UI/InfoRow/InfoValue/Address/index.ts | 1 + .../InfoValue/InfoURL/InfoURL.styles.ts | 39 + .../InfoValue/InfoURL/InfoURL.test.tsx | 16 + .../UI/InfoRow/InfoValue/InfoURL/InfoURL.tsx | 50 + .../__snapshots__/InfoURL.test.tsx.snap | 27 + .../UI/InfoRow/InfoValue/InfoURL/index.ts | 1 + .../UI/InfoRow/InfoValue/InfoURL/style.ts | 36 + .../__snapshots__/InfoRow.test.tsx.snap | 24 +- .../components}/UI/InfoRow/index.ts | 0 .../components/UI/Tooltip/Tooltip.stories.tsx | 18 + .../components/UI/Tooltip/Tooltip.styles.ts | 45 + .../components/UI/Tooltip/Tooltip.test.tsx | 37 + .../components/UI/Tooltip/Tooltip.tsx | 64 + .../__snapshots__/Tooltip.test.tsx.snap | 67 + .../components/UI/Tooltip/index.ts | 1 + .../hooks/useAccountInfo.test.ts | 51 + .../confirmations/hooks/useAccountInfo.ts | 26 + .../useMinimumVersions.test.ts | 68 + .../MinimumVersions/useMinimumVersions.tsx | 29 +- .../useAddressBalance/useAddressBalance.ts | 2 +- app/components/hooks/useBlockExplorer.test.ts | 30 +- app/components/hooks/useBlockExplorer.ts | 3 +- .../hooks/useMetrics/useMetrics.test.tsx | 16 +- app/components/hooks/useMetrics/useMetrics.ts | 128 +- .../hooks/useMetrics/useMetrics.types.ts | 17 + app/components/hooks/useOnboardingHeader.tsx | 44 + app/components/hooks/useTooltipModal.tsx | 3 +- app/constants/navigation/Routes.ts | 5 + app/core/Analytics/MetaMetrics.events.ts | 6 + app/core/Analytics/MetaMetrics.ts | 112 +- app/core/Analytics/MetaMetrics.types.ts | 84 +- .../Analytics/MetricsEventBuilder.test.ts | 158 + app/core/Analytics/MetricsEventBuilder.ts | 168 + app/core/AppConstants.ts | 3 +- app/core/AppStateEventListener.test.ts | 58 +- app/core/AppStateEventListener.ts | 17 +- app/core/BackgroundBridge/BackgroundBridge.js | 4 + .../ParseManager/extractURLParams.test.ts | 4 + .../ParseManager/extractURLParams.ts | 2 + app/core/Engine.test.js | 11 +- app/core/Engine.ts | 182 +- app/core/EngineService/EngineService.ts | 8 +- app/core/NotificationManager.js | 7 +- .../RPCMethods/RPCMethodMiddleware.test.ts | 211 +- app/core/RPCMethods/RPCMethodMiddleware.ts | 34 +- .../RPCMethods/wallet_addEthereumChain.js | 121 +- .../wallet_addEthereumChain.test.js | 22 +- .../RPCMethods/wallet_switchEthereumChain.js | 15 +- app/core/RPCMethods/wallet_watchAsset.test.ts | 24 +- .../handlers/handleConnectionMessage.test.ts | 10 +- .../createTracingMiddleware/index.test.ts | 39 + app/core/createTracingMiddleware/index.ts | 45 + app/core/processAttribution.test.tsx | 77 +- app/core/processAttribution.tsx | 50 +- app/images/flare-mainnet.png | Bin 0 -> 15256 bytes app/images/networks1.png | Bin 0 -> 5923 bytes app/images/songbird.png | Bin 0 -> 67703 bytes app/lib/ppom/ppom-util.test.ts | 52 +- app/lib/snaps/SnapsExecutionWebView.tsx | 10 +- app/reducers/fiatOrders/index.test.ts | 243 +- app/reducers/index.ts | 4 +- app/reducers/security/index.ts | 9 + app/reducers/swaps/index.js | 2 +- .../accountTrackerController.test.ts | 18 +- ...accountTrackerControllerReRenders.test.tsx | 141 +- app/selectors/currencyRateController.ts | 18 +- app/selectors/networkController.ts | 140 +- app/selectors/nftController.ts | 18 +- app/selectors/preferencesController.ts | 6 + app/selectors/selectedNetworkController.ts | 38 +- app/selectors/tokensController.ts | 32 +- app/selectors/types.ts | 8 +- app/store/index.ts | 60 +- app/store/migrations/023.test.js | 22 + app/store/migrations/029.ts | 26 +- app/store/migrations/031.ts | 4 +- app/store/migrations/035.test.ts | 6 +- app/store/migrations/043.test.ts | 5 +- app/store/migrations/051.test.ts | 1 + app/store/migrations/054.test.ts | 521 + app/store/migrations/054.ts | 39 + app/store/migrations/055.test.ts | 584 + app/store/migrations/055.ts | 403 + app/store/migrations/index.ts | 4 + app/store/storage-wrapper.js | 69 - app/store/storage-wrapper.test.ts | 95 + app/store/storage-wrapper.ts | 158 + app/util/address/index.test.ts | 50 +- app/util/address/index.ts | 2 +- app/util/dappTransactions/index.test.ts | 2 +- app/util/hideKeyFromUrl.test.ts | 70 +- app/util/hideKeyFromUrl.ts | 8 + .../TrackError/trackErrorAsAnalytics.ts | 2 +- app/util/networks/customNetworks.tsx | 5 + app/util/networks/handleNetworkSwitch.test.ts | 92 +- app/util/networks/handleNetworkSwitch.ts | 28 +- app/util/networks/index.js | 43 +- app/util/networks/index.test.ts | 139 +- .../networks/isNetworkUiRedesignEnabled.ts | 3 +- .../notifications/androidChannels.test.ts | 10 +- app/util/notifications/hooks/index.test.ts | 198 +- app/util/notifications/hooks/index.ts | 4 +- app/util/notifications/hooks/types.ts | 4 +- .../hooks/useNotifications.test.tsx | 37 + .../notifications/hooks/useNotifications.ts | 16 +- .../sentry/__snapshots__/utils.test.ts.snap | 2 +- app/util/sentry/tags/index.test.ts | 229 + app/util/sentry/tags/index.ts | 30 + app/util/sentry/utils.js | 9 +- app/util/sentry/utils.test.ts | 2 +- app/util/test/initial-background-state.json | 95 +- app/util/test/network-store.js | 5 + app/util/test/network.ts | 76 +- app/util/trace.test.ts | 54 +- app/util/trace.ts | 163 +- ...pers.js => transaction-reducer-helpers.ts} | 29 +- babel.config.js | 4 + bitrise.yml | 55 +- docs/readme/testing.md | 2 +- e2e/fixtures/fixture-builder.js | 232 +- e2e/pages/CommonView.js | 13 +- e2e/pages/ImportAccountView.js | 53 - e2e/pages/LoginView.js | 37 +- e2e/pages/Ramps/BuildQuoteView.js | 13 + e2e/pages/Ramps/BuyGetStartedView.js | 15 + e2e/pages/Ramps/SelectPaymentMethodView.js | 21 + e2e/pages/Ramps/SelectRegionView.js | 28 + e2e/pages/Settings/NetworksView.js | 35 + .../RevealSecretRecoveryPhrase.js | 18 - e2e/pages/importAccount/ImportAccountView.js | 32 + .../importAccount/SuccessImportAccountView.js | 19 + e2e/pages/modals/NetworkApprovalModal.js | 3 +- e2e/pages/modals/NetworkListModal.js | 56 +- e2e/pages/modals/WalletActionsModal.js | 8 + e2e/pages/wallet/WalletView.js | 8 - .../ImportAccountFromPrivateKey.selectors.js | 6 + .../SuccessImportAccount.selectors.js | 4 + .../ImportAccountFromPrivateKey.selectors.js | 6 - e2e/selectors/LoginView.selectors.js | 4 +- .../Modals/NetworkListModal.selectors.js | 3 + e2e/selectors/Ramps/BuildQuote.selectors.js | 6 + e2e/selectors/Ramps/GetStarted.selectors.js | 5 + .../Ramps/SelectPaymentMethod.selectors.js | 5 + e2e/selectors/Ramps/SelectRegion.selectors.js | 6 + .../Settings/AdvancedView.selectors.js | 1 + .../Settings/NetworksView.selectors.js | 4 + .../RevealSeedView.selectors.js | 1 - .../SecurityPrivacyView.selectors.js | 1 - e2e/specs/accounts/auto-lock.spec.js | 2 +- .../accounts/change-account-name.spec.js | 2 +- .../accounts/import-wallet-account.spec.js | 12 +- ...imported-account-remove-and-import.spec.js | 9 +- e2e/specs/assets/nft-detection-modal.spec.js | 17 +- e2e/specs/networks/add-custom-rpc.spec.js | 92 +- .../networks/add-popular-networks.spec.js | 17 +- .../networks/connect-test-network.spec.js | 4 + e2e/specs/networks/networks-search.spec.js | 42 +- .../onboarding-wizard-opt-in.spec.js | 3 +- .../permission-system-delete-wallet.spec.js | 7 +- e2e/specs/quarantine/deeplinks.failing.js | 10 +- ...ystem-removing-imported-account.failing.js | 13 +- e2e/specs/ramps/onramp.spec.js | 59 + e2e/specs/settings/delete-wallet.spec.js | 2 +- e2e/specs/wallet/send-ERC-token.spec.js | 2 + e2e/specs/wallet/suggestedGasApi.mock.spec.js | 9 +- e2e/utils/Gestures.js | 2 +- e2e/viewHelper.js | 14 +- index.js | 1 - ios/Podfile | 2 +- ios/Podfile.lock | 17 +- locales/languages/en.json | 61 +- package.json | 32 +- ...tamask+preferences-controller+13.0.3.patch | 13 + .../@metamask+assets-controllers+30.0.0.patch | 1160 -- .../@metamask+assets-controllers+32.0.0.patch | 1022 ++ patches/@metamask+nonce-tracker+5.0.0.patch | 30 - ...tamask+preferences-controller+11.0.0.patch | 58 +- ...tamask+transaction-controller+35.0.0.patch | 2588 --- ...ative-community+datetimepicker+7.7.0.patch | 13 - scripts/build.sh | 30 +- scripts/docker/Dockerfile | 4 +- wdio/screen-objects/ImportAccountScreen.js | 15 +- wdio/screen-objects/ImportSuccessScreen.js | 9 +- wdio/screen-objects/LoginScreen.js | 25 +- .../Screens/ImportAccountScreen.testIds.js | 5 - .../Screens/ImportSuccessScreen.testIds.js | 2 - .../testIDs/Screens/LoginScreen.testIds.js | 11 - .../RevelSecretRecoveryPhrase.testIds.js | 16 - .../Screens/SecurityPrivacy.testIds.js | 3 - yarn.lock | 740 +- 546 files changed, 47206 insertions(+), 35603 deletions(-) rename {scripts => .github/scripts}/get-next-semver-version.sh (93%) rename app/components/Base/HorizontalSelector/{index.js => index.tsx} (73%) create mode 100644 app/components/UI/ApprovalTagUrl/ApprovalTagUrl.test.tsx create mode 100644 app/components/UI/ApprovalTagUrl/__snapshots__/ApprovalTagUrl.test.tsx.snap rename app/components/UI/Fox/{index.js => index.tsx} (98%) delete mode 100644 app/components/UI/InfoRow/InfoRow.tsx delete mode 100644 app/components/UI/InfoRow/InfoSection/InfoSection.tsx delete mode 100644 app/components/UI/InfoRow/style.ts create mode 100644 app/components/UI/NetworkCell/NetworkCell.styles.ts create mode 100644 app/components/UI/NetworkCell/NetworkCell.test.tsx create mode 100644 app/components/UI/NetworkCell/NetworkCell.tsx create mode 100644 app/components/UI/NetworkCell/__snapshots__/NetworkCell.test.tsx.snap create mode 100644 app/components/UI/Ramp/components/ListItemColumnEnd.tsx delete mode 100644 app/components/UI/Stake/Views/InputView/StakeInputView.tsx create mode 100644 app/components/UI/Stake/Views/StakeConfirmationView/StakeConfirmationView.styles.ts create mode 100644 app/components/UI/Stake/Views/StakeConfirmationView/StakeConfirmationView.test.tsx create mode 100644 app/components/UI/Stake/Views/StakeConfirmationView/StakeConfirmationView.tsx create mode 100644 app/components/UI/Stake/Views/StakeConfirmationView/StakeConfirmationView.types.ts create mode 100644 app/components/UI/Stake/Views/StakeConfirmationView/__snapshots__/StakeConfirmationView.test.tsx.snap rename app/components/UI/Stake/Views/{InputView => StakeInputView}/StakeInputView.styles.ts (65%) rename app/components/UI/Stake/Views/{InputView => StakeInputView}/StakeInputView.test.tsx (99%) create mode 100644 app/components/UI/Stake/Views/StakeInputView/StakeInputView.tsx rename app/components/UI/Stake/Views/{InputView => StakeInputView}/__snapshots__/StakeInputView.test.tsx.snap (95%) create mode 100644 app/components/UI/Stake/Views/UnstakeInputView/UnstakeBanner.tsx create mode 100644 app/components/UI/Stake/Views/UnstakeInputView/UnstakeInputView.styles.ts create mode 100644 app/components/UI/Stake/Views/UnstakeInputView/UnstakeInputView.test.tsx create mode 100644 app/components/UI/Stake/Views/UnstakeInputView/UnstakeInputView.tsx create mode 100644 app/components/UI/Stake/Views/UnstakeInputView/__snapshots__/UnstakeInputView.test.tsx.snap create mode 100644 app/components/UI/Stake/components/InputDisplay.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/AccountHeaderCard/AccountHeaderCard.styles.ts create mode 100644 app/components/UI/Stake/components/StakingConfirmation/AccountHeaderCard/AccountHeaderCard.test.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/AccountHeaderCard/AccountHeaderCard.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/AccountHeaderCard/AccountHeaderCard.types.ts create mode 100644 app/components/UI/Stake/components/StakingConfirmation/AccountHeaderCard/__snapshots__/AccountHeaderCard.test.tsx.snap create mode 100644 app/components/UI/Stake/components/StakingConfirmation/AccountTag/AccountTag.test.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/AccountTag/AccountTag.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/AccountTag/AccountTag.types.ts create mode 100644 app/components/UI/Stake/components/StakingConfirmation/AccountTag/__snapshots__/AccountTag.test.tsx.snap create mode 100644 app/components/UI/Stake/components/StakingConfirmation/ConfirmationFooter/ConfirmationFooter.styles.ts create mode 100644 app/components/UI/Stake/components/StakingConfirmation/ConfirmationFooter/ConfirmationFooter.test.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/ConfirmationFooter/ConfirmationFooter.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/ConfirmationFooter/FooterButtonGroup/FooterButtonGroup.styles.ts create mode 100644 app/components/UI/Stake/components/StakingConfirmation/ConfirmationFooter/FooterButtonGroup/FooterButtonGroup.test.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/ConfirmationFooter/FooterButtonGroup/FooterButtonGroup.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/ConfirmationFooter/FooterButtonGroup/__snapshots__/FooterButtonGroup.test.tsx.snap create mode 100644 app/components/UI/Stake/components/StakingConfirmation/ConfirmationFooter/LegalLinks/LegalLinks.styles.ts create mode 100644 app/components/UI/Stake/components/StakingConfirmation/ConfirmationFooter/LegalLinks/LegalLinks.test.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/ConfirmationFooter/LegalLinks/LegalLinks.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/ConfirmationFooter/LegalLinks/__snapshots__/LegalLinks.test.tsx.snap create mode 100644 app/components/UI/Stake/components/StakingConfirmation/ConfirmationFooter/__snapshots__/ConfirmationFooter.test.tsx.snap create mode 100644 app/components/UI/Stake/components/StakingConfirmation/ContractTag/ContractTag.test.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/ContractTag/ContractTag.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/ContractTag/ContractTag.types.ts create mode 100644 app/components/UI/Stake/components/StakingConfirmation/ContractTag/__snapshots__/ContractTag.test.tsx.snap create mode 100644 app/components/UI/Stake/components/StakingConfirmation/EstimatedGasCard/EstimatedGasCard.styles.ts create mode 100644 app/components/UI/Stake/components/StakingConfirmation/EstimatedGasCard/EstimatedGasCard.test.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/EstimatedGasCard/EstimatedGasCard.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/EstimatedGasCard/EstimatedGasCard.types.ts create mode 100644 app/components/UI/Stake/components/StakingConfirmation/EstimatedGasCard/__snapshots__/EstimatedGasCard.test.tsx.snap create mode 100644 app/components/UI/Stake/components/StakingConfirmation/EstimatedGasFeeTooltipContent/EstimatedGasFeeTooltipContent.styles.ts create mode 100644 app/components/UI/Stake/components/StakingConfirmation/EstimatedGasFeeTooltipContent/EstimatedGasFeeTooltipContent.test.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/EstimatedGasFeeTooltipContent/EstimatedGasFeeTooltipContent.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/EstimatedGasFeeTooltipContent/__snapshots__/EstimatedGasFeeTooltipContent.test.tsx.snap create mode 100644 app/components/UI/Stake/components/StakingConfirmation/RewardsCard/RewardsCard.styles.ts create mode 100644 app/components/UI/Stake/components/StakingConfirmation/RewardsCard/RewardsCard.test.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/RewardsCard/RewardsCard.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/RewardsCard/RewardsCard.types.ts create mode 100644 app/components/UI/Stake/components/StakingConfirmation/RewardsCard/__snapshots__/RewardsCard.test.tsx.snap create mode 100644 app/components/UI/Stake/components/StakingConfirmation/TokenValueStack/TokenValueStack.styles.ts create mode 100644 app/components/UI/Stake/components/StakingConfirmation/TokenValueStack/TokenValueStack.test.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/TokenValueStack/TokenValueStack.tsx create mode 100644 app/components/UI/Stake/components/StakingConfirmation/TokenValueStack/TokenValueStack.types.ts create mode 100644 app/components/UI/Stake/components/StakingConfirmation/TokenValueStack/__snapshots__/TokenValueStack.test.tsx.snap create mode 100644 app/components/UI/Stake/hooks/useStakingInput.ts rename app/components/UI/StyledButton/{styledButtonStyles.js => styledButtonStyles.ts} (97%) rename app/components/UI/Swaps/components/{InfoModal.js => InfoModal.tsx} (56%) create mode 100644 app/components/UI/Tokens/TokenList/PortfolioBalance/index.tsx create mode 100644 app/components/UI/Tokens/TokenList/ScamWarningIcon/index.tsx create mode 100644 app/components/UI/Tokens/TokenList/ScamWarningModal/index.tsx create mode 100644 app/components/UI/Tokens/TokenList/StakeButton/index.tsx create mode 100644 app/components/UI/Tokens/TokenList/TokenListFooter/index.tsx create mode 100644 app/components/UI/Tokens/TokenList/TokenListItem/index.tsx create mode 100644 app/components/UI/Tokens/TokenList/index.tsx create mode 100644 app/components/UI/Tokens/util/deriveBalanceFromAssetMarketDetails.test.ts create mode 100644 app/components/UI/Tokens/util/deriveBalanceFromAssetMarketDetails.ts create mode 100644 app/components/UI/Tokens/util/index.ts create mode 100644 app/components/UI/Tokens/util/sortAssets.test.ts create mode 100644 app/components/UI/Tokens/util/sortAssets.ts rename app/components/Views/AndroidBackHandler/{index.js => index.tsx} (67%) create mode 100644 app/components/Views/MultiRpcModal/MultiRpcModal.constants.ts create mode 100644 app/components/Views/MultiRpcModal/MultiRpcModal.styles.ts create mode 100644 app/components/Views/MultiRpcModal/MultiRpcModal.test.tsx create mode 100644 app/components/Views/MultiRpcModal/MultiRpcModal.tsx create mode 100644 app/components/Views/MultiRpcModal/__snapshots__/MultiRpcModal.test.tsx.snap create mode 100644 app/components/Views/MultiRpcModal/index.ts create mode 100644 app/components/Views/OnboardingSuccess/DefaultSettings/__snapshots__/index.test.tsx.snap create mode 100644 app/components/Views/OnboardingSuccess/DefaultSettings/index.test.tsx create mode 100644 app/components/Views/OnboardingSuccess/OnboardingAssetsSettings/__snapshots__/index.test.tsx.snap create mode 100644 app/components/Views/OnboardingSuccess/OnboardingAssetsSettings/index.styles.ts create mode 100644 app/components/Views/OnboardingSuccess/OnboardingAssetsSettings/index.test.tsx create mode 100644 app/components/Views/OnboardingSuccess/OnboardingAssetsSettings/index.tsx rename app/components/Views/OnboardingSuccess/{DefaultSettings/__snapshots__/index.test.js.snap => OnboardingGeneralSettings/__snapshots__/index.test.tsx.snap} (87%) rename app/components/Views/OnboardingSuccess/{DefaultSettings/index.test.js => OnboardingGeneralSettings/index.test.tsx} (73%) create mode 100644 app/components/Views/OnboardingSuccess/OnboardingGeneralSettings/index.tsx create mode 100644 app/components/Views/OnboardingSuccess/OnboardingSecuritySettings/__snapshots__/index.test.tsx.snap create mode 100644 app/components/Views/OnboardingSuccess/OnboardingSecuritySettings/index.test.tsx create mode 100644 app/components/Views/OnboardingSuccess/OnboardingSecuritySettings/index.tsx create mode 100644 app/components/Views/Settings/BatchAccountBalanceSettings/__snapshots__/index.test.tsx.snap create mode 100644 app/components/Views/Settings/BatchAccountBalanceSettings/index.constants.ts create mode 100644 app/components/Views/Settings/BatchAccountBalanceSettings/index.styles.ts create mode 100644 app/components/Views/Settings/BatchAccountBalanceSettings/index.test.tsx create mode 100644 app/components/Views/Settings/BatchAccountBalanceSettings/index.tsx create mode 100644 app/components/Views/Settings/DisplayNFTMediaSettings/__snapshots__/index.test.tsx.snap create mode 100644 app/components/Views/Settings/DisplayNFTMediaSettings/index.constants.ts create mode 100644 app/components/Views/Settings/DisplayNFTMediaSettings/index.styles.ts create mode 100644 app/components/Views/Settings/DisplayNFTMediaSettings/index.test.tsx create mode 100644 app/components/Views/Settings/DisplayNFTMediaSettings/index.tsx create mode 100644 app/components/Views/Settings/IPFSGatewaySettings/__snapshots__/index.test.tsx.snap create mode 100644 app/components/Views/Settings/IPFSGatewaySettings/index.constants.ts create mode 100644 app/components/Views/Settings/IPFSGatewaySettings/index.styles.ts create mode 100644 app/components/Views/Settings/IPFSGatewaySettings/index.test.tsx create mode 100644 app/components/Views/Settings/IPFSGatewaySettings/index.tsx create mode 100644 app/components/Views/Settings/IPFSGatewaySettings/index.types.ts create mode 100644 app/components/Views/Settings/IncomingTransactionsSettings/__snapshots__/index.test.tsx.snap create mode 100644 app/components/Views/Settings/IncomingTransactionsSettings/index.constants.ts create mode 100644 app/components/Views/Settings/IncomingTransactionsSettings/index.styles.ts create mode 100644 app/components/Views/Settings/IncomingTransactionsSettings/index.test.tsx create mode 100644 app/components/Views/Settings/IncomingTransactionsSettings/index.tsx create mode 100644 app/components/Views/Settings/IncomingTransactionsSettings/index.types.ts create mode 100644 app/components/Views/Settings/NetworkDetailsCheckSettings/__snapshots__/index.test.tsx.snap create mode 100644 app/components/Views/Settings/NetworkDetailsCheckSettings/index.constants.ts create mode 100644 app/components/Views/Settings/NetworkDetailsCheckSettings/index.styles.ts create mode 100644 app/components/Views/Settings/NetworkDetailsCheckSettings/index.test.tsx create mode 100644 app/components/Views/Settings/NetworkDetailsCheckSettings/index.tsx create mode 100644 app/components/Views/Settings/NotificationsSettings/useToggleNotifications.test.tsx create mode 100644 app/components/Views/Settings/NotificationsSettings/useToggleNotifications.ts create mode 100644 app/components/Views/confirmations/Confirm/Confirm.styles.ts delete mode 100644 app/components/Views/confirmations/Confirm/style.ts create mode 100644 app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfo.test.tsx create mode 100644 app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfo.tsx create mode 100644 app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoCollapsed/AccountNetworkInfoCollapsed.styles.ts create mode 100644 app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoCollapsed/AccountNetworkInfoCollapsed.test.tsx create mode 100644 app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoCollapsed/AccountNetworkInfoCollapsed.tsx create mode 100644 app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoCollapsed/__snapshots__/AccountNetworkInfoCollapsed.test.tsx.snap create mode 100644 app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoCollapsed/index.ts create mode 100644 app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.test.tsx create mode 100644 app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/AccountNetworkInfoExpanded.tsx create mode 100644 app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/__snapshots__/AccountNetworkInfoExpanded.test.tsx.snap create mode 100644 app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/AccountNetworkInfoExpanded/index.ts create mode 100644 app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/__snapshots__/AccountNetworkInfo.test.tsx.snap create mode 100644 app/components/Views/confirmations/components/Confirm/AccountNetworkInfo/index.ts create mode 100644 app/components/Views/confirmations/components/Confirm/Footer/Footer.styles.ts delete mode 100644 app/components/Views/confirmations/components/Confirm/Footer/style.ts create mode 100644 app/components/Views/confirmations/components/Confirm/Info/Info.test.tsx create mode 100644 app/components/Views/confirmations/components/Confirm/Info/Info.tsx create mode 100644 app/components/Views/confirmations/components/Confirm/Info/PersonalSign/Message/Message.styles.ts create mode 100644 app/components/Views/confirmations/components/Confirm/Info/PersonalSign/Message/Message.test.tsx create mode 100644 app/components/Views/confirmations/components/Confirm/Info/PersonalSign/Message/Message.tsx create mode 100644 app/components/Views/confirmations/components/Confirm/Info/PersonalSign/Message/__snapshots__/Message.test.tsx.snap create mode 100644 app/components/Views/confirmations/components/Confirm/Info/PersonalSign/Message/index.ts create mode 100644 app/components/Views/confirmations/components/Confirm/Info/PersonalSign/PersonalSign.test.tsx create mode 100644 app/components/Views/confirmations/components/Confirm/Info/PersonalSign/PersonalSign.tsx create mode 100644 app/components/Views/confirmations/components/Confirm/Info/PersonalSign/Simulation/Simulation.test.tsx create mode 100644 app/components/Views/confirmations/components/Confirm/Info/PersonalSign/Simulation/Simulation.tsx create mode 100644 app/components/Views/confirmations/components/Confirm/Info/PersonalSign/Simulation/__snapshots__/Simulation.test.tsx.snap create mode 100644 app/components/Views/confirmations/components/Confirm/Info/PersonalSign/Simulation/index.ts create mode 100644 app/components/Views/confirmations/components/Confirm/Info/PersonalSign/__snapshots__/PersonalSign.test.tsx.snap create mode 100644 app/components/Views/confirmations/components/Confirm/Info/PersonalSign/index.ts create mode 100644 app/components/Views/confirmations/components/Confirm/Info/__snapshots__/Info.test.tsx.snap create mode 100644 app/components/Views/confirmations/components/Confirm/Info/index.ts create mode 100644 app/components/Views/confirmations/components/Confirm/Title/Title.styles.ts delete mode 100644 app/components/Views/confirmations/components/Confirm/Title/style.ts rename app/components/{ => Views/confirmations/components}/UI/BottomModal/BottomModal.test.tsx (83%) rename app/components/{ => Views/confirmations/components}/UI/BottomModal/BottomModal.tsx (73%) rename app/components/{ => Views/confirmations/components}/UI/BottomModal/__snapshots__/BottomModal.test.tsx.snap (100%) rename app/components/{ => Views/confirmations/components}/UI/BottomModal/index.tsx (100%) create mode 100644 app/components/Views/confirmations/components/UI/CopyButton/CopyButton.stories.tsx create mode 100644 app/components/Views/confirmations/components/UI/CopyButton/CopyButton.test.tsx create mode 100644 app/components/Views/confirmations/components/UI/CopyButton/CopyButton.tsx create mode 100644 app/components/Views/confirmations/components/UI/CopyButton/__snapshots__/CopyButton.test.tsx.snap create mode 100644 app/components/Views/confirmations/components/UI/CopyButton/index.tsx create mode 100644 app/components/Views/confirmations/components/UI/ExpandableSection/ExpandableSection.stories.tsx create mode 100644 app/components/Views/confirmations/components/UI/ExpandableSection/ExpandableSection.styles.ts create mode 100644 app/components/Views/confirmations/components/UI/ExpandableSection/ExpandableSection.test.tsx create mode 100644 app/components/Views/confirmations/components/UI/ExpandableSection/ExpandableSection.tsx create mode 100644 app/components/Views/confirmations/components/UI/ExpandableSection/__snapshots__/ExpandableSection.test.tsx.snap create mode 100644 app/components/Views/confirmations/components/UI/ExpandableSection/index.ts rename app/components/{ => Views/confirmations/components}/UI/InfoRow/InfoRow.stories.tsx (71%) create mode 100644 app/components/Views/confirmations/components/UI/InfoRow/InfoRow.styles.ts rename app/components/{ => Views/confirmations/components}/UI/InfoRow/InfoRow.test.tsx (100%) create mode 100644 app/components/Views/confirmations/components/UI/InfoRow/InfoRow.tsx create mode 100644 app/components/Views/confirmations/components/UI/InfoRow/InfoSection/InfoSection.styles.ts rename app/components/{ => Views/confirmations/components}/UI/InfoRow/InfoSection/InfoSection.test.tsx (100%) create mode 100644 app/components/Views/confirmations/components/UI/InfoRow/InfoSection/InfoSection.tsx rename app/components/{ => Views/confirmations/components}/UI/InfoRow/InfoSection/__snapshots__/InfoSection.test.tsx.snap (93%) rename app/components/{ => Views/confirmations/components}/UI/InfoRow/InfoSection/index.ts (100%) rename app/components/{ => Views/confirmations/components}/UI/InfoRow/InfoSection/style.ts (73%) create mode 100644 app/components/Views/confirmations/components/UI/InfoRow/InfoValue/Address/Address.test.tsx create mode 100644 app/components/Views/confirmations/components/UI/InfoRow/InfoValue/Address/Address.tsx create mode 100644 app/components/Views/confirmations/components/UI/InfoRow/InfoValue/Address/__snapshots__/Address.test.tsx.snap create mode 100644 app/components/Views/confirmations/components/UI/InfoRow/InfoValue/Address/index.ts create mode 100644 app/components/Views/confirmations/components/UI/InfoRow/InfoValue/InfoURL/InfoURL.styles.ts create mode 100644 app/components/Views/confirmations/components/UI/InfoRow/InfoValue/InfoURL/InfoURL.test.tsx create mode 100644 app/components/Views/confirmations/components/UI/InfoRow/InfoValue/InfoURL/InfoURL.tsx create mode 100644 app/components/Views/confirmations/components/UI/InfoRow/InfoValue/InfoURL/__snapshots__/InfoURL.test.tsx.snap create mode 100644 app/components/Views/confirmations/components/UI/InfoRow/InfoValue/InfoURL/index.ts create mode 100644 app/components/Views/confirmations/components/UI/InfoRow/InfoValue/InfoURL/style.ts rename app/components/{ => Views/confirmations/components}/UI/InfoRow/__snapshots__/InfoRow.test.tsx.snap (65%) rename app/components/{ => Views/confirmations/components}/UI/InfoRow/index.ts (100%) create mode 100644 app/components/Views/confirmations/components/UI/Tooltip/Tooltip.stories.tsx create mode 100644 app/components/Views/confirmations/components/UI/Tooltip/Tooltip.styles.ts create mode 100644 app/components/Views/confirmations/components/UI/Tooltip/Tooltip.test.tsx create mode 100644 app/components/Views/confirmations/components/UI/Tooltip/Tooltip.tsx create mode 100644 app/components/Views/confirmations/components/UI/Tooltip/__snapshots__/Tooltip.test.tsx.snap create mode 100644 app/components/Views/confirmations/components/UI/Tooltip/index.ts create mode 100644 app/components/Views/confirmations/hooks/useAccountInfo.test.ts create mode 100644 app/components/Views/confirmations/hooks/useAccountInfo.ts create mode 100644 app/components/hooks/MinimumVersions/useMinimumVersions.test.ts create mode 100644 app/components/hooks/useOnboardingHeader.tsx create mode 100644 app/core/Analytics/MetricsEventBuilder.test.ts create mode 100644 app/core/Analytics/MetricsEventBuilder.ts create mode 100644 app/core/createTracingMiddleware/index.test.ts create mode 100644 app/core/createTracingMiddleware/index.ts create mode 100644 app/images/flare-mainnet.png create mode 100644 app/images/networks1.png create mode 100644 app/images/songbird.png create mode 100644 app/store/migrations/054.test.ts create mode 100644 app/store/migrations/054.ts create mode 100644 app/store/migrations/055.test.ts create mode 100644 app/store/migrations/055.ts delete mode 100644 app/store/storage-wrapper.js create mode 100644 app/store/storage-wrapper.test.ts create mode 100644 app/store/storage-wrapper.ts create mode 100644 app/util/sentry/tags/index.test.ts create mode 100644 app/util/sentry/tags/index.ts rename app/util/{transaction-reducer-helpers.js => transaction-reducer-helpers.ts} (64%) delete mode 100644 e2e/pages/ImportAccountView.js create mode 100644 e2e/pages/Ramps/BuildQuoteView.js create mode 100644 e2e/pages/Ramps/BuyGetStartedView.js create mode 100644 e2e/pages/Ramps/SelectPaymentMethodView.js create mode 100644 e2e/pages/Ramps/SelectRegionView.js create mode 100644 e2e/pages/importAccount/ImportAccountView.js create mode 100644 e2e/pages/importAccount/SuccessImportAccountView.js create mode 100644 e2e/selectors/ImportAccount/ImportAccountFromPrivateKey.selectors.js create mode 100644 e2e/selectors/ImportAccount/SuccessImportAccount.selectors.js delete mode 100644 e2e/selectors/ImportAccountFromPrivateKey.selectors.js create mode 100644 e2e/selectors/Ramps/BuildQuote.selectors.js create mode 100644 e2e/selectors/Ramps/GetStarted.selectors.js create mode 100644 e2e/selectors/Ramps/SelectPaymentMethod.selectors.js create mode 100644 e2e/selectors/Ramps/SelectRegion.selectors.js create mode 100644 e2e/specs/ramps/onramp.spec.js create mode 100644 patches/@metamask+assets-controllers++@metamask+preferences-controller+13.0.3.patch delete mode 100644 patches/@metamask+assets-controllers+30.0.0.patch create mode 100644 patches/@metamask+assets-controllers+32.0.0.patch delete mode 100644 patches/@metamask+nonce-tracker+5.0.0.patch delete mode 100644 patches/@metamask+transaction-controller+35.0.0.patch delete mode 100644 patches/@react-native-community+datetimepicker+7.7.0.patch delete mode 100644 wdio/screen-objects/testIDs/Screens/ImportAccountScreen.testIds.js delete mode 100644 wdio/screen-objects/testIDs/Screens/ImportSuccessScreen.testIds.js delete mode 100644 wdio/screen-objects/testIDs/Screens/LoginScreen.testIds.js delete mode 100644 wdio/screen-objects/testIDs/Screens/RevelSecretRecoveryPhrase.testIds.js diff --git a/.depcheckrc.yml b/.depcheckrc.yml index e8fe7a446ec..f51f487fd9b 100644 --- a/.depcheckrc.yml +++ b/.depcheckrc.yml @@ -2,10 +2,10 @@ ignores: - '@metamask/oss-attribution-generator' - 'webpack-cli' - - '@react-native-community/datetimepicker' - '@react-native-community/slider' - 'patch-package' - '@lavamoat/allow-scripts' + - 'babel-plugin-inline-import' # This is used on the patch for TokenRatesController of Assets controllers, for we to be able to use the last version of it - cockatiel diff --git a/.detoxrc.js b/.detoxrc.js index d637d3c937c..b1a80212b46 100644 --- a/.detoxrc.js +++ b/.detoxrc.js @@ -26,7 +26,7 @@ module.exports = { configurations: { 'ios.sim.apiSpecs': { device: 'ios.simulator', - app: 'ios.debug', + app: process.env.CI ? 'ios.qa' :'ios.debug', testRunner: { args: { "$0": "node e2e/api-specs/run-api-spec-tests.js", @@ -41,10 +41,9 @@ module.exports = { device: 'ios.simulator', app: 'ios.release', }, - // because e2e run on debug mode in bitrise - 'android.emu.bitrise.debug': { - device: 'android.bitrise.emulator', - app: 'android.bitrise.debug', + 'ios.sim.qa': { + device: 'ios.simulator', + app: 'ios.qa', }, 'android.emu.debug': { @@ -86,32 +85,21 @@ module.exports = { binaryPath: 'ios/build/Build/Products/Debug-iphonesimulator/MetaMask.app', build: 'yarn start:ios:e2e', }, - 'ios.release': { + 'ios.qa': { type: 'ios.app', binaryPath: - 'ios/build/Build/Products/Release-iphonesimulator/MetaMask.app', - build: "METAMASK_BUILD_TYPE='main' METAMASK_ENVIRONMENT='production' yarn build:ios:release:e2e", - }, - 'android.bitrise.debug': { - type: 'android.apk', - binaryPath: 'android/app/build/outputs/apk/prod/debug/app-prod-debug.apk', - build: 'yarn start:android:e2e', + 'ios/build/Build/Products/Release-iphonesimulator/MetaMask-QA.app', + build: "METAMASK_BUILD_TYPE='main' METAMASK_ENVIRONMENT='qa' yarn build:ios:qa", }, 'android.debug': { type: 'android.apk', binaryPath: 'android/app/build/outputs/apk/prod/debug/app-prod-debug.apk', build: 'yarn start:android:e2e', }, - 'android.release': { - type: 'android.apk', - binaryPath: - 'android/app/build/outputs/apk/prod/release/app-prod-release.apk', - build: "METAMASK_BUILD_TYPE='main' METAMASK_ENVIRONMENT='production' yarn build:android:release:e2e", - }, 'android.qa': { type: 'android.apk', binaryPath: 'android/app/build/outputs/apk/qa/release/app-qa-release.apk', - build: "METAMASK_BUILD_TYPE='main' METAMASK_ENVIRONMENT='qa' yarn build:android:qa:e2e", + build: "METAMASK_BUILD_TYPE='main' METAMASK_ENVIRONMENT='qa' yarn build:android:qa", }, }, }; diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 9de39ff6af2..594f7f4bf17 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -2,3 +2,5 @@ 57afe4ca921d85a51a923470239ca977fccbd1ae # Standardize prettier configuration https://github.com/MetaMask/metamask-mobile/pull/4182 bdb7f37c90e4fc923881a07fca38d4e77c73a579 +# Fix mixed tabs and spaces https://github.com/MetaMask/metamask-mobile/pull/1379 +9f9a1121c6899e06d4aeef29017bb479df142adb diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 727f5b7c4d0..a483a7157ca 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,7 +4,7 @@ * @MetaMask/mobile-devs # Design System Team -app/component-library/ @MetaMask/design-system-engineers @MetaMask/mobile-platform +app/component-library/ @MetaMask/design-system-engineers # Platform Team patches/ @MetaMask/mobile-platform @@ -94,10 +94,25 @@ app/components/Views/NftDetails @MetaMask/metamask-assets app/reducers/collectibles @MetaMask/metamask-assets # UX Team -app/components @MetaMask/wallet-ux -app/reducers/experimentalSettings @MetaMask/wallet-ux -app/reducers/modals @MetaMask/wallet-ux -app/reducers/navigation @MetaMask/wallet-ux -app/reducers/onboarding @MetaMask/wallet-ux -app/reducers/privacy @MetaMask/wallet-ux -app/reducers/settings @MetaMask/wallet-ux +app/components/Views/AccountActions @MetaMask/wallet-ux +app/components/Views/AccountSelector @MetaMask/wallet-ux +app/components/Views/AddressQRCode @MetaMask/wallet-ux +app/components/Views/EditAccountName @MetaMask/wallet-ux +app/components/Views/LockScreen @MetaMask/wallet-ux +app/components/Views/Login @MetaMask/wallet-ux +app/components/Views/NetworkConnect @MetaMask/wallet-ux +app/components/Views/NetworkSelector @MetaMask/wallet-ux +app/components/Views/Onboarding @MetaMask/wallet-ux +app/components/Views/OnboardingCarousel @MetaMask/wallet-ux +app/components/Views/OnboardingSuccess @MetaMask/wallet-ux +app/components/Views/QRAccountDisplay @MetaMask/wallet-ux +app/components/Views/QRScanner @MetaMask/wallet-ux +app/components/Views/Settings @MetaMask/wallet-ux +app/components/Views/TermsAndConditions @MetaMask/wallet-ux + +app/reducers/experimentalSettings @MetaMask/wallet-ux +app/reducers/modals @MetaMask/wallet-ux +app/reducers/navigation @MetaMask/wallet-ux +app/reducers/onboarding @MetaMask/wallet-ux +app/reducers/privacy @MetaMask/wallet-ux +app/reducers/settings @MetaMask/wallet-ux diff --git a/scripts/get-next-semver-version.sh b/.github/scripts/get-next-semver-version.sh similarity index 93% rename from scripts/get-next-semver-version.sh rename to .github/scripts/get-next-semver-version.sh index 8107471978e..552e1fa7061 100755 --- a/scripts/get-next-semver-version.sh +++ b/.github/scripts/get-next-semver-version.sh @@ -16,7 +16,7 @@ VERSION_BRANCHES=$(git branch -r | grep -o 'release/[0-9]*\.[0-9]*\.[0-9]*' | gr VERSION_TAGS=$(git tag | grep -o 'v[0-9]*\.[0-9]*\.[0-9]*' | grep -o '[0-9]*\.[0-9]*\.[0-9]*' | sort --version-sort | tail -n 1) # Get the version from package.json -VERSION_PACKAGE=$(node -p "require('./package.json').version") +VERSION_PACKAGE=$(node -p "require('../../package.json').version") # Compare versions and keep the highest one HIGHEST_VERSION=$(printf "%s\n%s\n%s" "$VERSION_BRANCHES" "$VERSION_TAGS" "$VERSION_PACKAGE" | sort --version-sort | tail -n 1) diff --git a/.github/workflows/add-release-label.yml b/.github/workflows/add-release-label.yml index a5a4daa7103..80941c64536 100644 --- a/.github/workflows/add-release-label.yml +++ b/.github/workflows/add-release-label.yml @@ -30,7 +30,7 @@ jobs: id: get-next-semver-version env: FORCE_NEXT_SEMVER_VERSION: ${{ vars.FORCE_NEXT_SEMVER_VERSION }} - run: ./scripts/get-next-semver-version.sh "$FORCE_NEXT_SEMVER_VERSION" + run: ./get-next-semver-version.sh "$FORCE_NEXT_SEMVER_VERSION" working-directory: '.github/scripts' - name: Add release label to PR and linked issues diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5864ba001ec..75b4cf336b9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,18 +21,6 @@ jobs: bundler-cache: true env: BUNDLE_GEMFILE: ios/Gemfile - - name: Determine whether the current PR is a draft - id: set-is-draft - if: github.event_name == 'pull_request' && github.event.pull_request.number - run: echo "IS_DRAFT=$(gh pr view --json isDraft --jq '.isDraft' "${PR_NUMBER}")" >> "$GITHUB_OUTPUT" - env: - PR_NUMBER: ${{ github.event.pull_request.number }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Setup registry config for using package previews on draft PRs - if: github.event_name == 'pull_request' && steps.set-is-draft.outputs.IS_DRAFT == 'true' - run: printf '%s\n\n%s' '@metamask:registry=https://npm.pkg.github.com' "//npm.pkg.github.com/:_authToken=${PACKAGE_READ_TOKEN}" > .npmrc - env: - PACKAGE_READ_TOKEN: ${{ secrets.PACKAGE_READ_TOKEN }} - run: yarn setup - name: Require clean working directory shell: bash @@ -179,14 +167,14 @@ jobs: with: name: ios-bundle path: ios/main.jsbundle - + ship-js-bundle-size-check: runs-on: ubuntu-latest needs: [js-bundle-size-check] if: ${{ github.ref == 'refs/heads/main' }} steps: - uses: actions/checkout@v4 - + - name: Download iOS bundle uses: actions/download-artifact@v4 with: diff --git a/.iyarc b/.iyarc index 7fb6e40287c..abbf0e189d2 100644 --- a/.iyarc +++ b/.iyarc @@ -1,7 +1,3 @@ # ReDoS vulnerability, no impact to this application, and fix not backported yet to the versions we use GHSA-c2qf-rxjj-qqgw - -# Sentry SDK Prototype Pollution gadget in JavaScript SDKs - -GHSA-593m-55hh-j8gv diff --git a/.storybook/storybook.requires.js b/.storybook/storybook.requires.js index 31f1669fd92..a1ca7774ac8 100644 --- a/.storybook/storybook.requires.js +++ b/.storybook/storybook.requires.js @@ -123,7 +123,10 @@ const getStories = () => { "./app/component-library/base-components/TagBase/TagBase.stories.tsx": require("../app/component-library/base-components/TagBase/TagBase.stories.tsx"), "./app/component-library/components-temp/TagColored/TagColored.stories.tsx": require("../app/component-library/components-temp/TagColored/TagColored.stories.tsx"), "./app/component-library/components-temp/KeyValueRow/KeyValueRow.stories.tsx": require("../app/component-library/components-temp/KeyValueRow/KeyValueRow.stories.tsx"), - "./app/components/UI/InfoRow/InfoRow.stories.tsx": require("../app/components/UI/InfoRow/InfoRow.stories.tsx"), + "./app/components/Views/confirmations/components/UI/InfoRow/InfoRow.stories.tsx": require("../app/components/Views/confirmations/components/UI/InfoRow/InfoRow.stories.tsx"), + "./app/components/Views/confirmations/components/UI/ExpandableSection/ExpandableSection.stories.tsx": require("../app/components/Views/confirmations/components/UI/ExpandableSection/ExpandableSection.stories.tsx"), + "./app/components/Views/confirmations/components/UI/Tooltip/Tooltip.stories.tsx": require("../app/components/Views/confirmations/components/UI/Tooltip/Tooltip.stories.tsx"), + "./app/components/Views/confirmations/components/UI/CopyButton/CopyButton.stories.tsx": require("../app/components/Views/confirmations/components/UI/CopyButton/CopyButton.stories.tsx"), }; }; diff --git a/CHANGELOG.md b/CHANGELOG.md index 1afbe7ca333..8db93d47c3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,16 +2,13 @@ ## Current Main Branch -## 7.33.0 - Oct 3, 2024 +## 7.33.0 - Oct 17, 2024 ### Added - [#11507](https://github.com/MetaMask/metamask-mobile/pull/11507): feat: 10550 Re-introduce test for measuring cold app start + JS bundle load time (#11507) -- [#11347](https://github.com/MetaMask/metamask-mobile/pull/11347): "chore: revert ""feat: react native fast crypto for notifications"" (#11347)" - [#11318](https://github.com/MetaMask/metamask-mobile/pull/11318): feat: app event manager and attribution id parameters (#11318) - [#11445](https://github.com/MetaMask/metamask-mobile/pull/11445): feat: add the abilty to hide the disconnect all button as well as showing and hiding the accounts row when necessary (#11445) - [#11386](https://github.com/MetaMask/metamask-mobile/pull/11386): feat(3299): add tracking to network switching and confirmation (#11386) -- [#11379](https://github.com/MetaMask/metamask-mobile/pull/11379): refactor: rename the feature flag since it had a typo (#11379) - [#11239](https://github.com/MetaMask/metamask-mobile/pull/11239): feat(2739): permission summary view gets the ability to disconnect all (#11239) -- [#11382](https://github.com/MetaMask/metamask-mobile/pull/11382): chore(runway): cherry-pick feat: app event manager and attribution id parameters (#11382) - [#11497](https://github.com/MetaMask/metamask-mobile/pull/11497): feat: simple key-> value component for text value type (#11497) - [#11478](https://github.com/MetaMask/metamask-mobile/pull/11478): feat: adding title to confirmation page (#11478) - [#11477](https://github.com/MetaMask/metamask-mobile/pull/11477): feat: adding footer section to confirmation page (#11477) @@ -23,21 +20,20 @@ - [#11399](https://github.com/MetaMask/metamask-mobile/pull/11399): feat: add learn more modal component for staking (#11399) - [#11261](https://github.com/MetaMask/metamask-mobile/pull/11261): feat: STAKE-822 build your balance component (#11261) - [#11294](https://github.com/MetaMask/metamask-mobile/pull/11294): feat: added KeyValueRow to component-library/components-temp (#11294) -- [#11185](https://github.com/MetaMask/metamask-mobile/pull/11185): "feat: display ""Snaps (Beta)"" decorator tag in accounts list (#11185)" +- [#11185](https://github.com/MetaMask/metamask-mobile/pull/11185): feat: display ""Snaps (Beta)"" decorator tag in accounts list (#11185) - [#10829](https://github.com/MetaMask/metamask-mobile/pull/10829): feat: Eth snap keyring (#10829) - [#11455](https://github.com/MetaMask/metamask-mobile/pull/11455): feat: bootstrap a reset notifications feat (#11455) - [#11466](https://github.com/MetaMask/metamask-mobile/pull/11466): feat: add support for external links (#11466) - [#11429](https://github.com/MetaMask/metamask-mobile/pull/11429): feat: add timeout handler (#11429) - [#11427](https://github.com/MetaMask/metamask-mobile/pull/11427): feat: add feature announcements channel for android (#11427) -- [#11250](https://github.com/MetaMask/metamask-mobile/pull/11250): fix: push notifications (#11250) - [#11069](https://github.com/MetaMask/metamask-mobile/pull/11069): feat: react native fast crypto for notifications (#11069) ### Changed +- [#11379](https://github.com/MetaMask/metamask-mobile/pull/11379): refactor: rename the feature flag since it had a typo (#11379) - [#11615](https://github.com/MetaMask/metamask-mobile/pull/11615): chore: exclude temporarily sentry SDK advisory (#11615) - [#11577](https://github.com/MetaMask/metamask-mobile/pull/11577): ci: disable swaps e2e workflow (#11577) - [#11350](https://github.com/MetaMask/metamask-mobile/pull/11350): chore: replace Segment patch by plugin (#11350) - [#11287](https://github.com/MetaMask/metamask-mobile/pull/11287): chore: remove unused events (#11287) -- [#11512](https://github.com/MetaMask/metamask-mobile/pull/11512): fix: android firebase docs template (#11512) - [#11517](https://github.com/MetaMask/metamask-mobile/pull/11517): chore: delete swaps token charts test (#11517) - [#11515](https://github.com/MetaMask/metamask-mobile/pull/11515): test: disable swaps token charts regression tests (#11515) - [#11504](https://github.com/MetaMask/metamask-mobile/pull/11504): chore: revert measuring with react native performance (#11504) @@ -83,13 +79,15 @@ - [#11104](https://github.com/MetaMask/metamask-mobile/pull/11104): chore(deps): Bump `@metamask/address-book-controller` from `^4.0.1` to `^6.0.1` (#11104) - [#10917](https://github.com/MetaMask/metamask-mobile/pull/10917): chore(ci): split out ci scripts and devDeps into separate project (#10917) - [#11081](https://github.com/MetaMask/metamask-mobile/pull/11081): chore: Prevent redundant Sentry sourcemap uploads (#11081) -- [#11430](https://github.com/MetaMask/metamask-mobile/pull/11430): fix: refactor Logger usage (#11430) - [#11470](https://github.com/MetaMask/metamask-mobile/pull/11470): chore: [Design quality] Update token details (#11470) -- [#11439](https://github.com/MetaMask/metamask-mobile/pull/11439): "chore: cherry-pick fix: ""chore(deps): Bump @metamask/base-controller from ^6.0.0 to ^7.0.0 (#11207)"" (#11439)" -- [#11169](https://github.com/MetaMask/metamask-mobile/pull/11169): "chore(deps): Bump `@metamask/signature-controller` from `^17.0.0` to `^19.1.0` -- [#11352](https://github.com/MetaMask/metamask-mobile/pull/11352): "chore(deps): Bump `@metamask/accounts-controller` to `^18.2.1` +- [#11439](https://github.com/MetaMask/metamask-mobile/pull/11439): chore: cherry-pick fix: ""chore(deps): Bump @metamask/base-controller from ^6.0.0 to ^7.0.0 (#11207)"" (#11439) +- [#11169](https://github.com/MetaMask/metamask-mobile/pull/11169): chore(deps): Bump `@metamask/signature-controller` from `^17.0.0` to `^19.1.0` +- [#11352](https://github.com/MetaMask/metamask-mobile/pull/11352): chore(deps): Bump `@metamask/accounts-controller` to `^18.2.1` ### Fixed +- [#11512](https://github.com/MetaMask/metamask-mobile/pull/11512): fix: android firebase docs template (#11512) +- [#11430](https://github.com/MetaMask/metamask-mobile/pull/11430): fix: refactor Logger usage (#11430) +- [#11250](https://github.com/MetaMask/metamask-mobile/pull/11250): fix: push notifications (#11250) - [#11581](https://github.com/MetaMask/metamask-mobile/pull/11581): fix: Fix invalid browser url crash (#11581) - [#11467](https://github.com/MetaMask/metamask-mobile/pull/11467): fix: Reorder prep_environment (#11467) - [#11367](https://github.com/MetaMask/metamask-mobile/pull/11367): fix: Update steps of the methods that are no longer valid (#11367) @@ -470,10 +468,7 @@ - [#10383](https://github.com/MetaMask/metamask-mobile/pull/10383): fix: race condition issues when doing batch-rpc calls in the DeeplinkProtocolService (#10383) - [#10365](https://github.com/MetaMask/metamask-mobile/pull/10365): fix: attribution link (#10365) - [#10303](https://github.com/MetaMask/metamask-mobile/pull/10303): fix: page navigation during QR accounts selection (#10303) -<<<<<<< HEAD -======= ->>>>>>> main ## 7.28.1 - Aug 15, 2024 ### Fixed - [#10637](https://github.com/MetaMask/metamask-mobile/pull/10637): fix: swap button blocked by SwapsController polling issue (#10637) diff --git a/android/app/build.gradle b/android/app/build.gradle index d406752ae5a..f2379b86e80 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -229,7 +229,7 @@ android { release { manifestPlaceholders.isDebug = false minifyEnabled enableProguardInReleaseBuilds - proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro", "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro", "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules.pro" } } diff --git a/app/actions/notification/constants/index.ts b/app/actions/notification/constants/index.ts index c75c9eb0082..ee8c63fdffa 100644 --- a/app/actions/notification/constants/index.ts +++ b/app/actions/notification/constants/index.ts @@ -19,6 +19,7 @@ export enum notificationsErrors { UPDATE_TRIGGER_PUSH_NOTIFICATIONS = 'Error while trying to update trigger push notifications', ENABLE_NOTIFICATIONS_SERVICES = 'Error while trying to enable notifications services', DISABLE_NOTIFICATIONS_SERVICES = 'Error while trying to disable notifications services', + DELETE_STORAGE_KEY = 'Error while trying to delete storage key', } export default notificationsErrors; diff --git a/app/actions/notification/helpers/index.ts b/app/actions/notification/helpers/index.ts index 0cd827ad3ef..9f47da07f88 100644 --- a/app/actions/notification/helpers/index.ts +++ b/app/actions/notification/helpers/index.ts @@ -171,3 +171,20 @@ export const markMetamaskNotificationsAsRead = async ( return getErrorMessage(error); } }; +/** + * Perform the deletion of the notifications storage key and the creation of on chain triggers to reset the notifications. + * + * @returns {Promise} A promise that resolves to a string error message or undefined if successful. + */ +export const performDeleteStorage = async (): Promise => { + try { + await Engine.context.UserStorageController.performDeleteStorage('notifications.notification_settings'); + await Engine.context.NotificationServicesController.createOnChainTriggers( + { + resetNotifications: true, + }, + ); + } catch (error) { + return getErrorMessage(error); + } +}; diff --git a/app/actions/security/index.ts b/app/actions/security/index.ts index e0e87a0ef55..661c1d1119d 100644 --- a/app/actions/security/index.ts +++ b/app/actions/security/index.ts @@ -8,6 +8,7 @@ export enum ActionType { SET_AUTOMATIC_SECURITY_CHECKS_MODAL_OPEN = 'SET_AUTOMATIC_SECURITY_CHECKS_MODAL_OPEN', SET_DATA_COLLECTION_FOR_MARKETING = 'SET_DATA_COLLECTION_FOR_MARKETING', SET_NFT_AUTO_DETECTION_MODAL_OPEN = 'SET_NFT_AUTO_DETECTION_MODAL_OPEN', + SET_MULTI_RPC_MIGRATION_MODAL_OPEN = 'SET_MULTI_RPC_MIGRATION_MODAL_OPEN', } export interface AllowLoginWithRememberMeUpdated @@ -35,6 +36,11 @@ export interface SetNftAutoDetectionModalOpen open: boolean; } +export interface SetMultiRpcMigrationModalOpen + extends ReduxAction { + open: boolean; +} + export interface SetDataCollectionForMarketing extends ReduxAction { enabled: boolean; @@ -46,7 +52,8 @@ export type Action = | UserSelectedAutomaticSecurityChecksOptions | SetAutomaticSecurityChecksModalOpen | SetDataCollectionForMarketing - | SetNftAutoDetectionModalOpen; + | SetNftAutoDetectionModalOpen + | SetMultiRpcMigrationModalOpen; export const setAllowLoginWithRememberMe = ( enabled: boolean, @@ -82,6 +89,13 @@ export const setNftAutoDetectionModalOpen = ( open, }); +export const setMultiRpcMigrationModalOpen = ( + open: boolean, +): SetMultiRpcMigrationModalOpen => ({ + type: ActionType.SET_MULTI_RPC_MIGRATION_MODAL_OPEN, + open, +}); + export const setDataCollectionForMarketing = (enabled: boolean) => ({ type: ActionType.SET_DATA_COLLECTION_FOR_MARKETING, enabled, diff --git a/app/component-library/components-temp/Accounts/AccountBase/AccountBase.styles.ts b/app/component-library/components-temp/Accounts/AccountBase/AccountBase.styles.ts index cda7d7fe248..f755c07b3eb 100644 --- a/app/component-library/components-temp/Accounts/AccountBase/AccountBase.styles.ts +++ b/app/component-library/components-temp/Accounts/AccountBase/AccountBase.styles.ts @@ -29,7 +29,6 @@ const styleSheet = StyleSheet.create({ justifyContent: 'flex-start', }, accountNameLabelText: { - marginLeft: 4, paddingHorizontal: 8, borderWidth: 1, borderRadius: 8, diff --git a/app/component-library/components-temp/Accounts/AccountBase/AccountBase.tsx b/app/component-library/components-temp/Accounts/AccountBase/AccountBase.tsx index 14f619c98e0..88e0f809d05 100644 --- a/app/component-library/components-temp/Accounts/AccountBase/AccountBase.tsx +++ b/app/component-library/components-temp/Accounts/AccountBase/AccountBase.tsx @@ -49,15 +49,17 @@ const AccountBase = ({ {accountName} - {accountTypeLabel && ( + + {accountTypeLabel && ( + {strings(accountTypeLabel)} - )} + )} diff --git a/app/component-library/components-temp/CellSelectWithMenu/CellSelectWithMenu.tsx b/app/component-library/components-temp/CellSelectWithMenu/CellSelectWithMenu.tsx index ff8df60913a..e18ed046595 100644 --- a/app/component-library/components-temp/CellSelectWithMenu/CellSelectWithMenu.tsx +++ b/app/component-library/components-temp/CellSelectWithMenu/CellSelectWithMenu.tsx @@ -33,6 +33,7 @@ const CellSelectWithMenu = ({ tagLabel, isSelected = false, children, + withAvatar = true, ...props }: CellSelectWithMenuProps) => { const { styles } = useStyles(styleSheet, { style }); @@ -46,12 +47,15 @@ const CellSelectWithMenu = ({ > {/* DEV Note: Account Avatar should be replaced with Avatar with Badge whenever available */} - + {withAvatar ? ( + + ) : null} + @@ -16,10 +14,10 @@ exports[`CellSelectWithMenu should render with default settings correctly 1`] = disabled={false} style={ { + "flex": 1, "opacity": 1, "padding": 16, "position": "relative", - "width": "95%", "zIndex": 1, } } @@ -287,7 +285,13 @@ exports[`CellSelectWithMenu should render with default settings correctly 1`] = - + { +const KeyValueRowLabel = ({ label, tooltip }: KeyValueRowLabelProps) => { const { styles } = useStyles(styleSheet, {}); const { openTooltipModal } = useTooltipModal(); - const hasTooltip = tooltip?.title && tooltip?.text; + const hasTooltip = tooltip?.title && tooltip?.content; const onNavigateToTooltipModal = () => { if (!hasTooltip) return; - openTooltipModal(tooltip.title, tooltip.text); + openTooltipModal(tooltip.title, tooltip.content); }; return ( - + {isPreDefinedKeyValueRowLabel(label) ? ( + + ) : ( + label + )} {hasTooltip && ( )} diff --git a/app/component-library/components-temp/KeyValueRow/KeyValueRow.stories.tsx b/app/component-library/components-temp/KeyValueRow/KeyValueRow.stories.tsx index e5a440b3276..ee34ef3c4b4 100644 --- a/app/component-library/components-temp/KeyValueRow/KeyValueRow.stories.tsx +++ b/app/component-library/components-temp/KeyValueRow/KeyValueRow.stories.tsx @@ -8,6 +8,7 @@ import KeyValueRowComponent, { import Text, { TextColor, TextVariant } from '../../components/Texts/Text'; import Title from '../../../components/Base/Title'; import { IconColor, IconName, IconSize } from '../../components/Icons/Icon'; +import Button, { ButtonVariants } from '../../components/Buttons/Button'; const KeyValueRowMeta = { title: 'Components Temp / KeyValueRow', @@ -38,42 +39,56 @@ export const KeyValueRow = { + {/* Using Custom ReactNode */} + alert('test')} + /> + ), + }} + /> ), diff --git a/app/component-library/components-temp/KeyValueRow/KeyValueRow.test.tsx b/app/component-library/components-temp/KeyValueRow/KeyValueRow.test.tsx index a9b00ece7e8..389a3213db5 100644 --- a/app/component-library/components-temp/KeyValueRow/KeyValueRow.test.tsx +++ b/app/component-library/components-temp/KeyValueRow/KeyValueRow.test.tsx @@ -19,8 +19,8 @@ describe('KeyValueRow', () => { it('should render when there is only text', () => { const { toJSON } = render( , ); @@ -31,17 +31,17 @@ describe('KeyValueRow', () => { const { toJSON } = render( , @@ -54,13 +54,13 @@ describe('KeyValueRow', () => { const { toJSON } = render( { const { toJSON } = render( , diff --git a/app/component-library/components-temp/KeyValueRow/KeyValueRow.tsx b/app/component-library/components-temp/KeyValueRow/KeyValueRow.tsx index 18c6300b1cf..212396f888e 100644 --- a/app/component-library/components-temp/KeyValueRow/KeyValueRow.tsx +++ b/app/component-library/components-temp/KeyValueRow/KeyValueRow.tsx @@ -8,7 +8,6 @@ import { } from './KeyValueRow.types'; import Icon from '../../components/Icons/Icon'; import { View } from 'react-native'; -import { areKeyValueRowPropsEqual } from './KeyValueRow.utils'; import KeyValueSection from './KeyValueSection/KeyValueSection'; import KeyValueRowLabel from './KeyValueLabel/KeyValueLabel'; import KeyValueRowRoot from './KeyValueRoot/KeyValueRoot'; @@ -45,12 +44,7 @@ const KeyValueRow = React.memo(({ field, value, style }: KeyValueRowProps) => { (fieldIcon.side === KeyValueRowFieldIconSides.LEFT || fieldIcon.side === KeyValueRowFieldIconSides.BOTH || !fieldIcon?.side) && } - + {shouldShowFieldIcon && (fieldIcon?.side === KeyValueRowFieldIconSides.RIGHT || fieldIcon?.side === KeyValueRowFieldIconSides.BOTH) && ( @@ -64,12 +58,7 @@ const KeyValueRow = React.memo(({ field, value, style }: KeyValueRowProps) => { (valueIcon?.side === KeyValueRowFieldIconSides.LEFT || valueIcon?.side === KeyValueRowFieldIconSides.BOTH || !valueIcon?.side) && } - + {shouldShowValueIcon && (valueIcon?.side === KeyValueRowFieldIconSides.RIGHT || valueIcon?.side === KeyValueRowFieldIconSides.BOTH) && ( @@ -79,7 +68,7 @@ const KeyValueRow = React.memo(({ field, value, style }: KeyValueRowProps) => { ); -}, areKeyValueRowPropsEqual); +}); /** * Exported sub-components to provide a base for new KeyValueRow variants. diff --git a/app/component-library/components-temp/KeyValueRow/KeyValueRow.types.ts b/app/component-library/components-temp/KeyValueRow/KeyValueRow.types.ts index 0e9c864d309..fc4e825921e 100644 --- a/app/component-library/components-temp/KeyValueRow/KeyValueRow.types.ts +++ b/app/component-library/components-temp/KeyValueRow/KeyValueRow.types.ts @@ -19,9 +19,9 @@ interface KeyValueRowTooltip { */ title: string; /** - * The text displayed within the tooltip body. + * The content displayed within the tooltip body. */ - text: string; + content: string | ReactNode; /** * Optional size of the tooltip icon. * @default TooltipSizes.Md @@ -47,19 +47,9 @@ export enum KeyValueRowFieldIconSides { */ interface KeyValueRowField { /** - * The text to display. - */ - text: string; - /** - * Optional text variant. - * @default TextVariant.BodyMDMedium + * The label content displayed. */ - variant?: TextProps['variant']; - /** - * Optional text color. - * @default TextColor.Default - */ - color?: TextProps['color']; + label: PreDefinedKeyValueRowLabel | ReactNode; /** * Optional icon to display. If undefined, no icon is displayed. */ @@ -74,16 +64,11 @@ export const IconSizes = IconSize; export const TooltipSizes = ButtonIconSizes; -/** - * The KeyValueRowLabel prop interface. - * - * @see KeyValueRowLabel in ./KeyValueRow.tsx - */ -export interface KeyValueRowLabelProps { +export interface PreDefinedKeyValueRowLabel { /** * Text to display. */ - label: string; + text: string; /** * Optional text variant. * @default TextVariant.BodyMDMedium @@ -94,6 +79,18 @@ export interface KeyValueRowLabelProps { * @default TextColor.Default */ color?: TextProps['color']; +} + +/** + * The KeyValueRowLabel prop interface. + * + * @see KeyValueRowLabel in ./KeyValueRow.tsx + */ +export interface KeyValueRowLabelProps { + /** + * The label content displayed. + */ + label: PreDefinedKeyValueRowLabel | ReactNode; /** * Optional tooltip. If undefined, the tooltip won't be displayed. */ diff --git a/app/component-library/components-temp/KeyValueRow/KeyValueRow.utils.ts b/app/component-library/components-temp/KeyValueRow/KeyValueRow.utils.ts index bf4c38843e4..3361cb4d66f 100644 --- a/app/component-library/components-temp/KeyValueRow/KeyValueRow.utils.ts +++ b/app/component-library/components-temp/KeyValueRow/KeyValueRow.utils.ts @@ -1,8 +1,9 @@ -import { KeyValueRowProps } from './KeyValueRow.types'; +import { + KeyValueRowLabelProps, + PreDefinedKeyValueRowLabel, +} from './KeyValueRow.types'; -export const areKeyValueRowPropsEqual = ( - prevProps: KeyValueRowProps, - newProps: KeyValueRowProps, -) => - JSON.stringify(prevProps.field) === JSON.stringify(newProps.field) && - JSON.stringify(prevProps.value) === JSON.stringify(newProps.value); +export const isPreDefinedKeyValueRowLabel = ( + label: KeyValueRowLabelProps['label'], +): label is PreDefinedKeyValueRowLabel => + !!label && typeof label === 'object' && 'text' in label; diff --git a/app/component-library/components-temp/KeyValueRow/__snapshots__/KeyValueRow.test.tsx.snap b/app/component-library/components-temp/KeyValueRow/__snapshots__/KeyValueRow.test.tsx.snap index c83d3a4fd5f..a4c9e5f6bfe 100644 --- a/app/component-library/components-temp/KeyValueRow/__snapshots__/KeyValueRow.test.tsx.snap +++ b/app/component-library/components-temp/KeyValueRow/__snapshots__/KeyValueRow.test.tsx.snap @@ -201,7 +201,7 @@ exports[`KeyValueRow Prebuilt Component KeyValueRow should render text with icon Key Text { const { getByRole } = render( , @@ -64,7 +66,9 @@ describe('ListItemMultiSelectButton', () => { const { getByTestId } = render( , diff --git a/app/component-library/components-temp/ListItemMultiSelectButton/ListItemMultiSelectButton.tsx b/app/component-library/components-temp/ListItemMultiSelectButton/ListItemMultiSelectButton.tsx index e8610e45735..a3cb0d079ff 100644 --- a/app/component-library/components-temp/ListItemMultiSelectButton/ListItemMultiSelectButton.tsx +++ b/app/component-library/components-temp/ListItemMultiSelectButton/ListItemMultiSelectButton.tsx @@ -20,6 +20,12 @@ import { IconColor, IconName, } from '../../../component-library/components/Icons/Icon'; +import Button, { + ButtonSize, + ButtonVariants, + ButtonWidthTypes, +} from '../../../component-library/components/Buttons/Button'; +import { TextVariant } from '../../../component-library/components/Texts/Text'; const ListItemMultiSelectButton: React.FC = ({ style, @@ -27,7 +33,9 @@ const ListItemMultiSelectButton: React.FC = ({ isDisabled = false, children, gap = DEFAULT_LISTITEMMULTISELECT_GAP, + showButtonIcon = true, buttonIcon = IconName.MoreVertical, + buttonProps, ...props }) => { const { styles } = useStyles(styleSheet, { @@ -55,15 +63,29 @@ const ListItemMultiSelectButton: React.FC = ({ )} - - - + {showButtonIcon ? ( + + + + ) : null} + {buttonProps?.textButton ? ( + +