Skip to content

Use new assets state in TransactionPayController (behind feature flag)#8163

Open
bergarces wants to merge 31 commits intomainfrom
transaction-pay-controller-new-assets-state
Open

Use new assets state in TransactionPayController (behind feature flag)#8163
bergarces wants to merge 31 commits intomainfrom
transaction-pay-controller-new-assets-state

Conversation

@bergarces
Copy link
Contributor

@bergarces bergarces commented Mar 10, 2026

Explanation

Uses the new assets controller state in TransactionPayController. With the feature flag off, it should not require any additional changes.

The messenger requires two new actions, one to determine the current version of the app for feature flag filtering, and another to fetch state from the new AssetsController.

Preview PR with the breaking changes.
Extension: MetaMask/metamask-extension#40712 (extension is several major versions behind, we are only applying breaking changes from this PR)
Mobile: MetaMask/metamask-mobile#27359

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
Changes how TransactionPayController reads token metadata, balances, and pricing by optionally switching to AssetsController:getStateForTransactionPay behind a remote feature flag, which could affect quote calculations if state shapes or flag gating are incorrect. Also introduces a breaking messenger permission change requiring consumers to allow the new AssetsController action.

Overview
Adds a new remote feature flag check (assetsUnifyState, version 1) and, when enabled, switches getTokenBalance, getTokenInfo, and getTokenFiatRate to source balances/metadata/prices from AssetsController:getStateForTransactionPay instead of calling multiple legacy controller getState actions.

Updates typing, tests, and mocks to support the new messenger action (breaking AllowedActions change), adds @metamask/assets-controller as a dependency, and wires TS project references accordingly.

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

@bergarces bergarces requested review from a team as code owners March 10, 2026 14:44
@bergarces bergarces force-pushed the transaction-pay-controller-new-assets-state branch from 1a70549 to 1e09ec5 Compare March 10, 2026 14:46
@bergarces
Copy link
Contributor Author

@metamaskbot publish-previews

