1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-26 12:29:06 +01:00

Improvement on approval pages (#18545)

This commit is contained in:
Jyoti Puri 2023-04-13 22:54:33 +05:30 committed by Dan Miller
parent 467858fb78
commit ca7f61126c
7 changed files with 80 additions and 2 deletions

View File

@ -1,4 +1,4 @@
import React, { useState, useContext, useEffect } from 'react';
import React, { useState, useContext, useEffect, useRef } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import classnames from 'classnames';
@ -41,6 +41,7 @@ export default function CustomSpendingCap({
}) {
const t = useContext(I18nContext);
const dispatch = useDispatch();
const inputRef = useRef(null);
const value = useSelector(getCustomTokenAmount);
@ -139,6 +140,15 @@ export default function CustomSpendingCap({
passTheErrorText(error);
}, [error, passTheErrorText]);
useEffect(() => {
if (inputRef.current) {
inputRef.current.focus({
preventScroll: true,
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [inputRef.current]);
const chooseTooltipContentText = decConversionGreaterThan(
value,
currentTokenBalance,
@ -182,8 +192,8 @@ export default function CustomSpendingCap({
}
>
<FormField
inputRef={inputRef}
dataTestId="custom-spending-cap-input"
autoFocus
wrappingLabelProps={{ as: 'div' }}
id={
decConversionGreaterThan(value, currentTokenBalance)

View File

@ -43,6 +43,7 @@ export default function FormField({
id,
inputProps,
wrappingLabelProps,
inputRef,
}) {
return (
<div
@ -110,6 +111,7 @@ export default function FormField({
dataTestId={dataTestId}
placeholder={placeholder}
id={id}
inputRef={inputRef}
/>
) : (
<input
@ -125,6 +127,7 @@ export default function FormField({
data-testid={dataTestId}
placeholder={placeholder}
id={id}
ref={inputRef}
{...inputProps}
/>
)}
@ -285,4 +288,8 @@ FormField.propTypes = {
* If used ensure the id prop is set on the input and a label element is present using htmlFor with the same id to ensure accessibility.
*/
wrappingLabelProps: PropTypes.object,
/**
* ref for input component
*/
inputRef: PropTypes.object,
};

View File

@ -20,6 +20,7 @@ export default function NumericInput({
placeholder,
id,
name,
inputRef,
}) {
return (
<div
@ -48,6 +49,7 @@ export default function NumericInput({
placeholder={placeholder}
id={id}
name={name}
ref={inputRef}
/>
{detailText && (
<Typography
@ -80,4 +82,5 @@ NumericInput.propTypes = {
* The id of the input element. Should be used with htmlFor with a label element.
*/
id: PropTypes.string,
inputRef: PropTypes.object,
};

View File

@ -11,6 +11,8 @@ import Button from '../../../components/ui/button';
import SimulationErrorMessage from '../../../components/ui/simulation-error-message';
import EditGasFeeButton from '../../../components/app/edit-gas-fee-button';
import MultiLayerFeeMessage from '../../../components/app/multilayer-fee-message';
import SecurityProviderBannerMessage from '../../../components/app/security-provider-banner-message/security-provider-banner-message';
import { SECURITY_PROVIDER_MESSAGE_SEVERITIES } from '../../../components/app/security-provider-banner-message/security-provider-banner-message.constants';
import {
BLOCK_SIZES,
JustifyContent,
@ -555,6 +557,15 @@ export default class ConfirmApproveContent extends Component {
'confirm-approve-content--full': showFullTxDetails,
})}
>
{(txData?.securityProviderResponse?.flagAsDangerous !== undefined &&
txData?.securityProviderResponse?.flagAsDangerous !==
SECURITY_PROVIDER_MESSAGE_SEVERITIES.NOT_MALICIOUS) ||
(txData?.securityProviderResponse &&
Object.keys(txData.securityProviderResponse).length === 0) ? (
<SecurityProviderBannerMessage
securityProviderResponse={txData.securityProviderResponse}
/>
) : null}
{warning && (
<div className="confirm-approve-content__custom-nonce-warning">
<ConfirmPageContainerWarning warning={warning} />

View File

@ -325,4 +325,22 @@ describe('ConfirmApproveContent Component', () => {
expect(container).toMatchSnapshot();
});
it('should render security provider response if transaction is malicious', () => {
const securityProviderResponse = {
flagAsDangerous: 1,
reason:
'This has been flagged as potentially suspicious. If you sign, you could lose access to all of your NFTs and any funds or other assets in your wallet.',
reason_header: 'Warning',
};
const { getByText } = renderComponent({
...props,
txData: {
...props.txData,
securityProviderResponse,
},
});
expect(getByText(securityProviderResponse.reason)).toBeInTheDocument();
});
});

View File

@ -67,6 +67,8 @@ import {
ICON_NAMES,
} from '../../components/component-library/icon/deprecated';
import LedgerInstructionField from '../../components/app/ledger-instruction-field/ledger-instruction-field';
import { SECURITY_PROVIDER_MESSAGE_SEVERITIES } from '../../components/app/security-provider-banner-message/security-provider-banner-message.constants';
import SecurityProviderBannerMessage from '../../components/app/security-provider-banner-message/security-provider-banner-message';
const ALLOWED_HOSTS = ['portfolio.metamask.io'];
@ -272,6 +274,15 @@ export default function TokenAllowance({
<Box>
<ConfirmPageContainerNavigation />
</Box>
{(txData?.securityProviderResponse?.flagAsDangerous !== undefined &&
txData?.securityProviderResponse?.flagAsDangerous !==
SECURITY_PROVIDER_MESSAGE_SEVERITIES.NOT_MALICIOUS) ||
(txData?.securityProviderResponse &&
Object.keys(txData.securityProviderResponse).length === 0) ? (
<SecurityProviderBannerMessage
securityProviderResponse={txData.securityProviderResponse}
/>
) : null}
<Box
paddingLeft={4}
paddingRight={4}

View File

@ -278,4 +278,22 @@ describe('TokenAllowancePage', () => {
expect(queryByText('Prior to clicking confirm:')).toBeNull();
});
it('should render security provider response if transaction is malicious', () => {
const securityProviderResponse = {
flagAsDangerous: 1,
reason:
'This has been flagged as potentially suspicious. If you sign, you could lose access to all of your NFTs and any funds or other assets in your wallet.',
reason_header: 'Warning',
};
const { getByText } = renderWithProvider(
<TokenAllowance
{...props}
txData={{ ...props.txData, securityProviderResponse }}
/>,
store,
);
expect(getByText(securityProviderResponse.reason)).toBeInTheDocument();
});
});