Skip to content

Commit cb0a747

Browse files
AxelGeswachunei
andauthored
fix(ramps): use asset chainId to fetch correct token balance in useBalance cp-7.61.0 (MetaMask#23719)
## **Description** The `useBalance` hook in the Ramp Aggregator was using `selectContractBalances`, which returns token balances only for the **currently selected network**. This caused incorrect behavior. **Solution:** Changed the hook to use `selectContractBalancesPerChainId` and access the correct chain's balances using the `asset.chainId` parameter that is already passed to the hook. ## **Changelog** CHANGELOG entry: Fixed incorrect token balance check in Ramp when selecting tokens from non-active networks ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TRAM-2875?atlOrigin=eyJpIjoiNDE5YjQ4YjQ3NGRkNGUzMGFkODUxNjI0M2QxMzlkNjUiLCJwIjoiaiJ9 Fixes MetaMask#23722 ## **Manual testing steps** ```gherkin Feature: Ramp token balance check Scenario: user sells USDC on Arbitrum while connected to different network Given user has 40 USDC on Arbitrum And user's wallet is connected to Mainnet When user navigates to Sell flow in Ramp And user selects USDC on Arbitrum as the asset to sell And user enters an amount less than their balance (e.g. 22) Then the "this amount is higher than your balance" error should NOT appear And the balance should correctly reflect the Arbitrum USDC balance ``` ## **Screenshots/Recordings** ### **Before** `balanceBN` was `null` for tokens on non-active networks, causing false insufficient balance errors. (quick amount selector isn't shown because amount is not being detected) <img width="300" alt="image" src="https://github.com/user-attachments/assets/6c45f7b0-f5d6-4dd5-a413-350a3fa2bf3f" /> ### **After** `balanceBN` correctly reflects the token balance on the asset's chain regardless of the currently active network. <img width="300" alt="image" src="https://github.com/user-attachments/assets/987d5eba-e430-4a1a-b678-850a40259373" /> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/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-mobile/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] > Compute token balances from the asset’s chain using per-chain balances, fixing incorrect balances when the active network differs. > > - **Ramp Aggregator `useBalance`** (`app/components/UI/Ramp/Aggregator/hooks/useBalance.ts`): > - Switch to `selectContractBalancesPerChainId` and index by the asset’s `chainId` (via `toHex`) to retrieve correct per-chain ERC-20 balances. > - Update balance computations (`balance`, `balanceBN`, `balanceFiat`) to use chain-scoped balances and existing exchange rates. > - Ensure native balance lookup uses `accountsByChainId[hexChainId]` guard for the asset’s chain. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 2fa36f1. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Pedro Pablo Aste Kompen <wachunei@gmail.com>
1 parent 488a864 commit cb0a747

1 file changed

Lines changed: 9 additions & 6 deletions

File tree

app/components/UI/Ramp/Aggregator/hooks/useBalance.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
selectCurrentCurrency,
77
} from '../../../../../selectors/currencyRateController';
88
import { selectSelectedInternalAccountFormattedAddress } from '../../../../../selectors/accountsController';
9-
import { selectContractBalances } from '../../../../../selectors/tokenBalancesController';
9+
import { selectContractBalancesPerChainId } from '../../../../../selectors/tokenBalancesController';
1010
import { selectContractExchangeRates } from '../../../../../selectors/tokenRatesController';
1111
import { safeToChecksumAddress } from '../../../../../util/address';
1212
import {
@@ -52,7 +52,7 @@ export default function useBalance(asset?: Asset) {
5252
const conversionRate = useSelector(selectConversionRate);
5353
const currentCurrency = useSelector(selectCurrentCurrency);
5454
const tokenExchangeRates = useSelector(selectContractExchangeRates);
55-
const balances = useSelector(selectContractBalances);
55+
const balancesPerChainId = useSelector(selectContractBalancesPerChainId);
5656

5757
if (!asset || (!asset.address && !asset.assetId) || !selectedAddress) {
5858
return defaultReturn;
@@ -99,10 +99,13 @@ export default function useBalance(asset?: Asset) {
9999
} else if (asset.address) {
100100
const assetAddress = safeToChecksumAddress(asset.address);
101101
const exchangeRate = tokenExchangeRates?.[assetAddress as Hex]?.price;
102+
// Use the asset's chainId to get balances for the correct chain
103+
const hexChainId = asset.chainId ? toHex(asset.chainId) : undefined;
104+
const chainBalances = hexChainId ? balancesPerChainId[hexChainId] : {};
102105
balance =
103-
assetAddress && assetAddress in balances
106+
assetAddress && chainBalances && assetAddress in chainBalances
104107
? renderFromTokenMinimalUnit(
105-
balances[assetAddress],
108+
chainBalances[assetAddress],
106109
asset.decimals ?? 18,
107110
)
108111
: 0;
@@ -113,8 +116,8 @@ export default function useBalance(asset?: Asset) {
113116
currentCurrency,
114117
);
115118
balanceBN =
116-
assetAddress && assetAddress in balances
117-
? hexToBN(balances[assetAddress])
119+
assetAddress && chainBalances && assetAddress in chainBalances
120+
? hexToBN(chainBalances[assetAddress])
118121
: null;
119122
}
120123

0 commit comments

Comments
 (0)