@github-actions
Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/account-tree-controller": "5.0.0-preview-3b760ee09",
  "@metamask-previews/accounts-controller": "37.0.0-preview-3b760ee09",
  "@metamask-previews/address-book-controller": "7.0.1-preview-3b760ee09",
  "@metamask-previews/ai-controllers": "0.2.0-preview-3b760ee09",
  "@metamask-previews/analytics-controller": "1.0.0-preview-3b760ee09",
  "@metamask-previews/analytics-data-regulation-controller": "0.0.0-preview-3b760ee09",
  "@metamask-previews/announcement-controller": "8.0.0-preview-3b760ee09",
  "@metamask-previews/app-metadata-controller": "2.0.0-preview-3b760ee09",
  "@metamask-previews/approval-controller": "8.0.0-preview-3b760ee09",
  "@metamask-previews/assets-controller": "2.3.0-preview-3b760ee09",
  "@metamask-previews/assets-controllers": "100.2.0-preview-3b760ee09",
  "@metamask-previews/base-controller": "9.0.0-preview-3b760ee09",
  "@metamask-previews/base-data-service": "0.0.0-preview-3b760ee09",
  "@metamask-previews/bridge-controller": "69.0.0-preview-3b760ee09",
  "@metamask-previews/bridge-status-controller": "68.0.1-preview-3b760ee09",
  "@metamask-previews/build-utils": "3.0.4-preview-3b760ee09",
  "@metamask-previews/chain-agnostic-permission": "1.4.0-preview-3b760ee09",
  "@metamask-previews/claims-controller": "0.4.2-preview-3b760ee09",
  "@metamask-previews/client-controller": "1.0.0-preview-3b760ee09",
  "@metamask-previews/compliance-controller": "1.0.1-preview-3b760ee09",
  "@metamask-previews/composable-controller": "12.0.0-preview-3b760ee09",
  "@metamask-previews/config-registry-controller": "0.1.0-preview-3b760ee09",
  "@metamask-previews/connectivity-controller": "0.1.0-preview-3b760ee09",
  "@metamask-previews/controller-utils": "11.19.0-preview-3b760ee09",
  "@metamask-previews/core-backend": "6.1.0-preview-3b760ee09",
  "@metamask-previews/delegation-controller": "2.0.2-preview-3b760ee09",
  "@metamask-previews/earn-controller": "11.1.2-preview-3b760ee09",
  "@metamask-previews/eip-5792-middleware": "3.0.0-preview-3b760ee09",
  "@metamask-previews/eip-7702-internal-rpc-middleware": "0.1.0-preview-3b760ee09",
  "@metamask-previews/eip1193-permission-middleware": "1.0.3-preview-3b760ee09",
  "@metamask-previews/ens-controller": "19.0.3-preview-3b760ee09",
  "@metamask-previews/error-reporting-service": "3.0.1-preview-3b760ee09",
  "@metamask-previews/eth-block-tracker": "15.0.1-preview-3b760ee09",
  "@metamask-previews/eth-json-rpc-middleware": "23.1.0-preview-3b760ee09",
  "@metamask-previews/eth-json-rpc-provider": "6.0.0-preview-3b760ee09",
  "@metamask-previews/foundryup": "1.0.1-preview-3b760ee09",
  "@metamask-previews/gas-fee-controller": "26.0.3-preview-3b760ee09",
  "@metamask-previews/gator-permissions-controller": "2.1.0-preview-3b760ee09",
  "@metamask-previews/geolocation-controller": "0.1.1-preview-3b760ee09",
  "@metamask-previews/json-rpc-engine": "10.2.3-preview-3b760ee09",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.8-preview-3b760ee09",
  "@metamask-previews/keyring-controller": "25.1.0-preview-3b760ee09",
  "@metamask-previews/logging-controller": "7.0.1-preview-3b760ee09",
  "@metamask-previews/message-manager": "14.1.0-preview-3b760ee09",
  "@metamask-previews/messenger": "0.3.0-preview-3b760ee09",
  "@metamask-previews/multichain-account-service": "7.1.0-preview-3b760ee09",
  "@metamask-previews/multichain-api-middleware": "1.2.7-preview-3b760ee09",
  "@metamask-previews/multichain-network-controller": "3.0.5-preview-3b760ee09",
  "@metamask-previews/multichain-transactions-controller": "7.0.2-preview-3b760ee09",
  "@metamask-previews/name-controller": "9.0.0-preview-3b760ee09",
  "@metamask-previews/network-controller": "30.0.0-preview-3b760ee09",
  "@metamask-previews/network-enablement-controller": "4.2.0-preview-3b760ee09",
  "@metamask-previews/notification-services-controller": "22.0.0-preview-3b760ee09",
  "@metamask-previews/permission-controller": "12.2.0-preview-3b760ee09",
  "@metamask-previews/permission-log-controller": "5.0.0-preview-3b760ee09",
  "@metamask-previews/perps-controller": "1.0.0-preview-3b760ee09",
  "@metamask-previews/phishing-controller": "16.3.0-preview-3b760ee09",
  "@metamask-previews/polling-controller": "16.0.3-preview-3b760ee09",
  "@metamask-previews/preferences-controller": "23.0.0-preview-3b760ee09",
  "@metamask-previews/profile-metrics-controller": "3.0.2-preview-3b760ee09",
  "@metamask-previews/profile-sync-controller": "27.1.0-preview-3b760ee09",
  "@metamask-previews/ramps-controller": "10.2.0-preview-3b760ee09",
  "@metamask-previews/rate-limit-controller": "7.0.0-preview-3b760ee09",
  "@metamask-previews/remote-feature-flag-controller": "4.1.0-preview-3b760ee09",
  "@metamask-previews/sample-controllers": "4.0.3-preview-3b760ee09",
  "@metamask-previews/seedless-onboarding-controller": "8.1.0-preview-3b760ee09",
  "@metamask-previews/selected-network-controller": "26.0.3-preview-3b760ee09",
  "@metamask-previews/shield-controller": "5.0.1-preview-3b760ee09",
  "@metamask-previews/signature-controller": "39.0.5-preview-3b760ee09",
  "@metamask-previews/storage-service": "1.0.0-preview-3b760ee09",
  "@metamask-previews/subscription-controller": "6.0.0-preview-3b760ee09",
  "@metamask-previews/transaction-controller": "62.21.0-preview-3b760ee09",
  "@metamask-previews/transaction-pay-controller": "16.4.1-preview-3b760ee09",
  "@metamask-previews/user-operation-controller": "41.0.3-preview-3b760ee09"
}

@bergarces
Copy link
Contributor Author

@metamaskbot publish-previews

