fix(@desktop/wallet): Remove auto retries for connections errors. In case of an error there are two things that can happen

1. The user can manually click on "Retry now"
2. We have a 10 in timer on wallet, after whichb all the data shown is refreshed

fixes #10124
This commit is contained in:
Khushboo Mehta 2023-04-03 19:13:23 +02:00 committed by Khushboo-dev-cpp
parent ef4ffce909
commit 0426d7de55
8 changed files with 81 additions and 143 deletions

View File

@ -27,7 +27,7 @@ proc delete*(self: Controller) =
proc init*(self: Controller) =
self.events.on(SIGNAL_CONNECTION_UPDATE) do(e:Args):
let args = NetworkConnectionsArgs(e)
self.delegate.networkConnectionStatusUpdate(args.website, args.completelyDown, ord(args.connectionState), args.chainIds, args.lastCheckedAt, args.timeToAutoRetryInSecs)
self.delegate.networkConnectionStatusUpdate(args.website, args.completelyDown, ord(args.connectionState), args.chainIds, args.lastCheckedAt)
self.events.on(SIGNAL_NETWORK_CONNECTED) do(e: Args):
self.networkConnectionService.networkConnected(true)

View File

@ -19,7 +19,7 @@ method isLoaded*(self: AccessInterface): bool {.base.} =
method viewDidLoad*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method networkConnectionStatusUpdate*(self: AccessInterface, website: string, completelyDown: bool, connectionState: int, chainIds: string, lastCheckedAt: int, timeToAutoRetryInSecs: int) {.base.} =
method networkConnectionStatusUpdate*(self: AccessInterface, website: string, completelyDown: bool, connectionState: int, chainIds: string, lastCheckedAt: int) {.base.} =
raise newException(ValueError, "No implementation available")
method refreshBlockchainValues*(self: AccessInterface) {.base.} =

View File

@ -49,8 +49,8 @@ proc checkIfModuleDidLoad(self: Module) =
method viewDidLoad*(self: Module) =
self.checkIfModuleDidLoad()
method networkConnectionStatusUpdate*(self: Module, website: string, completelyDown: bool, connectionState: int, chainIds: string, lastCheckedAt: int, timeToAutoRetryInSecs: int) =
self.view.updateNetworkConnectionStatus(website, completelyDown, connectionState, chainIds, lastCheckedAt, timeToAutoRetryInSecs)
method networkConnectionStatusUpdate*(self: Module, website: string, completelyDown: bool, connectionState: int, chainIds: string, lastCheckedAt: int) =
self.view.updateNetworkConnectionStatus(website, completelyDown, connectionState, chainIds, lastCheckedAt)
method refreshBlockchainValues*(self: Module) =
self.controller.refreshBlockchainValues()

View File

@ -6,27 +6,24 @@ QtObject:
connectionState: int
chainIds: string
lastCheckedAt: int
timeToAutoRetryInSecs: int
proc delete*(self: NetworkConnectionItem) =
self.QObject.delete
proc newNetworkConnectionItem*(completelyDown = false, connectionState = 0, chainIds = "", lastCheckedAt = 0, timeToAutoRetryInSecs = 0): NetworkConnectionItem =
proc newNetworkConnectionItem*(completelyDown = false, connectionState = 0, chainIds = "", lastCheckedAt = 0): NetworkConnectionItem =
new(result, delete)
result.QObject.setup
result.completelyDown = completelyDown
result.connectionState = connectionState
result.chainIds = chainIds
result.lastCheckedAt = lastCheckedAt
result.timeToAutoRetryInSecs = timeToAutoRetryInSecs
proc `$`*(self: NetworkConnectionItem): string =
result = fmt"""NetworkConnectionItem[
completelyDown: {self.completelyDown},
connectionState: {self.connectionState},
chainIds: {self.chainIds},
lastCheckedAt: {self.lastCheckedAt},
timeToAutoRetryInSecs: {self.timeToAutoRetryInSecs}
lastCheckedAt: {self.lastCheckedAt}
]"""
proc completelyDownChanged*(self: NetworkConnectionItem) {.signal.}
@ -57,15 +54,8 @@ QtObject:
read = getLastCheckedAt
notify = lastCheckedAtChanged
proc timeToAutoRetryInSecsChanged*(self: NetworkConnectionItem) {.signal.}
proc getTimeToAutoRetryInSecs*(self: NetworkConnectionItem): int {.slot.} =
return self.timeToAutoRetryInSecs
QtProperty[int] timeToAutoRetryInSecs:
read = getTimeToAutoRetryInSecs
notify = timeToAutoRetryInSecsChanged
proc updateValues*(self: NetworkConnectionItem, completelyDown: bool, connectionState: int,
chainIds: string, lastCheckedAt: int, timeToAutoRetryInSecs: int) =
chainIds: string, lastCheckedAt: int) =
if self.completelyDown != completelyDown :
self.completelyDown = completelyDown
self.completelyDownChanged()
@ -81,7 +71,3 @@ QtObject:
if self.lastCheckedAt != lastCheckedAt :
self.lastCheckedAt = lastCheckedAt
self.lastCheckedAtChanged()
if self.timeToAutoRetryInSecs != timeToAutoRetryInSecs :
self.timeToAutoRetryInSecs = timeToAutoRetryInSecs
self.timeToAutoRetryInSecsChanged()

