Skip to content

feat: assets unify balance and traces - #44978

Merged
salimtb merged 7 commits into
mainfrom
feat/assets-unify-balance-and-traces
Jul 29, 2026
Merged

feat: assets unify balance and traces#44978
salimtb merged 7 commits into
mainfrom
feat/assets-unify-balance-and-traces

Conversation

@salimtb

@salimtb salimtb commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Description

we now add traces under a FF for the new assets controller , this will help to make some future improvements

Changelog

CHANGELOG entry: assets unify balance and traces

Related issues

Fixes:

Manual testing steps

  1. Go to this page...

Screenshots/Recordings

Before

After

Pre-merge author checklist

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.

Note

Medium Risk
Changes how displayed wallet and group fiat totals are computed when unify is enabled, including a temporary aggregation workaround; tracing is off by default but touches observability when enabled.

Overview
Adds remote-gated Sentry tracing for AssetsController via a new assetsUnifyState.tracesEnabled flag. Init wires a trace callback that only calls traceAsControllerCallback when unify is enabled for the build and the flag is on; otherwise work runs with no span. Init messenger access to RemoteFeatureFlagController:getState supports reading that flag.

Unified fiat balances are refactored: local assets.balance-utils is removed in favor of @metamask/assets-controller calculateBalanceForAllWallets / calculateBalanceChangeForAccountGroup when assets-unify-state is on. Aggregation still strips assetsInfo before totals (#44786). New selectUnifiedBalanceBySelectedAccountGroup and getUnifiedBalanceForAccountGroup feed the selected-group path; AccountGroupBalance picks unified vs legacy selectors from getIsAssetsUnifyStateEnabled.

E2E registry and UI flag schema include tracesEnabled (default off in prod defaults).

Reviewed by Cursor Bugbot for commit 8c4904f. Bugbot is set up for automated code reviews on this repo. Configure here.

salimtb and others added 2 commits July 29, 2026 10:23
…bled

Use package balance helpers for unified account-group fiat totals, gate
the account-group balance UI behind assetsUnifyState, and remove the
local balance-utils polyfill.

Co-authored-by: Cursor <cursoragent@cursor.com>
…acesEnabled

Wire controller init through traceAsControllerCallback and only emit
traces when assetsUnifyState is enabled with tracesEnabled true.
@github-actions

Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@salimtb salimtb changed the title Feat/assets unify balance and traces feat: assets unify balance and traces Jul 29, 2026
@metamask-ci

metamask-ci Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

✨ Files requiring CODEOWNER review ✨

💎 @MetaMask/metamask-assets (2 files, +40 -2)
  • 📁 ui/
    • 📁 components/
      • 📁 app/
        • 📁 assets/
          • 📁 account-group-balance/
            • 📄 account-group-balance.test.tsx +28 -1
            • 📄 account-group-balance.tsx +12 -1

@metamask-ci

metamask-ci Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor
Builds ready [bf902e6]
⚡ Performance Benchmarks (Total: 🟢 15 pass · 🟡 7 warn · 🔴 2 fail)

Baseline (latest main): 171ed20 | Date: 7/28/2026 | Pipeline: 30438648307 | Baseline logs

Metricschrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 srpButtonToSrpForm(p95) [CI log]🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🔴 [CI log]🟡 [CI log]

Regressions (🔴 2 failures)

Interaction Benchmarks · Samples: 5
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
confirmTx
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • bridgeUserActions/bridge_load_page: +117%
  • bridgeUserActions/bridge_load_asset_picker: +35%
  • bridgeUserActions/longTaskCount: +11%
  • bridgeUserActions/longTaskTotalDuration: +17%
  • bridgeUserActions/tbt: +32%
  • bridgeUserActions/total: +14%
  • bridgeUserActions/inp: +15%
  • loadNewAccount/inp: -24%
  • loadNewAccount/fcp: -50%
  • loadNewAccount/lcp: +1116%
  • confirmTx/confirm_tx: +10%
  • confirmTx/longTaskCount: -100%
  • confirmTx/longTaskTotalDuration: -100%
  • confirmTx/longTaskMaxDuration: -100%
  • confirmTx/tbt: -100%
  • confirmTx/total: +10%
  • confirmTx/inp: -24%
  • confirmTx/fcp: -48%
  • confirmTx/lcp: +1135%
  • bridgeUserActions/bridge_load_page: +219%
  • bridgeUserActions/bridge_load_asset_picker: +73%
  • bridgeUserActions/longTaskCount: -100%
  • bridgeUserActions/longTaskTotalDuration: -100%
  • bridgeUserActions/longTaskMaxDuration: -100%
  • bridgeUserActions/tbt: -100%
  • bridgeUserActions/total: +30%
  • bridgeUserActions/inp: -23%
  • bridgeUserActions/fcp: -48%
  • bridgeUserActions/lcp: +1108%
Startup Benchmarks · Samples: 100
Benchmarkchrome-webpackfirefox-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
startupPowerUserHome
[Sentry log · main/release]
🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • startupStandardHome/domInteractive: -14%
  • startupStandardHome/fcp: -11%
  • startupPowerUserHome/load: -12%
  • startupPowerUserHome/domContentLoaded: -12%
  • startupPowerUserHome/backgroundConnect: -27%
  • startupPowerUserHome/initialActions: +11%
  • startupPowerUserHome/loadScripts: -13%
  • startupPowerUserHome/setupStore: -78%
  • startupPowerUserHome/inp: -11%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 startupPowerUserHome/LCP: p75 2.6s
User Journey Benchmarks · Samples: 5 · mock API 🔴 2
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 [CI log]
🔴 total
🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🔴 [CI log]
🔴 total
🟡 [CI log]
🟡 total
assetDetails
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
importSrpHome
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
sendTransactions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
swap
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • onboardingImportWallet/srpButtonToSrpForm: +41%
  • onboardingImportWallet/confirmSrpToPwForm: +38%
  • onboardingImportWallet/pwFormToMetricsScreen: +34%
  • onboardingImportWallet/metricsToWalletReadyScreen: +17%
  • onboardingImportWallet/doneButtonToHomeScreen: -77%
  • onboardingImportWallet/openAccountMenuToAccountListLoaded: -46%
  • onboardingImportWallet/longTaskCount: -86%
  • onboardingImportWallet/longTaskTotalDuration: -95%
  • onboardingImportWallet/longTaskMaxDuration: -90%
  • onboardingImportWallet/tbt: -98%
  • onboardingImportWallet/total: -79%
  • onboardingNewWallet/srpButtonToPwForm: -17%
  • onboardingNewWallet/createPwToRecoveryScreen: -12%
  • onboardingNewWallet/agreeButtonToOnboardingSuccess: -18%
  • onboardingNewWallet/doneButtonToAssetList: -17%
  • onboardingNewWallet/longTaskCount: -69%
  • onboardingNewWallet/longTaskTotalDuration: -77%
  • onboardingNewWallet/longTaskMaxDuration: -47%
  • onboardingNewWallet/tbt: -100%
  • onboardingNewWallet/total: -16%
  • solanaAssetDetails/assetClickToPriceChart: -58%
  • solanaAssetDetails/longTaskCount: -100%
  • solanaAssetDetails/longTaskTotalDuration: -100%
  • solanaAssetDetails/longTaskMaxDuration: -100%
  • solanaAssetDetails/tbt: -100%
  • solanaAssetDetails/total: -58%
  • solanaAssetDetails/fcp: +13%
  • importSrpHome/loginToHomeScreen: -12%
  • importSrpHome/homeAfterImportWithNewWallet: -18%
  • importSrpHome/longTaskCount: -37%
  • importSrpHome/longTaskTotalDuration: -35%
  • importSrpHome/tbt: -26%
  • importSrpHome/total: -17%
  • importSrpHome/inp: -30%
  • importSrpHome/cls: +382%
  • sendTransactions/openSendPageFromHome: -32%
  • sendTransactions/reviewTransactionToConfirmationPage: -98%
  • sendTransactions/longTaskCount: -100%
  • sendTransactions/longTaskTotalDuration: -100%
  • sendTransactions/longTaskMaxDuration: -100%
  • sendTransactions/tbt: -100%
  • sendTransactions/total: -95%
  • sendTransactions/inp: -22%
  • sendTransactions/lcp: -59%
  • sendTransactions/cls: +171%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 assetDetails/FCP: p75 1.8s
  • 🟡 importSrpHome/INP: p75 216ms
  • 🟡 importSrpHome/FCP: p75 1.8s
  • 🟡 assetDetails/FCP: p75 2.1s
  • 🟡 solanaAssetDetails/FCP: p75 2.0s
  • 🟡 importSrpHome/FCP: p75 1.9s
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]
Bundle size diffs
  • background: 565 Bytes (0%)
  • ui: 166 Bytes (0%)
  • common: 0 Bytes (0%)
  • other: 0 Bytes (0%)
  • contentScripts: -14 Bytes (0%)
  • zip: 203 Bytes (0%)

