1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

provide skeleton for submitting gas form (#11496)

This commit is contained in:
Brad Decker 2021-07-12 14:35:54 -05:00 committed by GitHub
parent 621dc62b77
commit 9416d1ca71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 158 additions and 56 deletions

View File

@ -289,6 +289,9 @@
"cancel": {
"message": "Cancel"
},
"cancelPopoverTitle": {
"message": "Cancel transaction"
},
"cancellationGasFee": {
"message": "Cancellation Gas Fee"
},

View File

@ -63,6 +63,8 @@ export default class ConfirmPageContainer extends Component {
disabled: PropTypes.bool,
editingGas: PropTypes.bool,
handleCloseEditGas: PropTypes.func,
// Gas Popover
currentTransaction: PropTypes.object.isRequired,
};
render() {
@ -110,6 +112,7 @@ export default class ConfirmPageContainer extends Component {
ethGasPriceWarning,
editingGas,
handleCloseEditGas,
currentTransaction,
} = this.props;
const renderAssetImage = contentComponent || !identiconAddress;
@ -188,7 +191,12 @@ export default class ConfirmPageContainer extends Component {
)}
</PageContainerFooter>
)}
{editingGas && <EditGasPopover onClose={handleCloseEditGas} />}
{editingGas && (
<EditGasPopover
onClose={handleCloseEditGas}
transaction={currentTransaction}
/>
)}
</div>
);
}

View File

