-
-
Notifications
You must be signed in to change notification settings - Fork 267
feat(assets-controller): first version of AssetsController #7685
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
71bafa0 to
1970164
Compare
0b59481 to
b233e63
Compare
f6b72f5 to
bba023a
Compare
bba023a to
c5056a4
Compare
c5056a4 to
8622b38
Compare
8622b38 to
e7c0346
Compare
e7c0346 to
163ec47
Compare
- Add AssetsController with data source architecture - Add AbstractDataSource base class for data sources - Add AccountsApiDataSource, BackendWebsocketDataSource, PriceDataSource, RpcDataSource, SnapDataSource, TokenDataSource - Add DetectionMiddleware for token detection - Update token-selectors in assets-controllers
163ec47 to
aae01b4
Compare
There was a problem hiding this 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.
| displayName, | ||
|
|
||
| // An object that configures minimum threshold enforcement for coverage results | ||
| // TODO: Increase thresholds as more tests are added |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let me create a task for this todo here
|
|
||
| // ============================================================================ | ||
| // ABSTRACT DATA SOURCE | ||
| // ============================================================================ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need this comments , usually we just add js doc , we ca clean later
## Explanation **Current state:** The `RpcDataSource` was using manual `setInterval` for polling balance updates and token detection. This approach had several limitations: - Polling logic was tightly coupled within `RpcDataSource`, making it harder to test and maintain - Balance fetching and token detection shared the same polling mechanism despite having different optimal intervals (30s vs 3 minutes) - The polling intervals were not configurable from the initialization layer **Solution:** This PR refactors the polling architecture by delegating polling responsibilities to the individual services: 1. **`BalanceFetcher` and `TokenDetector` now extend `StaticIntervalPollingControllerOnly`** - Each service manages its own polling lifecycle with independent intervals, enabling fine-grained control over polling behavior. 2. **`RpcDataSource` simplified to an orchestrator** - Instead of managing polling directly, `RpcDataSource` now: - Starts/stops polling through `subscribe`/`unsubscribe` by calling the services' `startPolling`/`stopPollingByPollingToken` methods - Receives updates via callbacks (`setOnBalanceUpdate`, `setOnDetectionUpdate`) - Manages polling tokens for proper cleanup 3. **Configurable polling intervals** - Added `RpcDataSourceConfig` type to `initDataSources.ts` allowing consumers to configure: - `balanceInterval` (default: 30s) - `detectionInterval` (default: 180s / 3 min) - `tokenDetectionEnabled` (default: false) - `timeout` (default: 10s) 4. **Improved test coverage** - All modified files now have near 100% test coverage using the `withController` pattern for consistent test setup and teardown. ## References - Related to #7683 (TokenDetector service) - Related to #7684 (BalanceFetcher service) - Builds on #7685 (AssetsController rewrite) ## Checklist - [x] I've updated the test suite for new or updated code as appropriate - [x] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate - [x] 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] > Modernizes asset polling and configuration across the assets controller. > > - **RpcDataSource**: Reworked as an orchestrator; delegates polling to services, adds `caipChainIdToHex`, multicall provider getter/cache, improved active-chain handling, and updates `assetsMiddleware` behavior > - **Services**: `BalanceFetcher` and `TokenDetector` now extend `StaticIntervalPollingControllerOnly`; expose start/stop polling, interval getters/setters, and update callbacks to `AssetsController` > - **Configuration**: Adds `RpcDataSourceConfig` in `initDataSources` to set `balanceInterval`, `detectionInterval`, `tokenDetectionEnabled`, and `timeout`; messengers wired for `AssetsController`/`TokenList`/`NetworkEnablement` state access > - **Tests**: Large new test suites for `RpcDataSource`, `BalanceFetcher`, and `initDataSources` covering subscriptions, callbacks, error paths, and provider caching > - **Meta**: Updates changelog; adds dependencies (`@metamask/polling-controller`, controller/network utils) > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 4186208. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## Explanation This PR adds comprehensive unit tests for the new `@metamask/assets-controller` package to ensure code quality and maintainability. **Current state:** The assets-controller package was recently introduced with a middleware-based architecture for unified asset management across all blockchain networks. However, test coverage was limited, leaving critical code paths untested. **Changes in this PR:** - Added unit tests for all data sources: - `AccountsApiDataSource` (18 tests, includes timer cleanup fix using `.unref()` to prevent Jest worker process hanging) - `BackendWebsocketDataSource` (19 tests) - `PriceDataSource` (29 tests) - `TokenDataSource` (20 tests) - `SnapDataSource` (47 tests) - Added unit tests for `DetectionMiddleware` (13 tests, 100% coverage) - Expanded unit tests for `AssetsController` (42 tests, coverage increased from 33% to 81%) **Test architecture patterns used:** - `setupController` / `withController` helper functions for consistent test setup - Proper messenger mocking with `MOCK_ANY_NAMESPACE` - Test cleanup to prevent resource leaks - `it.each` for parameterized tests where applicable - Flat test structure avoiding deeply nested describe blocks ## References - Related to #7685 (AssetsController middleware architecture) - Related to #7587 (Initial assets-controller release) ## Checklist - [x] I've updated the test suite for new or updated code as appropriate - [x] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate - [x] 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] > Significantly increases test coverage and validates core behaviors across the new middleware-based assets stack. > > - Add extensive unit tests for `AssetsController`, `DetectionMiddleware`, and data sources: `AbstractDataSource`, `AccountsApiDataSource`, `BackendWebsocketDataSource`, `PriceDataSource`, `RpcDataSource`, and `SnapDataSource` > - Cover subscriptions, middleware chaining, lifecycle/events (app/keyring/network), WebSocket handling, pricing polls, and snap-based balances > - Update `RpcDataSource` to import `BalanceFetcher`, `MulticallClient`, and `TokenDetector` from `evm-rpc-services` (was `rpc-datasource`) > - Update `CHANGELOG.md` to note test additions > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 9b08b0a. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Explanation
Current State
The current asset management in MetaMask is fragmented across multiple controllers with different patterns for EVM vs non-EVM chains. Each chain type (Ethereum, Solana, Bitcoin, Tron) has separate logic paths, making it difficult to maintain consistency and add new chain support.
Solution
This PR introduces a complete rewrite of the
AssetsControllerwith a middleware architecture for unified asset management across all blockchain networks (EVM and non-EVM). The new architecture provides:BackendWebsocketDataSource- Real-time push (highest priority)AccountsApiDataSource- HTTP polling fallbackSnapDataSource- Solana/Bitcoin/Tron via SnapsRpcDataSource- Direct RPC queries (lowest priority)Architecture
New Files
src/AssetsController.tssrc/types.tssrc/README.mdsrc/data-sources/AbstractDataSource.tssrc/data-sources/BackendWebsocketDataSource.tssrc/data-sources/AccountsApiDataSource.tssrc/data-sources/SnapDataSource.tssrc/data-sources/RpcDataSource.tssrc/data-sources/DetectionMiddleware.tssrc/data-sources/TokenDataSource.tssrc/data-sources/PriceDataSource.tssrc/data-sources/initDataSources.tsState Structure
Published Events
References
Checklist
[ ] I've updated the test suite for new or updated code as appropriate
[x] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
[x] 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
Implements a unified, middleware-based
AssetsControllerwith pluggable data sources and lifecycle-aware subscriptions for multi-chain asset management.src/AssetsController.tswith request/response middleware (fetch stack and event stack), Messenger-integrated actions/events, state (assetsMetadata,assetsBalance,customAssets), ID normalization, and app/keyring lifecycle handlingBackendWebsocketDataSource(real-time),AccountsApiDataSource(HTTP),RpcDataSource(RPC), andPriceDataSource(spot price polling); chain assignment/prioritization and subscription management includedgetAssets,getAssetsBalance,getAssetMetadata,getAssetsPrice,addCustomAsset/removeCustomAsset/getCustomAssets; publishesbalanceChanged,priceChanged,assetsDetectedsrc/README.md) and tests (AssetsController.test.ts); updates deps and lowers Jest coverage thresholds for initial iterationWritten by Cursor Bugbot for commit aae01b4. This will update automatically on new commits. Configure here.