@github-actions
Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/account-tree-controller": "5.0.1-preview-d8831108d",
  "@metamask-previews/accounts-controller": "37.0.0-preview-d8831108d",
  "@metamask-previews/address-book-controller": "7.0.1-preview-d8831108d",
  "@metamask-previews/ai-controllers": "0.2.0-preview-d8831108d",
  "@metamask-previews/analytics-controller": "1.0.0-preview-d8831108d",
  "@metamask-previews/analytics-data-regulation-controller": "0.0.0-preview-d8831108d",
  "@metamask-previews/announcement-controller": "8.0.0-preview-d8831108d",
  "@metamask-previews/app-metadata-controller": "2.0.0-preview-d8831108d",
  "@metamask-previews/approval-controller": "8.0.0-preview-d8831108d",
  "@metamask-previews/assets-controller": "2.3.0-preview-d8831108d",
  "@metamask-previews/assets-controllers": "100.2.1-preview-d8831108d",
  "@metamask-previews/base-controller": "9.0.0-preview-d8831108d",
  "@metamask-previews/base-data-service": "0.0.0-preview-d8831108d",
  "@metamask-previews/bridge-controller": "69.0.1-preview-d8831108d",
  "@metamask-previews/bridge-status-controller": "68.0.2-preview-d8831108d",
  "@metamask-previews/build-utils": "3.0.4-preview-d8831108d",
  "@metamask-previews/chain-agnostic-permission": "1.4.0-preview-d8831108d",
  "@metamask-previews/claims-controller": "0.4.3-preview-d8831108d",
  "@metamask-previews/client-controller": "1.0.0-preview-d8831108d",
  "@metamask-previews/compliance-controller": "1.0.1-preview-d8831108d",
  "@metamask-previews/composable-controller": "12.0.0-preview-d8831108d",
  "@metamask-previews/config-registry-controller": "0.1.1-preview-d8831108d",
  "@metamask-previews/connectivity-controller": "0.1.0-preview-d8831108d",
  "@metamask-previews/controller-utils": "11.19.0-preview-d8831108d",
  "@metamask-previews/core-backend": "6.1.1-preview-d8831108d",
  "@metamask-previews/delegation-controller": "2.0.2-preview-d8831108d",
  "@metamask-previews/earn-controller": "11.1.2-preview-d8831108d",
  "@metamask-previews/eip-5792-middleware": "3.0.0-preview-d8831108d",
  "@metamask-previews/eip-7702-internal-rpc-middleware": "0.1.0-preview-d8831108d",
  "@metamask-previews/eip1193-permission-middleware": "1.0.3-preview-d8831108d",
  "@metamask-previews/ens-controller": "19.0.3-preview-d8831108d",
  "@metamask-previews/error-reporting-service": "3.0.1-preview-d8831108d",
  "@metamask-previews/eth-block-tracker": "15.0.1-preview-d8831108d",
  "@metamask-previews/eth-json-rpc-middleware": "23.1.0-preview-d8831108d",
  "@metamask-previews/eth-json-rpc-provider": "6.0.0-preview-d8831108d",
  "@metamask-previews/foundryup": "1.0.1-preview-d8831108d",
  "@metamask-previews/gas-fee-controller": "26.0.3-preview-d8831108d",
  "@metamask-previews/gator-permissions-controller": "2.1.0-preview-d8831108d",
  "@metamask-previews/geolocation-controller": "0.1.1-preview-d8831108d",
  "@metamask-previews/json-rpc-engine": "10.2.3-preview-d8831108d",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.8-preview-d8831108d",
  "@metamask-previews/keyring-controller": "25.1.0-preview-d8831108d",
  "@metamask-previews/logging-controller": "7.0.1-preview-d8831108d",
  "@metamask-previews/message-manager": "14.1.0-preview-d8831108d",
  "@metamask-previews/messenger": "0.3.0-preview-d8831108d",
  "@metamask-previews/multichain-account-service": "7.1.0-preview-d8831108d",
  "@metamask-previews/multichain-api-middleware": "1.2.7-preview-d8831108d",
  "@metamask-previews/multichain-network-controller": "3.0.5-preview-d8831108d",
  "@metamask-previews/multichain-transactions-controller": "7.0.2-preview-d8831108d",
  "@metamask-previews/name-controller": "9.0.0-preview-d8831108d",
  "@metamask-previews/network-controller": "30.0.0-preview-d8831108d",
  "@metamask-previews/network-enablement-controller": "4.2.0-preview-d8831108d",
  "@metamask-previews/notification-services-controller": "22.1.0-preview-d8831108d",
  "@metamask-previews/permission-controller": "12.2.0-preview-d8831108d",
  "@metamask-previews/permission-log-controller": "5.0.0-preview-d8831108d",
  "@metamask-previews/perps-controller": "1.0.1-preview-d8831108d",
  "@metamask-previews/phishing-controller": "16.3.0-preview-d8831108d",
  "@metamask-previews/polling-controller": "16.0.3-preview-d8831108d",
  "@metamask-previews/preferences-controller": "23.0.0-preview-d8831108d",
  "@metamask-previews/profile-metrics-controller": "3.0.3-preview-d8831108d",
  "@metamask-previews/profile-sync-controller": "28.0.0-preview-d8831108d",
  "@metamask-previews/ramps-controller": "10.2.0-preview-d8831108d",
  "@metamask-previews/rate-limit-controller": "7.0.0-preview-d8831108d",
  "@metamask-previews/remote-feature-flag-controller": "4.1.0-preview-d8831108d",
  "@metamask-previews/sample-controllers": "4.0.3-preview-d8831108d",
  "@metamask-previews/seedless-onboarding-controller": "8.1.0-preview-d8831108d",
  "@metamask-previews/selected-network-controller": "26.0.3-preview-d8831108d",
  "@metamask-previews/shield-controller": "5.0.1-preview-d8831108d",
  "@metamask-previews/signature-controller": "39.0.5-preview-d8831108d",
  "@metamask-previews/storage-service": "1.0.0-preview-d8831108d",
  "@metamask-previews/subscription-controller": "6.0.1-preview-d8831108d",
  "@metamask-previews/transaction-controller": "62.21.0-preview-d8831108d",
  "@metamask-previews/transaction-pay-controller": "16.4.1-preview-d8831108d",
  "@metamask-previews/user-operation-controller": "41.0.3-preview-d8831108d"
}

@bergarces
Copy link
Contributor Author

@metamaskbot publish-previews