@ -8,12 +8,26 @@ import EditGasDisplay from '../edit-gas-display';
import EditGasDisplayEducation from '../edit-gas-display-education';
import { I18nContext } from '../../../contexts/i18n';
import { hideModal, hideSidebar } from '../../../store/actions';
import {
createCancelTransaction,
createSpeedUpTransaction,
hideModal,
hideSidebar,
updateTransaction,
} from '../../../store/actions';
export const EDIT_GAS_MODE = {
SPEED_UP: 'speed-up',
CANCEL: 'cancel',
MODIFY_IN_PLACE: 'modify-in-place',
};
export default function EditGasPopover({
popoverTitle,
confirmButtonText,
editGasDisplayProps,
transaction,
mode,
onClose,
}) {
const t = useContext(I18nContext);
@ -37,6 +51,40 @@ export default function EditGasPopover({
}
}, [showSidebar, onClose, dispatch]);
const onSubmit = useCallback(() => {
if (!transaction || !mode) {
closePopover();
}
switch (mode) {
case EDIT_GAS_MODE.CANCEL:
dispatch(
createCancelTransaction(transaction.id, {
/** new gas settings */
}),
);
break;
case EDIT_GAS_MODE.SPEED_UP:
dispatch(
createSpeedUpTransaction(transaction.id, {
/** new gas settings */
}),
);
break;
case EDIT_GAS_MODE.MODIFY_IN_PLACE:
dispatch(
updateTransaction({
...transaction,
txParams: { ...transaction.txParams /** ...newGasSettings */ },
}),
);
break;
default:
break;
}
closePopover();
}, [transaction, mode, dispatch, closePopover]);
const title = showEducationContent
? t('editGasEducationModalTitle')
: popoverTitle || t('editGasTitle');
@ -51,7 +99,7 @@ export default function EditGasPopover({
}
footer={
<>
<Button type="primary" onClick={closePopover}>
<Button type="primary" onClick={onSubmit}>
{footerButtonText}
</Button>
</>
@ -77,6 +125,8 @@ EditGasPopover.propTypes = {
confirmButtonText: PropTypes.string,
showEducationButton: PropTypes.bool,
onClose: PropTypes.func,
transaction: PropTypes.object,
mode: PropTypes.oneOf(Object.values(EDIT_GAS_MODE)),
};
EditGasPopover.defaultProps = {

View File

@ -4,8 +4,6 @@ import ReactCSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
import CustomizeGas from '../gas-customization/gas-modal-page-container';
import { MILLISECOND } from '../../../../shared/constants/time';
import EditGasPopover from '../edit-gas-popover/edit-gas-popover.component';
export default class Sidebar extends Component {
static propTypes = {
sidebarOpen: PropTypes.bool,
@ -54,18 +52,6 @@ export default class Sidebar extends Component {
}
}
renderGasPopover() {
const { t } = this.context;
return (
<EditGasPopover
popoverTitle={t('speedUpPopoverTitle')}
editGasDisplayProps={{ alwaysShowForm: true, type: 'speed-up' }}
confirmButtonText={t('submit')}
/>
);
}
componentDidUpdate(prevProps) {
if (!prevProps.sidebarShouldClose && this.props.sidebarShouldClose) {
this.props.hideSidebar();
@ -77,10 +63,6 @@ export default class Sidebar extends Component {
const showSidebar = sidebarOpen && !sidebarShouldClose;
if (showSidebar && process.env.SHOW_EIP_1559_UI) {
return this.renderGasPopover();
}
return (
<div>
<ReactCSSTransitionGroup

View File

@ -18,6 +18,8 @@ import {
TRANSACTION_GROUP_CATEGORIES,
TRANSACTION_STATUSES,
} from '../../../../shared/constants/transaction';
import EditGasPopover from '../edit-gas-popover';
import { EDIT_GAS_MODE } from '../edit-gas-popover/edit-gas-popover.component';
export default function TransactionListItem({
transactionGroup,
@ -32,10 +34,15 @@ export default function TransactionListItem({
initialTransaction: { id },
primaryTransaction: { err, status },
} = transactionGroup;
const [cancelEnabled, cancelTransaction] = useCancelTransaction(
transactionGroup,
);
const retryTransaction = useRetryTransaction(transactionGroup);
const [
cancelEnabled,
{ cancelTransaction, showCancelEditGasPopover, closeCancelEditGasPopover },
] = useCancelTransaction(transactionGroup);
const {
retryTransaction,
showRetryEditGasPopover,
closeRetryEditGasPopover,
} = useRetryTransaction(transactionGroup);
const shouldShowSpeedUp = useShouldShowSpeedUp(
transactionGroup,
isEarliestNonce,
@ -203,6 +210,22 @@ export default function TransactionListItem({
cancelDisabled={!cancelEnabled}
/>
)}
{process.env.SHOW_EIP_1559_UI && showRetryEditGasPopover && (
<EditGasPopover
popoverTitle={t('cancelPopoverTitle')}
onClose={closeRetryEditGasPopover}
mode={EDIT_GAS_MODE.SPEED_UP}
transaction={transactionGroup.primaryTransaction}
/>
)}
{process.env.SHOW_EIP_1559_UI && showCancelEditGasPopover && (
<EditGasPopover
popoverTitle={t('speedUpPopoverTitle')}
onClose={closeCancelEditGasPopover}
mode={EDIT_GAS_MODE.CANCEL}
transaction={transactionGroup.primaryTransaction}
/>
)}
</>
);
}

View File

@ -1,5 +1,5 @@
import { useDispatch, useSelector } from 'react-redux';
import { useCallback } from 'react';
import { useCallback, useState } from 'react';
import { showModal, showSidebar } from '../store/actions';
import { isBalanceSufficient } from '../pages/send/send.utils';
import { getSelectedAccount, getIsMainnet } from '../selectors';
@ -34,9 +34,19 @@ export function useCancelTransaction(transactionGroup) {
const conversionRate = useSelector(getConversionRate);
const isMainnet = useSelector(getIsMainnet);
const hideBasic = !(isMainnet || process.env.IN_TEST);
const [showCancelEditGasPopover, setShowCancelEditGasPopover] = useState(
false,
);
const closeCancelEditGasPopover = () => setShowCancelEditGasPopover(false);
const cancelTransaction = useCallback(
(event) => {
event.stopPropagation();
if (process.env.SHOW_EIP_1559_UI) {
return setShowCancelEditGasPopover(true);
}
if (isLegacyTransaction(primaryTransaction)) {
// To support the current process of cancelling or speeding up
// a transaction, we have to inform the custom gas state of the new
@ -88,5 +98,8 @@ export function useCancelTransaction(transactionGroup) {
conversionRate,
});
return [hasEnoughCancelGas, cancelTransaction];
return [
hasEnoughCancelGas,
{ cancelTransaction, showCancelEditGasPopover, closeCancelEditGasPopover },
];
}

View File

@ -58,8 +58,10 @@ describe('useCancelTransaction', function () {
const { result } = renderHook(() =>
useCancelTransaction(transactionGroup),
);
expect(typeof result.current[1]).toStrictEqual('function');
result.current[1]({
expect(typeof result.current[1].cancelTransaction).toStrictEqual(
'function',
);
result.current[1].cancelTransaction({
preventDefault: () => undefined,
stopPropagation: () => undefined,
});
@ -134,8 +136,10 @@ describe('useCancelTransaction', function () {
const { result } = renderHook(() =>
useCancelTransaction(transactionGroup),
);
expect(typeof result.current[1]).toStrictEqual('function');
result.current[1]({
expect(typeof result.current[1].cancelTransaction).toStrictEqual(
'function',
);
result.current[1].cancelTransaction({
preventDefault: () => undefined,
stopPropagation: () => undefined,
});

View File

@ -1,6 +1,6 @@
import { useDispatch, useSelector } from 'react-redux';
import { useCallback } from 'react';
import { useCallback, useState } from 'react';
import { showSidebar } from '../store/actions';
import {
fetchBasicGasEstimates,
@ -11,11 +11,20 @@ import { getIsMainnet } from '../selectors';
import { isLegacyTransaction } from '../../shared/modules/transaction.utils';
import { useMetricEvent } from './useMetricEvent';
import { useIncrementedGasFees } from './useIncrementedGasFees';
/**
* @typedef {Object} RetryTransactionReturnValue
* @property {(event: Event) => void} retryTransaction - open edit gas popover
* to begin setting retry gas fees
* @property {boolean} showRetryEditGasPopover - Whether to show the popover
* @property {() => void} closeRetryEditGasPopover - close the popover.
*/
/**
* Provides a reusable hook that, given a transactionGroup, will return
* a method for beginning the retry process
* @param {Object} transactionGroup - the transaction group
* @return {Function}
* @return {RetryTransactionReturnValue}
*/
export function useRetryTransaction(transactionGroup) {
const { primaryTransaction } = transactionGroup;
@ -30,30 +39,35 @@ export function useRetryTransaction(transactionGroup) {
},
});
const dispatch = useDispatch();
const [showRetryEditGasPopover, setShowRetryEditGasPopover] = useState(false);
const closeRetryEditGasPopover = () => setShowRetryEditGasPopover(false);
const retryTransaction = useCallback(
async (event) => {
event.stopPropagation();
trackMetricsEvent();
if (process.env.SHOW_EIP_1559_UI === true) {
if (process.env.SHOW_EIP_1559_UI) {
setShowRetryEditGasPopover(true);
} else {
await dispatch(fetchBasicGasEstimates);
}
if (isLegacyTransaction(primaryTransaction)) {
// To support the current process of cancelling or speeding up
// a transaction, we have to inform the custom gas state of the new
// gasPrice to start at.
dispatch(setCustomGasPriceForRetry(customGasSettings.gasPrice));
dispatch(setCustomGasLimit(primaryTransaction.txParams.gas));
}
if (isLegacyTransaction(primaryTransaction)) {
// To support the current process of cancelling or speeding up
// a transaction, we have to inform the custom gas state of the new
// gasPrice to start at.
dispatch(setCustomGasPriceForRetry(customGasSettings.gasPrice));
dispatch(setCustomGasLimit(primaryTransaction.txParams.gas));
}
dispatch(
showSidebar({
transitionName: 'sidebar-left',
type: 'customize-gas',
props: { transaction: primaryTransaction, hideBasic },
}),
);
dispatch(
showSidebar({
transitionName: 'sidebar-left',
type: 'customize-gas',
props: { transaction: primaryTransaction, hideBasic },
}),
);
}
},
[
dispatch,
@ -64,5 +78,9 @@ export function useRetryTransaction(transactionGroup) {
],
);
return retryTransaction;
return {
retryTransaction,
showRetryEditGasPopover,
closeRetryEditGasPopover,
};
}

View File

@ -53,8 +53,8 @@ describe('useRetryTransaction', () => {
const { result } = renderHook(() =>
useRetryTransaction(retryEnabledTransaction, true),
);
const retry = result.current;
retry(event);
const { retryTransaction } = result.current;
retryTransaction(event);
expect(trackEvent.calledOnce).toStrictEqual(true);
});
@ -62,8 +62,8 @@ describe('useRetryTransaction', () => {
const { result } = renderHook(() =>
useRetryTransaction(retryEnabledTransaction, true),
);
const retry = result.current;
await retry(event);
const { retryTransaction } = result.current;
await retryTransaction(event);
expect(
dispatch.calledWith(
showSidebar({
@ -108,8 +108,8 @@ describe('useRetryTransaction', () => {
const { result } = renderHook(() =>
useRetryTransaction(cancelledTransaction, true),
);
const retry = result.current;
await retry(event);
const { retryTransaction } = result.current;
await retryTransaction(event);
expect(
dispatch.calledWith(
showSidebar({

View File

@ -817,6 +817,7 @@ export default class ConfirmTransactionBase extends Component {
ethGasPriceWarning={ethGasPriceWarning}
editingGas={editingGas}
handleCloseEditGas={() => this.handleCloseNewGasPopover()}
currentTransaction={txData}
/>
);
}