Skip to content

Fix: break circular dependencies#40887

Draft
rvelaz wants to merge 8 commits intomainfrom
fix-break-circular-dependencies
Draft

Fix: break circular dependencies#40887
rvelaz wants to merge 8 commits intomainfrom
fix-break-circular-dependencies

Conversation

@rvelaz
Copy link
Contributor

@rvelaz rvelaz commented Mar 14, 2026

This PR removes all circular dependency cycles in the MetaMask extension codebase, reducing the count from 9 to 0. The changes follow the "break selector chains" and "extract shared code" strategies by introducing standalone selector modules that do not depend on the metamask duck or the rest of the selectors.

Changes

New files (TypeScript)

File Purpose
ui/selectors/send-ether-selectors.ts Send-ether selectors (getAddressBook, accountsWithSendEtherInfoSelector, checkNetworkAndAccountSupports1559, isEIP1559Network, isNotEIP1559Network) with no metamask/selectors dependency; accountsWithSendEtherInfoSelector memoized via createSelector
ui/selectors/metamask-gas-selectors.ts Gas selectors (getGasEstimateType, getGasFeeEstimates, getNativeCurrency) used by confirm-transaction and custom-gas
ui/selectors/metamask-selectors-standalone.ts Metamask selectors (getConversionRate, getIsUnlocked, getLedgerTransportType, isAddressLedger, getCompletedOnboarding, isNotEIP1559Network) used by selectors.js
ui/selectors/metamask-state-basic.ts Minimal metamask state selectors (getAlertEnabledness, getUnconnectedAccountAlertEnabledness, getCompletedOnboarding, getIsMainnet) with no store/actions dependency
ui/components/app/metamask-template-renderer/template-renderer-context.ts Context to inject template renderer into MetaMaskTranslation (breaks translation ↔ renderer cycle)
ui/pages/confirmations/confirmation/templates/approval-types.ts TEMPLATED_CONFIRMATION_APPROVAL_TYPES constant (breaks selectors → templates → actions cycle)

Modified files

  • ui/ducks/metamask/metamask.js – Imports from send-ether-selectors and metamask-state-basic instead of selectors; removed isEIP1559Network, getAlertEnabledness, getUnconnectedAccountAlertEnabledness, getCompletedOnboarding (moved to extracted modules)
  • ui/selectors/confirm-transaction.js – Imports gas selectors from metamask-gas-selectors instead of metamask
  • ui/selectors/custom-gas.js – Imports from metamask-gas-selectors, metamask-state-basic, and send-ether-selectors instead of metamask/selectors
  • ui/selectors/selectors.js – Imports from metamask-selectors-standalone, send-ether-selectors, metamask-state-basic, and approval-types; re-exports getIsMainnet, getAddressBook, accountsWithSendEtherInfoSelector, checkNetworkAndAccountSupports1559
  • ui/store/actions.ts – Imports from metamask-state-basic instead of metamask duck
  • .madgerc – Set allowedCircularGlob to [] (no remaining cycles)

Other prior commits (included in branch)

  • Keyring extraction to shared (keyring-utils.ts, metamask-keyring.ts)
  • Template-renderer / translation cycle broken via TemplateRendererContext
  • Metamask ↔ actions cycle broken via metamask-state-basic.ts
  • Smart-transactions decoupled from ui/selectors
  • Selectors → templates cycle broken via approval-types.ts

rvelaz added 8 commits March 13, 2026 23:40
…→ui cycle

- Add shared/lib/selectors/keyring-utils.ts with pure keyring helpers
- Add shared/lib/selectors/metamask-keyring.ts for getCurrentKeyringFromState
- Implement isHardwareWallet and getHardwareWalletType in shared/lib/selectors/account.ts
- Remove shared/lib/selectors index imports from ui/selectors/selectors
- Regenerate circular-deps.jsonc (cycle count unchanged: 9)