@github-actions
Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/account-tree-controller": "5.0.1-preview-d8a0c2fc5",
  "@metamask-previews/accounts-controller": "37.0.0-preview-d8a0c2fc5",
  "@metamask-previews/address-book-controller": "7.0.1-preview-d8a0c2fc5",
  "@metamask-previews/ai-controllers": "0.2.0-preview-d8a0c2fc5",
  "@metamask-previews/analytics-controller": "1.0.0-preview-d8a0c2fc5",
  "@metamask-previews/analytics-data-regulation-controller": "0.0.0-preview-d8a0c2fc5",
  "@metamask-previews/announcement-controller": "8.0.0-preview-d8a0c2fc5",
  "@metamask-previews/app-metadata-controller": "2.0.0-preview-d8a0c2fc5",
  "@metamask-previews/approval-controller": "8.0.0-preview-d8a0c2fc5",
  "@metamask-previews/assets-controller": "2.3.0-preview-d8a0c2fc5",
  "@metamask-previews/assets-controllers": "100.2.1-preview-d8a0c2fc5",
  "@metamask-previews/base-controller": "9.0.0-preview-d8a0c2fc5",
  "@metamask-previews/base-data-service": "0.0.0-preview-d8a0c2fc5",
  "@metamask-previews/bridge-controller": "69.1.0-preview-d8a0c2fc5",
  "@metamask-previews/bridge-status-controller": "68.1.0-preview-d8a0c2fc5",
  "@metamask-previews/build-utils": "3.0.4-preview-d8a0c2fc5",
  "@metamask-previews/chain-agnostic-permission": "1.4.0-preview-d8a0c2fc5",
  "@metamask-previews/claims-controller": "0.4.3-preview-d8a0c2fc5",
  "@metamask-previews/client-controller": "1.0.0-preview-d8a0c2fc5",
  "@metamask-previews/compliance-controller": "1.0.1-preview-d8a0c2fc5",
  "@metamask-previews/composable-controller": "12.0.0-preview-d8a0c2fc5",
  "@metamask-previews/config-registry-controller": "0.1.1-preview-d8a0c2fc5",
  "@metamask-previews/connectivity-controller": "0.1.0-preview-d8a0c2fc5",
  "@metamask-previews/controller-utils": "11.19.0-preview-d8a0c2fc5",
  "@metamask-previews/core-backend": "6.1.1-preview-d8a0c2fc5",
  "@metamask-previews/delegation-controller": "2.0.2-preview-d8a0c2fc5",
  "@metamask-previews/earn-controller": "11.1.2-preview-d8a0c2fc5",
  "@metamask-previews/eip-5792-middleware": "3.0.0-preview-d8a0c2fc5",
  "@metamask-previews/eip-7702-internal-rpc-middleware": "0.1.0-preview-d8a0c2fc5",
  "@metamask-previews/eip1193-permission-middleware": "1.0.3-preview-d8a0c2fc5",
  "@metamask-previews/ens-controller": "19.0.3-preview-d8a0c2fc5",
  "@metamask-previews/error-reporting-service": "3.0.1-preview-d8a0c2fc5",
  "@metamask-previews/eth-block-tracker": "15.0.1-preview-d8a0c2fc5",
  "@metamask-previews/eth-json-rpc-middleware": "23.1.0-preview-d8a0c2fc5",
  "@metamask-previews/eth-json-rpc-provider": "6.0.0-preview-d8a0c2fc5",
  "@metamask-previews/foundryup": "1.0.1-preview-d8a0c2fc5",
  "@metamask-previews/gas-fee-controller": "26.0.3-preview-d8a0c2fc5",
  "@metamask-previews/gator-permissions-controller": "2.1.0-preview-d8a0c2fc5",
  "@metamask-previews/geolocation-controller": "0.1.1-preview-d8a0c2fc5",
  "@metamask-previews/json-rpc-engine": "10.2.3-preview-d8a0c2fc5",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.8-preview-d8a0c2fc5",
  "@metamask-previews/keyring-controller": "25.1.0-preview-d8a0c2fc5",
  "@metamask-previews/logging-controller": "7.0.1-preview-d8a0c2fc5",
  "@metamask-previews/message-manager": "14.1.0-preview-d8a0c2fc5",
  "@metamask-previews/messenger": "0.3.0-preview-d8a0c2fc5",
  "@metamask-previews/multichain-account-service": "7.1.0-preview-d8a0c2fc5",
  "@metamask-previews/multichain-api-middleware": "1.2.7-preview-d8a0c2fc5",
  "@metamask-previews/multichain-network-controller": "3.0.5-preview-d8a0c2fc5",
  "@metamask-previews/multichain-transactions-controller": "7.0.2-preview-d8a0c2fc5",
  "@metamask-previews/name-controller": "9.0.0-preview-d8a0c2fc5",
  "@metamask-previews/network-controller": "30.0.0-preview-d8a0c2fc5",
  "@metamask-previews/network-enablement-controller": "4.2.0-preview-d8a0c2fc5",
  "@metamask-previews/notification-services-controller": "22.1.0-preview-d8a0c2fc5",
  "@metamask-previews/permission-controller": "12.2.0-preview-d8a0c2fc5",
  "@metamask-previews/permission-log-controller": "5.0.0-preview-d8a0c2fc5",
  "@metamask-previews/perps-controller": "1.0.1-preview-d8a0c2fc5",
  "@metamask-previews/phishing-controller": "16.3.0-preview-d8a0c2fc5",
  "@metamask-previews/polling-controller": "16.0.3-preview-d8a0c2fc5",
  "@metamask-previews/preferences-controller": "23.0.0-preview-d8a0c2fc5",
  "@metamask-previews/profile-metrics-controller": "3.0.3-preview-d8a0c2fc5",
  "@metamask-previews/profile-sync-controller": "28.0.0-preview-d8a0c2fc5",
  "@metamask-previews/ramps-controller": "12.0.0-preview-d8a0c2fc5",
  "@metamask-previews/rate-limit-controller": "7.0.0-preview-d8a0c2fc5",
  "@metamask-previews/remote-feature-flag-controller": "4.1.0-preview-d8a0c2fc5",
  "@metamask-previews/sample-controllers": "4.0.3-preview-d8a0c2fc5",
  "@metamask-previews/seedless-onboarding-controller": "8.1.0-preview-d8a0c2fc5",
  "@metamask-previews/selected-network-controller": "26.0.3-preview-d8a0c2fc5",
  "@metamask-previews/shield-controller": "5.0.1-preview-d8a0c2fc5",
  "@metamask-previews/signature-controller": "39.0.5-preview-d8a0c2fc5",
  "@metamask-previews/storage-service": "1.0.0-preview-d8a0c2fc5",
  "@metamask-previews/subscription-controller": "6.0.1-preview-d8a0c2fc5",
  "@metamask-previews/transaction-controller": "62.21.0-preview-d8a0c2fc5",
  "@metamask-previews/transaction-pay-controller": "16.4.1-preview-d8a0c2fc5",
  "@metamask-previews/user-operation-controller": "41.0.3-preview-d8a0c2fc5"
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Once the feature flag is gone for good. We will come here to remove the old references to assets-controllers and remove the branching logic that the feature flag requires.

