EIP-1559 - Provide Updated UI for Dapp-Suggested Gas fees (#11523)

feature/default_network_editable
David Walsh 3 years ago committed by GitHub
parent e77101138a
commit d8984d3cf3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      app/_locales/en/messages.json
  2. 13
      ui/components/app/edit-gas-display/edit-gas-display.component.js
  3. 6
      ui/components/app/edit-gas-display/index.scss
  4. 1
      ui/components/app/edit-gas-popover/edit-gas-popover.component.js
  5. 5
      ui/components/app/transaction-detail-item/index.scss
  6. 22
      ui/components/app/transaction-detail-item/transaction-detail-item.component.js
  7. 18
      ui/components/ui/actionable-message/actionable-message.js
  8. 2
      ui/components/ui/actionable-message/actionable-message.stories.js
  9. 14
      ui/components/ui/info-tooltip/index.scss
  10. 17
      ui/components/ui/info-tooltip/info-tooltip-icon.js
  11. 5
      ui/components/ui/info-tooltip/info-tooltip.js
  12. 42
      ui/pages/confirm-transaction-base/confirm-transaction-base.component.js
  13. 13
      ui/pages/swaps/fee-card/__snapshots__/fee-card.test.js.snap
  14. 10
      ui/pages/swaps/select-quote-popover/sort-list/__snapshots__/sort-list.test.js.snap
  15. 5
      ui/pages/swaps/select-quote-popover/sort-list/sort-list.test.js
  16. 5
      ui/pages/swaps/view-quote/__snapshots__/view-quote.test.js.snap
  17. 4
      ui/pages/swaps/view-quote/view-quote.test.js

@ -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;
}
}
}
}

@ -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={
<>
{t('transactionDetailGasHeading')}
<InfoTooltip contentText="" position="top">
<i className="fa fa-info-circle" />
</InfoTooltip>
</>
txData.dappSuggestedGasFees ? (
<>
{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"
/>
&lt;InfoTooltipIcon /&gt;
</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"
/>
&lt;InfoTooltipIcon /&gt;
</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"
/>
&lt;InfoTooltipIcon /&gt;
</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…
Cancel
Save