Skip to content

feat: add mUSD conversion hooks, selectors, and confirmation UI (Phase 1)#40223

Merged
nickewansmith merged 26 commits intomainfrom
MUSD-290-musd-migration-phase-1
Feb 25, 2026
Merged

feat: add mUSD conversion hooks, selectors, and confirmation UI (Phase 1)#40223
nickewansmith merged 26 commits intomainfrom
MUSD-290-musd-migration-phase-1

Conversation

@nickewansmith
Copy link
Contributor

@nickewansmith nickewansmith commented Feb 19, 2026

Description

Introduce the foundational layer for the mUSD stablecoin conversion feature, ported from metamask-mobile. This phase adds the core hooks, Redux selectors, and confirmation screen components needed to power the conversion flow.

Hooks (ui/hooks/musd/):

  • useMusdConversion: orchestrates the end-to-end conversion flow including education routing, transaction creation with dedup, and geo-blocking checks
  • useMusdConversionTokens: source of truth for eligible conversion tokens, filtered by allowlist/blocklist and minimum fiat balance
  • useMusdCtaVisibility: determines when to show Buy/Get mUSD CTAs based on feature flags, geo-blocking, token holdings, and dismissal state
  • useMusdBalance: detects mUSD token balance across multiple chains
  • useMusdGeoBlocking: checks user region against blocked regions list via the Ramps geolocation API with session-level caching
  • useMusdNetworkFilter: resolves network filter state for CTA visibility
  • useMusdConversionToastStatus: monitors conversion transaction lifecycle to trigger success/failure toast notifications
  • useMusdConversionTokenFilter: filters Asset tokens for the pay-with modal by ERC20 standard and allowlist/blocklist rules
  • useCustomAmount: manages custom amount input for conversion confirmations

Selectors (ui/selectors/musd/):

  • feature-flags: memoized selectors for all mUSD remote feature flags (enabled state, blocked regions, token allowlist/blocklist, min balance, CTA tokens, education URL, etc.)
  • persisted-state: selectors for education-seen and dismissed CTA keys

Confirmation UI (ui/pages/confirmations/):

  • musd-conversion-header: custom confirmation header with info tooltip
  • musd-conversion-info: amount input and override content for the conversion confirmation screen
  • musd-override-content: output amount tag and payment token selector
  • output-amount-tag: reusable tag displaying the mUSD output amount

Also adds mUSD education and icon image assets.

Open in GitHub Codespaces

Changelog

CHANGELOG entry: Adds foundational layer for the mUSD stablecoin conversion feature

Related issues

Fixes: https://consensyssoftware.atlassian.net/browse/MUSD-335
Fixes: https://consensyssoftware.atlassian.net/browse/MUSD-326
Fixes: https://consensyssoftware.atlassian.net/browse/MUSD-290

Manual testing steps

  • All unit tests should pass
  • No code should be accessed and logic is safe from feature leaking
  • App should work as before

Screenshots/Recordings

Before

n/a

After

n/a

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
Touches persisted background state, transaction creation/replacement logic, and introduces new network calls (token-cache/geolocation/relay endpoints), which can affect conversion flow correctness and telemetry but is largely additive and behind feature gating.

Overview
Introduces Phase 1 plumbing for mUSD conversion across background + UI. Adds persisted app-state for education seen and per-token CTA dismissals (with new controller mutators exposed via metamask-controller), expands MetaMetrics with mUSD conversion event names/category, and updates fixtures/state-log snapshots accordingly.

Builds out core mUSD client-side utilities and hooks: richer ui/components/app/musd/constants (chain/asset IDs, relay/geolocation endpoints, helpers), new analytics helpers in musd-events, allowlist/blocklist + geo-block validation utilities, and transaction helpers to create/replace TransactionType.musdConversion ERC-20 transfer txs (including same-chain enforcement and approval rejection on replacement).