@metamask-ci

metamask-ci Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor
Builds ready [1445496] [reused from bf902e6]
⚡ Performance Benchmarks (Total: 🟢 15 pass · 🟡 7 warn · 🔴 2 fail)

Baseline (latest main): 171ed20 | Date: 7/28/2026 | Pipeline: 30441047811 | Baseline logs

Metricschrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 srpButtonToSrpForm(p95) [CI log]🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🔴 [CI log]🟡 [CI log]

Regressions (🔴 2 failures)

Interaction Benchmarks · Samples: 5
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
confirmTx
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • bridgeUserActions/bridge_load_page: +117%
  • bridgeUserActions/bridge_load_asset_picker: +35%
  • bridgeUserActions/longTaskCount: +11%
  • bridgeUserActions/longTaskTotalDuration: +17%
  • bridgeUserActions/tbt: +32%
  • bridgeUserActions/total: +14%
  • bridgeUserActions/inp: +15%
  • loadNewAccount/inp: -24%
  • loadNewAccount/fcp: -50%
  • loadNewAccount/lcp: +1116%
  • confirmTx/confirm_tx: +10%
  • confirmTx/longTaskCount: -100%
  • confirmTx/longTaskTotalDuration: -100%
  • confirmTx/longTaskMaxDuration: -100%
  • confirmTx/tbt: -100%
  • confirmTx/total: +10%
  • confirmTx/inp: -24%
  • confirmTx/fcp: -48%
  • confirmTx/lcp: +1135%
  • bridgeUserActions/bridge_load_page: +219%
  • bridgeUserActions/bridge_load_asset_picker: +73%
  • bridgeUserActions/longTaskCount: -100%
  • bridgeUserActions/longTaskTotalDuration: -100%
  • bridgeUserActions/longTaskMaxDuration: -100%
  • bridgeUserActions/tbt: -100%
  • bridgeUserActions/total: +30%
  • bridgeUserActions/inp: -23%
  • bridgeUserActions/fcp: -48%
  • bridgeUserActions/lcp: +1108%
