fix(earn): aggregate mUSD balance across mainnet and Linea for estimated annual bonus#28663
fix(earn): aggregate mUSD balance across mainnet and Linea for estimated annual bonus#28663Kureev wants to merge 3 commits intoMetaMask:mainfrom
Conversation
… for bonus aggregation
|
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. |
The component now reads state.engine.backgroundState.AccountsController via selectAsset (added in fa2bad4 for cross-chain mUSD balance aggregation), which crashed all 15 tests because renderWithProvider was called with no state. Pass DeepPartial<RootState> with the standard backgroundState mock.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Reviewed by Cursor Bugbot for commit 61426a4. Configure here.
| ...overrides, | ||
| }); | ||
|
|
||
| const mockInitialState: DeepPartial<RootState> = { |
There was a problem hiding this comment.
New mUSD aggregation branch is completely untested
Medium Severity
The createMockAsset helper uses address '0x8d652c6d4A8F3Db96Cd866C1a9220B1447F29898' (aglaMerkl), so isMusdToken(asset.address) returns false in every test. The new mUSD aggregation branch — which sums mainnetMusdAsset?.balance and lineaMusdAsset?.balance via two selectAsset calls — is never exercised. Every test follows the non-mUSD fallback path (parseFloat(liveBalance || asset.balance)), leaving the core behavior change of this PR completely uncovered. This violates the "Different code paths — all if/else branches" requirement from Unit Testing Guidelines.
Additional Locations (1)
Triggered by project rule: Unit Testing Guidelines
Reviewed by Cursor Bugbot for commit 61426a4. Configure here.


Description
The "Estimated annual bonus" row in the bonus card on the mUSD asset details screen (and the Cash/Money tokens full view) was being computed against a single chain's mUSD balance. mUSD bonuses are actually distributed by Merkl across both Ethereum mainnet and Linea, so users with mUSD on both chains were seeing an estimate that only reflected one of those balances depending on which screen they opened:
Worse, none of those views agreed with each other, and none of them agreed with the "Lifetime bonus claimed" line shown right below the estimate — which is sourced from the Linea Merkl Distributor contract and is already global across both chains. Same component, two different scopes.
This PR makes the estimate global so it lines up with the lifetime line and with what users actually accrue:
useSelector(selectAsset, ...)calls (one per eligible chain) are added; both run unconditionally so hook order is stable.useTokenBalance(asset)behaviour is preserved untouched.isMusdToken(asset.address)so the test-token path is fully bypassed.balancevariable —hasBalance,formattedAnnualBonus, and the CTActaLabel/ctaDisabledderivation — automatically picks up the aggregate semantics. The CTA on the Linea details page will now correctly say "accruing next bonus" for a user whose only balance is on mainnet, matching the lifetime line above it.The 3% APY is still a hardcoded display constant. Switching it to a live Merkl APR is intentionally out of scope here (the rate fluctuates weekly and the wording around "estimated" is acceptable per product), and is tracked separately.
Changelog
CHANGELOG entry: Fixed the mUSD estimated annual bonus so it reflects the user's combined mUSD balance across Ethereum mainnet and Linea instead of only the chain currently being viewed.
Related issues
Fixes: MUSD-628
Manual testing steps
Screenshots/Recordings
Before
After
Pre-merge author checklist
Pre-merge reviewer checklist
Note
Medium Risk
Changes user-visible mUSD bonus/CTA state derivation by switching the balance source to cross-chain Redux lookups, which could affect displayed bonus amounts and enable/disable states if asset selection or balances are missing/misformatted.
Overview
Fixes the mUSD “Estimated annual bonus” (and downstream CTA state) to use the user’s combined mUSD holdings on Ethereum mainnet and Linea, regardless of which chain’s asset details screen is open.
This gates the aggregation behind
isMusdToken, pulls per-chain balances viaselectAssetusingMUSD_TOKEN_ADDRESS_BY_CHAIN+CHAIN_IDS, and updates tests to render with an explicit Reduxstate(includingbackgroundState) so the new selectors can resolve assets during unit tests.Reviewed by Cursor Bugbot for commit 61426a4. Bugbot is set up for automated code reviews on this repo. Configure here.