Skip to content

Commit e4feac8

Browse files
authored
feat: use aggregate3 or accountAPI to fetch balances (#6232)
You're absolutely right! Let me update that section to be more precise about the fallback strategy: ## Explanation ### Current State and Problem Previously, the TokenBalancesController fetched token balances using individual RPC calls for each token-account combination. This approach was inefficient and slow, especially for users with multiple accounts and many tokens across different networks. Each balance check required a separate `balanceOf` call, leading to: - High number of RPC requests - Slower balance updates - Potential rate limiting issues - Poor user experience during balance refreshes ### Solution This PR implements a **two-tier balance fetching strategy** with intelligent fallback: 1. **Primary**: **Accounts API** - Uses MetaMask's external API service for supported networks (faster, more efficient) 2. **Fallback**: **RPC with Aggregate3** - Uses Multicall3's `aggregate3` function for efficient batch RPC calls when: - The chain is not supported by the Accounts API - The Accounts API service is unavailable or fails - Any other API-related errors occur ### Key Technical Changes #### Smart Fallback Architecture - `TokenBalancesController` first attempts to fetch balances via the **Accounts API** for supported networks - For chains **not supported by the API** or when the **API fails**, it automatically falls back to **RPC calls using `aggregate3`** - Successfully processed chains are removed from subsequent fetchers, ensuring no duplicate work - Each fetcher only processes chains it can handle #### Accounts API Integration - Leverages MetaMask's backend infrastructure for faster balance retrieval - Supports a curated list of networks (`SUPPORTED_NETWORKS_ACCOUNTS_API_V4`) - Handles multi-account and multi-chain requests efficiently #### Aggregate3 Fallback Implementation When the Accounts API can't handle certain networks, the system uses Multicall3's `aggregate3` function to: - Batch multiple `balanceOf` calls into a single RPC request - Handle both ERC20 token balances and native token balances - Support staking contract balance queries - Process results efficiently with individual failure handling #### Performance Optimizations - **API-first strategy**: Fastest possible retrieval for supported networks - **Efficient RPC fallback**: Up to 300 calls per batch to avoid gas/size limits when API isn't available - **Serial batch execution**: Processes batches sequentially to prevent overwhelming the RPC - **Smart chain routing**: Each chain uses the most appropriate fetching method - **Selective updates**: Only updates state when balance changes are detected ### Technical Details The fallback mechanism ensures comprehensive network coverage: - **Supported networks** → Accounts API (fastest) - **Unsupported networks or API failures** → RPC with `aggregate3` (still much faster than individual calls) The `aggregate3` function provides significant improvements over individual RPC calls: - Each call can fail individually without affecting others (`allowFailure: true`) - Supports different call types (ERC20, native, staking) in the same batch - Automatically falls back to individual calls if multicall fails entirely ### Impact - **Optimal performance**: Uses fastest available method for each network - **Complete network coverage**: No network is left without efficient balance fetching - **Reduced RPC calls**: For non-API networks, reduces from N individual calls to 1 call per batch of up to 300 operations - **Better reliability**: Multiple fetching strategies ensure balance data is always available - **Graceful degradation**: Seamless fallback when services are unavailable ## References Addresses performance issues with token balance fetching by implementing Accounts API integration with aggregate3 RPC fallback for comprehensive and efficient balance retrieval across all networks. ## 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 - [ ] I've communicated my changes to consumers by [updating changelogs for packages I've changed](https://github.com/MetaMask/core/tree/main/docs/contributing.md#updating-changelogs), highlighting breaking changes as necessary - [ ] I've prepared draft pull requests for clients and consumer packages to resolve any breaking changes
1 parent a30342d commit e4feac8

21 files changed

+6170
-701
lines changed

eslint-warning-thresholds.json

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,14 @@
5353
"import-x/order": 1
5454
},
5555
"packages/assets-controllers/src/Standards/ERC20Standard.test.ts": {
56-
"prettier/prettier": 1
56+
"jest/no-commented-out-tests": 1
57+
},
58+
"packages/assets-controllers/src/Standards/NftStandards/ERC1155/ERC1155Standard.test.ts": {
59+
"import-x/no-named-as-default-member": 1
5760
},
5861
"packages/assets-controllers/src/Standards/NftStandards/ERC721/ERC721Standard.ts": {
5962
"prettier/prettier": 1
6063
},
61-
"packages/assets-controllers/src/TokenBalancesController.ts": {
62-
"@typescript-eslint/prefer-readonly": 4,
63-
"jsdoc/check-tag-names": 4,
64-
"jsdoc/tag-lines": 11
65-
},
6664
"packages/assets-controllers/src/TokenDetectionController.test.ts": {
6765
"import-x/namespace": 11,
6866
"jsdoc/tag-lines": 1
@@ -102,15 +100,9 @@
102100
"packages/assets-controllers/src/assetsUtil.ts": {
103101
"jsdoc/tag-lines": 2
104102
},
105-
"packages/assets-controllers/src/multi-chain-accounts-service/multi-chain-accounts.ts": {
106-
"jsdoc/tag-lines": 2
107-
},
108103
"packages/assets-controllers/src/multicall.test.ts": {
109104
"@typescript-eslint/prefer-promise-reject-errors": 2
110105
},
111-
"packages/assets-controllers/src/multicall.ts": {
112-
"jsdoc/tag-lines": 1
113-
},
114106
"packages/assets-controllers/src/token-prices-service/codefi-v2.test.ts": {
115107
"jsdoc/require-returns": 1
116108
},

packages/assets-controllers/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818
### Changed
1919

2020
- Bump `@metamask/account-tree-controller` from `^0.7.0` to `^0.9.0` ([#6310](https://github.com/MetaMask/core/pull/6310))
21+
- **BREAKING**: Improved `TokenBalancesController` performance with two-tier balance fetching strategy ([#6232](https://github.com/MetaMask/core/pull/6232))
22+
- Implements Accounts API as primary fetching method for supported networks (faster, more efficient)
23+
- Falls back to RPC calls using Multicall3's `aggregate3` for unsupported networks or API failures
24+
- Significantly reduces RPC calls from N individual requests to batched calls of up to 300 operations
25+
- Provides comprehensive network coverage with graceful degradation when services are unavailable
2126
- Bump `@metamask/base-controller` from `^8.0.1` to `^8.1.0` ([#6284](https://github.com/MetaMask/core/pull/6284))
2227
- Bump `@metamask/controller-utils` from `^11.11.0` to `^11.12.0` ([#6303](https://github.com/MetaMask/core/pull/6303))
2328

0 commit comments

Comments
 (0)