Skip to content

Conversation

@runway-github
Copy link
Contributor

@runway-github runway-github bot commented Nov 24, 2025

Description

Open in GitHub Codespaces

Changelog

CHANGELOG entry: fix missing native token balances in wallet balance

Related issues

Fixes: #38114

Manual testing steps

Onboard or existing user with AccountsAPI enabled

  1. Go to a network with native + erc tokens
  2. Notice aggregated wallet balance - it should have both native + erc
    tokens aggregated together for the balance.

Screenshots/Recordings

Before

After

https://www.loom.com/share/aeccc8e3cef4479da0e9d44fc5ebf4fa

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the
    app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described
    in the ticket it closes and includes the necessary testing evidence such
    as recordings and or screenshots.

Note

Patches assets-controllers to lower-case account keys in TokenBalancesController balance updates and wires the Yarn patch into the build.

  • Dependencies:
    • Apply Yarn patch to @metamask/assets-controllers@89.0.1 via package.json and yarn.lock.
  • Assets Controllers:
    • Update dist/TokenBalancesController.{cjs,mjs} to normalize account to lower-case when reading/updating d.tokenBalances, adjusting lookups and writes accordingly.

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

a2fe8c4

…oller to resolve missing balance state (#38126)

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/38126?quickstart=1)

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: fix missing native token balances in wallet balance

## **Related issues**

Fixes: #38114

## **Manual testing steps**

Onboard or existing user with AccountsAPI enabled
1. Go to a network with native + erc tokens
2. Notice aggregated wallet balance - it should have both native + erc
tokens aggregated together for the balance.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

https://www.loom.com/share/aeccc8e3cef4479da0e9d44fc5ebf4fa

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Patches `TokenBalancesController` to use lowercase account keys when
reading/writing `tokenBalances`, and wires the patch via a Yarn patched
dependency for `@metamask/assets-controllers@89.0.1`.
> 
> - **Assets Controllers Patch**:
> - Normalize `account` to lowercase in `TokenBalancesController`
(`dist/TokenBalancesController.{cjs,mjs}`) when checking and setting
`d.tokenBalances[account][chainId][tokenAddress]`.
> - **Build/Deps**:
> - Apply Yarn patch for `@metamask/assets-controllers@89.0.1` via
`package.json` and update lockfile to reference the patched package.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d4370d9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@github-actions
Copy link
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.