Startup Benchmarks · Samples: 100
Benchmarkchrome-webpackfirefox-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
startupPowerUserHome
[Sentry log · main/release]
🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • startupStandardHome/domInteractive: -14%
  • startupStandardHome/fcp: -11%
  • startupPowerUserHome/load: -12%
  • startupPowerUserHome/domContentLoaded: -12%
  • startupPowerUserHome/backgroundConnect: -27%
  • startupPowerUserHome/initialActions: +11%
  • startupPowerUserHome/loadScripts: -13%
  • startupPowerUserHome/setupStore: -78%
  • startupPowerUserHome/inp: -11%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 startupPowerUserHome/LCP: p75 2.6s
User Journey Benchmarks · Samples: 5 · mock API 🔴 2
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 [CI log]
🔴 total
🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🔴 [CI log]
🔴 total
🟡 [CI log]
🟡 total
assetDetails
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
importSrpHome
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
sendTransactions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
swap
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • onboardingImportWallet/srpButtonToSrpForm: +41%
  • onboardingImportWallet/confirmSrpToPwForm: +38%
  • onboardingImportWallet/pwFormToMetricsScreen: +34%
  • onboardingImportWallet/metricsToWalletReadyScreen: +17%
  • onboardingImportWallet/doneButtonToHomeScreen: -77%
  • onboardingImportWallet/openAccountMenuToAccountListLoaded: -46%
  • onboardingImportWallet/longTaskCount: -86%
  • onboardingImportWallet/longTaskTotalDuration: -95%
  • onboardingImportWallet/longTaskMaxDuration: -90%
  • onboardingImportWallet/tbt: -98%
  • onboardingImportWallet/total: -79%
  • onboardingNewWallet/srpButtonToPwForm: -17%
  • onboardingNewWallet/createPwToRecoveryScreen: -12%
  • onboardingNewWallet/agreeButtonToOnboardingSuccess: -18%
  • onboardingNewWallet/doneButtonToAssetList: -17%
  • onboardingNewWallet/longTaskCount: -69%
  • onboardingNewWallet/longTaskTotalDuration: -77%
  • onboardingNewWallet/longTaskMaxDuration: -47%
  • onboardingNewWallet/tbt: -100%
  • onboardingNewWallet/total: -16%
  • solanaAssetDetails/assetClickToPriceChart: -58%
  • solanaAssetDetails/longTaskCount: -100%
  • solanaAssetDetails/longTaskTotalDuration: -100%
  • solanaAssetDetails/longTaskMaxDuration: -100%
  • solanaAssetDetails/tbt: -100%
  • solanaAssetDetails/total: -58%
  • solanaAssetDetails/fcp: +13%
  • importSrpHome/loginToHomeScreen: -12%
  • importSrpHome/homeAfterImportWithNewWallet: -18%
  • importSrpHome/longTaskCount: -37%
  • importSrpHome/longTaskTotalDuration: -35%
  • importSrpHome/tbt: -26%
  • importSrpHome/total: -17%
  • importSrpHome/inp: -30%
  • importSrpHome/cls: +382%
  • sendTransactions/openSendPageFromHome: -32%
  • sendTransactions/reviewTransactionToConfirmationPage: -98%
  • sendTransactions/longTaskCount: -100%
  • sendTransactions/longTaskTotalDuration: -100%
  • sendTransactions/longTaskMaxDuration: -100%
  • sendTransactions/tbt: -100%
  • sendTransactions/total: -95%
  • sendTransactions/inp: -22%
  • sendTransactions/lcp: -59%
  • sendTransactions/cls: +171%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 assetDetails/FCP: p75 1.8s
  • 🟡 importSrpHome/INP: p75 216ms
  • 🟡 importSrpHome/FCP: p75 1.8s
  • 🟡 assetDetails/FCP: p75 2.1s
  • 🟡 solanaAssetDetails/FCP: p75 2.0s
  • 🟡 importSrpHome/FCP: p75 1.9s
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]
Bundle size diffs
  • background: 565 Bytes (0%)
  • ui: 166 Bytes (0%)
  • common: 0 Bytes (0%)
  • other: 0 Bytes (0%)
  • contentScripts: -14 Bytes (0%)
  • zip: 203 Bytes (0%)