@bergarces bergarces changed the title Transaction pay controller new assets state Use new assets state in TransactionPayController (behind feature flag) Mar 11, 2026
*/
export function getAssetsUnifyStateFeature(
messenger: TransactionPayControllerMessenger,
): boolean {
Copy link
Contributor

Choose a reason for hiding this comment

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

QQ if we want to test this , what is the way to turn this to true ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Currently only controlled by remote feature flags, unsure how much work would be required if we want to force to true.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

By doing black magic cjs updates in the client.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

With that said, if that cjs change is done with a patch and directly at the feature flag controller, it can be used to test selector changes too.

salimtb
salimtb previously approved these changes Mar 11, 2026
Copy link
Contributor

@salimtb salimtb left a comment

Choose a reason for hiding this comment

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

the changes LGTM and works as expected on the local build

@bergarces bergarces dismissed stale reviews from Prithpal-Sooriya and salimtb via e2f2a16 March 12, 2026 09:11
@bergarces
Copy link
Contributor Author

@metamaskbot publish-previews

@github-actions
Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/account-tree-controller": "5.0.1-preview-6e94df150",
  "@metamask-previews/accounts-controller": "37.0.0-preview-6e94df150",
  "@metamask-previews/address-book-controller": "7.0.1-preview-6e94df150",
  "@metamask-previews/ai-controllers": "0.2.0-preview-6e94df150",
  "@metamask-previews/analytics-controller": "1.0.0-preview-6e94df150",
  "@metamask-previews/analytics-data-regulation-controller": "0.0.0-preview-6e94df150",
  "@metamask-previews/announcement-controller": "8.0.0-preview-6e94df150",
  "@metamask-previews/app-metadata-controller": "2.0.0-preview-6e94df150",
  "@metamask-previews/approval-controller": "8.0.0-preview-6e94df150",
  "@metamask-previews/assets-controller": "2.3.0-preview-6e94df150",
  "@metamask-previews/assets-controllers": "100.2.1-preview-6e94df150",
  "@metamask-previews/base-controller": "9.0.0-preview-6e94df150",
  "@metamask-previews/base-data-service": "0.0.0-preview-6e94df150",
  "@metamask-previews/bridge-controller": "69.1.0-preview-6e94df150",
  "@metamask-previews/bridge-status-controller": "68.1.0-preview-6e94df150",
  "@metamask-previews/build-utils": "3.0.4-preview-6e94df150",
  "@metamask-previews/chain-agnostic-permission": "1.4.0-preview-6e94df150",
  "@metamask-previews/claims-controller": "0.4.3-preview-6e94df150",
  "@metamask-previews/client-controller": "1.0.0-preview-6e94df150",
  "@metamask-previews/compliance-controller": "1.0.1-preview-6e94df150",
  "@metamask-previews/composable-controller": "12.0.0-preview-6e94df150",
  "@metamask-previews/config-registry-controller": "0.1.1-preview-6e94df150",
  "@metamask-previews/connectivity-controller": "0.1.0-preview-6e94df150",
  "@metamask-previews/controller-utils": "11.19.0-preview-6e94df150",
  "@metamask-previews/core-backend": "6.1.1-preview-6e94df150",
  "@metamask-previews/delegation-controller": "2.0.2-preview-6e94df150",
  "@metamask-previews/earn-controller": "11.1.2-preview-6e94df150",
  "@metamask-previews/eip-5792-middleware": "3.0.0-preview-6e94df150",
  "@metamask-previews/eip-7702-internal-rpc-middleware": "0.1.0-preview-6e94df150",
  "@metamask-previews/eip1193-permission-middleware": "1.0.3-preview-6e94df150",
  "@metamask-previews/ens-controller": "19.0.3-preview-6e94df150",
  "@metamask-previews/error-reporting-service": "3.0.1-preview-6e94df150",
  "@metamask-previews/eth-block-tracker": "15.0.1-preview-6e94df150",
  "@metamask-previews/eth-json-rpc-middleware": "23.1.0-preview-6e94df150",
  "@metamask-previews/eth-json-rpc-provider": "6.0.0-preview-6e94df150",
  "@metamask-previews/foundryup": "1.0.1-preview-6e94df150",
  "@metamask-previews/gas-fee-controller": "26.0.3-preview-6e94df150",
  "@metamask-previews/gator-permissions-controller": "2.1.0-preview-6e94df150",
  "@metamask-previews/geolocation-controller": "0.1.1-preview-6e94df150",
  "@metamask-previews/json-rpc-engine": "10.2.3-preview-6e94df150",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.8-preview-6e94df150",
  "@metamask-previews/keyring-controller": "25.1.0-preview-6e94df150",
  "@metamask-previews/logging-controller": "7.0.1-preview-6e94df150",
  "@metamask-previews/message-manager": "14.1.0-preview-6e94df150",
  "@metamask-previews/messenger": "0.3.0-preview-6e94df150",
  "@metamask-previews/multichain-account-service": "7.1.0-preview-6e94df150",
  "@metamask-previews/multichain-api-middleware": "1.2.7-preview-6e94df150",
  "@metamask-previews/multichain-network-controller": "3.0.5-preview-6e94df150",
  "@metamask-previews/multichain-transactions-controller": "7.0.2-preview-6e94df150",
  "@metamask-previews/name-controller": "9.0.0-preview-6e94df150",
  "@metamask-previews/network-controller": "30.0.0-preview-6e94df150",
  "@metamask-previews/network-enablement-controller": "4.2.0-preview-6e94df150",
  "@metamask-previews/notification-services-controller": "23.0.0-preview-6e94df150",
  "@metamask-previews/permission-controller": "12.2.0-preview-6e94df150",
  "@metamask-previews/permission-log-controller": "5.0.0-preview-6e94df150",
  "@metamask-previews/perps-controller": "1.0.1-preview-6e94df150",
  "@metamask-previews/phishing-controller": "16.3.0-preview-6e94df150",
  "@metamask-previews/polling-controller": "16.0.3-preview-6e94df150",
  "@metamask-previews/preferences-controller": "23.0.0-preview-6e94df150",
  "@metamask-previews/profile-metrics-controller": "3.0.3-preview-6e94df150",
  "@metamask-previews/profile-sync-controller": "28.0.0-preview-6e94df150",
  "@metamask-previews/ramps-controller": "12.0.0-preview-6e94df150",
  "@metamask-previews/rate-limit-controller": "7.0.0-preview-6e94df150",
  "@metamask-previews/remote-feature-flag-controller": "4.1.0-preview-6e94df150",
  "@metamask-previews/sample-controllers": "4.0.3-preview-6e94df150",
  "@metamask-previews/seedless-onboarding-controller": "8.1.0-preview-6e94df150",
  "@metamask-previews/selected-network-controller": "26.0.3-preview-6e94df150",
  "@metamask-previews/shield-controller": "5.0.1-preview-6e94df150",
  "@metamask-previews/signature-controller": "39.0.5-preview-6e94df150",
  "@metamask-previews/storage-service": "1.0.0-preview-6e94df150",
  "@metamask-previews/subscription-controller": "6.0.1-preview-6e94df150",
  "@metamask-previews/transaction-controller": "62.21.0-preview-6e94df150",
  "@metamask-previews/transaction-pay-controller": "16.4.1-preview-6e94df150",
  "@metamask-previews/user-operation-controller": "41.0.3-preview-6e94df150"
}

