mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Add "Retry" option for failed transactions (#7296)
* Begin mocking out retry ui * Remove "Failed" * I guess this works? * Update corresponding test * wip * Ok, this appears to be working now * cleanup * Move this back to 3 * I don't think I need this * Rename showRetry to showSpeedUp * Address PR feedback * Remove notes * Rename shouldShowRetry -> shouldShowSpeedUp * oops
This commit is contained in:
parent
c8878f46d4
commit
af888d0ab2
@ -1442,6 +1442,9 @@
|
||||
"viewOnEtherscan": {
|
||||
"message": "View on Etherscan"
|
||||
},
|
||||
"retryTransaction": {
|
||||
"message": "Retry Transaction"
|
||||
},
|
||||
"visitWebSite": {
|
||||
"message": "Visit our web site"
|
||||
},
|
||||
|
@ -42,6 +42,7 @@ export default class GasModalPageContainer extends Component {
|
||||
]),
|
||||
customPriceIsSafe: PropTypes.bool,
|
||||
isSpeedUp: PropTypes.bool,
|
||||
isRetry: PropTypes.bool,
|
||||
disableSave: PropTypes.bool,
|
||||
isEthereumNetwork: PropTypes.bool,
|
||||
}
|
||||
@ -80,6 +81,7 @@ export default class GasModalPageContainer extends Component {
|
||||
gasEstimatesLoading,
|
||||
customPriceIsSafe,
|
||||
isSpeedUp,
|
||||
isRetry,
|
||||
infoRowProps: {
|
||||
transactionFee,
|
||||
},
|
||||
@ -99,6 +101,7 @@ export default class GasModalPageContainer extends Component {
|
||||
gasEstimatesLoading={gasEstimatesLoading}
|
||||
customPriceIsSafe={customPriceIsSafe}
|
||||
isSpeedUp={isSpeedUp}
|
||||
isRetry={isRetry}
|
||||
isEthereumNetwork={isEthereumNetwork}
|
||||
/>
|
||||
)
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
setGasLimit,
|
||||
setGasPrice,
|
||||
createSpeedUpTransaction,
|
||||
createRetryTransaction,
|
||||
hideSidebar,
|
||||
updateSendAmount,
|
||||
setGasTotal,
|
||||
@ -153,6 +154,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
},
|
||||
transaction: txData || transaction,
|
||||
isSpeedUp: transaction.status === 'submitted',
|
||||
isRetry: transaction.status === 'failed',
|
||||
txId: transaction.id,
|
||||
insufficientBalance,
|
||||
gasEstimatesLoading,
|
||||
@ -187,6 +189,9 @@ const mapDispatchToProps = dispatch => {
|
||||
createSpeedUpTransaction: (txId, gasPrice) => {
|
||||
return dispatch(createSpeedUpTransaction(txId, gasPrice))
|
||||
},
|
||||
createRetryTransaction: (txId, gasPrice) => {
|
||||
return dispatch(createRetryTransaction(txId, gasPrice))
|
||||
},
|
||||
hideGasButtonGroup: () => dispatch(hideGasButtonGroup()),
|
||||
setCustomTimeEstimate: (timeEstimateInSeconds) => dispatch(setCustomTimeEstimate(timeEstimateInSeconds)),
|
||||
hideSidebar: () => dispatch(hideSidebar()),
|
||||
@ -206,6 +211,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||
isConfirm,
|
||||
txId,
|
||||
isSpeedUp,
|
||||
isRetry,
|
||||
insufficientBalance,
|
||||
maxModeOn,
|
||||
customGasPrice,
|
||||
@ -221,6 +227,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||
setGasData: dispatchSetGasData,
|
||||
updateConfirmTxGasAndCalculate: dispatchUpdateConfirmTxGasAndCalculate,
|
||||
createSpeedUpTransaction: dispatchCreateSpeedUpTransaction,
|
||||
createRetryTransaction: dispatchCreateRetryTransaction,
|
||||
hideSidebar: dispatchHideSidebar,
|
||||
cancelAndClose: dispatchCancelAndClose,
|
||||
hideModal: dispatchHideModal,
|
||||
@ -248,6 +255,10 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||
dispatchCreateSpeedUpTransaction(txId, gasPrice)
|
||||
dispatchHideSidebar()
|
||||
dispatchCancelAndClose()
|
||||
} else if (isRetry) {
|
||||
dispatchCreateRetryTransaction(txId, gasPrice)
|
||||
dispatchHideSidebar()
|
||||
dispatchCancelAndClose()
|
||||
} else {
|
||||
dispatchSetGasData(gasLimit, gasPrice)
|
||||
dispatchHideGasButtonGroup()
|
||||
@ -268,7 +279,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||
},
|
||||
cancelAndClose: () => {
|
||||
dispatchCancelAndClose()
|
||||
if (isSpeedUp) {
|
||||
if (isSpeedUp || isRetry) {
|
||||
dispatchHideSidebar()
|
||||
}
|
||||
},
|
||||
|
@ -157,6 +157,7 @@ describe('gas-modal-page-container container', () => {
|
||||
},
|
||||
insufficientBalance: true,
|
||||
isSpeedUp: false,
|
||||
isRetry: false,
|
||||
txId: 34,
|
||||
isEthereumNetwork: true,
|
||||
isMainnet: true,
|
||||
|
@ -70,7 +70,7 @@ describe('TransactionListItemDetails Component', () => {
|
||||
const wrapper = shallow(
|
||||
<TransactionListItemDetails
|
||||
transactionGroup={transactionGroup}
|
||||
showRetry={true}
|
||||
showSpeedUp={true}
|
||||
/>,
|
||||
{ context: { t: (str1, str2) => str2 ? str1 + str2 : str1 } }
|
||||
)
|
||||
|
@ -21,6 +21,7 @@ export default class TransactionListItemDetails extends PureComponent {
|
||||
onCancel: PropTypes.func,
|
||||
onRetry: PropTypes.func,
|
||||
showCancel: PropTypes.bool,
|
||||
showSpeedUp: PropTypes.bool,
|
||||
showRetry: PropTypes.bool,
|
||||
isEarliestNonce: PropTypes.bool,
|
||||
cancelDisabled: PropTypes.bool,
|
||||
@ -123,6 +124,7 @@ export default class TransactionListItemDetails extends PureComponent {
|
||||
const { justCopied } = this.state
|
||||
const {
|
||||
transactionGroup,
|
||||
showSpeedUp,
|
||||
showRetry,
|
||||
onCancel,
|
||||
onRetry,
|
||||
@ -138,7 +140,7 @@ export default class TransactionListItemDetails extends PureComponent {
|
||||
<div>{ t('details') }</div>
|
||||
<div className="transaction-list-item-details__header-buttons">
|
||||
{
|
||||
showRetry && (
|
||||
showSpeedUp && (
|
||||
<Button
|
||||
type="raised"
|
||||
onClick={this.handleRetry}
|
||||
@ -172,6 +174,17 @@ export default class TransactionListItemDetails extends PureComponent {
|
||||
<img src="/images/arrow-popout.svg" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{
|
||||
showRetry && <Tooltip title={blockExplorerUrl ? t('viewOnCustomBlockExplorer', [blockExplorerUrl]) : t('retryTransaction')}>
|
||||
<Button
|
||||
type="raised"
|
||||
onClick={this.handleRetry}
|
||||
className="transaction-list-item-details__header-button"
|
||||
>
|
||||
<i className="fa fa-refresh"></i>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div className="transaction-list-item-details__body">
|
||||
|
@ -24,7 +24,7 @@ export default class TransactionListItem extends PureComponent {
|
||||
showCancelModal: PropTypes.func,
|
||||
showCancel: PropTypes.bool,
|
||||
hasEnoughCancelGas: PropTypes.bool,
|
||||
showRetry: PropTypes.bool,
|
||||
showSpeedUp: PropTypes.bool,
|
||||
isEarliestNonce: PropTypes.bool,
|
||||
showFiat: PropTypes.bool,
|
||||
token: PropTypes.object,
|
||||
@ -177,7 +177,7 @@ export default class TransactionListItem extends PureComponent {
|
||||
primaryTransaction,
|
||||
showCancel,
|
||||
hasEnoughCancelGas,
|
||||
showRetry,
|
||||
showSpeedUp,
|
||||
tokenData,
|
||||
transactionGroup,
|
||||
rpcPrefs,
|
||||
@ -233,7 +233,8 @@ export default class TransactionListItem extends PureComponent {
|
||||
<TransactionListItemDetails
|
||||
transactionGroup={transactionGroup}
|
||||
onRetry={this.handleRetry}
|
||||
showRetry={showRetry}
|
||||
showSpeedUp={showSpeedUp}
|
||||
showRetry={getStatusKey(primaryTransaction) === 'failed'}
|
||||
isEarliestNonce={isEarliestNonce}
|
||||
onCancel={this.handleCancel}
|
||||
showCancel={showCancel}
|
||||
|
@ -37,7 +37,7 @@ export default class TransactionList extends PureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
shouldShowRetry = (transactionGroup, isEarliestNonce) => {
|
||||
shouldShowSpeedUp = (transactionGroup, isEarliestNonce) => {
|
||||
const { transactions = [], hasRetried } = transactionGroup
|
||||
const [earliestTransaction = {}] = transactions
|
||||
const { submittedTime } = earliestTransaction
|
||||
@ -100,7 +100,7 @@ export default class TransactionList extends PureComponent {
|
||||
<TransactionListItem
|
||||
transactionGroup={transactionGroup}
|
||||
key={`${transactionGroup.nonce}:${index}`}
|
||||
showRetry={isPendingTx && this.shouldShowRetry(transactionGroup, index === 0)}
|
||||
showSpeedUp={isPendingTx && this.shouldShowSpeedUp(transactionGroup, index === 0)}
|
||||
showCancel={isPendingTx && this.shouldShowCancel(transactionGroup)}
|
||||
isEarliestNonce={isPendingTx && index === 0}
|
||||
token={selectedToken}
|
||||
|
@ -206,6 +206,10 @@ class Routes extends Component {
|
||||
}
|
||||
: null
|
||||
|
||||
const sidebarShouldClose = sidebarTransaction &&
|
||||
!sidebarTransaction.status === 'failed' &&
|
||||
!submittedPendingTransactions.find(({ id }) => id === sidebarTransaction.id)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classnames('app', { 'mouse-user-styles': isMouseUser})}
|
||||
@ -232,7 +236,7 @@ class Routes extends Component {
|
||||
}
|
||||
<Sidebar
|
||||
sidebarOpen={sidebarIsOpen}
|
||||
sidebarShouldClose={sidebarTransaction && !submittedPendingTransactions.find(({ id }) => id === sidebarTransaction.id)}
|
||||
sidebarShouldClose={sidebarShouldClose}
|
||||
hideSidebar={this.props.hideSidebar}
|
||||
transitionName={sidebarTransitionName}
|
||||
type={sidebarType}
|
||||
|
@ -350,6 +350,7 @@ var actions = {
|
||||
|
||||
createCancelTransaction,
|
||||
createSpeedUpTransaction,
|
||||
createRetryTransaction,
|
||||
|
||||
approveProviderRequestByOrigin,
|
||||
rejectProviderRequestByOrigin,
|
||||
@ -1860,6 +1861,28 @@ function createSpeedUpTransaction (txId, customGasPrice) {
|
||||
}
|
||||
}
|
||||
|
||||
function createRetryTransaction (txId, customGasPrice) {
|
||||
log.debug('background.createRetryTransaction')
|
||||
let newTx
|
||||
|
||||
return dispatch => {
|
||||
return new Promise((resolve, reject) => {
|
||||
background.createSpeedUpTransaction(txId, customGasPrice, (err, newState) => {
|
||||
if (err) {
|
||||
dispatch(actions.displayWarning(err.message))
|
||||
return reject(err)
|
||||
}
|
||||
|
||||
const { selectedAddressTxList } = newState
|
||||
newTx = selectedAddressTxList[selectedAddressTxList.length - 1]
|
||||
resolve(newState)
|
||||
})
|
||||
})
|
||||
.then(newState => dispatch(actions.updateMetamaskState(newState)))
|
||||
.then(() => newTx)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// config
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user