@sonarqubecloud

Copy link
Copy Markdown

@metamask-ci

metamask-ci Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor
Builds ready [8c4904f] [reused from bf902e6]
⚡ Performance Benchmarks (Total: 🟢 15 pass · 🟡 7 warn · 🔴 2 fail)

Baseline (latest main): 171ed20 | Date: 7/28/2026 | Pipeline: 30444704393 | Baseline logs

Metricschrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 srpButtonToSrpForm(p95) [CI log]🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🔴 [CI log]🟡 [CI log]

Regressions (🔴 2 failures)

Interaction Benchmarks · Samples: 5
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
confirmTx
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • bridgeUserActions/bridge_load_page: +117%
  • bridgeUserActions/bridge_load_asset_picker: +35%
  • bridgeUserActions/longTaskCount: +11%
  • bridgeUserActions/longTaskTotalDuration: +17%
  • bridgeUserActions/tbt: +32%
  • bridgeUserActions/total: +14%
  • bridgeUserActions/inp: +15%
  • loadNewAccount/inp: -24%
  • loadNewAccount/fcp: -50%
  • loadNewAccount/lcp: +1116%
  • confirmTx/confirm_tx: +10%
  • confirmTx/longTaskCount: -100%
  • confirmTx/longTaskTotalDuration: -100%
  • confirmTx/longTaskMaxDuration: -100%
  • confirmTx/tbt: -100%
  • confirmTx/total: +10%
  • confirmTx/inp: -24%
  • confirmTx/fcp: -48%
  • confirmTx/lcp: +1135%
  • bridgeUserActions/bridge_load_page: +219%
  • bridgeUserActions/bridge_load_asset_picker: +73%
  • bridgeUserActions/longTaskCount: -100%
  • bridgeUserActions/longTaskTotalDuration: -100%
  • bridgeUserActions/longTaskMaxDuration: -100%
  • bridgeUserActions/tbt: -100%
  • bridgeUserActions/total: +30%
  • bridgeUserActions/inp: -23%
  • bridgeUserActions/fcp: -48%
  • bridgeUserActions/lcp: +1108%