View File

@ -62,18 +62,18 @@ QtObject:
proc refreshCollectiblesValues*(self: View) {.slot.} =
self.delegate.refreshCollectiblesValues()
proc networkConnectionStatusUpdate*(self: View, website: string, completelyDown: bool, connectionState: int, chainIds: string, lastCheckedAt: int, timeToAutoRetryInSecs: int) {.signal.}
proc networkConnectionStatusUpdate*(self: View, website: string, completelyDown: bool, connectionState: int, chainIds: string, lastCheckedAt: int) {.signal.}
proc updateNetworkConnectionStatus*(self: View, website: string, completelyDown: bool, connectionState: int, chainIds: string, lastCheckedAt: int, timeToAutoRetryInSecs: int) =
proc updateNetworkConnectionStatus*(self: View, website: string, completelyDown: bool, connectionState: int, chainIds: string, lastCheckedAt: int) =
case website:
of BLOCKCHAINS:
self.blockchainNetworkConnection.updateValues(completelyDown, connectionState, chainIds, lastCheckedAt, timeToAutoRetryInSecs)
self.blockchainNetworkConnection.updateValues(completelyDown, connectionState, chainIds, lastCheckedAt)
self.blockchainNetworkConnectionChanged()
of COLLECTIBLES:
self.collectiblesNetworkConnection.updateValues(completelyDown, connectionState, chainIds, lastCheckedAt, timeToAutoRetryInSecs)
self.collectiblesNetworkConnection.updateValues(completelyDown, connectionState, chainIds, lastCheckedAt)
self.collectiblesNetworkConnectionChanged()
of MARKET:
self.marketValuesNetworkConnection.updateValues(completelyDown, connectionState, chainIds, lastCheckedAt, timeToAutoRetryInSecs)
self.marketValuesNetworkConnection.updateValues(completelyDown, connectionState, chainIds, lastCheckedAt)
self.marketValuesNetworkConnectionChanged()
self.networkConnectionStatusUpdate(website, completelyDown, connectionState, chainIds, lastCheckedAt, timeToAutoRetryInSecs)
self.networkConnectionStatusUpdate(website, completelyDown, connectionState, chainIds, lastCheckedAt)

View File

