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:
parent
d7adbb6f41
commit
1c0ff8a6e8
@ -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',
|
||||||
},
|
},
|
||||||
|
98
test/e2e/tests/multiple-transactions.spec.js
Normal file
98
test/e2e/tests/multiple-transactions.spec.js
Normal 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"]');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -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:
|
||||||
|
@ -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 =
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user