mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Fix network form save behavior (#9851)
* Fix chainId display in network form on save * Disable save button while submitting * Ensure submission state if encountering error during onSubmit
This commit is contained in:
commit
6b38017b23
@ -9,6 +9,14 @@ import Tooltip from '../../../../components/ui/tooltip'
|
|||||||
import { isPrefixedFormattedHexString } from '../../../../../../app/scripts/lib/util'
|
import { isPrefixedFormattedHexString } from '../../../../../../app/scripts/lib/util'
|
||||||
import { jsonRpcRequest } from '../../../../helpers/utils/util'
|
import { jsonRpcRequest } from '../../../../helpers/utils/util'
|
||||||
|
|
||||||
|
const FORM_STATE_KEYS = [
|
||||||
|
'rpcUrl',
|
||||||
|
'chainId',
|
||||||
|
'ticker',
|
||||||
|
'networkName',
|
||||||
|
'blockExplorerUrl',
|
||||||
|
]
|
||||||
|
|
||||||
export default class NetworkForm extends PureComponent {
|
export default class NetworkForm extends PureComponent {
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
t: PropTypes.func.isRequired,
|
t: PropTypes.func.isRequired,
|
||||||
@ -35,25 +43,17 @@ export default class NetworkForm extends PureComponent {
|
|||||||
|
|
||||||
state = {
|
state = {
|
||||||
rpcUrl: this.props.rpcUrl,
|
rpcUrl: this.props.rpcUrl,
|
||||||
chainId: this.getDisplayChainIdFromProps(),
|
chainId: this.getDisplayChainId(this.props.chainId),
|
||||||
ticker: this.props.ticker,
|
ticker: this.props.ticker,
|
||||||
networkName: this.props.networkName,
|
networkName: this.props.networkName,
|
||||||
blockExplorerUrl: this.props.blockExplorerUrl,
|
blockExplorerUrl: this.props.blockExplorerUrl,
|
||||||
errors: {},
|
errors: {},
|
||||||
|
isSubmitting: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
const {
|
const { networksTabIsInAddMode: prevAddMode } = prevProps
|
||||||
rpcUrl: prevRpcUrl,
|
const { networksTabIsInAddMode } = this.props
|
||||||
networksTabIsInAddMode: prevAddMode,
|
|
||||||
} = prevProps
|
|
||||||
const {
|
|
||||||
rpcUrl,
|
|
||||||
ticker,
|
|
||||||
networkName,
|
|
||||||
networksTabIsInAddMode,
|
|
||||||
blockExplorerUrl,
|
|
||||||
} = this.props
|
|
||||||
|
|
||||||
if (!prevAddMode && networksTabIsInAddMode) {
|
if (!prevAddMode && networksTabIsInAddMode) {
|
||||||
this.setState({
|
this.setState({
|
||||||
@ -63,16 +63,15 @@ export default class NetworkForm extends PureComponent {
|
|||||||
networkName: '',
|
networkName: '',
|
||||||
blockExplorerUrl: '',
|
blockExplorerUrl: '',
|
||||||
errors: {},
|
errors: {},
|
||||||
|
isSubmitting: false,
|
||||||
})
|
})
|
||||||
} else if (prevRpcUrl !== rpcUrl) {
|
} else {
|
||||||
this.setState({
|
for (const key of FORM_STATE_KEYS) {
|
||||||
rpcUrl,
|
if (prevProps[key] !== this.props[key]) {
|
||||||
chainId: this.getDisplayChainIdFromProps(),
|
this.resetForm()
|
||||||
ticker,
|
break
|
||||||
networkName,
|
}
|
||||||
blockExplorerUrl,
|
}
|
||||||
errors: {},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,86 +92,100 @@ export default class NetworkForm extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resetForm() {
|
resetForm() {
|
||||||
const { rpcUrl, ticker, networkName, blockExplorerUrl } = this.props
|
const {
|
||||||
|
rpcUrl,
|
||||||
|
chainId,
|
||||||
|
ticker,
|
||||||
|
networkName,
|
||||||
|
blockExplorerUrl,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
rpcUrl,
|
rpcUrl,
|
||||||
chainId: this.getDisplayChainIdFromProps(),
|
chainId: this.getDisplayChainId(chainId),
|
||||||
ticker,
|
ticker,
|
||||||
networkName,
|
networkName,
|
||||||
blockExplorerUrl,
|
blockExplorerUrl,
|
||||||
errors: {},
|
errors: {},
|
||||||
|
isSubmitting: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures that the chainId is always displayed in decimal, even though
|
* Attempts to convert the given chainId to a decimal string, for display
|
||||||
* it's stored in hexadecimal.
|
* 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.
|
* 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() {
|
getDisplayChainId(chainId) {
|
||||||
const { chainId: propsChainId } = this.props
|
if (!chainId || typeof chainId !== 'string' || !chainId.startsWith('0x')) {
|
||||||
|
return chainId
|
||||||
if (
|
|
||||||
!propsChainId ||
|
|
||||||
typeof propsChainId !== 'string' ||
|
|
||||||
!propsChainId.startsWith('0x')
|
|
||||||
) {
|
|
||||||
return propsChainId
|
|
||||||
}
|
}
|
||||||
return new BigNumber(propsChainId, 16).toString(10)
|
return new BigNumber(chainId, 16).toString(10)
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit = async () => {
|
onSubmit = async () => {
|
||||||
const {
|
this.setState({
|
||||||
setRpcTarget,
|
isSubmitting: true,
|
||||||
rpcUrl: propsRpcUrl,
|
})
|
||||||
editRpc,
|
|
||||||
rpcPrefs = {},
|
|
||||||
onClear,
|
|
||||||
networksTabIsInAddMode,
|
|
||||||
} = this.props
|
|
||||||
const {
|
|
||||||
networkName,
|
|
||||||
rpcUrl,
|
|
||||||
chainId: stateChainId,
|
|
||||||
ticker,
|
|
||||||
blockExplorerUrl,
|
|
||||||
} = this.state
|
|
||||||
|
|
||||||
const formChainId = stateChainId.trim().toLowerCase()
|
try {
|
||||||
// Ensure chainId is a 0x-prefixed, lowercase hex string
|
const {
|
||||||
let chainId = formChainId
|
setRpcTarget,
|
||||||
if (!chainId.startsWith('0x')) {
|
rpcUrl: propsRpcUrl,
|
||||||
chainId = `0x${new BigNumber(chainId, 10).toString(16)}`
|
editRpc,
|
||||||
}
|
rpcPrefs = {},
|
||||||
|
onClear,
|
||||||
|
networksTabIsInAddMode,
|
||||||
|
} = this.props
|
||||||
|
const {
|
||||||
|
networkName,
|
||||||
|
rpcUrl,
|
||||||
|
chainId: stateChainId,
|
||||||
|
ticker,
|
||||||
|
blockExplorerUrl,
|
||||||
|
} = this.state
|
||||||
|
|
||||||
if (!(await this.validateChainIdOnSubmit(formChainId, chainId, rpcUrl))) {
|
const formChainId = stateChainId.trim().toLowerCase()
|
||||||
return
|
// 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 (propsRpcUrl && rpcUrl !== propsRpcUrl) {
|
if (!(await this.validateChainIdOnSubmit(formChainId, chainId, rpcUrl))) {
|
||||||
await editRpc(propsRpcUrl, rpcUrl, chainId, ticker, networkName, {
|
this.setState({
|
||||||
blockExplorerUrl: blockExplorerUrl || rpcPrefs.blockExplorerUrl,
|
isSubmitting: false,
|
||||||
...rpcPrefs,
|
})
|
||||||
})
|
return
|
||||||
} else {
|
}
|
||||||
await setRpcTarget(rpcUrl, chainId, ticker, networkName, {
|
|
||||||
blockExplorerUrl: blockExplorerUrl || rpcPrefs.blockExplorerUrl,
|
|
||||||
...rpcPrefs,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (networksTabIsInAddMode) {
|
// After this point, isSubmitting will be reset in componentDidUpdate
|
||||||
onClear()
|
if (propsRpcUrl && rpcUrl !== propsRpcUrl) {
|
||||||
} else {
|
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) {
|
||||||
this.setState({
|
this.setState({
|
||||||
chainId: this.getDisplayChainIdFromProps(),
|
isSubmitting: false,
|
||||||
})
|
})
|
||||||
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,6 +210,10 @@ export default class NetworkForm extends PureComponent {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isSubmitting() {
|
||||||
|
return this.state.isSubmitting
|
||||||
|
}
|
||||||
|
|
||||||
stateIsUnchanged() {
|
stateIsUnchanged() {
|
||||||
const {
|
const {
|
||||||
rpcUrl,
|
rpcUrl,
|
||||||
@ -220,7 +237,7 @@ export default class NetworkForm extends PureComponent {
|
|||||||
const chainIdIsUnchanged =
|
const chainIdIsUnchanged =
|
||||||
typeof propsChainId === 'string' &&
|
typeof propsChainId === 'string' &&
|
||||||
propsChainId.toLowerCase().startsWith('0x') &&
|
propsChainId.toLowerCase().startsWith('0x') &&
|
||||||
stateChainId === this.getDisplayChainIdFromProps()
|
stateChainId === this.getDisplayChainId(propsChainId)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
stateRpcUrl === rpcUrl &&
|
stateRpcUrl === rpcUrl &&
|
||||||
@ -424,6 +441,7 @@ export default class NetworkForm extends PureComponent {
|
|||||||
!networksTabIsInAddMode && !isCurrentRpcTarget && !viewOnly
|
!networksTabIsInAddMode && !isCurrentRpcTarget && !viewOnly
|
||||||
|
|
||||||
const isSubmitDisabled =
|
const isSubmitDisabled =
|
||||||
|
this.isSubmitting() ||
|
||||||
this.stateIsUnchanged() ||
|
this.stateIsUnchanged() ||
|
||||||
!rpcUrl ||
|
!rpcUrl ||
|
||||||
!chainId ||
|
!chainId ||
|
||||||
|
Loading…
x
Reference in New Issue
Block a user