Skip to content

feat(assets-controller): batch API requests and split pipeline for faster asset loading#8383

Merged
salimtb merged 8 commits intomainfrom
feat/assets-controller-pipeline-batching-optimization
Apr 7, 2026
Merged

feat(assets-controller): batch API requests and split pipeline for faster asset loading#8383
salimtb merged 8 commits intomainfrom
feat/assets-controller-pipeline-batching-optimization

Conversation

@salimtb
Copy link
Copy Markdown
Contributor

@salimtb salimtb commented Apr 6, 2026

  • Split getAssets pipeline into a fast awaited path (AccountsApi + StakedBalance) and a parallel background path (Snap + RPC) to reduce perceived latency on unlock and onboarding
  • Batch PriceDataSource and TokenDataSource API requests in chunks of 50 using reduceInBatchesSerially to avoid DynamoDB 100-item batch limit errors
  • Filter synthetic slip44:NUMBER-* staking-position asset IDs from Price API calls
  • Filter EVM ERC-20 tokens by occurrences >= 3 (treat missing occurrences as 0)
  • Fix ESLint "in" operator violation in PriceDataSource isValidMarketData`

Explanation

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 core asset-loading flow to run RPC/Snap in a fire-and-forget background pipeline and alters token/price enrichment behavior (especially in RPC-only mode), which could affect state consistency and displayed balances/prices if regressions occur.

Overview
Speeds up perceived asset loading by splitting AssetsController.getAssets into an awaited fast pipeline (Accounts API + staked balance → detection → token/price) and a background Snap/RPC pipeline that merges results into state asynchronously.

Tightens RPC-only behavior: when basic functionality is disabled, token/price enrichment is skipped in both getAssets and handleAssetsUpdate, and setSelectedCurrency no longer triggers a price refresh.

Reduces backend/API failure risk by batching PriceDataSource spot-price requests and TokenDataSource metadata requests into chunks of 50, and by filtering synthetic slip44:<number>-* staking-position asset IDs out of Price API calls; token spam filtering is updated to require occurrences >= 3 for EVM ERC-20s (missing treated as 0) while non-EVM token assets continue to use Blockaid. Tests/changelog are updated accordingly.

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

…ster asset loading

- Split getAssets pipeline into a fast awaited path (AccountsApi + StakedBalance)
  and a parallel background path (Snap + RPC) to reduce perceived latency on
  unlock and onboarding
- Batch PriceDataSource and TokenDataSource API requests in chunks of 50 using
  reduceInBatchesSerially to avoid DynamoDB 100-item batch limit errors
- Filter synthetic slip44:NUMBER-* staking-position asset IDs from Price API calls
- Filter EVM ERC-20 tokens by occurrences >= 3 (treat missing occurrences as 0)
- Fix ESLint "in" operator violation in PriceDataSource isValidMarketData`
@salimtb salimtb changed the title feat(assets-controller): batch API requests and split pipeline for fa… feat(assets-controller): batch API requests and split pipeline for faster asset loading Apr 6, 2026
@salimtb salimtb marked this pull request as ready for review April 7, 2026 08:26
@salimtb salimtb requested review from a team as code owners April 7, 2026 08:26
Copy link
Copy Markdown

@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 2 potential issues.

There are 3 total unresolved issues (including 1 from previous review).

Fix All in Cursor

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

Reviewed by Cursor Bugbot for commit 32d17b5. Configure here.

// number (e.g. slip44:195-ready-for-withdrawal, slip44:195-in-lock-period,
// slip44:195-staking-rewards, slip44:195-staked-for-…) is a MetaMask-internal
// synthetic asset that has no market price.
/\/slip44:\d+-/u,
Copy link
Copy Markdown
Contributor

@bergarces bergarces Apr 7, 2026

Choose a reason for hiding this comment

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

If we want to match and exclude anything that has a non-numeric value after /slip44:, we could use /\/slip44:.*\D/u.

That will cover anything that has a non-numeric value in any position.

Are there any assets that have non-numeric values and we do not want to exclude? Because otherwise, we no longer need the Tron exceptions.

Suggested change
/\/slip44:\d+-/u,
/\/slip44:.*\D/u,

//
// Both the fast and background pipelines use 'merge' mode because neither
// alone represents the full set of data sources. Using 'full' in either
// would wipe balances from the sources handled by the other pipeline.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Are we going to need a full wipe at some point? Or is that something we can live without?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i think we can live without , the old controllers was following this logic


if (!this.#isBasicFunctionality()) {
return;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good catch.

Not for this PR, but maybe we should move the basic functionality check to the data source fetching itself, that way we don't need to keep guessing if something can or can't be done at this level.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

agreed yes

@salimtb salimtb added this pull request to the merge queue Apr 7, 2026
Merged via the queue into main with commit e690731 Apr 7, 2026
341 checks passed
@salimtb salimtb deleted the feat/assets-controller-pipeline-batching-optimization branch April 7, 2026 10:27
micaelae pushed a commit that referenced this pull request Apr 7, 2026
…ster asset loading (#8383)

- Split getAssets pipeline into a fast awaited path (AccountsApi +
StakedBalance) and a parallel background path (Snap + RPC) to reduce
perceived latency on unlock and onboarding
- Batch PriceDataSource and TokenDataSource API requests in chunks of 50
using reduceInBatchesSerially to avoid DynamoDB 100-item batch limit
errors
- Filter synthetic slip44:NUMBER-* staking-position asset IDs from Price
API calls
- Filter EVM ERC-20 tokens by occurrences >= 3 (treat missing
occurrences as 0)
- Fix ESLint "in" operator violation in PriceDataSource
isValidMarketData`

## Explanation

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## 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](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes core asset-loading flow to run RPC/Snap in a fire-and-forget
background pipeline and alters token/price enrichment behavior
(especially in RPC-only mode), which could affect state consistency and
displayed balances/prices if regressions occur.
> 
> **Overview**
> **Speeds up perceived asset loading** by splitting
`AssetsController.getAssets` into an awaited *fast* pipeline (Accounts
API + staked balance → detection → token/price) and a *background*
Snap/RPC pipeline that merges results into state asynchronously.
> 
> **Tightens RPC-only behavior**: when basic functionality is disabled,
token/price enrichment is skipped in both `getAssets` and
`handleAssetsUpdate`, and `setSelectedCurrency` no longer triggers a
price refresh.
> 
> **Reduces backend/API failure risk** by batching `PriceDataSource`
spot-price requests and `TokenDataSource` metadata requests into chunks
of 50, and by filtering synthetic `slip44:<number>-*` staking-position
asset IDs out of Price API calls; token spam filtering is updated to
require `occurrences >= 3` for EVM ERC-20s (missing treated as 0) while
non-EVM `token` assets continue to use Blockaid. Tests/changelog are
updated accordingly.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
32d17b5. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
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.

2 participants