Skip to content

Commit f871763

Browse files
authored
fix: Implement nonEVM zero balance check to send flow before onAmountInput (#38043)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **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? --> This PR adds zero balance check before `onAmountInput` RPC call to nonEVM send flow amount validations. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/38043?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: ## **Related issues** Fixes: MetaMask/metamask-mobile#22812 ## **Manual testing steps** 1. Go to send flow 2. Don't have any Tron / SOL / BTC 3. Try sending it but see "insufficient balance" error ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <img width="416" height="627" alt="Screenshot 2025-11-20 at 14 14 31" src="https://github.com/user-attachments/assets/a570e0b5-6d26-4b38-975c-fc289dc563c0" /> ## **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] > Adds an early zero-balance check for non-EVM send amount validation and covers it with a new test. > > - **Validation (send)**: > - Non-EVM: Add early zero-balance check in `useAmountValidation` (`validateNonEvmAmount`) returning `insufficientFundsSend` before snap RPC; include `rawBalanceNumeric` in hook deps. > - **Tests**: > - Add test ensuring non-EVM accounts with zero balance surface "Insufficient funds". > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit cd0a0e6. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent d1385fb commit f871763

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

ui/pages/confirmations/hooks/send/useAmountValidation.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,4 +415,25 @@ describe('useAmountValidation', () => {
415415
const error = await result.current.validateNonEvmAmountAsync();
416416
expect(error).toEqual(undefined);
417417
});
418+
419+
it('returns error when non-EVM account has zero balance', async () => {
420+
jest.spyOn(SendContext, 'useSendContext').mockReturnValue({
421+
asset: {
422+
isNative: true,
423+
rawBalance: '0x0',
424+
decimals: 18,
425+
},
426+
chainId: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
427+
from: MOCK_ADDRESS_1,
428+
value: '1',
429+
} as unknown as SendContext.SendContextType);
430+
431+
const { result } = renderHookWithProvider(
432+
() => useAmountValidation(),
433+
mockState,
434+
);
435+
await waitFor(() =>
436+
expect(result.current.amountError).toEqual('Insufficient funds'),
437+
);
438+
});
418439
});

ui/pages/confirmations/hooks/send/useAmountValidation.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ export const useAmountValidation = () => {
3737
return undefined;
3838
}
3939

40+
if (rawBalanceNumeric.isZero()) {
41+
return t('insufficientFundsSend');
42+
}
43+
4044
try {
4145
const result = (await validateAmountWithSnap(
4246
value || '0',
@@ -49,7 +53,7 @@ export const useAmountValidation = () => {
4953
} catch (error) {
5054
return t('invalidValue');
5155
}
52-
}, [t, value, validateAmountWithSnap, isNonEvmSendType]);
56+
}, [t, value, validateAmountWithSnap, isNonEvmSendType, rawBalanceNumeric]);
5357

5458
const validateAmountAsync = useCallback(async () => {
5559
if (!value) {

0 commit comments

Comments
 (0)