Adds initial hooks to orchestrate the conversion flow (useMusdConversion with geo gating, education routing, and duplicate-prevention), derive buy availability via ramp token-cache API (useCanBuyMusd with caching/fail-closed behavior), compute mUSD balances across legacy/multichain assets, show output-amount tag for musdConversion confirmations (useCustomAmount), and monitor conversion lifecycle for in-progress/success/failure toasts (useMusdConversionToastStatus). Also classifies musdConversion transactions as send for transaction list grouping, and broadens CODEOWNERS to cover **/musd/** plus the deep link route file.

Written by Cursor Bugbot for commit d249ca1. This will update automatically on new commits. Configure here.

@github-actions
Copy link
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.

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 19, 2026

✨ Files requiring CODEOWNER review ✨

👨‍🔧 @MetaMask/core-extension-ux (2 files, +7 -0)
  • 📁 ui/
    • 📁 components/
      • 📁 app/
        • 📁 transaction-list-item/
          • 📄 helpers.test.ts +6 -0
          • 📄 helpers.ts +1 -0

👨‍🔧 @MetaMask/extension-platform (1 files, +3 -1)
  • 📁 test/
    • 📁 e2e/
      • 📁 fixtures/
        • 📄 onboarding-fixture.json +3 -1

🕵️ @MetaMask/extension-privacy-reviewers (1 files, +2 -0)
  • 📁 test/
    • 📁 e2e/
      • 📁 tests/
        • 📁 settings/
          • 📄 state-logs.json +2 -0

🔒 @MetaMask/extension-security-team (1 files, +2 -2)
  • 📁 .github/
    • 📄 CODEOWNERS +2 -2

👨‍🔧 @MetaMask/metamask-earn (12 files, +2561 -5)
  • 📁 ui/
    • 📁 components/
      • 📁 app/
        • 📁 musd/
          • 📁 utils/
            • 📄 index.ts +25 -0
            • 📄 token-allowlist.test.ts +179 -0
            • 📄 token-allowlist.ts +103 -0
            • 📄 transaction-utils.test.ts +476 -0
            • 📄 transaction-utils.ts +421 -0
            • 📄 validation.test.ts +42 -0
            • 📄 validation.ts +47 -0
            • 📄 constants.test.ts +277 -0
            • 📄 constants.ts +182 -5
            • 📄 musd-events.ts +366 -0
    • 📁 hooks/
      • 📁 musd/
        • 📄 index.ts +55 -0
        • 📄 useCanBuyMusd.test.ts +388 -0

🧪 @MetaMask/qa (2 files, +5 -1)
  • 📁 test/
    • 📁 e2e/
      • 📁 fixtures/
        • 📄 onboarding-fixture.json +3 -1
      • 📁 tests/
        • 📁 settings/
          • 📄 state-logs.json +2 -0

@nickewansmith nickewansmith marked this pull request as ready for review February 19, 2026 06:26
@nickewansmith nickewansmith requested review from a team as code owners February 19, 2026 06:26
@nickewansmith nickewansmith force-pushed the MUSD-290-musd-migration-phase-1 branch from 8affb61 to 6fba078 Compare February 19, 2026 06:29
@nickewansmith nickewansmith removed the request for review from a team February 19, 2026 06:30
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 19, 2026

Builds ready [6fba078]
UI Startup Metrics (1383 ± 114 ms)
PlatformBuildTypePageMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
ChromeBrowserifyStandard HomeuiStartup13831153182311414741562
load1166949161010812511326
domContentLoaded1158942160110812441317
domInteractive261688182375
firstPaint202601324213200325
backgroundConnect22019941423224246
firstReactRender17104041823
initialActions106113
loadScripts958752140910610421111
setupStore1273441420
numNetworkReqs312294212290
BrowserifyPower User HomeuiStartup17611421224814517882140
load11951091170413511871591
domContentLoaded11791077167112911741564
domInteractive3518170243576
firstPaint1717144281236295
backgroundConnect34231143723354384
firstReactRender23154462636
initialActions103112
loadScripts91580513881289051310
setupStore1575781635
numNetworkReqs58351472457120
WebpackStandard HomeuiStartup8697001119919251022
load73962292486794893
domContentLoaded73361891986789887
domInteractive2815109192579
firstPaint1196542264135222
backgroundConnect302075103351
firstReactRender2012127132134
initialActions104112
loadScripts73161691185787883
setupStore1263551223
numNetworkReqs312294202587
WebpackPower User HomeuiStartup1233856216417613091524
load72363013881257131061
domContentLoaded71462513761257041056
domInteractive37191823233120
firstPaint1376359282166268
backgroundConnect16512832942170271
firstReactRender22173032428
initialActions101011
loadScripts71162413631227021045
setupStore1253941318
numNetworkReqs1013724649135214
FirefoxBrowserifyStandard HomeuiStartup16091376226217916522032
load13521158200614613861617
domContentLoaded13511155200614613851617
domInteractive74313455291147
firstPaint------
backgroundConnect6030209246690
firstReactRender13112621416
initialActions103112
loadScripts13251132197014013631590
setupStore197152271452
numNetworkReqs311995212791
BrowserifyPower User HomeuiStartup26642026382436328533371
load15521269223225916482050
domContentLoaded15521265223225916472046
domInteractive12237727136107536
firstPaint------
backgroundConnect229107907173218562
firstReactRender18146891821
initialActions203122
loadScripts15091252218124515592008
setupStore109669615796471
numNetworkReqs57271373373128
WebpackStandard HomeuiStartup16971433322625217162029
load14151203184010514711587
domContentLoaded14151203184010514711587
domInteractive882927852130172
firstPaint------
backgroundConnect5524212296192
firstReactRender15123531619
initialActions102122
loadScripts1391118217349914461550
setupStore186142181646
numNetworkReqs301989172776
WebpackPower User HomeuiStartup26882127388541528253552
load15991301243629517412261
domContentLoaded15991301243629517412261
domInteractive14236872159110546
firstPaint------
backgroundConnect19811182499216359
firstReactRender21166062330
initialActions213123
loadScripts15681267241329516792238
setupStore1729715217241647
numNetworkReqs56261383490122
📊 Page Load Benchmark Results

Current Commit: 6fba078 | Date: 2/19/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.05s (±38ms) 🟡 | historical mean value: 1.03s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 736ms (±37ms) 🟢 | historical mean value: 726ms ⬆️ (historical data)
  • firstContentfulPaint-> current mean value: 81ms (±12ms) 🟢 | historical mean value: 86ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.05s 38ms 1.02s 1.34s 1.07s 1.34s
domContentLoaded 736ms 37ms 715ms 1.02s 749ms 1.02s
firstPaint 81ms 12ms 64ms 180ms 88ms 180ms
firstContentfulPaint 81ms 12ms 64ms 180ms 88ms 180ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 96.04 KiB (2.23%)
  • ui: 42.92 KiB (0.53%)
  • common: 15.33 KiB (0.14%)

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 19, 2026

Builds ready [4692dba]
UI Startup Metrics (1333 ± 104 ms)
PlatformBuildTypePageMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
ChromeBrowserifyStandard HomeuiStartup13331123160210413851517
load114093614099811781319
domContentLoaded113293214019611721305
domInteractive261690162368
firstPaint213631417246204367
backgroundConnect21519226613220244
firstReactRender16112731822
initialActions104113
loadScripts9327441191929701100
setupStore1162131418
numNetworkReqs3122101222292
BrowserifyPower User HomeuiStartup17701413235117518112143
load11901062184615711661614
domContentLoaded11761055177115211571583
domInteractive36182073134103
firstPaint192741782181231369
backgroundConnect34030445225350389
firstReactRender22155262335
initialActions104112
loadScripts91480614721468911318
setupStore1664381834
numNetworkReqs59361502759130
WebpackStandard HomeuiStartup8657031197919091032
load73661996084781876
domContentLoaded73061595483776870
domInteractive2917105202484
firstPaint1266538161165235
backgroundConnect29206693344
firstReactRender19125172133
initialActions103112
loadScripts72761394682774862
setupStore1273651324
numNetworkReqs312298212590
WebpackPower User HomeuiStartup1261870178217413371582
load73364912601157221029
domContentLoaded72364312561157131016
domInteractive38191843435134
firstPaint1386546483136321
backgroundConnect17013435843178251
firstReactRender24183542630
initialActions102111
loadScripts72064112471127111007
setupStore1252641419
numNetworkReqs1013625751134228
FirefoxBrowserifyStandard HomeuiStartup15571326264621315831977
load12971134229715913541556
domContentLoaded12951128229616013531556
domInteractive60361903081119
firstPaint------
backgroundConnect59272233457128
firstReactRender13102321417
initialActions104112
loadScripts12691117227015113251487
setupStore2372093814113
numNetworkReqs3220100212592
BrowserifyPower User HomeuiStartup26732036404437327913393
load15511247219225917152110
domContentLoaded15511246219225917152110
domInteractive12130714130109388
firstPaint------
backgroundConnect295123926241302886
firstReactRender18146551824
initialActions103122
loadScripts15101219213324516292065
setupStore111675117774594
numNetworkReqs58271433373125
WebpackStandard HomeuiStartup17411414310126817352083
load14741235278924614801776
domContentLoaded14731230278924614801775
domInteractive109301478146131183
firstPaint------
backgroundConnect65272603965151
firstReactRender16132831624
initialActions102112
loadScripts14461221276424314551667
setupStore227172321569
numNetworkReqs312091172775
WebpackPower User HomeuiStartup28002126485750929853817
load15951325272828816982257
domContentLoaded15941324272828816972257
domInteractive135321329183111525
firstPaint------
backgroundConnect3111141353260301909
firstReactRender2415104122532
initialActions203122
loadScripts15491301270426916542087
setupStore19391188271279720
numNetworkReqs56281343382130
📊 Page Load Benchmark Results

Current Commit: 4692dba | Date: 2/19/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.04s (±43ms) 🟡 | historical mean value: 1.03s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 729ms (±41ms) 🟢 | historical mean value: 726ms ⬆️ (historical data)
  • firstContentfulPaint-> current mean value: 79ms (±12ms) 🟢 | historical mean value: 86ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.04s 43ms 1.01s 1.33s 1.06s 1.33s
domContentLoaded 729ms 41ms 709ms 1.01s 748ms 1.01s
firstPaint 79ms 12ms 64ms 184ms 88ms 184ms
firstContentfulPaint 79ms 12ms 64ms 184ms 88ms 184ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 701 Bytes (0.02%)
  • ui: 43 Bytes (0%)
  • common: 1 KiB (0.01%)

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 19, 2026

Builds ready [674b2a8]
UI Startup Metrics (1445 ± 111 ms)
PlatformBuildTypePageMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
ChromeBrowserifyStandard HomeuiStartup14451255190011114661678
load12231038163110012431416
domContentLoaded1216103516229812351405
domInteractive2917146222582
firstPaint179691228199215349
backgroundConnect25523529414259287
firstReactRender18124351925
initialActions104112
loadScripts97779113739510021165
setupStore147141141520
numNetworkReqs312291202287
BrowserifyPower User HomeuiStartup2200146310648144919854303
load12111069185817112291621
domContentLoaded11941058177216012181593
domInteractive3419149233474
firstPaint1797356592226332
backgroundConnect619308877111853771655
firstReactRender23164262537
initialActions104112
loadScripts93481015121559461308
setupStore1663761732
numNetworkReqs65361502673121
WebpackStandard HomeuiStartup8687141173939011084
load73762496584780891
domContentLoaded73262095983777884
domInteractive2917113212684
firstPaint1326636963167237
backgroundConnect28175883145
firstReactRender19124472132
initialActions104112
loadScripts72961895082775881
setupStore1274561220
numNetworkReqs312299212591
WebpackPower User HomeuiStartup1241868170615613081592
load75064911911197341076
domContentLoaded73964411821197231066
domInteractive41191853237120
firstPaint1507643670181279
backgroundConnect16413438039167239
firstReactRender23173232428
initialActions101011
loadScripts73664211711167201049
setupStore1344161521
numNetworkReqs1193525351143228
FirefoxBrowserifyStandard HomeuiStartup16471384311524716382148
load13861165283921114001642
domContentLoaded13841165283321114001636
domInteractive893383896104171
firstPaint------
backgroundConnect61252983562100
firstReactRender14112121416
initialActions102122
loadScripts13581141280720513751572
setupStore198186281558
numNetworkReqs312097192587
BrowserifyPower User HomeuiStartup28282156853568329893640
load16591340717861017582133
domContentLoaded16591340717861017582133
domInteractive143361238169122434
firstPaint------
backgroundConnect3621161252280417915
firstReactRender221468132162
initialActions213122
loadScripts16171315713860616752100
setupStore1408789190128622
numNetworkReqs65271703582132
WebpackStandard HomeuiStartup17551448331032117842173
load14641207286423014981624
domContentLoaded14631207286423114981623
domInteractive105281527150129149
firstPaint------
backgroundConnect7326143914073118
firstReactRender16133731620
initialActions102122
loadScripts14381192284722814731578
setupStore34713851371763
numNetworkReqs312090172779
WebpackPower User HomeuiStartup27972116395840629293804
load15771330260727116602090
domContentLoaded15771329260127116602090
domInteractive157331175184133620
firstPaint------
backgroundConnect4201281776335590958
firstReactRender23167992529
initialActions2058623
loadScripts15351267258925616302025
setupStore17481150230192692
numNetworkReqs64262273985134
📊 Page Load Benchmark Results

Current Commit: 674b2a8 | Date: 2/19/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.06s (±39ms) 🟡 | historical mean value: 1.03s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 742ms (±37ms) 🟢 | historical mean value: 724ms ⬆️ (historical data)
  • firstContentfulPaint-> current mean value: 82ms (±11ms) 🟢 | historical mean value: 86ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.06s 39ms 1.03s 1.35s 1.08s 1.35s
domContentLoaded 742ms 37ms 716ms 1.03s 760ms 1.03s
firstPaint 82ms 11ms 68ms 172ms 92ms 172ms
firstContentfulPaint 82ms 11ms 68ms 172ms 92ms 172ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 701 Bytes (0.02%)
  • ui: 43 Bytes (0%)
  • common: 1 KiB (0.01%)

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 24, 2026

Builds ready [38b699c]
⚡ Performance Benchmarks (1376 ± 103 ms)
👆 Interaction Benchmarks
ActionMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account28723299318
total28723299318
Confirm Txconfirm_tx60381260496056
total60381260496056
Bridge User Actionsbridge_load_page22835257267
bridge_load_asset_picker17945216219
bridge_search_token71420730745
total11002411061133
🔌 Startup Benchmarks
BuildMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
Chrome Browserify Startup Standard HomeuiStartup13761175168610314151550
load116195914049312071325
domContentLoaded115495613969312041320
domInteractive2815129212383
firstPaint185621139157210339
backgroundConnect20718729314212230
firstReactRender18123841924
initialActions104113
loadScripts96476311819210161131
setupStore1273141420
numNetworkReqs3122102212288
Chrome Browserify Startup Power User HomeuiStartup17791305418746217442673
load1109991204015910931366
domContentLoaded1093983203315210831340
domInteractive3317187253266
firstPaint209741744193243307
backgroundConnect3302542351228305510
firstReactRender23155272636
initialActions106112
loadScripts88877817611468841144
setupStore1473561430
numNetworkReqs61381672467113
Chrome Webpack Startup Standard HomeuiStartup8356871139948661075
load71360990584764874
domContentLoaded70760489683760863
domInteractive2715122222284
firstPaint1115834757140213
backgroundConnect28188393141
firstReactRender18124262130
initialActions106112
loadScripts70460288982758855
setupStore1263751222
numNetworkReqs312292202586
Chrome Webpack Startup Power User HomeuiStartup1211892179216212821540
load7156291145111704994
domContentLoaded7066241130110691985
domInteractive36181883135109
firstPaint1356754686143293
backgroundConnect16713035842162261
firstReactRender22174642428
initialActions102111
loadScripts7036221118108688974
setupStore1344991436
numNetworkReqs1103925346138218
Firefox Browserify Startup Standard HomeuiStartup19101624292730418862809
load16091347265326516042395
domContentLoaded16071347265326516042395
domInteractive94401169117112153
firstPaint------
backgroundConnect71352142873130
firstReactRender15135341618
initialActions103122
loadScripts15761320262126115732355
setupStore2581663318127
numNetworkReqs321998202787
Firefox Browserify Startup Power User HomeuiStartup27062023376938928483588
load15761275243827516712271
domContentLoaded15751274243727516702271
domInteractive14334662133133435
firstPaint------
backgroundConnect2761071033235266870
firstReactRender17142721822
initialActions103122
loadScripts15401251239626716332228
setupStore15561098234111724
numNetworkReqs68291943589142
Firefox Webpack Startup Standard HomeuiStartup16971483364926517101954
load14221220271215714671540
domContentLoaded14211215271115714671540
domInteractive108291407137131170
firstPaint------
backgroundConnect60252213570114
firstReactRender15123031524
initialActions103122
loadScripts13971202268015214451515
setupStore197274291550
numNetworkReqs302090172780
Firefox Webpack Startup Power User HomeuiStartup27722105457044529083660
load15761308340130216572029
domContentLoaded15751307340130216572029
domInteractive13331699134129498
firstPaint------
backgroundConnect3241171473271351906
firstReactRender21153342329
initialActions203122
loadScripts15301290332928116151905
setupStore1828820234228769
numNetworkReqs66282144381141
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2192220222
srpButtonToSrpForm9019091
confirmSrpToPwForm2102121
pwFormToMetricsScreen1501515
metricsToWalletReadyScreen1511516
doneButtonToHomeScreen8002009981075
openAccountMenuToAccountListLoaded703643774567664
total819950686628909
Onboarding New WalletcreateWalletToSocialScreen2181219220
srpButtonToPwForm1102111113
createPwToRecoveryScreen9099
skipBackupToMetricsScreen3813839
agreeButtonToOnboardingSuccess1701718
doneButtonToAssetList87532312021311
total126732415981703
Asset DetailsassetClickToPriceChart50155577
total50155577
Solana Asset DetailsassetClickToPriceChart4825051
total4825051
Import Srp HomeloginToHomeScreen18864819061955
openAccountMenuAfterLogin4054346
homeAfterImportWithNewWallet235610323582519
total428410743554402
Send TransactionsopenSendPageFromHome33114345
selectTokenToSendFormLoaded1912121
reviewTransactionToConfirmationPage8568860869
total90819923935
SwapopenSwapPageFromHome12543151178
fetchAndDisplaySwapQuotes46358046114772
total47488847484880
🌐 Dapp Page Load Benchmarks

Current Commit: 38b699c | Date: 2/24/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.01s (±37ms) 🟡 | historical mean value: 1.04s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 700ms (±34ms) 🟢 | historical mean value: 729ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 79ms (±11ms) 🟢 | historical mean value: 82ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.01s 37ms 980ms 1.28s 1.04s 1.28s
domContentLoaded 700ms 34ms 674ms 948ms 713ms 948ms
firstPaint 79ms 11ms 68ms 180ms 88ms 180ms
firstContentfulPaint 79ms 11ms 68ms 180ms 88ms 180ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚀 Bundle size reduced!]
  • background: 8.43 KiB (0.19%)
  • ui: 5.19 KiB (0.06%)
  • common: -32.13 KiB (-0.29%)

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 24, 2026

Builds ready [7886c5d]
⚡ Performance Benchmarks (1383 ± 115 ms)
👆 Interaction Benchmarks
ActionMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account2674268272
total2674268272
Confirm Txconfirm_tx6042160436043
total6042160436043
Bridge User Actionsbridge_load_page25721279280
bridge_load_asset_picker13818131169
bridge_search_token6954698700
total10971311081110
🔌 Startup Benchmarks
BuildMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
Chrome Browserify Startup Standard HomeuiStartup13831171183711514221599
load117098615749612011358
domContentLoaded116298015329411941337
domInteractive2816109212384
firstPaint157671217134204342
backgroundConnect20618926715206243
firstReactRender19134552027
initialActions103112
loadScripts97478713389310101155
setupStore1366171422
numNetworkReqs312292202284
Chrome Browserify Startup Power User HomeuiStartup2195129810054151619574711
load1125944163715611591536
domContentLoaded1110935156915011491509
domInteractive36181783330131
firstPaint1736743291238369
backgroundConnect568241770310183132390
firstReactRender23145272539
initialActions1010113
loadScripts91475613801459501285
setupStore1655391732
numNetworkReqs69391512873133
Chrome Webpack Startup Standard HomeuiStartup84868211961068891103
load711606106894758885
domContentLoaded706602106193753880
domInteractive2715102202380
firstPaint1146033355146200
backgroundConnect291975103347
firstReactRender19124362333
initialActions105112
loadScripts703600105992751873
setupStore1264151320
numNetworkReqs3222103212589
Chrome Webpack Startup Power User HomeuiStartup12071018240719712641560
load7166221327115710990
domContentLoaded7076121319115698983
domInteractive36181723135132
firstPaint1376542675161276
backgroundConnect16712832944161272
firstReactRender22173232428
initialActions104111
loadScripts7046101307113695974
setupStore1254551316
numNetworkReqs1163825750142203
Firefox Browserify Startup Standard HomeuiStartup16641388245021517072052
load13991181215718314431686
domContentLoaded13981181215218314431686
domInteractive78342304199138
firstPaint------
backgroundConnect5929227256696
firstReactRender14114131417
initialActions103122
loadScripts13721158212917914131666
setupStore207170271560
numNetworkReqs3221102202688
Firefox Browserify Startup Power User HomeuiStartup28322097405440130073736
load16021219276528016502298
domContentLoaded16011219276428016492293
domInteractive13535652124128369
firstPaint------
backgroundConnect3381121292270407923
firstReactRender19148171923
initialActions203122
loadScripts15601190271526915722280
setupStore113874915696449
numNetworkReqs69292003988141
Firefox Webpack Startup Standard HomeuiStartup16971427236913417651922
load1429120417478914821554
domContentLoaded1429120417478914811554
domInteractive942926148131163
firstPaint------
backgroundConnect62232033370115
firstReactRender16123541625
initialActions103122
loadScripts1404118416968814541530
setupStore217166291470
numNetworkReqs311996182775
Firefox Webpack Startup Power User HomeuiStartup26971888412347029563690
load15901260311633916952295
domContentLoaded15901255311633916942295
domInteractive141331036176116523
firstPaint------
backgroundConnect316831257263396903
firstReactRender20155352228
initialActions203122
loadScripts15561238308433816562279
setupStore1629765207190674
numNetworkReqs67292324282143
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2191219220
srpButtonToSrpForm9119293
confirmSrpToPwForm2102121
pwFormToMetricsScreen1501515
metricsToWalletReadyScreen1511617
doneButtonToHomeScreen1266312681268
openAccountMenuToAccountListLoaded71607272277227
total887612589429022
Onboarding New WalletcreateWalletToSocialScreen2191219220
srpButtonToPwForm1031103104
createPwToRecoveryScreen8088
skipBackupToMetricsScreen3523737
agreeButtonToOnboardingSuccess1601616
doneButtonToAssetList59080623719
total9692510021002
Asset DetailsassetClickToPriceChart3944243
total3944243
Solana Asset DetailsassetClickToPriceChart4614646
total4614646
Import Srp HomeloginToHomeScreen19995520372061
openAccountMenuAfterLogin4254748
homeAfterImportWithNewWallet256411226182756
total45599745534703
Send TransactionsopenSendPageFromHome2483235
selectTokenToSendFormLoaded1912020
reviewTransactionToConfirmationPage8472848849
total89711903913
SwapopenSwapPageFromHome11713113138
fetchAndDisplaySwapQuotes46228145914761
total47487847484874
🌐 Dapp Page Load Benchmarks

Current Commit: 7886c5d | Date: 2/24/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.05s (±40ms) 🟡 | historical mean value: 1.04s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 735ms (±38ms) 🟢 | historical mean value: 729ms ⬆️ (historical data)
  • firstContentfulPaint-> current mean value: 80ms (±10ms) 🟢 | historical mean value: 82ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.05s 40ms 1.03s 1.36s 1.09s 1.36s
domContentLoaded 735ms 38ms 715ms 1.03s 756ms 1.03s
firstPaint 80ms 10ms 68ms 164ms 88ms 164ms
firstContentfulPaint 80ms 10ms 68ms 164ms 88ms 164ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚀 Bundle size reduced!]
  • background: 8.43 KiB (0.19%)
  • ui: 5.19 KiB (0.06%)
  • common: -32.13 KiB (-0.29%)

setError(null);

try {
const response = await fetch(GEOLOCATION_API_ENDPOINT, {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a good example of where you can benefit from Tanstack Query so you don't manage your own loading, setLoading, error, setError, states which are error prone

It's ready-to-use in the repo

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am not that familiar with Tanstack just yet, but I will dive into it this week so that I understand better how I can use it. This PR is mostly to get a core layer in that others can depend on to move forward with development.

const accountGroupAssets = useSelector(getAssetsBySelectedAccountGroup);

// Get all account tokens
const allTokens = useMemo((): TokenWithFiatAmount[] => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this PR introduces an musd folder for selectors consider creating and moving some of these logic inside new selectors instead to be more performant

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This makes sense, I have 2 other PRs after this one so I can roll that change in once this core one is merged

Copy link

@cursor cursor bot left a comment

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 3 potential issues.

@sonarqubecloud
Copy link

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 24, 2026

Builds ready [d249ca1]
⚡ Performance Benchmarks (1371 ± 100 ms)
👆 Interaction Benchmarks
ActionMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account28218299300
total28218299300
Confirm Txconfirm_tx6029560336034
total6029560336034
Bridge User Actionsbridge_load_page21324230249
bridge_load_asset_picker20830232247
bridge_search_token71722737749
total11376012041218
🔌 Startup Benchmarks
BuildMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
Chrome Browserify Startup Standard HomeuiStartup13711158158310014471522
load117195813849512221336
domContentLoaded116295413499312161320
domInteractive2616109182373
firstPaint1446939671193268
backgroundConnect20418824913206232
firstReactRender17122831924
initialActions106113
loadScripts97476311719310341132
setupStore1272341419
numNetworkReqs312289192283
Chrome Browserify Startup Power User HomeuiStartup16981373215515317541990
load11321016182015811201551
domContentLoaded11151009170414511111459
domInteractive3219141223175
firstPaint188711468198215389
backgroundConnect28624340825293335
firstReactRender23154872737
initialActions104112
loadScripts91181814791429021267
setupStore1774772031
numNetworkReqs60371592656123
Chrome Webpack Startup Standard HomeuiStartup86969211201009601033
load74661691790811900
domContentLoaded73961091389808893
domInteractive2715102192376
firstPaint1176137862142219
backgroundConnect3019131143250
firstReactRender1911148142029
initialActions105112
loadScripts73760991088806891
setupStore1263841218
numNetworkReqs312298212592
Chrome Webpack Startup Power User HomeuiStartup1216989197116312861519
load71162912661156971002
domContentLoaded7036231251115687996
domInteractive36181843135110
firstPaint1346450584132312
backgroundConnect17412942751167298
firstReactRender22163132428
initialActions104112
loadScripts7006221240113685988
setupStore1454891439
numNetworkReqs1094027354139254
Firefox Browserify Startup Standard HomeuiStartup16031381213514916551950
load13481149175611014031558
domContentLoaded13471144175611014021553
domInteractive74341743894137
firstPaint------
backgroundConnect5828247296086
firstReactRender14113831416
initialActions102012
loadScripts13221128169110513751525
setupStore167144191430
numNetworkReqs3219103212589
Firefox Browserify Startup Power User HomeuiStartup26751957419743527533603
load15551249243828016442246
domContentLoaded15541249243828016442246
domInteractive11535732110112376
firstPaint------
backgroundConnect262109976227197852
firstReactRender19146681821
initialActions103122
loadScripts15191225237626916142187
setupStore1437730183173571
numNetworkReqs62331433382130
Firefox Webpack Startup Standard HomeuiStartup16671312309824016921962
load13931172282817514251594
domContentLoaded13921172282817514251594
domInteractive110301392137130192
firstPaint------
backgroundConnect6925139613663108
firstReactRender15112631523
initialActions105112
loadScripts13671144280817313921536
setupStore187155211557
numNetworkReqs311995172779
Firefox Webpack Startup Power User HomeuiStartup26781908385943628033556
load15561265232827817172175
domContentLoaded15551265232827817172175
domInteractive12733716147105520
firstPaint------
backgroundConnect243111912188212723
firstReactRender22167992329
initialActions206122
loadScripts15231247228927116612117
setupStore1658793219244668
numNetworkReqs60281513783140
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2181218220
srpButtonToSrpForm9009090
confirmSrpToPwForm2102121
pwFormToMetricsScreen1501515
metricsToWalletReadyScreen1621818
doneButtonToHomeScreen93470993993
openAccountMenuToAccountListLoaded726652076878038
total858043390099022
Onboarding New WalletcreateWalletToSocialScreen2180218218
srpButtonToPwForm1052104108
createPwToRecoveryScreen8088
skipBackupToMetricsScreen3613636
agreeButtonToOnboardingSuccess1601617
doneButtonToAssetList79125710881106
total117725714731495
Asset DetailsassetClickToPriceChart58126576
total58126576
Solana Asset DetailsassetClickToPriceChart4614647
total4614647
Import Srp HomeloginToHomeScreen20775120782149
openAccountMenuAfterLogin4344647
homeAfterImportWithNewWallet242514425452642
total45019445364665
Send TransactionsopenSendPageFromHome1811719
selectTokenToSendFormLoaded2012122
reviewTransactionToConfirmationPage8521853853
total89714910918
SwapopenSwapPageFromHome1259129139
fetchAndDisplaySwapQuotes45841145934596
total47061647144725
🌐 Dapp Page Load Benchmarks

Current Commit: d249ca1 | Date: 2/24/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.04s (±37ms) 🟡 | historical mean value: 1.04s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 729ms (±35ms) 🟢 | historical mean value: 724ms ⬆️ (historical data)
  • firstContentfulPaint-> current mean value: 79ms (±12ms) 🟢 | historical mean value: 77ms ⬆️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.04s 37ms 1.02s 1.32s 1.06s 1.32s
domContentLoaded 729ms 35ms 709ms 990ms 745ms 990ms
firstPaint 79ms 12ms 64ms 180ms 92ms 180ms
firstContentfulPaint 79ms 12ms 64ms 180ms 92ms 180ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: -261.38 KiB (-6.02%)
  • ui: 11.81 KiB (0.14%)
  • common: 191.92 KiB (1.72%)

Copy link
Contributor

@Matt561 Matt561 left a comment

Choose a reason for hiding this comment

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

Left some non-blocking comments. Approving to unblock subsequent PRs 👍

Copy link
Contributor

@davidmurdoch davidmurdoch left a comment

Choose a reason for hiding this comment

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

LGTM, based on my limited review of CO files only, as this PR does have 2 ✅ already.

@nickewansmith nickewansmith requested review from a team and removed request for Jwhiles and n3ps February 24, 2026 23:27
@nickewansmith nickewansmith added this pull request to the merge queue Feb 24, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-13.21.0 Issue or pull request that will be included in release 13.21.0 size-XL team-earn

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants