mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
EIP-1559 - Provide Updated UI for Dapp-Suggested Gas fees (#11523)
This commit is contained in:
parent
e77101138a
commit
d8984d3cf3
@ -2442,9 +2442,25 @@
|
||||
"transactionCreated": {
|
||||
"message": "Transaction created with a value of $1 at $2."
|
||||
},
|
||||
"transactionDetailDappGasHeading": {
|
||||
"message": "$1 suggested gas fee",
|
||||
"description": "$1 represents a dapp origin"
|
||||
},
|
||||
"transactionDetailDappGasTooltip": {
|
||||
"message": "This gas fee suggestion is using legacy gas estimation which may be inaccurate."
|
||||
},
|
||||
"transactionDetailGasHeading": {
|
||||
"message": "Estimated gas fee"
|
||||
},
|
||||
"transactionDetailGasTooltipConversion": {
|
||||
"message": "Learn more about gas fees"
|
||||
},
|
||||
"transactionDetailGasTooltipExplanation": {
|
||||
"message": "Gas fees are set by the network and fluctuate based on network traffic and transaction complexity."
|
||||
},
|
||||
"transactionDetailGasTooltipIntro": {
|
||||
"message": "Gas fees are paid to crypto miners who process transactions on the Ethereum network. MetaMask does not profit from gas fees."
|
||||
},
|
||||
"transactionDetailGasTotalSubtitle": {
|
||||
"message": "Amount + gas fee"
|
||||
},
|
||||
|
@ -28,8 +28,7 @@ export default function EditGasDisplay({
|
||||
alwaysShowForm = false,
|
||||
showEducationButton = false,
|
||||
onEducationClick,
|
||||
dappSuggestedGasFee = 0,
|
||||
dappOrigin = '',
|
||||
transaction,
|
||||
defaultEstimateToUse,
|
||||
maxPriorityFeePerGas,
|
||||
setMaxPriorityFeePerGas,
|
||||
@ -61,7 +60,7 @@ export default function EditGasDisplay({
|
||||
const t = useContext(I18nContext);
|
||||
|
||||
const requireDappAcknowledgement = Boolean(
|
||||
dappSuggestedGasFee && !dappSuggestedGasFeeAcknowledged,
|
||||
transaction?.dappSuggestedGasFees && !dappSuggestedGasFeeAcknowledged,
|
||||
);
|
||||
|
||||
return (
|
||||
@ -79,7 +78,8 @@ export default function EditGasDisplay({
|
||||
<div className="edit-gas-display__dapp-acknowledgement-warning">
|
||||
<ActionableMessage
|
||||
className="actionable-message--warning"
|
||||
message={t('gasDisplayDappWarning', [dappOrigin])}
|
||||
message={t('gasDisplayDappWarning', [transaction.dappOrigin])}
|
||||
iconFillColor="#f8c000"
|
||||
useIcon
|
||||
/>
|
||||
</div>
|
||||
@ -164,7 +164,7 @@ export default function EditGasDisplay({
|
||||
onChange={setEstimateToUse}
|
||||
/>
|
||||
)}
|
||||
{!alwaysShowForm && (
|
||||
{!alwaysShowForm && !requireDappAcknowledgement && (
|
||||
<button
|
||||
className="edit-gas-display__advanced-button"
|
||||
onClick={() => setShowAdvancedForm(!showAdvancedForm)}
|
||||
@ -217,8 +217,6 @@ EditGasDisplay.propTypes = {
|
||||
mode: PropTypes.oneOf(Object.values(EDIT_GAS_MODES)),
|
||||
showEducationButton: PropTypes.bool,
|
||||
onEducationClick: PropTypes.func,
|
||||
dappSuggestedGasFee: PropTypes.number,
|
||||
dappOrigin: PropTypes.string,
|
||||
defaultEstimateToUse: PropTypes.oneOf(Object.values(GAS_RECOMMENDATIONS)),
|
||||
maxPriorityFeePerGas: PropTypes.string,
|
||||
setMaxPriorityFeePerGas: PropTypes.func,
|
||||
@ -246,4 +244,5 @@ EditGasDisplay.propTypes = {
|
||||
showAdvancedForm: PropTypes.bool,
|
||||
setShowAdvancedForm: PropTypes.func,
|
||||
warning: PropTypes.string,
|
||||
transaction: PropTypes.object,
|
||||
};
|
||||
|
@ -2,6 +2,10 @@
|
||||
& .actionable-message--warning,
|
||||
& .actionable-message--error {
|
||||
margin-top: 0;
|
||||
|
||||
& .actionable-message__message {
|
||||
text-align: start;
|
||||
}
|
||||
}
|
||||
|
||||
&__top-tooltip {
|
||||
@ -22,7 +26,7 @@
|
||||
}
|
||||
|
||||
button.edit-gas-display__dapp-acknowledgement-button {
|
||||
margin: 0 auto;
|
||||
margin: 40px auto 0 auto;
|
||||
display: block;
|
||||
color: $secondary-1;
|
||||
border: 1px solid $secondary-1;
|
||||
|
@ -220,6 +220,7 @@ export default function EditGasPopover({
|
||||
isGasTooLow={isGasTooLow}
|
||||
onEducationClick={() => setShowEducationContent(true)}
|
||||
mode={mode}
|
||||
transaction={transaction}
|
||||
{...editGasDisplayProps}
|
||||
/>
|
||||
)}
|
||||
|
@ -9,6 +9,11 @@
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&__title--dapp-suggested {
|
||||
color: $secondary-1;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.info-tooltip {
|
||||
display: inline-block;
|
||||
margin-inline-start: 4px;
|
||||
|
@ -9,17 +9,18 @@ import {
|
||||
} from '../../../helpers/constants/design-system';
|
||||
|
||||
export default function TransactionDetailItem({
|
||||
detailTitle,
|
||||
detailText,
|
||||
detailTotal,
|
||||
subTitle,
|
||||
subText,
|
||||
detailTitle = '',
|
||||
detailText = '',
|
||||
detailTitleColor = COLORS.BLACK,
|
||||
detailTotal = '',
|
||||
subTitle = '',
|
||||
subText = '',
|
||||
}) {
|
||||
return (
|
||||
<div className="transaction-detail-item">
|
||||
<div className="transaction-detail-item__row">
|
||||
<Typography
|
||||
color={COLORS.BLACK}
|
||||
color={detailTitleColor}
|
||||
fontWeight={FONT_WEIGHT.BOLD}
|
||||
variant={TYPOGRAPHY.H6}
|
||||
className="transaction-detail-item__title"
|
||||
@ -64,16 +65,9 @@ export default function TransactionDetailItem({
|
||||
|
||||
TransactionDetailItem.propTypes = {
|
||||
detailTitle: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
||||
detailTitleColor: PropTypes.string,
|
||||
detailText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
||||
detailTotal: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
||||
subTitle: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
||||
subText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
||||
};
|
||||
|
||||
TransactionDetailItem.defaultProps = {
|
||||
detailTitle: '',
|
||||
detailText: '',
|
||||
detailTotal: '',
|
||||
subTitle: '',
|
||||
subText: '',
|
||||
};
|
||||
|
@ -2,6 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import InfoTooltip from '../info-tooltip';
|
||||
import InfoTooltipIcon from '../info-tooltip/info-tooltip-icon';
|
||||
|
||||
const CLASSNAME_WARNING = 'actionable-message--warning';
|
||||
const CLASSNAME_DANGER = 'actionable-message--danger';
|
||||
@ -21,7 +22,7 @@ export default function ActionableMessage({
|
||||
withRightButton = false,
|
||||
type = false,
|
||||
useIcon = false,
|
||||
iconFill = '#b8b8b8',
|
||||
iconFillColor = '',
|
||||
}) {
|
||||
const actionableMessageClassName = classnames(
|
||||
'actionable-message',
|
||||
@ -33,18 +34,7 @@ export default function ActionableMessage({
|
||||
|
||||
return (
|
||||
<div className={actionableMessageClassName}>
|
||||
{useIcon && (
|
||||
<svg
|
||||
viewBox="0 0 10 10"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="actionable-message__icon"
|
||||
>
|
||||
<path
|
||||
d="M5 0C2.2 0 0 2.2 0 5s2.2 5 5 5 5-2.2 5-5-2.2-5-5-5zm0 2c.4 0 .7.3.7.7s-.3.7-.7.7-.7-.2-.7-.6.3-.8.7-.8zm.7 6H4.3V4.3h1.5V8z"
|
||||
fill={iconFill}
|
||||
/>
|
||||
</svg>
|
||||
)}
|
||||
{useIcon && <InfoTooltipIcon fillColor={iconFillColor} />}
|
||||
{infoTooltipText && (
|
||||
<InfoTooltip
|
||||
position="left"
|
||||
@ -98,5 +88,5 @@ ActionableMessage.propTypes = {
|
||||
withRightButton: PropTypes.bool,
|
||||
infoTooltipText: PropTypes.string,
|
||||
useIcon: PropTypes.bool,
|
||||
iconFill: PropTypes.string,
|
||||
iconFillColor: PropTypes.string,
|
||||
};
|
||||
|
@ -78,7 +78,7 @@ export const withIcon = () => (
|
||||
)}
|
||||
className="actionable-message--left-aligned actionable-message--warning"
|
||||
useIcon
|
||||
iconFill="#f8c000"
|
||||
iconFillColor="#f8c000"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
.info-tooltip {
|
||||
img {
|
||||
svg {
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
}
|
||||
@ -41,6 +41,18 @@
|
||||
|
||||
text-align: left;
|
||||
color: $Grey-500;
|
||||
|
||||
a {
|
||||
color: $primary-1;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 12px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
17
ui/components/ui/info-tooltip/info-tooltip-icon.js
Normal file
17
ui/components/ui/info-tooltip/info-tooltip-icon.js
Normal file
@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export default function InfoTooltipIcon({ fillColor = '#b8b8b8' }) {
|
||||
return (
|
||||
<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5 0C2.2 0 0 2.2 0 5s2.2 5 5 5 5-2.2 5-5-2.2-5-5-5zm0 2c.4 0 .7.3.7.7s-.3.7-.7.7-.7-.2-.7-.6.3-.8.7-.8zm.7 6H4.3V4.3h1.5V8z"
|
||||
fill={fillColor}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
InfoTooltipIcon.propTypes = {
|
||||
fillColor: PropTypes.string,
|
||||
};
|
@ -2,6 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import Tooltip from '../tooltip';
|
||||
import InfoTooltipIcon from './info-tooltip-icon';
|
||||
|
||||
const positionArrowClassMap = {
|
||||
top: 'info-tooltip__top-tooltip-arrow',
|
||||
@ -16,6 +17,7 @@ export default function InfoTooltip({
|
||||
containerClassName,
|
||||
wrapperClassName,
|
||||
wide,
|
||||
iconFillColor = '',
|
||||
}) {
|
||||
return (
|
||||
<div className="info-tooltip">
|
||||
@ -32,7 +34,7 @@ export default function InfoTooltip({
|
||||
html={contentText}
|
||||
theme={wide ? 'tippy-tooltip-wideInfo' : 'tippy-tooltip-info'}
|
||||
>
|
||||
<img src="images/mm-info-icon.svg" alt="" />
|
||||
<InfoTooltipIcon fillColor={iconFillColor} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
@ -44,4 +46,5 @@ InfoTooltip.propTypes = {
|
||||
wide: PropTypes.bool,
|
||||
containerClassName: PropTypes.string,
|
||||
wrapperClassName: PropTypes.string,
|
||||
iconFillColor: PropTypes.string,
|
||||
};
|
||||
|
@ -35,6 +35,8 @@ import TransactionDetail from '../../components/app/transaction-detail/transacti
|
||||
import TransactionDetailItem from '../../components/app/transaction-detail-item/transaction-detail-item.component';
|
||||
import InfoTooltip from '../../components/ui/info-tooltip/info-tooltip';
|
||||
|
||||
import { COLORS } from '../../helpers/constants/design-system';
|
||||
|
||||
export default class ConfirmTransactionBase extends Component {
|
||||
static contextTypes = {
|
||||
t: PropTypes.func,
|
||||
@ -292,6 +294,7 @@ export default class ConfirmTransactionBase extends Component {
|
||||
isMainnet,
|
||||
isEthGasPrice,
|
||||
noGasPrice,
|
||||
txData,
|
||||
} = this.props;
|
||||
const { t } = this.context;
|
||||
|
||||
@ -363,13 +366,40 @@ export default class ConfirmTransactionBase extends Component {
|
||||
<TransactionDetailItem
|
||||
key="gas-item"
|
||||
detailTitle={
|
||||
txData.dappSuggestedGasFees ? (
|
||||
<>
|
||||
{t('transactionDetailGasHeading')}
|
||||
<InfoTooltip contentText="" position="top">
|
||||
{t('transactionDetailDappGasHeading', [txData.origin])}
|
||||
<InfoTooltip
|
||||
contentText={t('transactionDetailDappGasTooltip')}
|
||||
position="top"
|
||||
iconFillColor="#f66a0a"
|
||||
>
|
||||
<i className="fa fa-info-circle" />
|
||||
</InfoTooltip>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{t('transactionDetailGasHeading')}
|
||||
<InfoTooltip
|
||||
contentText={
|
||||
<>
|
||||
<p>{t('transactionDetailGasTooltipIntro')}</p>
|
||||
<p>{t('transactionDetailGasTooltipExplanation')}</p>
|
||||
<p>
|
||||
<a href="https://community.metamask.io/t/what-is-gas-why-do-transactions-take-so-long/3172">
|
||||
{t('transactionDetailGasTooltipConversion')}
|
||||
</a>
|
||||
</p>
|
||||
</>
|
||||
}
|
||||
position="top"
|
||||
>
|
||||
<i className="fa fa-info-circle" />
|
||||
</InfoTooltip>
|
||||
</>
|
||||
)
|
||||
}
|
||||
detailTitleColor={COLORS.SECONDARY1}
|
||||
detailText={
|
||||
<UserPreferencedCurrencyDisplay
|
||||
type={PRIMARY}
|
||||
|
@ -59,10 +59,15 @@ exports[`FeeCard renders the component with initial props 2`] = `
|
||||
style="display: inline;"
|
||||
tabindex="0"
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
src="images/mm-info-icon.svg"
|
||||
<svg
|
||||
viewBox="0 0 10 10"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M5 0C2.2 0 0 2.2 0 5s2.2 5 5 5 5-2.2 5-5-2.2-5-5-5zm0 2c.4 0 .7.3.7.7s-.3.7-.7.7-.7-.2-.7-.6.3-.8.7-.8zm.7 6H4.3V4.3h1.5V8z"
|
||||
fill=""
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -27,10 +27,7 @@ exports[`SortList renders the component with initial props 1`] = `
|
||||
style="display: inline;"
|
||||
tabindex="0"
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
src="images/mm-info-icon.svg"
|
||||
/>
|
||||
<InfoTooltipIcon />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -69,10 +66,7 @@ exports[`SortList renders the component with initial props 2`] = `
|
||||
style="display: inline;"
|
||||
tabindex="0"
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
src="images/mm-info-icon.svg"
|
||||
/>
|
||||
<InfoTooltipIcon />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3,6 +3,11 @@ import React from 'react';
|
||||
import { renderWithProvider } from '../../../../../test/jest';
|
||||
import SortList from './sort-list';
|
||||
|
||||
jest.mock(
|
||||
'../../../../components/ui/info-tooltip/info-tooltip-icon',
|
||||
() => () => '<InfoTooltipIcon />',
|
||||
);
|
||||
|
||||
const createProps = (customProps = {}) => {
|
||||
return {
|
||||
selectedAggId: 'Agg2',
|
||||
|
@ -126,10 +126,7 @@ exports[`ViewQuote renders the component with initial props 4`] = `
|
||||
style="display: inline;"
|
||||
tabindex="0"
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
src="images/mm-info-icon.svg"
|
||||
/>
|
||||
<InfoTooltipIcon />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -9,6 +9,10 @@ import {
|
||||
} from '../../../../test/jest';
|
||||
import ViewQuote from '.';
|
||||
|
||||
jest.mock('../../../components/ui/info-tooltip/info-tooltip-icon', () => () =>
|
||||
'<InfoTooltipIcon />',
|
||||
);
|
||||
|
||||
const middleware = [thunk];
|
||||
const createProps = (customProps = {}) => {
|
||||
return {
|
||||
|
Loading…
Reference in New Issue
Block a user