@metamaskbot metamaskbot added the team-bots Bot team (for MetaMask Bot, Runway Bot, etc.) label Nov 24, 2025
// Only update if the balance has actually changed
if (currentBalance !== newBalance) {
- ((_c = ((_a = d.tokenBalances)[_b = account] ?? (_a[_b] = {})))[chainId] ?? (_c[chainId] = {}))[tokenAddress] = newBalance;
+ ((_b = ((_a = d.tokenBalances)[lowerCaseAccount] ?? (_a[lowerCaseAccount] = {})))[chainId] ?? (_b[chainId] = {}))[tokenAddress] = newBalance;
Copy link

Choose a reason for hiding this comment

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

Bug: Case mismatch between stored and accessed account addresses

The patch stores token balances using lowercase account addresses via account.toLowerCase(), but consuming code accesses tokenBalances using selectedAccount.address directly without lowercasing. Since Ethereum addresses from AccountsController can be checksummed (mixed case per EIP-55), this creates a case-sensitivity mismatch. When the account address is checksummed, lookups like tokenBalances[selectedAccount.address] will fail to find balances stored under tokenBalances[selectedAccount.address.toLowerCase()], causing missing balance data in the UI.

Additional Locations (1)

Fix in Cursor Fix in Web

@metamaskbot
Copy link
Collaborator

Builds ready [5d6cd9f]
UI Startup Metrics (1220 ± 99 ms)
PlatformBuildTypePageMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
ChromeBrowserifyStandard HomeuiStartup1220107115329912711424
load103588713088711061204
domContentLoaded102887112938810981196
domInteractive241489182174
firstPaint51589130940910281183
backgroundConnect21519532216218242
firstReactRender28196483245
getState3316115123750
initialActions104112
loadScripts823663107486889974
setupStore1152441220
numNetworkReqs1257620572
BrowserifyPower User HomeuiStartup18481543257918119482202
load98387017281519721407
domContentLoaded96986517081499471396
domInteractive33151673228133
firstPaint5248817234059191435
backgroundConnect22020125911224242
firstReactRender79391391992111
getState16712725724177219
initialActions103112
loadScripts76666714921477511185
setupStore19104482335
numNetworkReqs1406830352181263
WebpackStandard HomeuiStartup834744124180862998
load62557393271624817
domContentLoaded62056892770621811
domInteractive2614134232290
firstPaint24691818172238614
backgroundConnect1263171528
firstReactRender29205863336
getState3014102123647
initialActions103112
loadScripts61756691768618800
setupStore1272941418
numNetworkReqs1257219569
WebpackPower User HomeuiStartup14091130207615315191626
load6675821263112664938
domContentLoaded6575771220110654932
domInteractive35172303530131
firstPaint268921236218250912
backgroundConnect1474551622
firstReactRender81461491589100
getState14912425018159180
initialActions103011
loadScripts6545751211108652922
setupStore19752102339
numNetworkReqs1476631358186307
FirefoxBrowserifyStandard HomeuiStartup12861097169313013431597
load107993312618711381256
domContentLoaded107793312618711371256
domInteractive65312474385134
firstPaint------
backgroundConnect4021159234388
firstReactRender23184952234
getState126153171022
initialActions102022
loadScripts105591712428411071225
setupStore126119141027
numNetworkReqs1156816662
BrowserifyPower User HomeuiStartup24331952324227526352931
load1132971180215611341479
domContentLoaded1132971180215611331479
domInteractive12232671105113382
firstPaint------
backgroundConnect1102862384115280
firstReactRender80331492292122
getState24956858204331692
initialActions3120237
loadScripts1092933176914610921425
setupStore14911809198113647
numNetworkReqs90532124088195
WebpackStandard HomeuiStartup14121250184712114731673
load1206106714819412631386
domContentLoaded1206106614819412631386
domInteractive60262353882138
firstPaint------
backgroundConnect3820110164173
firstReactRender27206972935
getState1167191128
initialActions102012
loadScripts1183105314578912401353
setupStore12575111037
numNetworkReqs1157116661
WebpackPower User HomeuiStartup26552102327228529003147
load13851128191919915451806
domContentLoaded13851128191919915441806
domInteractive12928645147107571
firstPaint------
backgroundConnect983344958123198
firstReactRender78401592091117
getState26345849225364781
initialActions505610330
loadScripts13511110188319614981787
setupStore99575413991426
numNetworkReqs87522113799162
📊 Page Load Benchmark Results

Current Commit: 5d6cd9f | Date: 11/24/2025

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.04s (±36ms) 🟡 | historical mean value: 1.04s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 721ms (±34ms) 🟢 | historical mean value: 722ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 76ms (±11ms) 🟢 | historical mean value: 78ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.04s 36ms 1.01s 1.30s 1.07s 1.30s
domContentLoaded 721ms 34ms 700ms 975ms 744ms 975ms
firstPaint 76ms 11ms 60ms 164ms 88ms 164ms
firstContentfulPaint 76ms 11ms 60ms 164ms 88ms 164ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms

@gauthierpetetin
Copy link
Contributor

Not needed as included in stable-sync PR: #38183

@gauthierpetetin gauthierpetetin changed the title release(runway): cherry-pick fix: cp-13.10.1 cp-13.11.0 patch TokenBalancesController to resolve missing balance state release(runway): cherry-pick fix: cp-13.11.0 patch TokenBalancesController to resolve missing balance state Nov 24, 2025
@github-actions github-actions bot locked and limited conversation to collaborators Nov 24, 2025
@HowardBraham HowardBraham deleted the runway-cherry-pick-13.11.0-1763989501 branch December 15, 2025 19:38
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

team-bots Bot team (for MetaMask Bot, Runway Bot, etc.)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants