diff --git a/common/containers/Tabs/SendTransaction/components/Fields/Fields.tsx b/common/containers/Tabs/SendTransaction/components/Fields/Fields.tsx index e55f26fc..3e63d69b 100644 --- a/common/containers/Tabs/SendTransaction/components/Fields/Fields.tsx +++ b/common/containers/Tabs/SendTransaction/components/Fields/Fields.tsx @@ -1,11 +1,12 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; -import translate from 'translations'; +import translate, { translateRaw } from 'translations'; import { AppState } from 'features/reducers'; import * as selectors from 'features/selectors'; import { getOffline, getNetworkConfig } from 'features/config'; import { scheduleSelectors } from 'features/schedule'; +import { notificationsActions } from 'features/notifications'; import { AddressField, AmountField, @@ -38,7 +39,26 @@ interface StateProps { useScheduling: scheduleSelectors.ICurrentSchedulingToggle['value']; } -class FieldsClass extends Component { +interface DispatchProps { + showNotification: notificationsActions.TShowNotification; +} + +class FieldsClass extends Component { + public componentDidCatch(error: Error) { + if (error.message === 'Serialized transaction not found') { + /** + * @desc Occasionally, when a new signed transaction matches a previous transaction, + * the nonce does not update, since the transaction has not yet been confirmed. This triggers + * the component inside the of to throw + * an error when selecting the current transaction's serialized parameters. + * A longer term fix will involve finding a better way to calculate nonces to avoid + * nonce duplication on serial transactions. + */ + this.props.showNotification('danger', translateRaw('SIMILAR_TRANSACTION_ERROR')); + this.forceUpdate(); + } + } + public render() { const { shouldDisplay, schedulingAvailable, useScheduling } = this.props; @@ -106,10 +126,15 @@ class FieldsClass extends Component { } } -export const Fields = connect((state: AppState) => ({ - schedulingAvailable: - getNetworkConfig(state).name === 'Kovan' && selectors.getUnit(state) === 'ETH', - shouldDisplay: !selectors.isAnyOfflineWithWeb3(state), - offline: getOffline(state), - useScheduling: scheduleSelectors.getCurrentSchedulingToggle(state).value -}))(FieldsClass); +export const Fields = connect( + (state: AppState) => ({ + schedulingAvailable: + getNetworkConfig(state).name === 'Kovan' && selectors.getUnit(state) === 'ETH', + shouldDisplay: !selectors.isAnyOfflineWithWeb3(state), + offline: getOffline(state), + useScheduling: scheduleSelectors.getCurrentSchedulingToggle(state).value + }), + { + showNotification: notificationsActions.showNotification + } +)(FieldsClass); diff --git a/common/translations/lang/en.json b/common/translations/lang/en.json index 75918737..a935fcbe 100644 --- a/common/translations/lang/en.json +++ b/common/translations/lang/en.json @@ -664,6 +664,7 @@ "PAYMENT_ID_WARNING": "Don't forget to send your XMR with the payment ID [[?]](https://getmonero.org/resources/moneropedia/paymentid.html) above, or you WILL lose your funds.", "WHAT_IS_PAYMENT_ID": "what's a payment ID?", "ANNOUNCEMENT_MESSAGE": "MyCrypto.com no longer allows the use of private keys, mnemonics, or keystore files in the browser. To continue using them, please download the [MyCrypto Desktop App](https://download.mycrypto.com).", - "U2F_NOT_SUPPORTED": "The U2F standard that hardware wallets use does not seem to be supported by your browser. Please try again using Google Chrome." + "U2F_NOT_SUPPORTED": "The U2F standard that hardware wallets use does not seem to be supported by your browser. Please try again using Google Chrome.", + "SIMILAR_TRANSACTION_ERROR": "This transaction is very similar to a recent transaction. Please wait a few moments and try again, or click 'Advanced' and manually set the nonce to a new value." } }