Skip to content

Commit 996034d

Browse files
authored
fix: For batch transactions sum total of gas needed for all transactions in the batched should be check to show insufficient funds error (#31555)
## **Description** For batch transactions sum total of gas needed for all transactions in the batched should be check to show insufficient funds error ## **Related issues** Fixes: MetaMask/MetaMask-planning#4571 ## **Manual testing steps** 1. Submit a batched transaction with a simple send whose value is more than your balance 2. You should see insufficient fund alert ## **Screenshots/Recordings** TODO ## **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.
1 parent bb1b8d9 commit 996034d

File tree

3 files changed

+64
-21
lines changed

3 files changed

+64
-21
lines changed

ui/pages/confirmations/hooks/alerts/transactions/useInsufficientBalanceAlerts.test.ts

+52-19
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ import { ApprovalType } from '@metamask/controller-utils';
22
import {
33
TransactionMeta,
44
TransactionParams,
5+
TransactionType,
56
} from '@metamask/transaction-controller';
67
import { createMockInternalAccount } from '../../../../../../test/jest/mocks';
78
import { getMockConfirmState } from '../../../../../../test/data/confirmations/helper';
89
import { genUnapprovedContractInteractionConfirmation } from '../../../../../../test/data/confirmations/contract-interaction';
910
import { renderHookWithConfirmContextProvider } from '../../../../../../test/lib/confirmations/render-helpers';
10-
import { Severity } from '../../../../../helpers/constants/design-system';
11-
import { RowAlertKey } from '../../../../../components/app/confirm/info/row/constants';
1211
import { useInsufficientBalanceAlerts } from './useInsufficientBalanceAlerts';
1312

1413
const TRANSACTION_ID_MOCK = '123-456';
@@ -27,6 +26,24 @@ const TRANSACTION_MOCK = {
2726
} as TransactionParams,
2827
} as TransactionMeta;
2928

29+
const ALERT = [
30+
{
31+
actions: [
32+
{
33+
key: 'buy',
34+
label: 'Buy ETH',
35+
},
36+
],
37+
field: 'estimatedFee',
38+
isBlocking: true,
39+
key: 'insufficientBalance',
40+
message:
41+
'You do not have enough ETH in your account to pay for network fees.',
42+
reason: 'Insufficient funds',
43+
severity: 'danger',
44+
},
45+
];
46+
3047
function buildState({
3148
balance,
3249
currentConfirmation,
@@ -113,6 +130,38 @@ describe('useInsufficientBalanceAlerts', () => {
113130
).toEqual([]);
114131
});
115132

133+
it('returns alerts for batch transaction if account has balance less than total of the transactions in the batch', () => {
134+
const BATCH_TRANSACTION_MOCK = {
135+
...TRANSACTION_MOCK,
136+
nestedTransactions: [
137+
{
138+
to: '0x1234567890123456789012345678901234567890',
139+
value: '0x3B9ACA00',
140+
type: TransactionType.simpleSend,
141+
},
142+
{
143+
to: '0x1234567890123456789012345678901234567891',
144+
value: '0x1DCD6500',
145+
type: TransactionType.simpleSend,
146+
},
147+
],
148+
};
149+
expect(
150+
runHook({
151+
balance: 210000000002,
152+
currentConfirmation: TRANSACTION_MOCK as Partial<TransactionMeta>,
153+
transaction: TRANSACTION_MOCK as Partial<TransactionMeta>,
154+
}),
155+
).toEqual([]);
156+
expect(
157+
runHook({
158+
balance: 210000000002,
159+
currentConfirmation: BATCH_TRANSACTION_MOCK as Partial<TransactionMeta>,
160+
transaction: BATCH_TRANSACTION_MOCK as Partial<TransactionMeta>,
161+
}),
162+
).toEqual(ALERT);
163+
});
164+
116165
it('returns no alerts if account has balance greater than gas fee plus value', () => {
117166
expect(
118167
runHook({
@@ -140,22 +189,6 @@ describe('useInsufficientBalanceAlerts', () => {
140189
transaction: TRANSACTION_MOCK,
141190
});
142191

143-
expect(alerts).toEqual([
144-
{
145-
actions: [
146-
{
147-
key: 'buy',
148-
label: 'Buy ETH',
149-
},
150-
],
151-
field: RowAlertKey.EstimatedFee,
152-
isBlocking: true,
153-
key: 'insufficientBalance',
154-
message:
155-
'You do not have enough ETH in your account to pay for network fees.',
156-
reason: 'Insufficient funds',
157-
severity: Severity.Danger,
158-
},
159-
]);
192+
expect(alerts).toEqual(ALERT);
160193
});
161194
});

ui/pages/confirmations/hooks/alerts/transactions/useInsufficientBalanceAlerts.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Hex } from '@metamask/utils';
12
import { useMemo } from 'react';
23
import { useSelector } from 'react-redux';
34

@@ -17,12 +18,18 @@ import {
1718
RowAlertKey,
1819
} from '../../../../../components/app/confirm/info/row/constants';
1920
import { useConfirmContext } from '../../../context/confirm';
21+
import { sumHexes } from '../../../../../../shared/modules/conversion.utils';
2022

2123
export function useInsufficientBalanceAlerts(): Alert[] {
2224
const t = useI18nContext();
2325
const { currentConfirmation } = useConfirmContext<TransactionMeta>();
2426
const { id: transactionId, selectedGasFeeToken } = currentConfirmation ?? {};
2527

28+
const batchTransactionValues =
29+
currentConfirmation?.nestedTransactions?.map(
30+
(trxn) => (trxn.value as Hex) ?? 0x0,
31+
) ?? [];
32+
2633
const balance = useSelector((state) =>
2734
selectTransactionAvailableBalance(state, transactionId),
2835
);
@@ -31,14 +38,16 @@ export function useInsufficientBalanceAlerts(): Alert[] {
3138
selectTransactionValue(state, transactionId),
3239
);
3340

41+
const totalValue = sumHexes(value, ...batchTransactionValues);
42+
3443
const { hexMaximumTransactionFee } = useSelector((state) =>
3544
selectTransactionFeeById(state, transactionId),
3645
);
3746

3847
const nativeCurrency = useSelector(getMultichainNativeCurrency);
3948

4049
const insufficientBalance = !isBalanceSufficient({
41-
amount: value,
50+
amount: totalValue,
4251
gasTotal: hexMaximumTransactionFee,
4352
balance,
4453
});

ui/pages/confirmations/send/send.utils.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { encode } from '@metamask/abi-utils';
2+
import { isHexString } from '@metamask/utils';
23
// TODO: Remove restricted import
34
// eslint-disable-next-line import/no-restricted-paths
45
import { addHexPrefix } from '../../../../app/scripts/lib/util';
@@ -30,7 +31,7 @@ function isBalanceSufficient({
3031
primaryCurrency = undefined,
3132
}) {
3233
let totalAmount = new Numeric(amount, 16).add(new Numeric(gasTotal, 16));
33-
let balanceNumeric = new Numeric(balance, 16);
34+
let balanceNumeric = new Numeric(balance, isHexString(balance) ? 16 : 10);
3435

3536
if (typeof primaryCurrency !== 'undefined' && primaryCurrency !== null) {
3637
totalAmount = totalAmount.applyConversionRate(conversionRate);

0 commit comments

Comments
 (0)