@ -23,8 +23,6 @@ type ConnectionStatus* = ref object of RootObj
completelyDown*: bool
chainIds*: seq[int]
lastCheckedAt*: int
timeToAutoRetryInSecs*: int
timer*: QTimer
const SIGNAL_CONNECTION_UPDATE* = "signalConnectionUpdate"
const SIGNAL_REFRESH_COLLECTIBLES* = "signalRefreshCollectibles"
@ -35,12 +33,10 @@ type NetworkConnectionsArgs* = ref object of Args
connectionState*: ConnectionState
chainIds*: string
lastCheckedAt*: int
timeToAutoRetryInSecs*: int
const BLOCKCHAINS* = "blockchains"
const MARKET* = "market"
const COLLECTIBLES* = "collectibles"
const BACKOFF_TIMERS* = [30, 60, 180, 600, 3600, 10800]
include ../../common/json_utils
@ -50,8 +46,6 @@ proc newConnectionStatus(): ConnectionStatus =
completelyDown: false,
chainIds: @[],
lastCheckedAt: 0,
timeToAutoRetryInSecs: BACKOFF_TIMERS[0],
timer: newQTimer()
)
QtObject:
@ -157,8 +151,7 @@ QtObject:
completelyDown: connectionStatus.completelyDown,
connectionState: connectionStatus.connectionState,
chainIds: self.getFormattedStringForChainIds(connectionStatus.chainIds),
lastCheckedAt: connectionStatus.lastCheckedAt,
timeToAutoRetryInSecs: connectionStatus.timeToAutoRetryInSecs
lastCheckedAt: connectionStatus.lastCheckedAt
)
proc updateConnectionStatus(self: Service,
@ -166,58 +159,31 @@ QtObject:
connectionState: ConnectionState,
completelyDown: bool,
chainIds: seq[int],
lastCheckedAt: int,
timeToAutoRetryInSecs: int
lastCheckedAt: int
) =
if self.connectionStatus.hasKey(website):
self.connectionStatus[website].connectionState = connectionState
self.connectionStatus[website].completelyDown = completelyDown
self.connectionStatus[website].chainIds = chainIds
self.connectionStatus[website].lastCheckedAt = lastCheckedAt
self.connectionStatus[website].timeToAutoRetryInSecs = timeToAutoRetryInSecs
proc increaseTimer(self: Service, connectionStatus: ConnectionStatus): int =
var backOffTimer: int = connectionStatus.timeToAutoRetryInSecs
# Is down even after retry we need to increase the timer duration
if connectionStatus.connectionState == ConnectionState.Retrying:
let index = BACKOFF_TIMERS.find(backOffTimer)
if index != -1 and index < BACKOFF_TIMERS.len:
backOffTimer = BACKOFF_TIMERS[index + 1]
return backOffTimer
proc updateMarketOrCollectibleStatus(self: Service, website: string, isDown: bool, at: int) =
if self.connectionStatus.hasKey(website):
if isDown:
self.updateConnectionStatus(website, ConnectionState.Failed, true, @[], at, self.increaseTimer(self.connectionStatus[website]))
# restart timer
signalConnect(self.connectionStatus[website].timer, "timeout()", self, website&"Retry()", 2)
self.connectionStatus[website].timer.setInterval(self.connectionStatus[website].timeToAutoRetryInSecs*1000)
self.connectionStatus[website].timer.start()
# trigger event
self.updateConnectionStatus(website, ConnectionState.Failed, true, @[], at)
self.events.emit(SIGNAL_CONNECTION_UPDATE, self.convertConnectionStatusToNetworkConnectionsArgs(website, self.connectionStatus[website]))
else:
# site was completely down and is back up now
# if site was completely down and is back up now, trigger event
if self.connectionStatus[website].completelyDown:
self.connectionStatus[website] = newConnectionStatus()
# trigger event
self.events.emit(SIGNAL_CONNECTION_UPDATE, self.convertConnectionStatusToNetworkConnectionsArgs(website, self.connectionStatus[website]))
proc updateBlockchainsStatus(self: Service, completelyDown: bool, chaindIdsDown: seq[int], at: int) =
if self.connectionStatus.hasKey(BLOCKCHAINS):
# if all the networks are down for the BLOCKCHAINS
# if all the networks are down for the BLOCKCHAINS, trigger event
if completelyDown:
var backOffTimer: int = self.connectionStatus[BLOCKCHAINS].timeToAutoRetryInSecs
if self.connectionStatus[BLOCKCHAINS].completelyDown:
backOffTimer = self.increaseTimer(self.connectionStatus[BLOCKCHAINS])
self.updateConnectionStatus(BLOCKCHAINS, ConnectionState.Failed, true, chaindIdsDown, at, backOffTimer)
# restart timer
signalConnect(self.connectionStatus[BLOCKCHAINS].timer, "timeout()", self, BLOCKCHAINS&"Retry()", 2)
self.connectionStatus[BLOCKCHAINS].timer.setInterval(self.connectionStatus[BLOCKCHAINS].timeToAutoRetryInSecs*1000)
self.connectionStatus[BLOCKCHAINS].timer.start()
# trigger event
self.updateConnectionStatus(BLOCKCHAINS, ConnectionState.Failed, true, chaindIdsDown, at)
self.events.emit(SIGNAL_CONNECTION_UPDATE, self.convertConnectionStatusToNetworkConnectionsArgs(BLOCKCHAINS, self.connectionStatus[BLOCKCHAINS]))
# if all the networks are not down for the website
@ -227,34 +193,25 @@ QtObject:
self.connectionStatus[BLOCKCHAINS] = newConnectionStatus()
self.events.emit(SIGNAL_CONNECTION_UPDATE, self.convertConnectionStatusToNetworkConnectionsArgs(BLOCKCHAINS, self.connectionStatus[BLOCKCHAINS]))
# case where a some of networks on the website are down
# case where a some of networks on the website are down, trigger event
if chaindIdsDown.len > 0:
self.updateConnectionStatus(BLOCKCHAINS, ConnectionState.Failed, false, chaindIdsDown, at, self.increaseTimer(self.connectionStatus[BLOCKCHAINS]))
# restart timer
signalConnect(self.connectionStatus[BLOCKCHAINS].timer, "timeout()", self, BLOCKCHAINS&"Retry()", 2)
self.connectionStatus[BLOCKCHAINS].timer.setInterval(self.connectionStatus[BLOCKCHAINS].timeToAutoRetryInSecs*1000)
self.connectionStatus[BLOCKCHAINS].timer.start()
# trigger event
self.updateConnectionStatus(BLOCKCHAINS, ConnectionState.Failed, false, chaindIdsDown, at)
self.events.emit(SIGNAL_CONNECTION_UPDATE, self.convertConnectionStatusToNetworkConnectionsArgs(BLOCKCHAINS, self.connectionStatus[BLOCKCHAINS]))
proc blockchainsRetry*(self: Service) {.slot.} =
if(self.connectionStatus.hasKey(BLOCKCHAINS)):
self.connectionStatus[BLOCKCHAINS].timer.stop()
self.connectionStatus[BLOCKCHAINS].connectionState = ConnectionState.Retrying
self.events.emit(SIGNAL_CONNECTION_UPDATE, self.convertConnectionStatusToNetworkConnectionsArgs(BLOCKCHAINS, self.connectionStatus[BLOCKCHAINS]))
self.walletService.reloadAccountTokens()
proc marketRetry*(self: Service) {.slot.} =
if(self.connectionStatus.hasKey(MARKET)):
self.connectionStatus[MARKET].timer.stop()
self.connectionStatus[MARKET].connectionState = ConnectionState.Retrying
self.events.emit(SIGNAL_CONNECTION_UPDATE, self.convertConnectionStatusToNetworkConnectionsArgs(MARKET, self.connectionStatus[MARKET]))
self.walletService.reloadAccountTokens()
proc collectiblesRetry*(self: Service) {.slot.} =
if(self.connectionStatus.hasKey(COLLECTIBLES)):
self.connectionStatus[COLLECTIBLES].timer.stop()
self.connectionStatus[COLLECTIBLES].connectionState = ConnectionState.Retrying
self.events.emit(SIGNAL_CONNECTION_UPDATE, self.convertConnectionStatusToNetworkConnectionsArgs(COLLECTIBLES, self.connectionStatus[COLLECTIBLES]))
self.events.emit(SIGNAL_REFRESH_COLLECTIBLES, Args())
@ -265,13 +222,10 @@ QtObject:
self.events.emit(SIGNAL_REFRESH_COLLECTIBLES, Args())
else:
if(self.connectionStatus.hasKey(BLOCKCHAINS)):
self.connectionStatus[BLOCKCHAINS].timer.stop()
self.connectionStatus[BLOCKCHAINS] = newConnectionStatus()
if(self.connectionStatus.hasKey(MARKET)):
self.connectionStatus[MARKET].timer.stop()
self.connectionStatus[MARKET] = newConnectionStatus()
if(self.connectionStatus.hasKey(COLLECTIBLES)):
self.connectionStatus[COLLECTIBLES].timer.stop()
self.connectionStatus[COLLECTIBLES] = newConnectionStatus()
proc checkIfConnected*(self: Service, website: string): bool =