Startup Benchmarks · Samples: 100
Benchmarkchrome-webpackfirefox-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
startupPowerUserHome
[Sentry log · main/release]
🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • startupStandardHome/domInteractive: -14%
  • startupStandardHome/fcp: -11%
  • startupPowerUserHome/load: -12%
  • startupPowerUserHome/domContentLoaded: -12%
  • startupPowerUserHome/backgroundConnect: -27%
  • startupPowerUserHome/initialActions: +11%
  • startupPowerUserHome/loadScripts: -13%
  • startupPowerUserHome/setupStore: -78%
  • startupPowerUserHome/inp: -11%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 startupPowerUserHome/LCP: p75 2.6s
User Journey Benchmarks · Samples: 5 · mock API 🔴 2
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 [CI log]
🔴 total
🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🔴 [CI log]
🔴 total
🟡 [CI log]
🟡 total
assetDetails
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
importSrpHome
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
sendTransactions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
swap
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • onboardingImportWallet/srpButtonToSrpForm: +41%
  • onboardingImportWallet/confirmSrpToPwForm: +38%
  • onboardingImportWallet/pwFormToMetricsScreen: +34%
  • onboardingImportWallet/metricsToWalletReadyScreen: +17%
  • onboardingImportWallet/doneButtonToHomeScreen: -77%
  • onboardingImportWallet/openAccountMenuToAccountListLoaded: -46%
  • onboardingImportWallet/longTaskCount: -86%
  • onboardingImportWallet/longTaskTotalDuration: -95%
  • onboardingImportWallet/longTaskMaxDuration: -90%
  • onboardingImportWallet/tbt: -98%
  • onboardingImportWallet/total: -79%
  • onboardingNewWallet/srpButtonToPwForm: -17%
  • onboardingNewWallet/createPwToRecoveryScreen: -12%
  • onboardingNewWallet/agreeButtonToOnboardingSuccess: -18%
  • onboardingNewWallet/doneButtonToAssetList: -17%
  • onboardingNewWallet/longTaskCount: -69%
  • onboardingNewWallet/longTaskTotalDuration: -77%
  • onboardingNewWallet/longTaskMaxDuration: -47%
  • onboardingNewWallet/tbt: -100%
  • onboardingNewWallet/total: -16%
  • solanaAssetDetails/assetClickToPriceChart: -58%
  • solanaAssetDetails/longTaskCount: -100%
  • solanaAssetDetails/longTaskTotalDuration: -100%
  • solanaAssetDetails/longTaskMaxDuration: -100%
  • solanaAssetDetails/tbt: -100%
  • solanaAssetDetails/total: -58%
  • solanaAssetDetails/fcp: +13%
  • importSrpHome/loginToHomeScreen: -12%
  • importSrpHome/homeAfterImportWithNewWallet: -18%
  • importSrpHome/longTaskCount: -37%
  • importSrpHome/longTaskTotalDuration: -35%
  • importSrpHome/tbt: -26%
  • importSrpHome/total: -17%
  • importSrpHome/inp: -30%
  • importSrpHome/cls: +382%
  • sendTransactions/openSendPageFromHome: -32%
  • sendTransactions/reviewTransactionToConfirmationPage: -98%
  • sendTransactions/longTaskCount: -100%
  • sendTransactions/longTaskTotalDuration: -100%
  • sendTransactions/longTaskMaxDuration: -100%
  • sendTransactions/tbt: -100%
  • sendTransactions/total: -95%
  • sendTransactions/inp: -22%
  • sendTransactions/lcp: -59%
  • sendTransactions/cls: +171%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 assetDetails/FCP: p75 1.8s
  • 🟡 importSrpHome/INP: p75 216ms
  • 🟡 importSrpHome/FCP: p75 1.8s
  • 🟡 assetDetails/FCP: p75 2.1s
  • 🟡 solanaAssetDetails/FCP: p75 2.0s
  • 🟡 importSrpHome/FCP: p75 1.9s
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]
Bundle size diffs
  • background: 565 Bytes (0%)
  • ui: 166 Bytes (0%)
  • common: 0 Bytes (0%)
  • other: 0 Bytes (0%)
  • contentScripts: -14 Bytes (0%)
  • zip: 203 Bytes (0%)

