1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 09:57:02 +01:00

Fix state in confirm transaction (#17838)

This commit is contained in:
Jyoti Puri 2023-02-24 22:37:26 +05:30 committed by GitHub
parent d7adbb6f41
commit 1c0ff8a6e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 155 additions and 26 deletions

View File

@ -653,14 +653,16 @@ class FixtureBuilder {
chainId: CHAIN_IDS.LOCALHOST, chainId: CHAIN_IDS.LOCALHOST,
dappSuggestedGasFees: { dappSuggestedGasFees: {
gas: '0x5208', gas: '0x5208',
gasPrice: '0x4a817c800', maxFeePerGas: '0x59682f0c',
maxPriorityFeePerGas: '0x59682f00',
}, },
history: [ history: [
{ {
chainId: CHAIN_IDS.LOCALHOST, chainId: CHAIN_IDS.LOCALHOST,
dappSuggestedGasFees: { dappSuggestedGasFees: {
gas: '0x5208', gas: '0x5208',
gasPrice: '0x4a817c800', maxFeePerGas: '0x59682f0c',
maxPriorityFeePerGas: '0x59682f00',
}, },
id: 7911313280012623, id: 7911313280012623,
loadingDefaults: true, loadingDefaults: true,
@ -671,7 +673,8 @@ class FixtureBuilder {
txParams: { txParams: {
from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
gas: '0x5208', gas: '0x5208',
gasPrice: '0x4a817c800', maxFeePerGas: '0x59682f0c',
maxPriorityFeePerGas: '0x59682f00',
to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
value: '0x29a2241af62c0000', value: '0x29a2241af62c0000',
}, },
@ -696,7 +699,8 @@ class FixtureBuilder {
txParams: { txParams: {
from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
gas: '0x5208', gas: '0x5208',
gasPrice: '0x4a817c800', maxFeePerGas: '0x59682f0c',
maxPriorityFeePerGas: '0x59682f00',
to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
value: '0x29a2241af62c0000', value: '0x29a2241af62c0000',
}, },
@ -706,14 +710,16 @@ class FixtureBuilder {
chainId: CHAIN_IDS.LOCALHOST, chainId: CHAIN_IDS.LOCALHOST,
dappSuggestedGasFees: { dappSuggestedGasFees: {
gas: '0x5208', gas: '0x5208',
gasPrice: '0x4a817c800', maxFeePerGas: '0x59682f0c',
maxPriorityFeePerGas: '0x59682f00',
}, },
history: [ history: [
{ {
chainId: CHAIN_IDS.LOCALHOST, chainId: CHAIN_IDS.LOCALHOST,
dappSuggestedGasFees: { dappSuggestedGasFees: {
gas: '0x5208', gas: '0x5208',
gasPrice: '0x4a817c800', maxFeePerGas: '0x59682f0c',
maxPriorityFeePerGas: '0x59682f00',
}, },
id: 7911313280012624, id: 7911313280012624,
loadingDefaults: true, loadingDefaults: true,
@ -724,7 +730,8 @@ class FixtureBuilder {
txParams: { txParams: {
from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
gas: '0x5208', gas: '0x5208',
gasPrice: '0x4a817c800', maxFeePerGas: '0x59682f0c',
maxPriorityFeePerGas: '0x59682f00',
to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
value: '0x29a2241af62c0000', value: '0x29a2241af62c0000',
}, },
@ -749,7 +756,8 @@ class FixtureBuilder {
txParams: { txParams: {
from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
gas: '0x5208', gas: '0x5208',
gasPrice: '0x4a817c800', maxFeePerGas: '0x59682f0c',
maxPriorityFeePerGas: '0x59682f00',
to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
value: '0x29a2241af62c0000', value: '0x29a2241af62c0000',
}, },
@ -759,14 +767,16 @@ class FixtureBuilder {
chainId: CHAIN_IDS.LOCALHOST, chainId: CHAIN_IDS.LOCALHOST,
dappSuggestedGasFees: { dappSuggestedGasFees: {
gas: '0x5208', gas: '0x5208',
gasPrice: '0x4a817c800', maxFeePerGas: '0x59682f0c',
maxPriorityFeePerGas: '0x59682f00',
}, },
history: [ history: [
{ {
chainId: CHAIN_IDS.LOCALHOST, chainId: CHAIN_IDS.LOCALHOST,
dappSuggestedGasFees: { dappSuggestedGasFees: {
gas: '0x5208', gas: '0x5208',
gasPrice: '0x4a817c800', maxFeePerGas: '0x59682f0c',
maxPriorityFeePerGas: '0x59682f00',
}, },
id: 7911313280012625, id: 7911313280012625,
loadingDefaults: true, loadingDefaults: true,
@ -777,7 +787,8 @@ class FixtureBuilder {
txParams: { txParams: {
from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
gas: '0x5208', gas: '0x5208',
gasPrice: '0x4a817c800', maxFeePerGas: '0x59682f0c',
maxPriorityFeePerGas: '0x59682f00',
to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
value: '0x29a2241af62c0000', value: '0x29a2241af62c0000',
}, },
@ -802,7 +813,8 @@ class FixtureBuilder {
txParams: { txParams: {
from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
gas: '0x5208', gas: '0x5208',
gasPrice: '0x4a817c800', maxFeePerGas: '0x59682f0c',
maxPriorityFeePerGas: '0x59682f00',
to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
value: '0x29a2241af62c0000', value: '0x29a2241af62c0000',
}, },
@ -812,14 +824,16 @@ class FixtureBuilder {
chainId: CHAIN_IDS.LOCALHOST, chainId: CHAIN_IDS.LOCALHOST,
dappSuggestedGasFees: { dappSuggestedGasFees: {
gas: '0x5208', gas: '0x5208',
gasPrice: '0x4a817c800', maxFeePerGas: '0x59682f0c',
maxPriorityFeePerGas: '0x59682f00',
}, },
history: [ history: [
{ {
chainId: CHAIN_IDS.LOCALHOST, chainId: CHAIN_IDS.LOCALHOST,
dappSuggestedGasFees: { dappSuggestedGasFees: {
gas: '0x5208', gas: '0x5208',
gasPrice: '0x4a817c800', maxFeePerGas: '0x59682f0c',
maxPriorityFeePerGas: '0x59682f00',
}, },
id: 7911313280012626, id: 7911313280012626,
loadingDefaults: true, loadingDefaults: true,
@ -830,7 +844,8 @@ class FixtureBuilder {
txParams: { txParams: {
from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
gas: '0x5208', gas: '0x5208',
gasPrice: '0x4a817c800', maxFeePerGas: '0x59682f0c',
maxPriorityFeePerGas: '0x59682f00',
to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
value: '0x29a2241af62c0000', value: '0x29a2241af62c0000',
}, },
@ -855,7 +870,8 @@ class FixtureBuilder {
txParams: { txParams: {
from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1', from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
gas: '0x5208', gas: '0x5208',
gasPrice: '0x4a817c800', maxFeePerGas: '0x59682f0c',
maxPriorityFeePerGas: '0x59682f00',
to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970', to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
value: '0x29a2241af62c0000', value: '0x29a2241af62c0000',
}, },

View File

@ -0,0 +1,98 @@
const { convertToHexValue, withFixtures } = require('../helpers');
const FixtureBuilder = require('../fixture-builder');
describe('Confirm transactions', function () {
const ganacheOptions = {
hardfork: 'london',
accounts: [
{
secretKey:
'0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC',
balance: convertToHexValue(25000000000000000000),
},
],
};
it('should be able to confirm multiple transactions', async function () {
await withFixtures(
{
fixtures: new FixtureBuilder()
.withTransactionControllerMultipleTransactions()
.build(),
ganacheOptions,
title: this.test.title,
},
async ({ driver }) => {
await driver.navigate();
await driver.fill('#password', 'correct horse battery staple');
await driver.press('#password', driver.Key.ENTER);
// confirm multiple transactions
await driver.waitForSelector({
text: 'Reject 4 transactions',
tag: 'a',
});
await driver.clickElement({ text: 'Confirm', tag: 'button' });
await driver.waitForSelector({
text: 'Reject 3 transactions',
tag: 'a',
});
await driver.clickElement({ text: 'Confirm', tag: 'button' });
await driver.waitForSelector({
text: 'Reject 2 transactions',
tag: 'a',
});
await driver.clickElement({ text: 'Confirm', tag: 'button' });
await driver.waitForElementNotPresent('.loading-overlay__spinner');
await driver.clickElement({ text: 'Confirm', tag: 'button' });
await driver.clickElement('[data-testid="home__activity-tab"]');
await driver.wait(async () => {
const confirmedTxes = await driver.findElements(
'.transaction-list__completed-transactions .transaction-list-item',
);
return confirmedTxes.length === 4;
}, 10000);
},
);
});
it('should be able to reject multiple transactions', async function () {
await withFixtures(
{
fixtures: new FixtureBuilder()
.withTransactionControllerMultipleTransactions()
.build(),
ganacheOptions,
title: this.test.title,
},
async ({ driver }) => {
await driver.navigate();
await driver.fill('#password', 'correct horse battery staple');
await driver.press('#password', driver.Key.ENTER);
// confirm multiple transactions
await driver.waitForSelector({
text: 'Reject 4 transactions',
tag: 'a',
});
await driver.clickElement({ text: 'Reject', tag: 'button' });
await driver.waitForSelector({
text: 'Reject 3 transactions',
tag: 'a',
});
await driver.clickElement({ text: 'Reject', tag: 'button' });
await driver.waitForSelector({
text: 'Reject 2 transactions',
tag: 'a',
});
await driver.clickElement({ text: 'Reject', tag: 'button' });
await driver.waitForElementNotPresent('.loading-overlay__spinner');
await driver.clickElement({ text: 'Reject', tag: 'button' });
await driver.waitForSelector('[data-testid="home__activity-tab"]');
},
);
});
});

View File

@ -4,6 +4,7 @@ const FixtureBuilder = require('../fixture-builder');
describe('Navigate transactions', function () { describe('Navigate transactions', function () {
const ganacheOptions = { const ganacheOptions = {
hardfork: 'london',
accounts: [ accounts: [
{ {
secretKey: secretKey:

View File

@ -776,14 +776,12 @@ export default class ConfirmTransactionBase extends Component {
cancelTransaction, cancelTransaction,
history, history,
mostRecentOverviewPage, mostRecentOverviewPage,
clearConfirmTransaction,
updateCustomNonce, updateCustomNonce,
} = this.props; } = this.props;
this._removeBeforeUnload(); this._removeBeforeUnload();
updateCustomNonce(''); updateCustomNonce('');
cancelTransaction(txData).then(() => { cancelTransaction(txData).then(() => {
clearConfirmTransaction();
history.push(mostRecentOverviewPage); history.push(mostRecentOverviewPage);
}); });
} }
@ -791,7 +789,6 @@ export default class ConfirmTransactionBase extends Component {
handleSubmit() { handleSubmit() {
const { const {
sendTransaction, sendTransaction,
clearConfirmTransaction,
txData, txData,
history, history,
mostRecentOverviewPage, mostRecentOverviewPage,
@ -865,7 +862,6 @@ export default class ConfirmTransactionBase extends Component {
sendTransaction(txData) sendTransaction(txData)
.then(() => { .then(() => {
clearConfirmTransaction();
if (!this._isMounted) { if (!this._isMounted) {
return; return;
} }
@ -995,6 +991,7 @@ export default class ConfirmTransactionBase extends Component {
componentWillUnmount() { componentWillUnmount() {
this._beforeUnloadForGasPolling(); this._beforeUnloadForGasPolling();
this._removeBeforeUnload(); this._removeBeforeUnload();
this.props.clearConfirmTransaction();
} }
supportsEIP1559 = supportsEIP1559 =

View File

@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react'; import React, { useCallback, useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { Switch, Route, useHistory, useParams } from 'react-router-dom'; import { Switch, Route, useHistory, useParams } from 'react-router-dom';
@ -61,8 +61,7 @@ const ConfirmTransaction = () => {
const unconfirmedMessages = useSelector(unconfirmedTransactionsHashSelector); const unconfirmedMessages = useSelector(unconfirmedTransactionsHashSelector);
const totalUnapproved = unconfirmedTxs.length || 0; const totalUnapproved = unconfirmedTxs.length || 0;
const getTransaction = useCallback(() => {
const transaction = useMemo(() => {
return totalUnapproved return totalUnapproved
? unapprovedTxs[paramsTransactionId] || ? unapprovedTxs[paramsTransactionId] ||
unconfirmedMessages[paramsTransactionId] || unconfirmedMessages[paramsTransactionId] ||
@ -75,10 +74,27 @@ const ConfirmTransaction = () => {
unconfirmedMessages, unconfirmedMessages,
unconfirmedTxs, unconfirmedTxs,
]); ]);
const [transaction, setTransaction] = useState(getTransaction);
useEffect(() => {
const tx = getTransaction();
setTransaction(tx);
if (tx?.id) {
dispatch(setTransactionToConfirm(tx.id));
}
}, [
dispatch,
getTransaction,
paramsTransactionId,
totalUnapproved,
unapprovedTxs,
unconfirmedMessages,
unconfirmedTxs,
]);
const { id, type } = transaction; const { id, type } = transaction;
const transactionId = id && String(id); const transactionId = id && String(id);
const isValidERC20TokenMethod = isTokenMethodAction(type); const isValidTokenMethod = isTokenMethodAction(type);
const isValidTransactionId = const isValidTransactionId =
transactionId && transactionId &&
(!paramsTransactionId || paramsTransactionId === transactionId); (!paramsTransactionId || paramsTransactionId === transactionId);
@ -152,7 +168,8 @@ const ConfirmTransaction = () => {
} else if ( } else if (
prevTransactionId && prevTransactionId &&
transactionId && transactionId &&
prevTransactionId !== transactionId prevTransactionId !== transactionId &&
paramsTransactionId !== transactionId
) { ) {
history.replace(mostRecentOverviewPage); history.replace(mostRecentOverviewPage);
} }
@ -168,7 +185,7 @@ const ConfirmTransaction = () => {
transactionId, transactionId,
]); ]);
if (isValidERC20TokenMethod && isValidTransactionId) { if (isValidTokenMethod && isValidTransactionId) {
return <ConfirmTokenTransactionSwitch transaction={transaction} />; return <ConfirmTokenTransactionSwitch transaction={transaction} />;
} }
// Show routes when state.confirmTransaction has been set and when either the ID in the params // Show routes when state.confirmTransaction has been set and when either the ID in the params