Conversation
Contributor
|
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
Contributor
Builds ready [c9c6e7a]
⚡ Performance Benchmarks
🌐 Dapp Page Load BenchmarksCurrent Commit: 📄 Localhost MetaMask Test DappSamples: 100 Summary
📈 Detailed Results
Bundle size diffs [🚨 Warning! Bundle size has increased!]
|
4 tasks
github-merge-queue bot
pushed a commit
to MetaMask/core
that referenced
this pull request
Mar 16, 2026
…balance on import (#8202) ## Explanation **Current state / problem:** UI PR: MetaMask/metamask-extension#40919 When a user imports a custom ERC20 token via `wallet_watchAsset` (e.g. a self-deployed token on Sepolia that is not indexed by the MetaMask tokens API), `addCustomAsset` is called with `pendingMetadata` containing the correct `symbol`, `name`, `decimals`, and `image`. This metadata is immediately persisted into `assetsInfo` so the UI can render the token without waiting for a backend fetch. However, `addCustomAsset` then calls `getAssets()` with `forceUpdate: true`, which triggers `#updateState`. The tokens API has no knowledge of this custom token and returns `{ symbol: "", name: "", decimals: 18 }`. The unconditional `metadata[key] = value` assignment in `#updateState` blindly overwrites the correct `pendingMetadata` with this empty API response. This causes three cascading issues: 1. **Wrong balance** — the raw on-chain balance is divided by `10^18` instead of the token's real decimals (e.g. `10^4`), producing a value like `1e-13` instead of `10` 2. **BigInt crash** — the scientific-notation balance string crashes `BigInt` parsing downstream: `SyntaxError: Cannot convert 1e-13 to a BigInt` 3. **Missing display data** — the token renders with no symbol and no name A second issue compounds this: `RpcDataSource.fetch()` was passing an empty `[]` for token addresses to `fetchBalancesForTokens`, meaning only the native token balance (e.g. ETH) was fetched via RPC. Custom ERC20 tokens in `request.customAssets` were completely ignored, so the on-chain ERC20 balance was never actually fetched during the initial import flow. **Solution:** Two fixes: 1. **Preserve `pendingMetadata` in `#updateState`** (`AssetsController.ts`): Before overwriting an entry in `assetsInfo`, check whether the incoming API response has both empty `symbol` and empty `name`. This is a reliable signal that the data source has no real knowledge of the token. When that condition is true and richer metadata already exists in state (from `pendingMetadata`), the existing `symbol`, `name`, `decimals`, and `image` are preserved while still merging any supplementary fields the API may provide (e.g. `aggregators`, `occurrences`). When the API returns real data (non-empty symbol or name), behaviour is unchanged. 2. **Forward custom asset addresses to `RpcDataSource.fetch()`** (`RpcDataSource.ts`): During a fetch, the method now extracts ERC20 token addresses from `request.customAssets` that match the chain currently being fetched, and passes them to `fetchBalancesForTokens`. This ensures the multicall includes the custom token so its on-chain balance is retrieved immediately after import. ## References * Fixes the `wallet_watchAsset` / custom token import bug reported internally * Related to the `pendingTokens` flow in the MetaMask extension ## 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] > **Medium Risk** > Changes how `AssetsController` merges incoming token metadata and how `RpcDataSource` computes/requests ERC20 balances, which can affect displayed balances and requires extra RPC calls (including a new `decimals()` call fallback). > > **Overview** > Fixes custom token import flow so user-provided metadata isn’t overwritten by empty token-API responses: `AssetsController.#updateState` now preserves existing `symbol`/`name` (and keeps richer `decimals`/`image`) when the incoming metadata has both fields empty. > > Updates `RpcDataSource` to immediately fetch balances for imported custom ERC20s by extracting matching-chain ERC20 addresses from `request.customAssets` and passing them into `BalanceFetcher.fetchBalancesForTokens`; balance handling now normalizes CAIP-19 IDs, allows async balance-update callbacks, and adds an RPC `decimals()` fallback when decimals are missing. Tests and changelog are updated accordingly. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 9e298fe. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Contributor
Builds ready [c56e2e5]
⚡ Performance Benchmarks
🌐 Dapp Page Load BenchmarksCurrent Commit: 📄 Localhost MetaMask Test DappSamples: 100 Summary
📈 Detailed Results
Bundle size diffs
|
bergarces
reviewed
Mar 17, 2026
bergarces
reviewed
Mar 17, 2026
Prithpal-Sooriya
previously approved these changes
Mar 17, 2026
|
Contributor
Builds ready [a4e8638]
⚡ Performance Benchmarks
🌐 Dapp Page Load BenchmarksCurrent Commit: 📄 Localhost MetaMask Test DappSamples: 100 Summary
📈 Detailed Results
Bundle size diffs
|
Prithpal-Sooriya
approved these changes
Mar 17, 2026
bergarces
approved these changes
Mar 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Description
refresh token list immediately after import when assetsUnifyState is enabled
Changelog
CHANGELOG entry: refresh token list immediately after import when assetsUnifyState is enabled
Related issues
Fixes:
Manual testing steps
Screenshots/Recordings
Before
After
after02.mov
after03.mov
Pre-merge author checklist
Pre-merge reviewer checklist
Note
Medium Risk
Changes selector logic that shapes EVM token balances and currency rates when
assetsUnifyStateis enabled, which can affect asset display across networks. Risk is moderate due to added fallback behavior and placeholder balances, but scope is limited to derived state and is covered by new tests.Overview
When
assetsUnifyStateis enabled,getTokenBalancesControllerTokenBalancesnow mergescustomAssetsinto the derived token balances by inserting zero-balance placeholders for custom EVM tokens that have metadata but no entry inassetsBalanceyet, without overriding real balances and while skipping non-EVM custom assets.getCurrencyRateControllerCurrencyRatesnow falls back to any chain-nativeslip44:*price key for the same EVM chain when the directassetsInfonative-asset ID lookup is missing, improving native rate derivation for chains where pricing uses a chain-specific slip44.Tests were updated/added to cover the new placeholder-balance behavior and guardrails (no overwrite, ignore non-EVM).
Written by Cursor Bugbot for commit a4e8638. This will update automatically on new commits. Configure here.