* @param minRequiredVersion - The minimum required version.
* @returns True if the app version satisfies the minimum required version, false otherwise.
*/
function hasMinimumRequiredVersion(
Copy link
Member

Choose a reason for hiding this comment

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

If this is a new feature flag, can this not be achieved by the version support in RemoteFeatureFlagController, so you just add a versions property to the root of the feature flag value in LaunchDarkly?

#7277

Copy link
Contributor Author

@bergarces bergarces Mar 12, 2026

Choose a reason for hiding this comment

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

I'll look into this. I'm all for letting feature flag controller handle the version logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. It's now using the built-in versioning.

* @param messenger - Controller messenger.
* @returns True if the assets unify state feature is enabled, false otherwise.
*/
export function getAssetsUnifyStateFeature(
Copy link
Member

@matthewwalsh0 matthewwalsh0 Mar 12, 2026

Choose a reason for hiding this comment

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

Why do we need to pivot on a feature flag at this point?

Could we not test the new controller for a time with standard client flows, and refactor this in one go when stable?

I'm naturally concerned given the risk to key in-development flows like MUSD, Perps, and Predict.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We cannot migrate in one go. There is a very complex network of selectors using other selectors that depend on our state, and we want to be able to work in manageable PR sizes.

What we have done so far is create a root selector for every single legacy piece of state and make it return the old state if the flag is off, and the new state in the shape of the old if the flag is on. We have hunted every single reference to legacy stated and replaced it with those selectors (in extension). We are now doing the same for the two controllers that fetch from those controller states as well.

Once that is done, we can safely turn the feature flag on in dev for QA to test. Once we are confident there are no regressions we can then start turning it on in other environments.

Not only that, but before we turn it on in dev we need to ensure all fixtures and tests that use legacy state also have the new controller state, otherwise those tests will fail.

This would have been very difficult to achieve in one PR without feature flags.

let getAccountsByChainId;
if (assetsUnifyStateFeatureEnabled) {
const assetsControllerState = messenger.call(
'AssetsController:getStateForTransactionPay',
Copy link
Member

@matthewwalsh0 matthewwalsh0 Mar 12, 2026

Choose a reason for hiding this comment

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

Why are we coupling actions to other controllers?

Would we not just want a single standard state model for consistency, that we then expose for all callers?

Does it not defeat the benefit of a clean new controller for asset state, if we then add complexity through alternate formats of the same data?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We could return AssetsController state, but then we would also have to add dependencies here to AccountsController (actually not that one as they are deprecating it, but I'm not even sure what they want us to use nowadays), as the AssetsController state stores balances based on the accountId, not the account address (so that it is consistent for both evm and non-evm).

Since the functions here seem to be evm-specific and use the account address, that means we would have to do a fetch and a lookup here from the address to the accountId so that we can access the new state.

So that's why we have favoured a thin layer that does all the transformations at our end and delivers them in the same shape as they are now so that the same logic can be reused. Easier to review and less risks of introducing a lot of new logic in an already pretty huge controller migration.

Copy link
Member

@matthewwalsh0 matthewwalsh0 Mar 12, 2026

Choose a reason for hiding this comment

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

I agree that does sound far more complex, if we'd have to correlate balances and accounts in here.

But maybe you could make that "view" still generic and decoupled with a name such as getStateEvm, getStateLegacy, or getStateByAddress so other controllers with only EVM or address usage requirements could benefit also?

It's no impact to us if you're happy to maintain it, just wanted to clarify the intent 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we had a lot of controllers that depended on it that should have been the approach, but there were only two (Bridge, which is already done and TransactionPay), so we had actions tailored to them directly. We are happy to maintain it like this.

Part of the intent is also to discourage the use of those actions in new code, as it'd be best to use the new state as it is.

With client selectors, since they are used everywhere, we have just generic ones for each piece of state, which we plan to mark as deprecated as soon as the feature flag is on and stable.

| AccountTrackerControllerState['accountsByChainId']
| undefined =>
messenger.call('AccountTrackerController:getState')?.accountsByChainId;
}
Copy link
Member

Choose a reason for hiding this comment

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

To clarify, this should be negligible though as just a synchronous state read?

* @param account - Address of the account.
* @returns The token balance as a BigNumber.
*/
export function getAllTokenBalances(
Copy link
Member

@matthewwalsh0 matthewwalsh0 Mar 12, 2026

Choose a reason for hiding this comment

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

Harmless to remove if not used, but TokenBalancesController:getState should be negligible in performance cost as it's not asynchronous, nor is there any logic associated with it, so it's just an object read but indirected through the messenger callbacks?

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 1 potential issue.

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

@bergarces
Copy link
Contributor Author

@metamaskbot publish-previews

@github-actions
Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/account-tree-controller": "5.0.1-preview-1f5463f7b",
  "@metamask-previews/accounts-controller": "37.0.0-preview-1f5463f7b",
  "@metamask-previews/address-book-controller": "7.0.1-preview-1f5463f7b",
  "@metamask-previews/ai-controllers": "0.3.0-preview-1f5463f7b",
  "@metamask-previews/analytics-controller": "1.0.0-preview-1f5463f7b",
  "@metamask-previews/analytics-data-regulation-controller": "0.0.0-preview-1f5463f7b",
  "@metamask-previews/announcement-controller": "8.0.0-preview-1f5463f7b",
  "@metamask-previews/app-metadata-controller": "2.0.0-preview-1f5463f7b",
  "@metamask-previews/approval-controller": "8.0.0-preview-1f5463f7b",
  "@metamask-previews/assets-controller": "2.3.0-preview-1f5463f7b",
  "@metamask-previews/assets-controllers": "100.2.1-preview-1f5463f7b",
  "@metamask-previews/base-controller": "9.0.0-preview-1f5463f7b",
  "@metamask-previews/base-data-service": "0.0.0-preview-1f5463f7b",
  "@metamask-previews/bridge-controller": "69.1.0-preview-1f5463f7b",
  "@metamask-previews/bridge-status-controller": "68.1.0-preview-1f5463f7b",
  "@metamask-previews/build-utils": "3.0.4-preview-1f5463f7b",
  "@metamask-previews/chain-agnostic-permission": "1.4.0-preview-1f5463f7b",
  "@metamask-previews/claims-controller": "0.4.3-preview-1f5463f7b",
  "@metamask-previews/client-controller": "1.0.0-preview-1f5463f7b",
  "@metamask-previews/compliance-controller": "1.0.1-preview-1f5463f7b",
  "@metamask-previews/composable-controller": "12.0.0-preview-1f5463f7b",
  "@metamask-previews/config-registry-controller": "0.1.1-preview-1f5463f7b",
  "@metamask-previews/connectivity-controller": "0.1.0-preview-1f5463f7b",
  "@metamask-previews/controller-utils": "11.19.0-preview-1f5463f7b",
  "@metamask-previews/core-backend": "6.1.1-preview-1f5463f7b",
  "@metamask-previews/delegation-controller": "2.0.2-preview-1f5463f7b",
  "@metamask-previews/earn-controller": "11.1.2-preview-1f5463f7b",
  "@metamask-previews/eip-5792-middleware": "3.0.0-preview-1f5463f7b",
  "@metamask-previews/eip-7702-internal-rpc-middleware": "0.1.0-preview-1f5463f7b",
  "@metamask-previews/eip1193-permission-middleware": "1.0.3-preview-1f5463f7b",
  "@metamask-previews/ens-controller": "19.0.3-preview-1f5463f7b",
  "@metamask-previews/error-reporting-service": "3.0.1-preview-1f5463f7b",
  "@metamask-previews/eth-block-tracker": "15.0.1-preview-1f5463f7b",
  "@metamask-previews/eth-json-rpc-middleware": "23.1.0-preview-1f5463f7b",
  "@metamask-previews/eth-json-rpc-provider": "6.0.0-preview-1f5463f7b",
  "@metamask-previews/foundryup": "1.0.1-preview-1f5463f7b",
  "@metamask-previews/gas-fee-controller": "26.0.3-preview-1f5463f7b",
  "@metamask-previews/gator-permissions-controller": "2.1.0-preview-1f5463f7b",
  "@metamask-previews/geolocation-controller": "0.1.1-preview-1f5463f7b",
  "@metamask-previews/json-rpc-engine": "10.2.3-preview-1f5463f7b",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.8-preview-1f5463f7b",
  "@metamask-previews/keyring-controller": "25.1.0-preview-1f5463f7b",
  "@metamask-previews/logging-controller": "7.0.1-preview-1f5463f7b",
  "@metamask-previews/message-manager": "14.1.0-preview-1f5463f7b",
  "@metamask-previews/messenger": "0.3.0-preview-1f5463f7b",
  "@metamask-previews/multichain-account-service": "7.1.0-preview-1f5463f7b",
  "@metamask-previews/multichain-api-middleware": "1.2.7-preview-1f5463f7b",
  "@metamask-previews/multichain-network-controller": "3.0.5-preview-1f5463f7b",
  "@metamask-previews/multichain-transactions-controller": "7.0.2-preview-1f5463f7b",
  "@metamask-previews/name-controller": "9.0.0-preview-1f5463f7b",
  "@metamask-previews/network-controller": "30.0.0-preview-1f5463f7b",
  "@metamask-previews/network-enablement-controller": "4.2.0-preview-1f5463f7b",
  "@metamask-previews/notification-services-controller": "23.0.0-preview-1f5463f7b",
  "@metamask-previews/permission-controller": "12.2.0-preview-1f5463f7b",
  "@metamask-previews/permission-log-controller": "5.0.0-preview-1f5463f7b",
  "@metamask-previews/perps-controller": "1.0.1-preview-1f5463f7b",
  "@metamask-previews/phishing-controller": "16.3.0-preview-1f5463f7b",
  "@metamask-previews/polling-controller": "16.0.3-preview-1f5463f7b",
  "@metamask-previews/preferences-controller": "23.0.0-preview-1f5463f7b",
  "@metamask-previews/profile-metrics-controller": "3.0.3-preview-1f5463f7b",
  "@metamask-previews/profile-sync-controller": "28.0.0-preview-1f5463f7b",
  "@metamask-previews/ramps-controller": "12.0.0-preview-1f5463f7b",
  "@metamask-previews/rate-limit-controller": "7.0.0-preview-1f5463f7b",
  "@metamask-previews/remote-feature-flag-controller": "4.1.0-preview-1f5463f7b",
  "@metamask-previews/sample-controllers": "4.0.3-preview-1f5463f7b",
  "@metamask-previews/seedless-onboarding-controller": "8.1.0-preview-1f5463f7b",
  "@metamask-previews/selected-network-controller": "26.0.3-preview-1f5463f7b",
  "@metamask-previews/shield-controller": "5.0.1-preview-1f5463f7b",
  "@metamask-previews/signature-controller": "39.0.5-preview-1f5463f7b",
  "@metamask-previews/storage-service": "1.0.0-preview-1f5463f7b",
  "@metamask-previews/subscription-controller": "6.0.1-preview-1f5463f7b",
  "@metamask-previews/transaction-controller": "62.21.0-preview-1f5463f7b",
  "@metamask-previews/transaction-pay-controller": "16.5.0-preview-1f5463f7b",
  "@metamask-previews/user-operation-controller": "41.0.3-preview-1f5463f7b"
}

@bergarces bergarces requested a review from matthewwalsh0 March 12, 2026 14:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants