From 9472061eaaf1aa807a56775d73c5a67e3382a6a6 Mon Sep 17 00:00:00 2001 From: Bilal Zahory Date: Thu, 1 Aug 2024 16:11:02 -0400 Subject: [PATCH 1/3] fix: add guard for draft tx in send validation --- ui/ducks/send/send.js | 9 +++++++++ ui/ducks/send/send.test.js | 41 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/ui/ducks/send/send.js b/ui/ducks/send/send.js index 8cfb7f4d5356..58f41b26863d 100644 --- a/ui/ducks/send/send.js +++ b/ui/ducks/send/send.js @@ -1456,6 +1456,10 @@ const slice = createSlice({ const draftTransaction = state.draftTransactions[state.currentTransactionUUID]; + if (!draftTransaction) { + return; + } + const amountValue = new Numeric(draftTransaction.amount.value, 16); switch (true) { @@ -1557,6 +1561,11 @@ const slice = createSlice({ validateGasField: (state) => { const draftTransaction = state.draftTransactions[state.currentTransactionUUID]; + + if (!draftTransaction) { + return; + } + const insufficientFunds = !isBalanceSufficient({ amount: draftTransaction.sendAsset.type === AssetType.native diff --git a/ui/ducks/send/send.test.js b/ui/ducks/send/send.test.js index 57b8021489da..2d75ed905104 100644 --- a/ui/ducks/send/send.test.js +++ b/ui/ducks/send/send.test.js @@ -1076,6 +1076,29 @@ describe('Send Slice', () => { ); expect(draftTransaction.status).toBe(SEND_STATUSES.INVALID); }); + + it('should not throw error when draft transaction does not exist', () => { + const tokenAssetState = getInitialSendStateWithExistingTxState({ + amount: { + value: '0x77359400', // 2000000000 + }, + sendAsset: { + type: AssetType.token, + balance: '0x6fc23ac0', // 1875000000 + details: { + decimals: 0, + }, + }, + }); + + const action = { + type: 'send/validateAmountField', + }; + + delete tokenAssetState.draftTransactions['test-uuid']; + + expect(() => sendReducer(tokenAssetState, action)).not.toThrow(); + }); }); describe('validateGasField', () => { @@ -1101,6 +1124,24 @@ describe('Send Slice', () => { INSUFFICIENT_FUNDS_ERROR, ); }); + it('should not throw error when draft transaction does not exist', () => { + const gasFieldState = getInitialSendStateWithExistingTxState({ + account: { + balance: '0x0', + }, + gas: { + gasTotal: '0x1319718a5000', // 21000000000000 + }, + }); + + delete gasFieldState.draftTransactions['test-uuid']; + + const action = { + type: 'send/validateGasField', + }; + + expect(() => sendReducer(gasFieldState, action)).not.toThrow(); + }); }); // TODO: update this From afdcef507d7d4b15700d6575d57507c362ca3ec7 Mon Sep 17 00:00:00 2001 From: Bilal Zahory Date: Thu, 1 Aug 2024 16:59:15 -0400 Subject: [PATCH 2/3] fix: add optional chains --- ui/ducks/send/send.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ducks/send/send.js b/ui/ducks/send/send.js index 58f41b26863d..65b40b221ed8 100644 --- a/ui/ducks/send/send.js +++ b/ui/ducks/send/send.js @@ -1080,7 +1080,7 @@ const slice = createSlice({ const draftTransaction = state.draftTransactions[state.currentTransactionUUID]; let amount = '0x0'; - if (draftTransaction.sendAsset.type === AssetType.token) { + if (draftTransaction?.sendAsset.type === AssetType.token) { const decimals = draftTransaction.sendAsset.details?.decimals ?? 0; const multiplier = Math.pow(10, Number(decimals)); @@ -1292,7 +1292,7 @@ const slice = createSlice({ state.gasTotalForLayer1 = action.payload; if ( state.amountMode === AMOUNT_MODES.MAX && - draftTransaction.sendAsset.type === AssetType.native + draftTransaction?.sendAsset.type === AssetType.native ) { slice.caseReducers.updateAmountToMax(state); } From bb906c0d4e179b03b2e54df986bb44aa1d1389cd Mon Sep 17 00:00:00 2001 From: Bilal Zahory Date: Thu, 1 Aug 2024 17:10:55 -0400 Subject: [PATCH 3/3] fix: add guard for `calculateGasTotal` action --- ui/ducks/send/send.js | 4 ++++ ui/ducks/send/send.test.js | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/ui/ducks/send/send.js b/ui/ducks/send/send.js index 65b40b221ed8..b915907f5b42 100644 --- a/ui/ducks/send/send.js +++ b/ui/ducks/send/send.js @@ -989,6 +989,10 @@ const slice = createSlice({ const draftTransaction = state.draftTransactions[state.currentTransactionUUID]; + if (!draftTransaction) { + return; + } + // use maxFeePerGas as the multiplier if working with a FEE_MARKET transaction // otherwise use gasPrice if ( diff --git a/ui/ducks/send/send.test.js b/ui/ducks/send/send.test.js index 2d75ed905104..bcb6117cbaeb 100644 --- a/ui/ducks/send/send.test.js +++ b/ui/ducks/send/send.test.js @@ -283,7 +283,28 @@ describe('Send Slice', () => { expect(draft.amount.value).toStrictEqual('0xadf7'); expect(draft.status).toStrictEqual(SEND_STATUSES.VALID); }); + + it('should not error when draft transaction is not defined', () => { + const state = getInitialSendStateWithExistingTxState({ + gas: { + gasPrice: '0x1', + maxFeePerGas: '0x2', + gasLimit: GAS_LIMITS.SIMPLE, + }, + }); + + delete state.draftTransactions['test-uuid']; + + const action = { + type: 'send/calculateGasTotal', + }; + + const runAction = () => sendReducer(state, action); + + expect(runAction).not.toThrow(); + }); }); + describe('resetSendState', () => { it('should set the state back to a blank slate matching the initialState object', () => { const action = {