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:
parent
522eb72e49
commit
328626debe
@ -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}
|
||||||
|
@ -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} />
|
||||||
|
@ -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);
|
|
||||||
|
@ -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}
|
||||||
/>
|
/>
|
||||||
|
@ -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' })),
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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({
|
||||||
|
Loading…
Reference in New Issue
Block a user