View File

@ -22,6 +22,7 @@ import shared.panels 1.0
import shared.popups 1.0
import shared.popups.keycard 1.0
import shared.status 1.0
import shared.stores 1.0
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
@ -52,6 +53,7 @@ Item {
openCreateChat: createChatView.opened
}
property ActivityCenterStore activityCenterStore: ActivityCenterStore {}
property NetworkConnectionStore networkConnectionStore: NetworkConnectionStore {}
// set from main.qml
property var sysPalette
@ -683,28 +685,28 @@ Item {
Layout.fillWidth: true
websiteDown: Constants.walletConnections.blockchains
withCache: networkConnectionStore.balanceCache
text: {
networkConnectionStore: appMain.networkConnectionStore
tooltipMessage: qsTr("Pocket Network (POKT) & Infura are currently both unavailable for %1. Balances for those chains are as of %2.").arg(jointChainIdString).arg(lastCheckedAt)
toastText: {
switch(connectionState) {
case Constants.ConnectionStatus.Success:
return qsTr("Pocket Network (POKT) connection successful")
case Constants.ConnectionStatus.Failure:
if(completelyDown) {
updateTimer.restart()
if(withCache)
return qsTr("POKT & Infura down. Token balances are as of %1. Retrying in %2.").arg(lastCheckedAt).arg(Utils.getTimerString(autoTryTimerInSecs))
return qsTr("POKT & Infura down. Token balances are as of %1.").arg(lastCheckedAt)
else
return qsTr("POKT & Infura down. Token balances cannot be retrieved. Retrying in %1.").arg(Utils.getTimerString(autoTryTimerInSecs))
return qsTr("POKT & Infura down. Token balances cannot be retrieved.")
}
else if(chainIdsDown.length > 0) {
updateTimer.restart()
if(chainIdsDown.length > 2) {
return qsTr("POKT & Infura down for <a href='#'>multiple chains </a>. Token balances for those chains cannot be retrieved. Retrying in %1.").arg(Utils.getTimerString(autoTryTimerInSecs))
return qsTr("POKT & Infura down for <a href='#'>multiple chains </a>. Token balances for those chains cannot be retrieved.")
}
else if(chainIdsDown.length === 1) {
return qsTr("POKT & Infura down for %1. %1 token balances are as of %2. Retrying in %3.").arg(jointChainIdString).arg(lastCheckedAt).arg(Utils.getTimerString(autoTryTimerInSecs))
return qsTr("POKT & Infura down for %1. %1 token balances are as of %2.").arg(jointChainIdString).arg(lastCheckedAt)
}
else {
return qsTr("POKT & Infura down for %1. %1 token balances cannot be retrieved. Retrying in %2.").arg(jointChainIdString).arg(Utils.getTimerString(autoTryTimerInSecs))
return qsTr("POKT & Infura down for %1. %1 token balances cannot be retrieved.").arg(jointChainIdString)
}
}
else
@ -715,16 +717,6 @@ Item {
return ""
}
}
onLinkActivated: {
let tootipMessage = qsTr("Pocket Network (POKT) & Infura are currently both unavailable for %1. Balances for those chains are as of %2.").arg(jointChainIdString).arg(lastCheckedAt)
toolTip.show(tootipMessage, 3000)
}
StatusToolTip {
id: toolTip
orientation: StatusToolTip.Orientation.Bottom
maxWidth: 300
}
}
ConnectionWarnings {
@ -733,17 +725,17 @@ Item {
Layout.fillWidth: true
websiteDown: Constants.walletConnections.collectibles
withCache: networkConnectionStore.collectiblesCache
text: {
networkConnectionStore: appMain.networkConnectionStore
toastText: {
switch(connectionState) {
case Constants.ConnectionStatus.Success:
return qsTr("Opensea connection successful")
case Constants.ConnectionStatus.Failure:
updateTimer.restart()
if(withCache){
return qsTr("Opensea down. Collectibles are as of %1. Retrying in %2.").arg(lastCheckedAt).arg(Utils.getTimerString(autoTryTimerInSecs))
return qsTr("Opensea down. Collectibles are as of %1.").arg(lastCheckedAt)
}
else {
return qsTr("Opensea down. Retrying in %1.").arg(Utils.getTimerString(autoTryTimerInSecs))
return qsTr("Opensea down.")
}
case Constants.ConnectionStatus.Retrying:
return qsTr("Retrying connection to Opensea...")
@ -753,28 +745,29 @@ Item {
}
}
ConnectionWarnings {
id: walletMarketConnectionBanner
objectName: "walletMarketConnectionBanner"
Layout.fillWidth: true
websiteDown: Constants.walletConnections.market
withCache: networkConnectionStore.marketValuesCache
text: {
networkConnectionStore: appMain.networkConnectionStore
toastText: {
switch(connectionState) {
case Constants.ConnectionStatus.Success:
return qsTr("CryptoCompare and CoinGecko connection successful")
case Constants.ConnectionStatus.Failure: {
updateTimer.restart()
if(withCache) {
return qsTr("CryptoCompare and CoinGecko down. Market values are as of %1. Retrying in %2.").arg(lastCheckedAt).arg(Utils.getTimerString(autoTryTimerInSecs))
return qsTr("CryptoCompare and CoinGecko down. Market values are as of %1.").arg(lastCheckedAt)
}
else {
return qsTr("CryptoCompare and CoinGecko down. Market values cannot be retrieved. Trying again in %1.").arg(Utils.getTimerString(autoTryTimerInSecs))
return qsTr("CryptoCompare and CoinGecko down. Market values cannot be retrieved.")
}
}
case Constants.ConnectionStatus.Retrying:
return qsTr("Retrying connection to CryptoCompare and CoinGecko...")
default:
return ""
}
}
}

View File

@ -1,60 +1,65 @@
import QtQuick 2.14
import StatusQ.Core 0.1
import StatusQ.Controls 0.1
import utils 1.0
import shared.stores 1.0
ModuleWarning {
Loader {
id: root
active: false
readonly property NetworkConnectionStore networkConnectionStore: NetworkConnectionStore {}
property var networkConnectionStore
readonly property string jointChainIdString: networkConnectionStore.getChainIdsJointString(chainIdsDown)
property string websiteDown
property int connectionState: -1
property int autoTryTimerInSecs: 0
property var chainIdsDown: []
property bool completelyDown: false
property string lastCheckedAt
property bool withCache: false
property Timer updateTimer: Timer {
interval: 1000
repeat: true
onTriggered: {
if (root.autoTryTimerInSecs === 0) {
stop()
return
}
root.autoTryTimerInSecs = root.autoTryTimerInSecs - 1
property string tooltipMessage
property string toastText
function updateBanner() {
root.active = true
if (connectionState === Constants.ConnectionStatus.Failure)
item.show()
else
item.showFor(3000)
}
sourceComponent: ModuleWarning {
QtObject {
id: d
readonly property bool isOnline: networkConnectionStore.isOnline
onIsOnlineChanged: if(!isOnline) hide()
}
onHideFinished: root.active = false
text: root.toastText
type: connectionState === Constants.ConnectionStatus.Success ? ModuleWarning.Success : ModuleWarning.Danger
buttonText: connectionState === Constants.ConnectionStatus.Failure ? qsTr("Retry now") : ""
onClicked: networkConnectionStore.retryConnection(websiteDown)
onCloseClicked: hide()
onLinkActivated: {
toolTip.show(root.tooltipMessage, 3000)
}
StatusToolTip {
id: toolTip
orientation: StatusToolTip.Orientation.Bottom
maxWidth: 300
}
}
function updateBanner() {
hide()
if (connectionState === Constants.ConnectionStatus.Failure)
show()
else
showFor(3000)
}
QtObject {
id: d
property bool isOnline: networkConnectionStore.isOnline
onIsOnlineChanged: if(!isOnline) root.hide()
}
type: connectionState === Constants.ConnectionStatus.Success ? ModuleWarning.Success : ModuleWarning.Danger
buttonText: connectionState === Constants.ConnectionStatus.Failure ? qsTr("Retry now") : ""
onClicked: networkConnectionStore.retryConnection(websiteDown)
onCloseClicked: hide()
Connections {
target: networkConnectionStore.networkConnectionModuleInst
function onNetworkConnectionStatusUpdate(website: string, completelyDown: bool, connectionState: int, chainIds: string, lastCheckedAt: int, timeToAutoRetryInSecs: int) {
function onNetworkConnectionStatusUpdate(website: string, completelyDown: bool, connectionState: int, chainIds: string, lastCheckedAt: int) {
if (website === websiteDown) {
root.connectionState = connectionState
root.autoTryTimerInSecs = timeToAutoRetryInSecs
root.chainIdsDown = chainIds.split(";")
root.completelyDown = completelyDown
root.lastCheckedAt = LocaleUtils.formatDateTime(new Date(lastCheckedAt*1000))