Skip to content

feat: (TokenBalancesController) add batching around update balance requests#8246

Open
Prithpal-Sooriya wants to merge 6 commits intomainfrom
feat/add-batching-around-update-balance-requests
Open

feat: (TokenBalancesController) add batching around update balance requests#8246
Prithpal-Sooriya wants to merge 6 commits intomainfrom
feat/add-batching-around-update-balance-requests

Conversation

@Prithpal-Sooriya
Copy link
Contributor

@Prithpal-Sooriya Prithpal-Sooriya commented Mar 19, 2026

Explanation

We have many things (events, interactions) invoking balance update requests. Since the balance update requests are pretty complicated, this potentially also opens up race conditions and causes flickering in the UI (see this conversation)

This adds some batching and aggregate logic to minimise the number of requests to process.

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
Introduces debounced batching for updateBalances, changing timing/ordering of balance refreshes and option-merging semantics, which could affect UI freshness and downstream callers that rely on immediate updates.

Overview
TokenBalancesController now coalesces rapid updateBalances calls via a new debounced batching layer (UPDATE_BALANCES_BATCH_MS) so multiple requests within a short window flush as a single balance fetch.

Adds UpdateBalancesOptions plus mergeUpdateBalancesOptions to merge queued calls (union chainIds/tokenAddresses, OR queryAllAccounts), and routes polling through the non-batched execution path (#executeUpdateBalances) while public updateBalances uses the batcher.

Introduces a reusable createBatchedHandler utility (with unit tests) and updates controller tests to account for async batching using a new waitFor helper; changelog updated to document the batching behavior.

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

We have many things (events, interactions) invoking balance update requests. This adds some batching and aggregate logic to minimise the number of requests to process.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Similar to react-testing-library, a waitFor test util to allow us to wait for assertions to complete.
This is much cleaner compared to the "promise flushing" and random timeouts added in the TokenBalancesController.test.ts test spec.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Generic batch handler creator.
Potential to reuse this on other controller methods that get called frequently and cannot use a debounce.

Copy link
Contributor Author

@Prithpal-Sooriya Prithpal-Sooriya Mar 19, 2026

Choose a reason for hiding this comment

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

Huuuuuuuge test spec update.

  1. Added tests around new changes
  2. Updated test specs to not use fake timers + promise flushing, most tests now use real timers and "waitFor", only some specific tests use fake timers (such as interval polling)

…calls

Added functionality to the TokenBalancesController to batch rapid updateBalances requests, coalescing multiple calls into a single processed request. This enhancement reduces redundant balance fetches and improves performance. Updated changelog to reflect this new feature.
@Prithpal-Sooriya Prithpal-Sooriya marked this pull request as ready for review March 19, 2026 12:56
@Prithpal-Sooriya Prithpal-Sooriya requested review from a team as code owners March 19, 2026 12:56
@Prithpal-Sooriya
Copy link
Contributor Author

@metamaskbot publish-preview

@github-actions
Copy link
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@5.0.1-preview-f163c70ab
@metamask-previews/accounts-controller@37.0.0-preview-f163c70ab
@metamask-previews/address-book-controller@7.1.0-preview-f163c70ab
@metamask-previews/ai-controllers@0.4.0-preview-f163c70ab
@metamask-previews/analytics-controller@1.0.0-preview-f163c70ab
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-f163c70ab
@metamask-previews/announcement-controller@8.0.0-preview-f163c70ab
@metamask-previews/app-metadata-controller@2.0.0-preview-f163c70ab
@metamask-previews/approval-controller@9.0.0-preview-f163c70ab
@metamask-previews/assets-controller@3.0.0-preview-f163c70ab
@metamask-previews/assets-controllers@101.0.1-preview-f163c70ab
@metamask-previews/base-controller@9.0.0-preview-f163c70ab
@metamask-previews/base-data-service@0.0.0-preview-f163c70ab
@metamask-previews/bridge-controller@69.1.1-preview-f163c70ab
@metamask-previews/bridge-status-controller@69.0.0-preview-f163c70ab
@metamask-previews/build-utils@3.0.4-preview-f163c70ab
@metamask-previews/chain-agnostic-permission@1.4.0-preview-f163c70ab
@metamask-previews/claims-controller@0.4.3-preview-f163c70ab
@metamask-previews/client-controller@1.0.0-preview-f163c70ab
@metamask-previews/compliance-controller@1.0.1-preview-f163c70ab
@metamask-previews/composable-controller@12.0.0-preview-f163c70ab
@metamask-previews/config-registry-controller@0.1.1-preview-f163c70ab
@metamask-previews/connectivity-controller@0.1.0-preview-f163c70ab
@metamask-previews/controller-utils@11.19.0-preview-f163c70ab
@metamask-previews/core-backend@6.2.0-preview-f163c70ab
@metamask-previews/delegation-controller@2.0.2-preview-f163c70ab
@metamask-previews/earn-controller@11.1.2-preview-f163c70ab
@metamask-previews/eip-5792-middleware@3.0.1-preview-f163c70ab
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.0-preview-f163c70ab
@metamask-previews/eip1193-permission-middleware@1.0.3-preview-f163c70ab
@metamask-previews/ens-controller@19.1.0-preview-f163c70ab
@metamask-previews/error-reporting-service@3.0.1-preview-f163c70ab
@metamask-previews/eth-block-tracker@15.0.1-preview-f163c70ab
@metamask-previews/eth-json-rpc-middleware@23.1.0-preview-f163c70ab
@metamask-previews/eth-json-rpc-provider@6.0.0-preview-f163c70ab
@metamask-previews/foundryup@1.0.1-preview-f163c70ab
@metamask-previews/gas-fee-controller@26.1.0-preview-f163c70ab
@metamask-previews/gator-permissions-controller@2.1.1-preview-f163c70ab
@metamask-previews/geolocation-controller@0.1.1-preview-f163c70ab
@metamask-previews/json-rpc-engine@10.2.3-preview-f163c70ab
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-f163c70ab
@metamask-previews/keyring-controller@25.1.0-preview-f163c70ab
@metamask-previews/logging-controller@8.0.0-preview-f163c70ab
@metamask-previews/message-manager@14.1.0-preview-f163c70ab
@metamask-previews/messenger@0.3.0-preview-f163c70ab
@metamask-previews/multichain-account-service@7.1.0-preview-f163c70ab
@metamask-previews/multichain-api-middleware@1.2.7-preview-f163c70ab
@metamask-previews/multichain-network-controller@3.0.5-preview-f163c70ab
@metamask-previews/multichain-transactions-controller@7.0.2-preview-f163c70ab
@metamask-previews/name-controller@9.1.0-preview-f163c70ab
@metamask-previews/network-controller@30.0.0-preview-f163c70ab
@metamask-previews/network-enablement-controller@5.0.0-preview-f163c70ab
@metamask-previews/notification-services-controller@23.0.0-preview-f163c70ab
@metamask-previews/permission-controller@12.2.1-preview-f163c70ab
@metamask-previews/permission-log-controller@5.0.0-preview-f163c70ab
@metamask-previews/perps-controller@1.3.0-preview-f163c70ab
@metamask-previews/phishing-controller@17.0.0-preview-f163c70ab
@metamask-previews/polling-controller@16.0.3-preview-f163c70ab
@metamask-previews/preferences-controller@23.0.0-preview-f163c70ab
@metamask-previews/profile-metrics-controller@3.1.1-preview-f163c70ab
@metamask-previews/profile-sync-controller@28.0.0-preview-f163c70ab
@metamask-previews/ramps-controller@12.0.0-preview-f163c70ab
@metamask-previews/rate-limit-controller@7.0.0-preview-f163c70ab
@metamask-previews/react-data-query@0.0.0-preview-f163c70ab
@metamask-previews/remote-feature-flag-controller@4.1.0-preview-f163c70ab
@metamask-previews/sample-controllers@4.0.3-preview-f163c70ab
@metamask-previews/seedless-onboarding-controller@9.0.0-preview-f163c70ab
@metamask-previews/selected-network-controller@26.0.3-preview-f163c70ab
@metamask-previews/shield-controller@5.0.2-preview-f163c70ab
@metamask-previews/signature-controller@39.1.0-preview-f163c70ab
@metamask-previews/storage-service@1.0.0-preview-f163c70ab
@metamask-previews/subscription-controller@6.0.2-preview-f163c70ab
@metamask-previews/transaction-controller@63.0.0-preview-f163c70ab
@metamask-previews/transaction-pay-controller@17.1.0-preview-f163c70ab
@metamask-previews/user-operation-controller@41.1.0-preview-f163c70ab

Refined the batching logic in TokenBalancesController to handle empty buffers more effectively. The updated implementation now initializes the merge with the first buffer element when available, ensuring that the batching process remains robust and efficient.

Additionally, enhanced error handling in the waitFor utility to provide more informative error messages upon timeout, improving debugging capabilities.
…ing to return Promises

Modified the batching logic in TokenBalancesController to ensure that the #batchedUpdateBalances method returns a Promise, allowing for better error handling and synchronization. Updated the createBatchedHandler utility to return Promises for capture calls, enabling callers to await the completion of batch flushes and handle errors appropriately. Enhanced tests to verify the new asynchronous behavior and error propagation.
…cription logic and enhance error handling

Reintroduced the subscription logic in the TokenBalancesController to ensure proper updates during balance changes. Additionally, improved the createBatchedHandler utility to handle errors more effectively by ensuring that all promises are settled correctly, enhancing the robustness of the batching mechanism. Updated tests to validate the new error handling behavior and ensure all scenarios are covered.
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.

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.

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.

1 participant