@salimtb
salimtb marked this pull request as ready for review July 29, 2026 11:14
@salimtb
salimtb requested a review from a team as a code owner July 29, 2026 11:14

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 8c4904f. Configure here.

);
const selectedGroupBalance = isAssetsUnifyStateEnabled
? unifiedSelectedGroupBalance
: legacySelectedGroupBalance;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dual balance selectors always both run

Medium Severity

AccountGroupBalance always subscribes to both selectBalanceBySelectedAccountGroup and selectUnifiedBalanceBySelectedAccountGroup, so both aggregations recompute on assets/account-tree updates even though only one result is used. selectBalanceBySelectedAccountGroup already switches on the unify flag via selectBalanceForAllWallets, so the unused path still pays for full all-wallets aggregation (or the unified per-group path) on every update.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 8c4904f. Configure here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will be cleaned once the FF is removed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeh... feature was shipped for some time now, maybe can scope out this clean up :)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tyy

Comment thread app/scripts/messenger-client-init/assets/assets-controller-init.ts

@juanmigdr juanmigdr left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@salimtb
salimtb added this pull request to the merge queue Jul 29, 2026
Merged via the queue into main with commit fadc943 Jul 29, 2026
144 checks passed
@salimtb
salimtb deleted the feat/assets-unify-balance-and-traces branch July 29, 2026 14:09
@metamaskbot metamaskbot added the release-13.43.0 Issue or pull request that will be included in release 13.43.0 label Jul 29, 2026
@metamask-ci metamask-ci Bot mentioned this pull request Jul 30, 2026
17 tasks
@MajorLift

MajorLift commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

🧪 Validation Run

Verdict: ⚠️ the trace path is off by default, but "off" is not free — the gate re-reads RemoteFeatureFlagController state on every trace call, in the one file that otherwise caches what it reads — Claim: the Sentry trace path this PR adds is off by default and costs nothing while the flag is off. head 8c4904f · 2026-08-02 · instrumentation-cost check

Note

Trial run of the MetaMask evidence skills
feedback welcome, on the finding or on whether this format is useful to a reviewer.
Not a review verdict; nothing here blocks the PR.

The callback handed to AssetsController, the function it consults to decide, and — for contrast — the one value this same file memoises, read out of the committed tree at the PR head over the full range f87e3bc..8c4904f:

Ran to completion (exit 0) — read the output, no verdict asserted

Claim under test: the Sentry trace path this PR adds is off by default and costs nothing while the flag is off

$ bash -c B=f87e3bc8db833aea5da91ab48e3a90d702fbbb19; H=8c4904f63a66685b490f0fb015e2dc45e0497be6
F=app/scripts/messenger-client-init/assets/assets-controller-init.ts
git fetch -q --depth=1 origin $B
echo "== production files this PR touches (tests excluded) =="
git diff --stat $B $H -- "*.ts" "*.tsx" ":(exclude)*.test.*" ":(exclude)test/*"
echo
echo "== the trace callback handed to AssetsController =="
git show $H:$F | cat -n | sed -n 130,142p
echo
echo "== what that callback re-reads on every invocation =="
git show $H:$F | cat -n | sed -n 102,121p
echo
echo "== the one value this same file caches across calls =="
git show $H:$F | cat -n | sed -n 28p
git show $H:$F | cat -n | sed -n 150,161p
echo
echo "== every messenger read in this file, by line =="
git grep -nE "initMessenger[.]call[(]" $H -- $F
== production files this PR touches (tests excluded) ==
 .../assets/assets-controller-init.ts               |  63 +++++++
 .../assets/assets-controller-messenger.ts          |   5 +-
 .../lib/assets-unify-state/remote-feature-flag.ts  |  26 +++
 .../account-group-balance.tsx                      |  13 +-
 ui/selectors/assets-unify-state/feature-flags.ts   |   1 +
 ui/selectors/assets.balance-utils.ts               | 189 ---------------------
 ui/selectors/assets.ts                             | 147 ++++++++++++++--
 7 files changed, 236 insertions(+), 208 deletions(-)

