|
|
@ -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 || |
|
|
|