From 4db9c8b36fd040c596bc4d6e95fd0ce7f59c131c Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Tue, 10 Nov 2020 22:41:19 -0800 Subject: [PATCH 1/4] Fix chainId display in network form on save --- .../network-form/network-form.component.js | 49 +++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js index 055e95d49..8f36bb484 100644 --- a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js +++ b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js @@ -35,7 +35,7 @@ export default class NetworkForm extends PureComponent { state = { rpcUrl: this.props.rpcUrl, - chainId: this.getDisplayChainIdFromProps(), + chainId: this.getDisplayChainId(this.props.chainId), ticker: this.props.ticker, networkName: this.props.networkName, blockExplorerUrl: this.props.blockExplorerUrl, @@ -49,6 +49,7 @@ export default class NetworkForm extends PureComponent { } = prevProps const { rpcUrl, + chainId, ticker, networkName, networksTabIsInAddMode, @@ -67,7 +68,7 @@ export default class NetworkForm extends PureComponent { } else if (prevRpcUrl !== rpcUrl) { this.setState({ rpcUrl, - chainId: this.getDisplayChainIdFromProps(), + chainId: this.getDisplayChainId(chainId), ticker, networkName, blockExplorerUrl, @@ -93,11 +94,17 @@ export default class NetworkForm extends PureComponent { } resetForm() { - const { rpcUrl, ticker, networkName, blockExplorerUrl } = this.props + const { + rpcUrl, + chainId, + ticker, + networkName, + blockExplorerUrl, + } = this.props this.setState({ rpcUrl, - chainId: this.getDisplayChainIdFromProps(), + chainId: this.getDisplayChainId(chainId), ticker, networkName, blockExplorerUrl, @@ -106,25 +113,21 @@ export default class NetworkForm extends PureComponent { } /** - * Ensures that the chainId is always displayed in decimal, even though - * it's stored in hexadecimal. + * Attempts to convert the given chainId to a decimal string, for display + * purposes. * - * Should be called to get the chainId whenever props are used to set the + * Should be called with the props chainId whenever it is used to set the * component's state. * - * @returns {string} The props chainId in decimal. + * @param {unknown} chainId - The chainId to convert. + * @returns {string} The props chainId in decimal, or the original value if + * it can't be converted. */ - getDisplayChainIdFromProps() { - const { chainId: propsChainId } = this.props - - if ( - !propsChainId || - typeof propsChainId !== 'string' || - !propsChainId.startsWith('0x') - ) { - return propsChainId + getDisplayChainId(chainId) { + if (!chainId || typeof chainId !== 'string' || !chainId.startsWith('0x')) { + return chainId } - return new BigNumber(propsChainId, 16).toString(10) + return new BigNumber(chainId, 16).toString(10) } onSubmit = async () => { @@ -157,22 +160,18 @@ export default class NetworkForm extends PureComponent { if (propsRpcUrl && rpcUrl !== propsRpcUrl) { await editRpc(propsRpcUrl, rpcUrl, chainId, ticker, networkName, { - blockExplorerUrl: blockExplorerUrl || rpcPrefs.blockExplorerUrl, ...rpcPrefs, + blockExplorerUrl: blockExplorerUrl || rpcPrefs.blockExplorerUrl, }) } else { await setRpcTarget(rpcUrl, chainId, ticker, networkName, { - blockExplorerUrl: blockExplorerUrl || rpcPrefs.blockExplorerUrl, ...rpcPrefs, + blockExplorerUrl: blockExplorerUrl || rpcPrefs.blockExplorerUrl, }) } if (networksTabIsInAddMode) { onClear() - } else { - this.setState({ - chainId: this.getDisplayChainIdFromProps(), - }) } } @@ -220,7 +219,7 @@ export default class NetworkForm extends PureComponent { const chainIdIsUnchanged = typeof propsChainId === 'string' && propsChainId.toLowerCase().startsWith('0x') && - stateChainId === this.getDisplayChainIdFromProps() + stateChainId === this.getDisplayChainId(propsChainId) return ( stateRpcUrl === rpcUrl && From 53bf9cb76644b174f22f11e65a72badbc99dd080 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Tue, 10 Nov 2020 23:39:49 -0800 Subject: [PATCH 2/4] Disable save button while submitting --- .../network-form/network-form.component.js | 54 +++++++++++-------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js index 8f36bb484..22a83324f 100644 --- a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js +++ b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js @@ -9,6 +9,14 @@ import Tooltip from '../../../../components/ui/tooltip' import { isPrefixedFormattedHexString } from '../../../../../../app/scripts/lib/util' import { jsonRpcRequest } from '../../../../helpers/utils/util' +const FORM_STATE_KEYS = [ + 'rpcUrl', + 'chainId', + 'ticker', + 'networkName', + 'blockExplorerUrl', +] + export default class NetworkForm extends PureComponent { static contextTypes = { t: PropTypes.func.isRequired, @@ -40,21 +48,12 @@ export default class NetworkForm extends PureComponent { networkName: this.props.networkName, blockExplorerUrl: this.props.blockExplorerUrl, errors: {}, + isSubmitting: false, } componentDidUpdate(prevProps) { - const { - rpcUrl: prevRpcUrl, - networksTabIsInAddMode: prevAddMode, - } = prevProps - const { - rpcUrl, - chainId, - ticker, - networkName, - networksTabIsInAddMode, - blockExplorerUrl, - } = this.props + const { networksTabIsInAddMode: prevAddMode } = prevProps + const { networksTabIsInAddMode } = this.props if (!prevAddMode && networksTabIsInAddMode) { this.setState({ @@ -64,16 +63,15 @@ export default class NetworkForm extends PureComponent { networkName: '', blockExplorerUrl: '', errors: {}, + isSubmitting: false, }) - } else if (prevRpcUrl !== rpcUrl) { - this.setState({ - rpcUrl, - chainId: this.getDisplayChainId(chainId), - ticker, - networkName, - blockExplorerUrl, - errors: {}, - }) + } else { + for (const key of FORM_STATE_KEYS) { + if (prevProps[key] !== this.props[key]) { + this.resetForm() + break + } + } } } @@ -109,6 +107,7 @@ export default class NetworkForm extends PureComponent { networkName, blockExplorerUrl, errors: {}, + isSubmitting: false, }) } @@ -131,6 +130,10 @@ export default class NetworkForm extends PureComponent { } onSubmit = async () => { + this.setState({ + isSubmitting: true, + }) + const { setRpcTarget, rpcUrl: propsRpcUrl, @@ -155,9 +158,13 @@ export default class NetworkForm extends PureComponent { } if (!(await this.validateChainIdOnSubmit(formChainId, chainId, rpcUrl))) { + this.setState({ + isSubmitting: false, + }) return } + // After this point, isSubmitting will be reset in componentDidUpdate if (propsRpcUrl && rpcUrl !== propsRpcUrl) { await editRpc(propsRpcUrl, rpcUrl, chainId, ticker, networkName, { ...rpcPrefs, @@ -196,6 +203,10 @@ export default class NetworkForm extends PureComponent { }) } + isSubmitting() { + return this.state.isSubmitting + } + stateIsUnchanged() { const { rpcUrl, @@ -423,6 +434,7 @@ export default class NetworkForm extends PureComponent { !networksTabIsInAddMode && !isCurrentRpcTarget && !viewOnly const isSubmitDisabled = + this.isSubmitting() || this.stateIsUnchanged() || !rpcUrl || !chainId || From a714da80693a82f070027d23e7360c89bdce897c Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Wed, 11 Nov 2020 12:28:20 -0800 Subject: [PATCH 3/4] Ensure submission state is reset on onSubmit error --- .../network-form/network-form.component.js | 87 ++++++++++--------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js index 22a83324f..4660c9f2e 100644 --- a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js +++ b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js @@ -134,51 +134,58 @@ export default class NetworkForm extends PureComponent { isSubmitting: true, }) - const { - setRpcTarget, - rpcUrl: propsRpcUrl, - editRpc, - rpcPrefs = {}, - onClear, - networksTabIsInAddMode, - } = this.props - const { - networkName, - rpcUrl, - chainId: stateChainId, - ticker, - blockExplorerUrl, - } = this.state + try { + const { + setRpcTarget, + rpcUrl: propsRpcUrl, + editRpc, + rpcPrefs = {}, + onClear, + networksTabIsInAddMode, + } = this.props + const { + networkName, + rpcUrl, + chainId: stateChainId, + ticker, + blockExplorerUrl, + } = this.state + + const formChainId = stateChainId.trim().toLowerCase() + // Ensure chainId is a 0x-prefixed, lowercase hex string + let chainId = formChainId + if (!chainId.startsWith('0x')) { + chainId = `0x${new BigNumber(chainId, 10).toString(16)}` + } - const formChainId = stateChainId.trim().toLowerCase() - // Ensure chainId is a 0x-prefixed, lowercase hex string - let chainId = formChainId - if (!chainId.startsWith('0x')) { - chainId = `0x${new BigNumber(chainId, 10).toString(16)}` - } + if (!(await this.validateChainIdOnSubmit(formChainId, chainId, rpcUrl))) { + this.setState({ + isSubmitting: false, + }) + return + } - if (!(await this.validateChainIdOnSubmit(formChainId, chainId, rpcUrl))) { + // After this point, isSubmitting will be reset in componentDidUpdate + if (propsRpcUrl && rpcUrl !== propsRpcUrl) { + await editRpc(propsRpcUrl, rpcUrl, chainId, ticker, networkName, { + ...rpcPrefs, + blockExplorerUrl: blockExplorerUrl || rpcPrefs.blockExplorerUrl, + }) + } else { + await setRpcTarget(rpcUrl, chainId, ticker, networkName, { + ...rpcPrefs, + blockExplorerUrl: blockExplorerUrl || rpcPrefs.blockExplorerUrl, + }) + } + + if (networksTabIsInAddMode) { + onClear() + } + } catch (error) { + log.error('Unexpected error during form submission.', error) this.setState({ isSubmitting: false, }) - return - } - - // After this point, isSubmitting will be reset in componentDidUpdate - if (propsRpcUrl && rpcUrl !== propsRpcUrl) { - await editRpc(propsRpcUrl, rpcUrl, chainId, ticker, networkName, { - ...rpcPrefs, - blockExplorerUrl: blockExplorerUrl || rpcPrefs.blockExplorerUrl, - }) - } else { - await setRpcTarget(rpcUrl, chainId, ticker, networkName, { - ...rpcPrefs, - blockExplorerUrl: blockExplorerUrl || rpcPrefs.blockExplorerUrl, - }) - } - - if (networksTabIsInAddMode) { - onClear() } } From 876ca136b33715cc0bb242697fa760da4bcc30e3 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Wed, 11 Nov 2020 12:39:26 -0800 Subject: [PATCH 4/4] Throw instead of log error --- .../networks-tab/network-form/network-form.component.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js index 4660c9f2e..327ff5fe7 100644 --- a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js +++ b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js @@ -182,10 +182,10 @@ export default class NetworkForm extends PureComponent { onClear() } } catch (error) { - log.error('Unexpected error during form submission.', error) this.setState({ isSubmitting: false, }) + throw error } }