fix(@desktop/wallet): Edit Networks: Add warning when failover and main rpc are the same

closes #11551
This commit is contained in:
Khushboo Mehta 2023-09-04 17:36:28 +02:00 committed by Khushboo-dev-cpp
parent 428ff4d089
commit a8cb40809c
12 changed files with 97 additions and 67 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -81,3 +81,4 @@ type ChainIdForUrlArgs* = ref object of Args
chainId*: int
success*: bool
url*: string
isMainUrl*: bool

View File

@ -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()
}

View File

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

View File

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

View File

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

View File

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