== the trace callback handed to AssetsController ==
   130	function createAssetsControllerTrace(
   131	  initMessenger: AssetsControllerInitMessenger,
   132	): ControllerTraceCallback {
   133	  return <Result>(
   134	    req: ControllerTraceRequest,
   135	    fn?: (ctx?: ControllerTraceContext) => Result,
   136	  ): Promise<Result> => {
   137	    if (!isAssetsControllerTracesEnabled(initMessenger)) {
   138	      return Promise.resolve(fn?.() as Result);
   139	    }
   140	    return traceAsControllerCallback(req, fn);
   141	  };
   142	}

== what that callback re-reads on every invocation ==
   102	function isAssetsControllerTracesEnabled(
   103	  initMessenger: AssetsControllerInitMessenger,
   104	): boolean {
   105	  try {
   106	    if (!getIsAssetsUnifiedStateIncludedInBuild()) {
   107	      return false;
   108	    }
   109	    const { remoteFeatureFlags } = initMessenger.call(
   110	      'RemoteFeatureFlagController:getState',
   111	    );
   112	    return isAssetsUnifyStateTracesEnabled(
   113	      remoteFeatureFlags?.[ASSETS_UNIFY_STATE_FLAG] as
   114	        | AssetsUnifyStateFeatureFlag
   115	        | undefined,
   116	      ASSETS_UNIFY_STATE_VERSION_1,
   117	    );
   118	  } catch {
   119	    return false;
   120	  }
   121	}

== the one value this same file caches across calls ==
    28	let apiClient: AssetsControllerOptions['queryApiClient'] | null = null;
   150	function getApiClient(
   151	  initMessenger: AssetsControllerInitMessenger,
   152	): AssetsControllerOptions['queryApiClient'] {
   153	  if (!apiClient) {
   154	    apiClient = createApiPlatformClient({
   155	      clientProduct: 'metamask-extension',
   156	      clientVersion: process.env.METAMASK_VERSION,
   157	      getBearerToken: () => safeGetBearerToken(initMessenger),
   158	    }) as unknown as AssetsControllerOptions['queryApiClient'];
   159	  }
   160	  return apiClient;
   161	}

== every messenger read in this file, by line ==
8c4904f63a66685b490f0fb015e2dc45e0497be6:app/scripts/messenger-client-init/assets/assets-controller-init.ts:40:    return await initMessenger.call('AuthenticationController:getBearerToken');
8c4904f63a66685b490f0fb015e2dc45e0497be6:app/scripts/messenger-client-init/assets/assets-controller-init.ts:56:    const preferencesState = initMessenger.call(
8c4904f63a66685b490f0fb015e2dc45e0497be6:app/scripts/messenger-client-init/assets/assets-controller-init.ts:79:      const { completedOnboarding } = initMessenger.call(
8c4904f63a66685b490f0fb015e2dc45e0497be6:app/scripts/messenger-client-init/assets/assets-controller-init.ts:85:      const preferencesState = initMessenger.call(
8c4904f63a66685b490f0fb015e2dc45e0497be6:app/scripts/messenger-client-init/assets/assets-controller-init.ts:109:    const { remoteFeatureFlags } = initMessenger.call(
8c4904f63a66685b490f0fb015e2dc45e0497be6:app/scripts/messenger-client-init/assets/assets-controller-init.ts:243:        const { completedOnboarding } = initMessenger.call(

Produced by capture.sh, not transcribed. head 8c4904f63a66685b490f0fb015e2dc45e0497be6 · 0 tracked changes · node v22.23.1 · Python 3.12.3 · yarn.lock 4d3d2eb5b2d72866. Run: https://github.com/MajorLift/metamask-skills/actions/runs/30768515963 — logs and artifacts attached there.

Follows from the above

  • The gate sits inside the returned callback (137), not outside it, so isAssetsControllerTracesEnabled is consulted once per trace request rather than once when the controller is built.
  • Each of those consultations goes through the messenger for RemoteFeatureFlagController:getState (109). With the flag off the span is skipped; the round trip is not.
  • The same file already shows the other shape: apiClient is built once behind a null check (28, 153). The flag read is the one thing on this path that is re-derived every time.
  • What that costs therefore scales with how often @metamask/assets-controller invokes the callback — decided inside that package, so nothing in this diff bounds it.

Open for review: how often does AssetsController call its trace callback in a normal session — per poll, per asset, per batch? If it is per asset, line 109 runs at that rate for users who have the feature disabled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-13.43.0 Issue or pull request that will be included in release 13.43.0 risk:medium size-L team-assets

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants