1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Fix #11703 - Provide wiring for approval modal (#11711)

This commit is contained in:
David Walsh 2021-08-02 09:07:15 -05:00 committed by GitHub
parent 81f274303e
commit 38ff2c937f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 123 additions and 211 deletions

View File

@ -792,13 +792,12 @@ describe('MetaMask', function () {
await driver.clickElement('.confirm-approve-content__small-blue-text');
await driver.delay(regularDelayMs);
// wait for gas modal to be visible
const gasModal = await driver.findVisibleElement('span .modal');
await driver.clickElement('.page-container__tab:nth-of-type(2)');
await driver.delay(regularDelayMs);
await driver.clickElement(
'.edit-gas-display__dapp-acknowledgement-button',
);
const [gasPriceInput, gasLimitInput] = await driver.findElements(
'.advanced-gas-inputs__gas-edit-row__input',
const [gasLimitInput, gasPriceInput] = await driver.findElements(
'.advanced-gas-controls input[type="number"]',
);
await gasPriceInput.fill('10');
@ -808,10 +807,7 @@ describe('MetaMask', function () {
await driver.delay(1000);
await driver.clickElement('.page-container__footer-button');
// wait for gas modal to be removed from DOM.
await gasModal.waitForElementState('hidden');
await driver.clickElement({ text: 'Save', tag: 'button' }, 10000);
const gasFeeInEth = await driver.findElement(
'.confirm-approve-content__transaction-details-content__secondary-fee',

View File

@ -11,7 +11,6 @@ import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app';
// Modal Components
import ConfirmCustomizeGasModal from '../gas-customization/gas-modal-page-container';
import SwapsGasCustomizationModal from '../../../pages/swaps/swaps-gas-customization-modal';
import EditGasPopover from '../edit-gas-popover/edit-gas-popover.component';
import DepositEtherModal from './deposit-ether-modal';
import AccountDetailsModal from './account-details-modal';
import ExportPrivateKeyModal from './export-private-key-modal';
@ -246,35 +245,6 @@ const MODALS = {
},
},
CUSTOMIZE_GAS: {
contents: <EditGasPopover />,
mobileModalStyle: {
width: '100vw',
height: '100vh',
top: '0',
transform: 'none',
left: '0',
right: '0',
margin: '0 auto',
},
laptopModalStyle: {
width: 'auto',
height: '0px',
top: '80px',
left: '0px',
transform: 'none',
margin: '0 auto',
position: 'relative',
},
contentStyle: {
borderRadius: '8px',
},
customOnHideOpts: {
action: resetCustomGasData,
args: [],
},
},
LEGACY_CUSTOMIZE_GAS: {
contents: <ConfirmCustomizeGasModal />,
mobileModalStyle: {

View File

@ -0,0 +1,26 @@
import { useCallback, useState } from 'react';
/**
* Determine whether a transaction can be approved and provide a method to
* kick off the approval process.
*
* Provides a reusable hook that, given a transactionGroup, will manage
* the process of editing gas for approvals
* @param {Object} transactionGroup
* @return {[boolean, Function]}
*/
export function useApproveTransaction() {
const [showCustomizeGasPopover, setShowCustomizeGasPopover] = useState(false);
const closeCustomizeGasPopover = () => setShowCustomizeGasPopover(false);
const approveTransaction = useCallback(() => {
return setShowCustomizeGasPopover(true);
}, []);
return {
approveTransaction,
showCustomizeGasPopover,
closeCustomizeGasPopover,
};
}

View File

@ -2,6 +2,7 @@ import React, { useEffect, useRef, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';
import ConfirmTransactionBase from '../confirm-transaction-base';
import { EDIT_GAS_MODES } from '../../../shared/constants/gas';
import {
showModal,
updateCustomNonce,
@ -14,11 +15,7 @@ import {
getTokenValueParam,
} from '../../helpers/utils/token-util';
import { useTokenTracker } from '../../hooks/useTokenTracker';
import {
getTokens,
getNativeCurrency,
isEIP1559Network,
} from '../../ducks/metamask/metamask';
import { getTokens, getNativeCurrency } from '../../ducks/metamask/metamask';
import {
transactionFeeSelector,
txDataSelector,
@ -27,13 +24,13 @@ import {
getUseNonceField,
getCustomNonceValue,
getNextSuggestedNonce,
getNoGasPriceFetched,
getIsEthGasPriceFetched,
getIsMainnet,
} from '../../selectors';
import { useApproveTransaction } from '../../hooks/useApproveTransaction';
import { currentNetworkTxListSelector } from '../../selectors/transactions';
import Loading from '../../components/ui/loading-screen';
import EditGasPopover from '../../components/app/edit-gas-popover/edit-gas-popover.component';
import { getCustomTxParamsData } from './confirm-approve.util';
import ConfirmApproveContent from './confirm-approve-content';
@ -53,7 +50,6 @@ export default function ConfirmApprove() {
const useNonceField = useSelector(getUseNonceField);
const nextNonce = useSelector(getNextSuggestedNonce);
const customNonceValue = useSelector(getCustomNonceValue);
const onEIP1559Network = useSelector(isEIP1559Network);
const transaction =
currentNetworkTxList.find(
@ -83,6 +79,12 @@ export default function ConfirmApprove() {
const previousTokenAmount = useRef(tokenAmount);
const {
approveTransaction,
showCustomizeGasPopover,
closeCustomizeGasPopover,
} = useApproveTransaction();
useEffect(() => {
if (customPermissionAmount && previousTokenAmount.current !== tokenAmount) {
setCustomPermissionAmount(tokenAmount);
@ -113,7 +115,6 @@ export default function ConfirmApprove() {
const formattedOrigin = origin
? origin[0].toUpperCase() + origin.slice(1)
: '';
const txData = transaction;
const { icon: siteImage = '' } = domainMetadata[origin] || {};
@ -124,11 +125,7 @@ export default function ConfirmApprove() {
const customData = customPermissionAmount
? getCustomTxParamsData(data, { customPermissionAmount, decimals })
: null;
const isEthGasPrice = useSelector(getIsEthGasPriceFetched);
const noGasPrice = useSelector(getNoGasPriceFetched);
const isMainnet = useSelector(getIsMainnet);
const hideBasic =
isEthGasPrice || noGasPrice || !(isMainnet || process.env.IN_TEST);
return tokenSymbol === undefined ? (
<Loading />
) : (
@ -138,85 +135,84 @@ export default function ConfirmApprove() {
showAccountInHeader
title={tokensText}
contentComponent={
<ConfirmApproveContent
decimals={decimals}
siteImage={siteImage}
setCustomAmount={setCustomPermissionAmount}
customTokenAmount={String(customPermissionAmount)}
tokenAmount={tokenAmount}
origin={formattedOrigin}
tokenSymbol={tokenSymbol}
tokenBalance={tokenBalance}
showCustomizeGasModal={() =>
dispatch(
showModal({
name: onEIP1559Network
? 'CUSTOMIZE_GAS'
: 'LEGACY_CUSTOMIZE_GAS',
txData,
hideBasic,
}),
)
}
showEditApprovalPermissionModal={({
/* eslint-disable no-shadow */
customTokenAmount,
decimals,
origin,
setCustomAmount,
tokenAmount,
tokenBalance,
tokenSymbol,
/* eslint-enable no-shadow */
}) =>
dispatch(
showModal({
name: 'EDIT_APPROVAL_PERMISSION',
customTokenAmount,
decimals,
origin,
setCustomAmount,
tokenAmount,
tokenBalance,
tokenSymbol,
}),
)
}
data={customData || data}
toAddress={toAddress}
currentCurrency={currentCurrency}
nativeCurrency={nativeCurrency}
ethTransactionTotal={ethTransactionTotal}
fiatTransactionTotal={fiatTransactionTotal}
useNonceField={useNonceField}
nextNonce={nextNonce}
customNonceValue={customNonceValue}
updateCustomNonce={(value) => {
dispatch(updateCustomNonce(value));
}}
getNextNonce={() => dispatch(getNextNonce())}
showCustomizeNonceModal={({
/* eslint-disable no-shadow */
useNonceField,
nextNonce,
customNonceValue,
updateCustomNonce,
getNextNonce,
/* eslint-disable no-shadow */
}) =>
dispatch(
showModal({
name: 'CUSTOMIZE_NONCE',
useNonceField,
nextNonce,
customNonceValue,
updateCustomNonce,
getNextNonce,
}),
)
}
warning={submitWarning}
/>
<>
<ConfirmApproveContent
decimals={decimals}
siteImage={siteImage}
setCustomAmount={setCustomPermissionAmount}
customTokenAmount={String(customPermissionAmount)}
tokenAmount={tokenAmount}
origin={formattedOrigin}
tokenSymbol={tokenSymbol}
tokenBalance={tokenBalance}
showCustomizeGasModal={approveTransaction}
showEditApprovalPermissionModal={({
/* eslint-disable no-shadow */
customTokenAmount,
decimals,
origin,
setCustomAmount,
tokenAmount,
tokenBalance,
tokenSymbol,
/* eslint-enable no-shadow */
}) =>
dispatch(
showModal({
name: 'EDIT_APPROVAL_PERMISSION',
customTokenAmount,
decimals,
origin,
setCustomAmount,
tokenAmount,
tokenBalance,
tokenSymbol,
}),
)
}
data={customData || data}
toAddress={toAddress}
currentCurrency={currentCurrency}
nativeCurrency={nativeCurrency}
ethTransactionTotal={ethTransactionTotal}
fiatTransactionTotal={fiatTransactionTotal}
useNonceField={useNonceField}
nextNonce={nextNonce}
customNonceValue={customNonceValue}
updateCustomNonce={(value) => {
dispatch(updateCustomNonce(value));
}}
getNextNonce={() => dispatch(getNextNonce())}
showCustomizeNonceModal={({
/* eslint-disable no-shadow */
useNonceField,
nextNonce,
customNonceValue,
updateCustomNonce,
getNextNonce,
/* eslint-disable no-shadow */
}) =>
dispatch(
showModal({
name: 'CUSTOMIZE_NONCE',
useNonceField,
nextNonce,
customNonceValue,
updateCustomNonce,
getNextNonce,
}),
)
}
warning={submitWarning}
/>
{showCustomizeGasPopover && (
<EditGasPopover
onClose={closeCustomizeGasPopover}
mode={EDIT_GAS_MODES.MODIFY_IN_PLACE}
transaction={transaction}
/>
)}
</>
}
hideSenderToRecipient
customTxParamsData={customData}

View File

@ -14,14 +14,7 @@ import {
tryReverseResolveAddress,
setDefaultHomeActiveTabName,
} from '../../store/actions';
import {
INSUFFICIENT_FUNDS_ERROR_KEY,
GAS_LIMIT_TOO_LOW_ERROR_KEY,
} from '../../helpers/constants/error-keys';
import { getHexGasTotal } from '../../helpers/utils/confirm-tx.util';
import { isBalanceSufficient, calcGasTotal } from '../send/send.utils';
import { conversionGreaterThan } from '../../../shared/modules/conversion.utils';
import { MIN_GAS_LIMIT_DEC } from '../send/send.constants';
import { shortenAddress, valuesFor } from '../../helpers/utils/util';
import {
getAdvancedInlineGasShown,
@ -210,16 +203,6 @@ export const mapDispatchToProps = (dispatch) => {
showTransactionConfirmedModal: ({ onSubmit }) => {
return dispatch(showModal({ name: 'TRANSACTION_CONFIRMED', onSubmit }));
},
showCustomizeGasModal: ({ txData, onSubmit, validate }) => {
return dispatch(
showModal({
name: 'CUSTOMIZE_GAS',
txData,
onSubmit,
validate,
}),
);
},
showRejectTransactionsConfirmationModal: ({
onSubmit,
unapprovedTxCount,
@ -241,78 +224,19 @@ export const mapDispatchToProps = (dispatch) => {
};
};
const getValidateEditGas = ({ balance, conversionRate, txData }) => {
const { txParams: { value: amount } = {} } = txData;
return ({ gasLimit, gasPrice }) => {
const gasTotal = getHexGasTotal({ gasLimit, gasPrice });
const hasSufficientBalance = isBalanceSufficient({
amount,
gasTotal,
balance,
conversionRate,
});
if (!hasSufficientBalance) {
return {
valid: false,
errorKey: INSUFFICIENT_FUNDS_ERROR_KEY,
};
}
const gasLimitTooLow =
gasLimit &&
conversionGreaterThan(
{
value: MIN_GAS_LIMIT_DEC,
fromNumericBase: 'dec',
conversionRate,
},
{
value: gasLimit,
fromNumericBase: 'hex',
},
);
if (gasLimitTooLow) {
return {
valid: false,
errorKey: GAS_LIMIT_TOO_LOW_ERROR_KEY,
};
}
return {
valid: true,
};
};
};
const mergeProps = (stateProps, dispatchProps, ownProps) => {
const { balance, conversionRate, txData, unapprovedTxs } = stateProps;
const { txData, unapprovedTxs } = stateProps;
const {
cancelAllTransactions: dispatchCancelAllTransactions,
showCustomizeGasModal: dispatchShowCustomizeGasModal,
updateTransactionGasFees: dispatchUpdateTransactionGasFees,
...otherDispatchProps
} = dispatchProps;
const validateEditGas = getValidateEditGas({
balance,
conversionRate,
txData,
});
return {
...stateProps,
...otherDispatchProps,
...ownProps,
showCustomizeGasModal: () =>
dispatchShowCustomizeGasModal({
txData,
onSubmit: (customGas) => dispatchUpdateTransactionGasFees(customGas),
validate: validateEditGas,
}),
cancelAllTransactions: () =>
dispatchCancelAllTransactions(valuesFor(unapprovedTxs)),
updateGasAndCalculate: ({ gasLimit, gasPrice }) => {