Made-with: Cursor
- Add TemplateRendererContext so MetaMaskTranslation does not import MetaMaskTemplateRenderer
- MetaMaskTemplateRenderer provides itself via context; translation consumes it
- Remove ui/components/app/** from .madgerc (no longer matches any cycle)
- Cycle count: 9 -> 8

Made-with: Cursor
…basic

- Add ui/selectors/metamask-state-basic.js with getAlertEnabledness, getUnconnectedAccountAlertEnabledness, getCompletedOnboarding
- actions.ts imports these from metamask-state-basic instead of ducks/metamask
- metamask.js re-exports from metamask-state-basic and removes duplicate definitions
- Cycle count: 8 -> 7

Made-with: Cursor
- Add getPreferences and accountSupportsSmartTx to shared/lib/selectors/metamask-keyring.ts
- Add selectNetworkConfigurationByChainId and selectDefaultRpcEndpointByChainId to shared/networks.ts
- smart-transactions.ts imports from shared instead of ui/selectors/selectors
- Add ui/pages/confirmations/** to .madgerc for remaining cycle
- Remove shared/lib/selectors/** from .madgerc (no longer in any cycle)
- Cycle count: 7 -> 2

Made-with: Cursor
- Extract TEMPLATED_CONFIRMATION_APPROVAL_TYPES to templates/approval-types.js
- approval-types only imports from constants no store or selectors
- selectors and useConfirmationNavigation import from approval-types
- Remove ui/pages/confirmations/** from .madgerc
- Cycle count: 2 (simplified 8-file confirmations cycle)

Made-with: Cursor
…ar-deps.jsonc

- Removed circular dependencies by introducing new selectors in send-ether-selectors.js and metamask-selectors-standalone.js.
- Updated imports in various files to utilize the new selectors, ensuring a cleaner architecture.
- Cleared the circular-deps.jsonc file as there are no longer any circular dependencies detected.

Made-with: Cursor
- Removed all entries from the allowedCircularGlob array in .madgerc, reflecting the recent architectural changes that have eliminated circular dependencies in the codebase.

Made-with: Cursor
- Convert template-renderer-context, approval-types, metamask-gas-selectors,
  metamask-selectors-standalone, metamask-state-basic, send-ether-selectors to .ts
- Memoize accountsWithSendEtherInfoSelector with createSelector
@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.

@metamaskbot metamaskbot added the team-extension-platform Extension Platform team label Mar 14, 2026
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Mar 14, 2026

✨ Files requiring CODEOWNER review ✨

@MetaMask/confirmations (6 files, +64 -24)
  • 📁 ui/
    • 📁 components/
      • 📁 app/
        • 📁 metamask-template-renderer/
          • 📄 metamask-template-renderer.js +18 -20
          • 📄 template-renderer-context.ts +13 -0
    • 📁 pages/
      • 📁 confirmations/
        • 📁 confirmation/
          • 📁 templates/
            • 📄 approval-types.ts +30 -0
            • 📄 index.js +1 -2
        • 📁 hooks/
          • 📄 useConfirmationNavigation.test.ts +1 -1
          • 📄 useConfirmationNavigation.ts +1 -1

🫰 @MetaMask/core-platform (2 files, +31 -20)
  • 📁 ui/
    • 📁 components/
      • 📁 app/
        • 📁 metamask-template-renderer/
          • 📄 metamask-template-renderer.js +18 -20
          • 📄 template-renderer-context.ts +13 -0

🔒 @MetaMask/extension-security-team (1 files, +1 -52)
  • 📁 development/
    • 📄 circular-deps.jsonc +1 -52

👨‍🔧 @dbrans (1 files, +1 -52)
  • 📁 development/
    • 📄 circular-deps.jsonc +1 -52

👨‍🔧 @HowardBraham (1 files, +1 -52)
  • 📁 development/
    • 📄 circular-deps.jsonc +1 -52

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Mar 14, 2026

Builds ready [c5bd633]
⚡ Performance Benchmarks
👆 Interaction Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account29826638651273386
total29826638651273386
Confirm Txconfirm_tx6020599860351460346035
total6020599860351460346035
Bridge User Actionsbridge_load_page24920729436281294
bridge_load_asset_picker23521125719256257
bridge_search_token75373777514763775
total1231121512391012391239
🔌 Startup Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Standard HomeuiStartup1532128618839715711711
load1276105815348813131435
domContentLoaded1269105115108713021424
domInteractive32181702726105
firstPaint160681215131202321
backgroundConnect26724045527272301
firstReactRender19134962133
initialActions1010113
loadScripts102179612508610501182
setupStore1276381423
numNetworkReqs393181154076
Power User HomeuiStartup5250188511540217864509047
load12711106175913012951546
domContentLoaded12481095172712512611534
domInteractive37193113734105
firstPaint224751444178257336
backgroundConnect18363218667184927615342
firstReactRender2718308292634
initialActions106113
loadScripts1025886148511810501294
setupStore14590101428
numNetworkReqs1354630947138244
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2192172212220221
srpButtonToSrpForm94929629496
confirmSrpToPwForm22222302223
pwFormToMetricsScreen15151501515
metricsToWalletReadyScreen18152232222
doneButtonToHomeScreen77259610611909361061
openAccountMenuToAccountListLoaded291029062913329132913
total3906387339342239163934
Onboarding New WalletcreateWalletToSocialScreen2212182263220226
srpButtonToPwForm1131111152115115
createPwToRecoveryScreen999099
skipBackupToMetricsScreen40394214242
agreeButtonToOnboardingSuccess18171801818
doneButtonToAssetList52548357037569570
total92888698541968985
Asset DetailsassetClickToPriceChart9484106897106
total9484106897106
Solana Asset DetailsassetClickToPriceChart1114217350162173
total1114217350162173
Import Srp HomeloginToHomeScreen2304223623705223332370
openAccountMenuAfterLogin894912526103125
homeAfterImportWithNewWallet1736609275190223902751
total42062933520696450585206
Send TransactionsopenSendPageFromHome28272912929
selectTokenToSendFormLoaded32273843738
reviewTransactionToConfirmationPage1018655149335613831493
total1092715155435114401554
SwapopenSwapPageFromHome96891005100100
fetchAndDisplaySwapQuotes267926732684426812684
total278527812790427902790
🌐 Dapp Page Load Benchmarks

Current Commit: c5bd633 | Date: 3/14/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.05s (±43ms) 🟡 | historical mean value: 1.06s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 742ms (±60ms) 🟢 | historical mean value: 745ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 93ms (±127ms) 🟢 | historical mean value: 85ms ⬆️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.05s 43ms 1.02s 1.40s 1.09s 1.40s
domContentLoaded 742ms 60ms 711ms 1.29s 764ms 1.29s
firstPaint 93ms 127ms 68ms 1.36s 88ms 1.36s
firstContentfulPaint 93ms 127ms 68ms 1.36s 88ms 1.36s
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 58 Bytes (0%)
  • ui: 923.2 KiB (10.86%)
  • common: -912.16 KiB (-8.1%)

@HowardBraham
Copy link
Contributor

@rvelaz you did it! But the tests are not all passing.

@n3ps
Copy link
Contributor

n3ps commented Mar 14, 2026

Nice work @rvelaz!

Minor - maybe the names of the new files can simplified or grouped by feature? "ui/selectors/metamask-selectors-basic" and "ui/selectors/metamask-selectors-standalone" might be confusing later on

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

Labels

size-L team-extension-platform Extension Platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants