fix(@desktop/wallet): Edit Networks: Add warning when failover and main rpc are the same
closes #11551
This commit is contained in:
parent
428ff4d089
commit
a8cb40809c
|
@ -36,7 +36,7 @@ proc init*(self: Controller) =
|
|||
|
||||
self.events.on(SIGNAL_WALLET_ACCOUNT_CHAIN_ID_FOR_URL_FETCHED) do(e: Args):
|
||||
let args = ChainIdForUrlArgs(e)
|
||||
self.delegate.chainIdFetchedForUrl(args.url, args.chainId, args.success)
|
||||
self.delegate.chainIdFetchedForUrl(args.url, args.chainId, args.success, args.isMainUrl)
|
||||
|
||||
self.events.on(SIGNAL_NETWORK_ENDPOINT_UPDATED) do(e: Args):
|
||||
self.delegate.refreshNetworks()
|
||||
|
@ -50,8 +50,8 @@ proc areTestNetworksEnabled*(self: Controller): bool =
|
|||
proc toggleTestNetworksEnabled*(self: Controller) =
|
||||
self.walletAccountService.toggleTestNetworksEnabled()
|
||||
|
||||
proc fetchChainIdForUrl*(self: Controller, url: string) =
|
||||
self.walletAccountService.fetchChainIdForUrl(url)
|
||||
proc fetchChainIdForUrl*(self: Controller, url: string, isMainUrl: bool) =
|
||||
self.walletAccountService.fetchChainIdForUrl(url, isMainUrl)
|
||||
|
||||
proc updateNetworkEndPointValues*(self: Controller, chainId: int, newMainRpcInput, newFailoverRpcUrl: string) =
|
||||
self.networkService.updateNetworkEndPointValues(chainId, newMainRpcInput, newFailoverRpcUrl)
|
||||
|
|
|
@ -31,8 +31,8 @@ method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} =
|
|||
method updateNetworkEndPointValues*(self: AccessInterface, chainId: int, newMainRpcInput, newFailoverRpcUrl: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method fetchChainIdForUrl*(self: AccessInterface, url: string) {.base.} =
|
||||
method fetchChainIdForUrl*(self: AccessInterface, url: string, isMainUrl: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method chainIdFetchedForUrl*(self: AccessInterface, url: string, chainId: int, success: bool) {.base.} =
|
||||
method chainIdFetchedForUrl*(self: AccessInterface, url: string, chainId: int, success: bool, isMainUrl: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
|
|
@ -103,8 +103,8 @@ method toggleTestNetworksEnabled*(self: Module) =
|
|||
method updateNetworkEndPointValues*(self: Module, chainId: int, newMainRpcInput, newFailoverRpcUrl: string) =
|
||||
self.controller.updateNetworkEndPointValues(chainId, newMainRpcInput, newFailoverRpcUrl)
|
||||
|
||||
method fetchChainIdForUrl*(self: Module, url: string) =
|
||||
self.controller.fetchChainIdForUrl(url)
|
||||
method fetchChainIdForUrl*(self: Module, url: string, isMainUrl: bool) =
|
||||
self.controller.fetchChainIdForUrl(url, isMainUrl)
|
||||
|
||||
method chainIdFetchedForUrl*(self: Module, url: string, chainId: int, success: bool) =
|
||||
self.view.chainIdFetchedForUrl(url, chainId, success)
|
||||
method chainIdFetchedForUrl*(self: Module, url: string, chainId: int, success: bool, isMainUrl: bool) =
|
||||
self.view.chainIdFetchedForUrl(url, chainId, success, isMainUrl)
|
||||
|
|
|
@ -76,7 +76,7 @@ QtObject:
|
|||
proc updateNetworkEndPointValues*(self: View, chainId: int, newMainRpcInput: string, newFailoverRpcUrl: string) {.slot.} =
|
||||
self.delegate.updateNetworkEndPointValues(chainId, newMainRpcInput, newFailoverRpcUrl)
|
||||
|
||||
proc fetchChainIdForUrl*(self: View, url: string) {.slot.} =
|
||||
self.delegate.fetchChainIdForUrl(url)
|
||||
proc fetchChainIdForUrl*(self: View, url: string, isMainUrl: bool) {.slot.} =
|
||||
self.delegate.fetchChainIdForUrl(url, isMainUrl)
|
||||
|
||||
proc chainIdFetchedForUrl*(self: View, url: string, chainId: int, success: bool) {.signal.}
|
||||
proc chainIdFetchedForUrl*(self: View, url: string, chainId: int, success: bool, isMainUrl: bool) {.signal.}
|
||||
|
|
|
@ -164,6 +164,7 @@ const deleteKeycardAccountsTask*: Task = proc(argEncoded: string) {.gcsafe, nimc
|
|||
type
|
||||
FetchChainIdForUrlTaskArg* = ref object of QObjectTaskArg
|
||||
url: string
|
||||
isMainUrl: bool
|
||||
|
||||
const fetchChainIdForUrlTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[FetchChainIdForUrlTaskArg](argEncoded)
|
||||
|
@ -172,14 +173,16 @@ const fetchChainIdForUrlTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall
|
|||
arg.finish(%*{
|
||||
"success": true,
|
||||
"chainId": response.result.getInt,
|
||||
"url": arg.url
|
||||
"url": arg.url,
|
||||
"isMainUrl": arg.isMainUrl
|
||||
})
|
||||
except Exception as e:
|
||||
error "error when fetching chaind id from url: ", message = e.msg
|
||||
arg.finish(%*{
|
||||
"success": false,
|
||||
"chainId": -1,
|
||||
"url": arg.url
|
||||
"url": arg.url,
|
||||
"isMainUrl": arg.isMainUrl
|
||||
})
|
||||
|
||||
#################################################
|
||||
|
@ -204,4 +207,4 @@ const migrateNonProfileKeycardKeypairToAppTask*: Task = proc(argEncoded: string)
|
|||
responseJson["success"] = %* success
|
||||
except Exception as e:
|
||||
error "error migrating a non profile keycard keypair: ", message = e.msg
|
||||
arg.finish(responseJson)
|
||||
arg.finish(responseJson)
|
||||
|
|
|
@ -731,14 +731,16 @@ proc onFetchChainIdForUrl*(self: Service, jsonString: string) {.slot.} =
|
|||
chainId: response{"chainId"}.getInt,
|
||||
success: response{"success"}.getBool,
|
||||
url: response{"url"}.getStr,
|
||||
isMainUrl: response{"isMainUrl"}.getBool
|
||||
))
|
||||
|
||||
proc fetchChainIdForUrl*(self: Service, url: string) =
|
||||
proc fetchChainIdForUrl*(self: Service, url: string, isMainUrl: bool) =
|
||||
let arg = FetchChainIdForUrlTaskArg(
|
||||
tptr: cast[ByteAddress](fetchChainIdForUrlTask),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "onFetchChainIdForUrl",
|
||||
url: url
|
||||
url: url,
|
||||
isMainUrl: isMainUrl
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
|
||||
|
@ -758,4 +760,4 @@ proc importPartiallyOperableAccounts(self: Service, keyUid: string, password: st
|
|||
## Whenever user provides a password/pin we need to make all partially operable accounts (if any exists) a fully operable.
|
||||
if keyUid != singletonInstance.userProfile.getKeyUid():
|
||||
return
|
||||
self.makePartiallyOperableAccoutsFullyOperable(password, not singletonInstance.userProfile.getIsKeycardUser())
|
||||
self.makePartiallyOperableAccoutsFullyOperable(password, not singletonInstance.userProfile.getIsKeycardUser())
|
||||
|
|
|
@ -81,3 +81,4 @@ type ChainIdForUrlArgs* = ref object of Args
|
|||
chainId*: int
|
||||
success*: bool
|
||||
url*: string
|
||||
isMainUrl*: bool
|
||||
|
|
|
@ -67,7 +67,7 @@ SplitView {
|
|||
signal urlVerified(string url, int status)
|
||||
property string url
|
||||
|
||||
function evaluateRpcEndPoint(url) {
|
||||
function evaluateRpcEndPoint(url, isMainUrl) {
|
||||
networkModule.url = url
|
||||
d.timer.restart()
|
||||
}
|
||||
|
|
|
@ -72,8 +72,8 @@ QtObject {
|
|||
root.walletModule.runKeypairImportPopup(keyUid, mode)
|
||||
}
|
||||
|
||||
function evaluateRpcEndPoint(url) {
|
||||
return networksModule.fetchChainIdForUrl(url)
|
||||
function evaluateRpcEndPoint(url, isMainUrl) {
|
||||
return networksModule.fetchChainIdForUrl(url, isMainUrl)
|
||||
}
|
||||
|
||||
function updateNetworkEndPointValues(chainId, newMainRpcInput, newFailoverRpcUrl) {
|
||||
|
|
|
@ -152,7 +152,7 @@ SettingsContentBase {
|
|||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
networksModule: root.walletStore.networksModule
|
||||
onEvaluateRpcEndPoint: root.walletStore.evaluateRpcEndPoint(url)
|
||||
onEvaluateRpcEndPoint: root.walletStore.evaluateRpcEndPoint(url, isMainUrl)
|
||||
onUpdateNetworkValues: {
|
||||
root.walletStore.updateNetworkEndPointValues(chainId, newMainRpcInput, newFailoverRpcUrl)
|
||||
stackContainer.currentIndex = networksViewIndex
|
||||
|
|
|
@ -13,7 +13,7 @@ ColumnLayout {
|
|||
|
||||
property var network
|
||||
property var networksModule
|
||||
signal evaluateRpcEndPoint(string url)
|
||||
signal evaluateRpcEndPoint(string url, bool isMainUrl)
|
||||
signal updateNetworkValues(int chainId, string newMainRpcInput, string newFailoverRpcUrl)
|
||||
|
||||
enum EvaluationState {
|
||||
|
@ -21,29 +21,28 @@ ColumnLayout {
|
|||
Pending,
|
||||
Verified,
|
||||
InvalidURL,
|
||||
PingUnsuccessful
|
||||
PingUnsuccessful,
|
||||
SameAsOther
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property int evaluationStatus: EditNetworkForm.UnTouched
|
||||
property int evaluationStatusMainRpc: EditNetworkForm.UnTouched
|
||||
property int evaluationStatusFallBackRpc: EditNetworkForm.UnTouched
|
||||
property var evaluateRpcEndPoint: Backpressure.debounce(root, 400, function (value) {
|
||||
property var evaluateRpcEndPoint: Backpressure.debounce(root, 400, function (value, isMainUrl) {
|
||||
if(!Utils.isURL(value)) {
|
||||
if(value === mainRpcInput.text) {
|
||||
d.evaluationStatus = EditNetworkForm.InvalidURL
|
||||
}
|
||||
else if(value === failoverRpcUrlInput.text) {
|
||||
if(isMainUrl)
|
||||
d.evaluationStatusMainRpc = EditNetworkForm.InvalidURL
|
||||
else
|
||||
d.evaluationStatusFallBackRpc = EditNetworkForm.InvalidURL
|
||||
}
|
||||
return
|
||||
}
|
||||
root.evaluateRpcEndPoint(value)
|
||||
root.evaluateRpcEndPoint(value, isMainUrl)
|
||||
})
|
||||
|
||||
function revertValues() {
|
||||
warningCheckbox.checked = false
|
||||
d.evaluationStatus = EditNetworkForm.UnTouched
|
||||
d.evaluationStatusMainRpc = EditNetworkForm.UnTouched
|
||||
d.evaluationStatusFallBackRpc = EditNetworkForm.UnTouched
|
||||
if(!!network) {
|
||||
mainRpcInput.text = network.rpcURL
|
||||
|
@ -61,6 +60,8 @@ ColumnLayout {
|
|||
return qsTr("RPC appears to be either offline or this is not a valid JSON RPC endpoint URL")
|
||||
case EditNetworkForm.Verified:
|
||||
return qsTr("RPC successfully reached")
|
||||
case EditNetworkForm.SameAsOther:
|
||||
return qsTr("Main and failover JSON RPC URLs are the same")
|
||||
default: return ""
|
||||
}
|
||||
}
|
||||
|
@ -70,17 +71,20 @@ ColumnLayout {
|
|||
|
||||
Connections {
|
||||
target: networksModule
|
||||
function onChainIdFetchedForUrl(url, chainId, success) {
|
||||
function onChainIdFetchedForUrl(url, chainId, success, isMainUrl) {
|
||||
let status = EditNetworkForm.PingUnsuccessful
|
||||
if(success) {
|
||||
status = EditNetworkForm.Verified
|
||||
}
|
||||
if(url === mainRpcInput.text) {
|
||||
d.evaluationStatus = status
|
||||
}
|
||||
else if(url === failoverRpcUrlInput.text) {
|
||||
d.evaluationStatusFallBackRpc = status
|
||||
if((isMainUrl && url === network.fallbackURL) ||
|
||||
(!isMainUrl && url === network.rpcURL)) {
|
||||
status = EditNetworkForm.SameAsOther
|
||||
}
|
||||
else
|
||||
status = EditNetworkForm.Verified
|
||||
}
|
||||
if(isMainUrl)
|
||||
d.evaluationStatusMainRpc = status
|
||||
else
|
||||
d.evaluationStatusFallBackRpc = status
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,26 +139,37 @@ ColumnLayout {
|
|||
if (!network) {
|
||||
return ""
|
||||
}
|
||||
if (network.originalRpcURL == network.rpcURL) {
|
||||
if (network.originalRpcURL === network.rpcURL) {
|
||||
return network.rpcURL.replace(/(.*\/).*/, '$1')
|
||||
}
|
||||
return network.rpcURL
|
||||
}
|
||||
onTextChanged: {
|
||||
if(!!text && text !== network.rpcURL.replace(/(.*\/).*/, '$1')) {
|
||||
d.evaluationStatus = EditNetworkForm.Pending
|
||||
Qt.callLater(d.evaluateRpcEndPoint, text);
|
||||
if(!!text &&
|
||||
(network.originalRpcURL === network.rpcURL && text !== network.rpcURL.replace(/(.*\/).*/, '$1')) ||
|
||||
(network.originalRpcURL !== network.rpcURL && text !== network.rpcURL)) {
|
||||
d.evaluationStatusMainRpc = EditNetworkForm.Pending
|
||||
Qt.callLater(d.evaluateRpcEndPoint, text, true);
|
||||
}
|
||||
}
|
||||
errorMessageCmp.horizontalAlignment: d.evaluationStatus === EditNetworkForm.Pending ||
|
||||
d.evaluationStatus === EditNetworkForm.Verified ?
|
||||
errorMessageCmp.horizontalAlignment: d.evaluationStatusMainRpc === EditNetworkForm.Pending ||
|
||||
d.evaluationStatusMainRpc === EditNetworkForm.Verified ||
|
||||
d.evaluationStatusMainRpc === EditNetworkForm.SameAsOther ?
|
||||
Text.AlignLeft: Text.AlignRight
|
||||
errorMessageCmp.visible: d.evaluationStatus !== EditNetworkForm.UnTouched
|
||||
errorMessageCmp.text: d.getUrlStatusText(d.evaluationStatus, text)
|
||||
errorMessageCmp.color: d.evaluationStatus === EditNetworkForm.Pending ?
|
||||
Theme.palette.baseColor1:
|
||||
d.evaluationStatus === EditNetworkForm.Verified ?
|
||||
Theme.palette.successColor1 : Theme.palette.dangerColor1
|
||||
errorMessageCmp.visible: d.evaluationStatusMainRpc !== EditNetworkForm.UnTouched
|
||||
errorMessageCmp.text: d.getUrlStatusText(d.evaluationStatusMainRpc, text)
|
||||
errorMessageCmp.color: {
|
||||
switch(d.evaluationStatusMainRpc) {
|
||||
case EditNetworkForm.Pending:
|
||||
return Theme.palette.baseColor1
|
||||
case EditNetworkForm.SameAsOther:
|
||||
return Theme.palette.warningColor1
|
||||
case EditNetworkForm.Verified:
|
||||
return Theme.palette.successColor1
|
||||
default: return Theme.palette.dangerColor1
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,27 +181,36 @@ ColumnLayout {
|
|||
if (!network) {
|
||||
return ""
|
||||
}
|
||||
if (network.originalFallbackURL == network.fallbackURL) {
|
||||
if (network.originalFallbackURL === network.fallbackURL) {
|
||||
return network.fallbackURL.replace(/(.*\/).*/, '$1')
|
||||
}
|
||||
return network.fallbackURL
|
||||
}
|
||||
onTextChanged: {
|
||||
if(!!text && text !== network.fallbackURL.replace(/(.*\/).*/, '$1')) {
|
||||
if(!!text &&
|
||||
(network.originalFallbackURL === network.fallbackURL && text !== network.fallbackURL.replace(/(.*\/).*/, '$1')) ||
|
||||
(network.originalFallbackURL !== network.fallbackURL && text !== network.fallbackURL)) {
|
||||
d.evaluationStatusFallBackRpc = EditNetworkForm.Pending
|
||||
Qt.callLater(d.evaluateRpcEndPoint, text);
|
||||
Qt.callLater(d.evaluateRpcEndPoint, text, false);
|
||||
}
|
||||
}
|
||||
errorMessageCmp.horizontalAlignment: d.evaluationStatusFallBackRpc === EditNetworkForm.Pending ||
|
||||
d.evaluationStatusFallBackRpc === EditNetworkForm.Verified ?
|
||||
d.evaluationStatusFallBackRpc === EditNetworkForm.Verified ||
|
||||
d.evaluationStatusFallBackRpc === EditNetworkForm.SameAsOther ?
|
||||
Text.AlignLeft: Text.AlignRight
|
||||
errorMessageCmp.visible: d.evaluationStatusFallBackRpc !== EditNetworkForm.UnTouched
|
||||
errorMessageCmp.text: d.getUrlStatusText(d.evaluationStatusFallBackRpc, text)
|
||||
errorMessageCmp.color: d.evaluationStatusFallBackRpc === EditNetworkForm.Pending ?
|
||||
Theme.palette.baseColor1:
|
||||
d.evaluationStatusFallBackRpc === EditNetworkForm.Verified ?
|
||||
Theme.palette.successColor1 : Theme.palette.dangerColor1
|
||||
|
||||
errorMessageCmp.color: {
|
||||
switch(d.evaluationStatusFallBackRpc) {
|
||||
case EditNetworkForm.Pending:
|
||||
return Theme.palette.baseColor1
|
||||
case EditNetworkForm.SameAsOther:
|
||||
return Theme.palette.warningColor1
|
||||
case EditNetworkForm.Verified:
|
||||
return Theme.palette.successColor1
|
||||
default: return Theme.palette.dangerColor1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusInput {
|
||||
|
@ -212,12 +236,12 @@ ColumnLayout {
|
|||
StatusButton {
|
||||
text: qsTr("Revert to default")
|
||||
normalColor: "transparent"
|
||||
enabled: d.evaluationStatus !== EditNetworkForm.UnTouched || d.evaluationStatusFallBackRpc !== EditNetworkForm.UnTouched
|
||||
enabled: d.evaluationStatusMainRpc !== EditNetworkForm.UnTouched || d.evaluationStatusFallBackRpc !== EditNetworkForm.UnTouched
|
||||
onClicked: d.revertValues()
|
||||
}
|
||||
StatusButton {
|
||||
text: qsTr("Save Changes")
|
||||
enabled: (d.evaluationStatus === EditNetworkForm.Verified || d.evaluationStatusFallBackRpc === EditNetworkForm.Verified) && warningCheckbox.checked
|
||||
enabled: (d.evaluationStatusMainRpc === EditNetworkForm.Verified || d.evaluationStatusFallBackRpc === EditNetworkForm.Verified || d.evaluationStatusMainRpc === EditNetworkForm.SameAsOther || d.evaluationStatusFallBackRpc === EditNetworkForm.SameAsOther) && warningCheckbox.checked
|
||||
onClicked: root.updateNetworkValues(network.chainId, mainRpcInput.text, failoverRpcUrlInput.text)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ ColumnLayout {
|
|||
property var networksModule
|
||||
property var combinedNetwork
|
||||
|
||||
signal evaluateRpcEndPoint(string url)
|
||||
signal evaluateRpcEndPoint(string url, bool isMainUrl)
|
||||
signal updateNetworkValues(int chainId, string newMainRpcInput, string newFailoverRpcUrl)
|
||||
|
||||
StatusTabBar {
|
||||
|
@ -39,7 +39,7 @@ ColumnLayout {
|
|||
EditNetworkForm {
|
||||
network: !!root.combinedNetwork ? root.combinedNetwork.prod: null
|
||||
networksModule: root.networksModule
|
||||
onEvaluateRpcEndPoint: root.evaluateRpcEndPoint(url)
|
||||
onEvaluateRpcEndPoint: root.evaluateRpcEndPoint(url, isMainUrl)
|
||||
onUpdateNetworkValues: root.updateNetworkValues(chainId, newMainRpcInput, newFailoverRpcUrl)
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ ColumnLayout {
|
|||
EditNetworkForm {
|
||||
network: !!root.combinedNetwork ? root.combinedNetwork.test: null
|
||||
networksModule: root.networksModule
|
||||
onEvaluateRpcEndPoint: root.evaluateRpcEndPoint(url)
|
||||
onEvaluateRpcEndPoint: root.evaluateRpcEndPoint(url, isMainUrl)
|
||||
onUpdateNetworkValues: root.updateNetworkValues(chainId, newMainRpcInput, newFailoverRpcUrl)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue