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

Warning on a Send transaction request (#16220)

This commit is contained in:
Adnan Sahovic 2022-11-09 16:36:21 +01:00 committed by GitHub
parent 522eb72e49
commit 328626debe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 35 additions and 109 deletions

View File

@ -9,7 +9,7 @@ import ErrorMessage from '../../../ui/error-message';
import { INSUFFICIENT_FUNDS_ERROR_KEY } from '../../../../helpers/constants/error-keys'; import { INSUFFICIENT_FUNDS_ERROR_KEY } from '../../../../helpers/constants/error-keys';
import Typography from '../../../ui/typography'; import Typography from '../../../ui/typography';
import { TYPOGRAPHY } from '../../../../helpers/constants/design-system'; import { TYPOGRAPHY } from '../../../../helpers/constants/design-system';
import { TRANSACTION_TYPES } from '../../../../../shared/constants/transaction'; import DepositPopover from '../../deposit-popover/deposit-popover';
import { ConfirmPageContainerSummary, ConfirmPageContainerWarning } from '.'; import { ConfirmPageContainerSummary, ConfirmPageContainerWarning } from '.';
@ -50,15 +50,17 @@ export default class ConfirmPageContainerContent extends Component {
hideTitle: PropTypes.bool, hideTitle: PropTypes.bool,
supportsEIP1559V2: PropTypes.bool, supportsEIP1559V2: PropTypes.bool,
hasTopBorder: PropTypes.bool, hasTopBorder: PropTypes.bool,
currentTransaction: PropTypes.object,
nativeCurrency: PropTypes.string, nativeCurrency: PropTypes.string,
networkName: PropTypes.string, networkName: PropTypes.string,
showBuyModal: PropTypes.func,
toAddress: PropTypes.string, toAddress: PropTypes.string,
transactionType: PropTypes.string, transactionType: PropTypes.string,
isBuyableChain: PropTypes.bool, isBuyableChain: PropTypes.bool,
}; };
state = {
setShowDepositPopover: false,
};
renderContent() { renderContent() {
const { detailsComponent, dataComponent } = this.props; const { detailsComponent, dataComponent } = this.props;
@ -153,10 +155,8 @@ export default class ConfirmPageContainerContent extends Component {
hideTitle, hideTitle,
supportsEIP1559V2, supportsEIP1559V2,
hasTopBorder, hasTopBorder,
currentTransaction,
nativeCurrency, nativeCurrency,
networkName, networkName,
showBuyModal,
toAddress, toAddress,
transactionType, transactionType,
isBuyableChain, isBuyableChain,
@ -169,6 +169,8 @@ export default class ConfirmPageContainerContent extends Component {
(errorKey || errorMessage) && (errorKey || errorMessage) &&
errorKey === INSUFFICIENT_FUNDS_ERROR_KEY; errorKey === INSUFFICIENT_FUNDS_ERROR_KEY;
const { setShowDepositPopover } = this.state;
return ( return (
<div <div
className={classnames('confirm-page-container-content', { className={classnames('confirm-page-container-content', {
@ -198,13 +200,11 @@ export default class ConfirmPageContainerContent extends Component {
transactionType={transactionType} transactionType={transactionType}
/> />
{this.renderContent()} {this.renderContent()}
{!supportsEIP1559V2 && {!supportsEIP1559V2 && (errorKey || errorMessage) && (
(errorKey || errorMessage) && <div className="confirm-page-container-content__error-container">
currentTransaction.type !== TRANSACTION_TYPES.SIMPLE_SEND && ( <ErrorMessage errorMessage={errorMessage} errorKey={errorKey} />
<div className="confirm-page-container-content__error-container"> </div>
<ErrorMessage errorMessage={errorMessage} errorKey={errorKey} /> )}
</div>
)}
{showInsuffienctFundsError && ( {showInsuffienctFundsError && (
<div className="confirm-page-container-content__error-container"> <div className="confirm-page-container-content__error-container">
<ActionableMessage <ActionableMessage
@ -219,7 +219,9 @@ export default class ConfirmPageContainerContent extends Component {
<Button <Button
type="inline" type="inline"
className="confirm-page-container-content__link" className="confirm-page-container-content__link"
onClick={showBuyModal} onClick={() =>
this.setState({ setShowDepositPopover: true })
}
key={`${nativeCurrency}-buy-button`} key={`${nativeCurrency}-buy-button`}
> >
{t('buyAsset', [nativeCurrency])} {t('buyAsset', [nativeCurrency])}
@ -241,7 +243,11 @@ export default class ConfirmPageContainerContent extends Component {
/> />
</div> </div>
)} )}
{setShowDepositPopover && (
<DepositPopover
onClose={() => this.setState({ setShowDepositPopover: false })}
/>
)}
<PageContainerFooter <PageContainerFooter
onCancel={onCancel} onCancel={onCancel}
cancelText={cancelText} cancelText={cancelText}

View File

@ -28,6 +28,7 @@ import Typography from '../../ui/typography';
import { TYPOGRAPHY } from '../../../helpers/constants/design-system'; import { TYPOGRAPHY } from '../../../helpers/constants/design-system';
import NetworkAccountBalanceHeader from '../network-account-balance-header/network-account-balance-header'; import NetworkAccountBalanceHeader from '../network-account-balance-header/network-account-balance-header';
import DepositPopover from '../deposit-popover/deposit-popover';
import EnableEIP1559V2Notice from './enableEIP1559V2-notice'; import EnableEIP1559V2Notice from './enableEIP1559V2-notice';
import { import {
ConfirmPageContainerHeader, ConfirmPageContainerHeader,
@ -38,6 +39,7 @@ import {
export default class ConfirmPageContainer extends Component { export default class ConfirmPageContainer extends Component {
state = { state = {
showNicknamePopovers: false, showNicknamePopovers: false,
setShowDepositPopover: false,
}; };
static contextTypes = { static contextTypes = {
@ -107,7 +109,6 @@ export default class ConfirmPageContainer extends Component {
isOwnedAccount: PropTypes.bool, isOwnedAccount: PropTypes.bool,
supportsEIP1559V2: PropTypes.bool, supportsEIP1559V2: PropTypes.bool,
nativeCurrency: PropTypes.string, nativeCurrency: PropTypes.string,
showBuyModal: PropTypes.func,
isBuyableChain: PropTypes.bool, isBuyableChain: PropTypes.bool,
isApprovalOrRejection: PropTypes.bool, isApprovalOrRejection: PropTypes.bool,
}; };
@ -164,7 +165,6 @@ export default class ConfirmPageContainer extends Component {
isOwnedAccount, isOwnedAccount,
supportsEIP1559V2, supportsEIP1559V2,
nativeCurrency, nativeCurrency,
showBuyModal,
isBuyableChain, isBuyableChain,
networkIdentifier, networkIdentifier,
isApprovalOrRejection, isApprovalOrRejection,
@ -193,6 +193,8 @@ export default class ConfirmPageContainer extends Component {
currentTransaction.type === currentTransaction.type ===
TRANSACTION_TYPES.TOKEN_METHOD_SET_APPROVAL_FOR_ALL; TRANSACTION_TYPES.TOKEN_METHOD_SET_APPROVAL_FOR_ALL;
const { setShowDepositPopover } = this.state;
const { t } = this.context; const { t } = this.context;
return ( return (
@ -298,7 +300,6 @@ export default class ConfirmPageContainer extends Component {
currentTransaction={currentTransaction} currentTransaction={currentTransaction}
nativeCurrency={nativeCurrency} nativeCurrency={nativeCurrency}
networkName={networkName} networkName={networkName}
showBuyModal={showBuyModal}
toAddress={toAddress} toAddress={toAddress}
transactionType={currentTransaction.type} transactionType={currentTransaction.type}
isBuyableChain={isBuyableChain} isBuyableChain={isBuyableChain}
@ -316,7 +317,9 @@ export default class ConfirmPageContainer extends Component {
<Button <Button
type="inline" type="inline"
className="confirm-page-container-content__link" className="confirm-page-container-content__link"
onClick={showBuyModal} onClick={() =>
this.setState({ setShowDepositPopover: true })
}
key={`${nativeCurrency}-buy-button`} key={`${nativeCurrency}-buy-button`}
> >
{t('buyAsset', [nativeCurrency])} {t('buyAsset', [nativeCurrency])}
@ -338,6 +341,11 @@ export default class ConfirmPageContainer extends Component {
/> />
</div> </div>
)} )}
{setShowDepositPopover && (
<DepositPopover
onClose={() => this.setState({ setShowDepositPopover: false })}
/>
)}
{shouldDisplayWarning && errorKey !== INSUFFICIENT_FUNDS_ERROR_KEY && ( {shouldDisplayWarning && errorKey !== INSUFFICIENT_FUNDS_ERROR_KEY && (
<div className="confirm-approve-content__warning"> <div className="confirm-approve-content__warning">
<ErrorMessage errorKey={errorKey} /> <ErrorMessage errorKey={errorKey} />

View File

@ -8,7 +8,6 @@ import {
getMetadataContractName, getMetadataContractName,
getAccountName, getAccountName,
} from '../../../selectors'; } from '../../../selectors';
import { showModal } from '../../../store/actions';
import ConfirmPageContainer from './confirm-page-container.component'; import ConfirmPageContainer from './confirm-page-container.component';
function mapStateToProps(state, ownProps) { function mapStateToProps(state, ownProps) {
@ -35,13 +34,4 @@ function mapStateToProps(state, ownProps) {
}; };
} }
const mapDispatchToProps = (dispatch) => { export default connect(mapStateToProps)(ConfirmPageContainer);
return {
showBuyModal: () => dispatch(showModal({ name: 'DEPOSIT_ETHER' })),
};
};
export default connect(
mapStateToProps,
mapDispatchToProps,
)(ConfirmPageContainer);

View File

@ -159,7 +159,6 @@ export default class ConfirmTransactionBase extends Component {
hardwareWalletRequiresConnection: PropTypes.bool, hardwareWalletRequiresConnection: PropTypes.bool,
isMultiLayerFeeNetwork: PropTypes.bool, isMultiLayerFeeNetwork: PropTypes.bool,
eip1559V2Enabled: PropTypes.bool, eip1559V2Enabled: PropTypes.bool,
showBuyModal: PropTypes.func,
isBuyableChain: PropTypes.bool, isBuyableChain: PropTypes.bool,
isApprovalOrRejection: PropTypes.bool, isApprovalOrRejection: PropTypes.bool,
///: BEGIN:ONLY_INCLUDE_IN(flask) ///: BEGIN:ONLY_INCLUDE_IN(flask)
@ -353,7 +352,6 @@ export default class ConfirmTransactionBase extends Component {
supportsEIP1559, supportsEIP1559,
isMultiLayerFeeNetwork, isMultiLayerFeeNetwork,
nativeCurrency, nativeCurrency,
showBuyModal,
isBuyableChain, isBuyableChain,
} = this.props; } = this.props;
const { t } = this.context; const { t } = this.context;
@ -614,7 +612,6 @@ export default class ConfirmTransactionBase extends Component {
userAcknowledgedGasMissing={userAcknowledgedGasMissing} userAcknowledgedGasMissing={userAcknowledgedGasMissing}
nativeCurrency={nativeCurrency} nativeCurrency={nativeCurrency}
networkName={networkName} networkName={networkName}
showBuyModal={showBuyModal}
type={txData.type} type={txData.type}
isBuyableChain={isBuyableChain} isBuyableChain={isBuyableChain}
/> />

View File

@ -289,7 +289,6 @@ export const mapDispatchToProps = (dispatch) => {
updateTransactionGasFees: (gasFees) => { updateTransactionGasFees: (gasFees) => {
dispatch(updateGasFees({ ...gasFees, expectHexWei: true })); dispatch(updateGasFees({ ...gasFees, expectHexWei: true }));
}, },
showBuyModal: () => dispatch(showModal({ name: 'DEPOSIT_ETHER' })),
}; };
}; };

View File

@ -7,28 +7,16 @@ import { submittedPendingTransactionsSelector } from '../../../selectors/transac
import { useGasFeeContext } from '../../../contexts/gasFee'; import { useGasFeeContext } from '../../../contexts/gasFee';
import { useI18nContext } from '../../../hooks/useI18nContext'; import { useI18nContext } from '../../../hooks/useI18nContext';
import ActionableMessage from '../../../components/ui/actionable-message/actionable-message'; import ActionableMessage from '../../../components/ui/actionable-message/actionable-message';
import Button from '../../../components/ui/button';
import Typography from '../../../components/ui/typography'; import Typography from '../../../components/ui/typography';
import { TYPOGRAPHY } from '../../../helpers/constants/design-system'; import { TYPOGRAPHY } from '../../../helpers/constants/design-system';
import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction';
import ZENDESK_URLS from '../../../helpers/constants/zendesk-url'; import ZENDESK_URLS from '../../../helpers/constants/zendesk-url';
const TransactionAlerts = ({ const TransactionAlerts = ({
userAcknowledgedGasMissing, userAcknowledgedGasMissing,
setUserAcknowledgedGasMissing, setUserAcknowledgedGasMissing,
isBuyableChain,
nativeCurrency,
networkName,
showBuyModal,
type,
}) => { }) => {
const { const { estimateUsed, hasSimulationError, supportsEIP1559V2, isNetworkBusy } =
balanceError, useGasFeeContext();
estimateUsed,
hasSimulationError,
supportsEIP1559V2,
isNetworkBusy,
} = useGasFeeContext();
const pendingTransactions = useSelector(submittedPendingTransactionsSelector); const pendingTransactions = useSelector(submittedPendingTransactionsSelector);
const t = useI18nContext(); const t = useI18nContext();
@ -89,39 +77,6 @@ const TransactionAlerts = ({
type="warning" type="warning"
/> />
)} )}
{balanceError && type === TRANSACTION_TYPES.DEPLOY_CONTRACT ? (
<ActionableMessage
className="actionable-message--warning"
message={
isBuyableChain ? (
<Typography variant={TYPOGRAPHY.H7} align="left">
{t('insufficientCurrencyBuyOrDeposit', [
nativeCurrency,
networkName,
<Button
type="inline"
className="confirm-page-container-content__link"
onClick={showBuyModal}
key={`${nativeCurrency}-buy-button`}
>
{t('buyAsset', [nativeCurrency])}
</Button>,
])}
</Typography>
) : (
<Typography variant={TYPOGRAPHY.H7} align="left">
{t('insufficientCurrencyDeposit', [
nativeCurrency,
networkName,
])}
</Typography>
)
}
useIcon
iconFillColor="var(--color-error-default)"
type="danger"
/>
) : null}
{estimateUsed === PRIORITY_LEVELS.LOW && ( {estimateUsed === PRIORITY_LEVELS.LOW && (
<ActionableMessage <ActionableMessage
dataTestId="low-gas-fee-alert" dataTestId="low-gas-fee-alert"
@ -164,11 +119,6 @@ const TransactionAlerts = ({
TransactionAlerts.propTypes = { TransactionAlerts.propTypes = {
userAcknowledgedGasMissing: PropTypes.bool, userAcknowledgedGasMissing: PropTypes.bool,
setUserAcknowledgedGasMissing: PropTypes.func, setUserAcknowledgedGasMissing: PropTypes.func,
nativeCurrency: PropTypes.string,
networkName: PropTypes.string,
showBuyModal: PropTypes.func,
type: PropTypes.string,
isBuyableChain: PropTypes.bool,
}; };
export default TransactionAlerts; export default TransactionAlerts;

View File

@ -2,7 +2,6 @@ import React from 'react';
import { fireEvent } from '@testing-library/react'; import { fireEvent } from '@testing-library/react';
import { renderWithProvider } from '../../../../test/jest'; import { renderWithProvider } from '../../../../test/jest';
import { submittedPendingTransactionsSelector } from '../../../selectors/transactions'; import { submittedPendingTransactionsSelector } from '../../../selectors/transactions';
import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction';
import { useGasFeeContext } from '../../../contexts/gasFee'; import { useGasFeeContext } from '../../../contexts/gasFee';
import configureStore from '../../../store/store'; import configureStore from '../../../store/store';
import TransactionAlerts from './transaction-alerts'; import TransactionAlerts from './transaction-alerts';
@ -142,29 +141,6 @@ describe('TransactionAlerts', () => {
}); });
}); });
describe('if balanceError from useGasFeeContext is true', () => {
it('informs the user that they have insufficient funds', () => {
const { getByText } = render({
useGasFeeContextValue: {
supportsEIP1559V2: true,
balanceError: true,
},
componentProps: {
nativeCurrency: 'ETH',
networkName: 'Goerli',
showBuyModal: jest.fn(),
chainId: '0x5',
type: TRANSACTION_TYPES.DEPLOY_CONTRACT,
},
});
expect(
getByText(
/You do not have enough ETH in your account to pay for transaction fees on Goerli network./u,
),
).toBeInTheDocument();
});
});
describe('if balanceError from useGasFeeContext is falsy', () => { describe('if balanceError from useGasFeeContext is falsy', () => {
it('does not inform the user that they have insufficient funds', () => { it('does not inform the user that they have insufficient funds', () => {
const { queryByText } = render({ const { queryByText } = render({