diff --git a/src/app/modules/main/network_connection/view.nim b/src/app/modules/main/network_connection/view.nim
index 4950ae282f..4c8afa79df 100644
--- a/src/app/modules/main/network_connection/view.nim
+++ b/src/app/modules/main/network_connection/view.nim
@@ -62,7 +62,7 @@ QtObject:
proc refreshCollectiblesValues*(self: View) {.slot.} =
self.delegate.refreshCollectiblesValues()
- proc networkConnectionStatusUpdate*(self: View, website: string, completelyDown: bool, connectionState: int, chainIds: string, lastCheckedAt: int) {.signal.}
+ proc networkConnectionStatusUpdate*(self: View, website: string, completelyDown: bool, connectionState: int, chainIds: string, lastCheckedAt: float) {.signal.}
proc updateNetworkConnectionStatus*(self: View, website: string, completelyDown: bool, connectionState: int, chainIds: string, lastCheckedAt: int) =
case website:
@@ -75,5 +75,5 @@ QtObject:
of MARKET:
self.marketValuesNetworkConnection.updateValues(completelyDown, connectionState, chainIds, lastCheckedAt)
self.marketValuesNetworkConnectionChanged()
- self.networkConnectionStatusUpdate(website, completelyDown, connectionState, chainIds, lastCheckedAt)
+ self.networkConnectionStatusUpdate(website, completelyDown, connectionState, chainIds, float(lastCheckedAt))
diff --git a/src/app_service/service/network_connection/service.nim b/src/app_service/service/network_connection/service.nim
index 5aa9b035a8..2a6d962306 100644
--- a/src/app_service/service/network_connection/service.nim
+++ b/src/app_service/service/network_connection/service.nim
@@ -7,6 +7,8 @@ import ../../../app/core/signals/types
import ../wallet_account/service as wallet_service
import ../network/service as network_service
import ../node/service as node_service
+import backend/connection_status as connection_status_backend
+import backend/collectibles as collectibles_backend
logScope:
topics = "network-connection-service"
@@ -23,7 +25,6 @@ type ConnectionStatus* = ref object of RootObj
lastCheckedAt*: int
const SIGNAL_CONNECTION_UPDATE* = "signalConnectionUpdate"
-const SIGNAL_REFRESH_COLLECTIBLES* = "signalRefreshCollectibles"
type NetworkConnectionsArgs* = ref object of Args
website*: string
@@ -43,7 +44,7 @@ proc newConnectionStatus(): ConnectionStatus =
connectionState: ConnectionState.Successful,
completelyDown: false,
chainIds: @[],
- lastCheckedAt: 0,
+ lastCheckedAt: connection_status_backend.INVALID_TIMESTAMP,
)
QtObject:
@@ -56,10 +57,11 @@ QtObject:
connectionStatus: Table[string, ConnectionStatus]
# Forward declaration
- proc updateBlockchainsStatus(self: Service, completelyDown: bool, chaindIdsDown: seq[int], at: int)
- proc updateMarketOrCollectibleStatus(self: Service, website: string, isDown: bool, at: int)
- proc getChainIdsDown(self: Service, message: string): (bool, seq[int])
- proc getIsDown(self: Service,message: string): bool
+ proc updateSimpleStatus(self: Service, website: string, isDown: bool, at: int)
+ proc updateMultichainStatus(self: Service, website: string, completelyDown: bool, chaindIdsDown: seq[int], at: int)
+ proc getChainIdsDown(self: Service, chainStatusTable: ConnectionStatusNotification): (bool, bool, seq[int], int)
+ proc getIsDown(message: string): bool
+ proc getChainStatusTable(message: string): ConnectionStatusNotification
proc delete*(self: Service) =
self.closingApp = true
@@ -88,42 +90,67 @@ QtObject:
case data.eventType:
of "wallet-blockchain-status-changed":
if self.nodeService.isConnected():
- let (allDown, chainsDown) = self.getChainIdsDown(data.message)
- self.updateBlockchainsStatus(allDown, chainsDown, data.at)
+ let chainStateTable = getChainStatusTable(data.message)
+ let (allKnown, allDown, chainsDown, at) = self.getChainIdsDown(chainStateTable)
+ self.updateMultichainStatus(BLOCKCHAINS, allDown, chainsDown, data.at)
of "wallet-market-status-changed":
if self.nodeService.isConnected():
- self.updateMarketOrCollectibleStatus(MARKET, self.getIsDown(data.message), data.at)
+ self.updateSimpleStatus(MARKET, getIsDown(data.message), data.at)
of "wallet-collectible-status-changed":
if self.nodeService.isConnected():
- self.updateMarketOrCollectibleStatus(COLLECTIBLES, self.getIsDown(data.message), data.at)
+ let chainStateTable = fromJson(parseJson(data.message), ConnectionStatusNotification)
+ let (allKnown, allDown, chainsDown, at) = self.getChainIdsDown(chainStateTable)
+ if allKnown:
+ self.updateMultichainStatus(COLLECTIBLES, allDown, chainsDown, at)
self.events.on(SIGNAL_WALLET_ACCOUNT_TOKENS_REBUILT) do(e:Args):
if self.connectionStatus.hasKey(MARKET):
let connectionStatus = self.connectionStatus[MARKET]
- self.updateMarketOrCollectibleStatus(MARKET, connectionStatus.completelyDown, connectionStatus.lastCheckedAt)
+ self.updateSimpleStatus(MARKET, connectionStatus.completelyDown, connectionStatus.lastCheckedAt)
if self.connectionStatus.hasKey(BLOCKCHAINS):
let connectionStatus = self.connectionStatus[BLOCKCHAINS]
- self.updateBlockchainsStatus(connectionStatus.completelyDown, connectionStatus.chainIds, connectionStatus.lastCheckedAt)
+ self.updateMultichainStatus(BLOCKCHAINS, connectionStatus.completelyDown, connectionStatus.chainIds, connectionStatus.lastCheckedAt)
- proc getIsDown(self: Service, message: string): bool =
+ proc getIsDown(message: string): bool =
result = message == "down"
- proc getChainIdsDown(self: Service, message: string): (bool, seq[int]) =
- let chainStatusTable = parseJson(message)
+ proc getStateValue(message: string): connection_status_backend.StateValue =
+ if message == "down":
+ return connection_status_backend.StateValue.Disconnected
+ elif message == "up":
+ return connection_status_backend.StateValue.Connected
+ else:
+ return connection_status_backend.StateValue.Unknown
+
+ proc getChainStatusTable(message: string): ConnectionStatusNotification =
+ result = initCustomStatusNotification()
+
+ let chainStatusTable = parseJson(message)
+ if chainStatusTable.kind != JNull:
+ for k, v in chainStatusTable.pairs:
+ result[k] = connection_status_backend.initConnectionState(
+ value = getStateValue(v.getStr)
+ )
+
+ proc getChainIdsDown(self: Service, chainStatusTable: ConnectionStatusNotification): (bool, bool, seq[int], int) =
+ var allKnown: bool = true
var allDown: bool = true
var chaindIdsDown: seq[int] = @[]
+ var lastSuccessAt: int = connection_status_backend.INVALID_TIMESTAMP # latest succesful connectinon between the down chains
let allChainIds = self.networkService.getNetworks().map(a => a.chainId)
- if chainStatusTable.kind != JNull:
- for id in allChainIds:
- if chainStatusTable[$id].kind != JNull:
- let isDown = self.getIsDown(chainStatusTable[$id].getStr)
- if isDown:
- chaindIdsDown.add(id)
- else:
- allDown = false
- return (allDown, chaindIdsDown)
+ for id in allChainIds:
+ if chainStatusTable.hasKey($id) and chainStatusTable[$id].value != connection_status_backend.StateValue.Unknown:
+ if chainStatusTable[$id].value == connection_status_backend.StateValue.Connected:
+ allDown = false
+ else:
+ chaindIdsDown.add(id)
+ lastSuccessAt = max(lastSuccessAt, chainStatusTable[$id].lastSuccessAt)
+ else:
+ allKnown = false
+
+ return (allKnown, allDown, chaindIdsDown, lastSuccessAt)
proc getFormattedStringForChainIds(self: Service, chainIds: seq[int]): string =
for chainId in chainIds:
@@ -142,6 +169,9 @@ QtObject:
lastCheckedAt: connectionStatus.lastCheckedAt
)
+ proc resetConnectionStatus(self: Service, website: string) =
+ self.connectionStatus[website] = newConnectionStatus()
+
proc updateConnectionStatus(self: Service,
website: string,
connectionState: ConnectionState,
@@ -155,7 +185,7 @@ QtObject:
self.connectionStatus[website].chainIds = chainIds
self.connectionStatus[website].lastCheckedAt = lastCheckedAt
- proc updateMarketOrCollectibleStatus(self: Service, website: string, isDown: bool, at: int) =
+ proc updateSimpleStatus(self: Service, website: string, isDown: bool, at: int) =
if self.connectionStatus.hasKey(website):
if isDown:
# trigger event
@@ -167,24 +197,23 @@ QtObject:
self.connectionStatus[website] = newConnectionStatus()
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, trigger event
+ proc updateMultichainStatus(self: Service, website: string, completelyDown: bool, chaindIdsDown: seq[int], at: int) =
+ if self.connectionStatus.hasKey(website):
+ # if all the networks are down for the website, trigger event
if completelyDown:
- self.updateConnectionStatus(BLOCKCHAINS, ConnectionState.Failed, true, chaindIdsDown, at)
- self.events.emit(SIGNAL_CONNECTION_UPDATE, self.convertConnectionStatusToNetworkConnectionsArgs(BLOCKCHAINS, self.connectionStatus[BLOCKCHAINS]))
-
+ self.updateConnectionStatus(website, ConnectionState.Failed, true, chaindIdsDown, at)
+ self.events.emit(SIGNAL_CONNECTION_UPDATE, self.convertConnectionStatusToNetworkConnectionsArgs(website, self.connectionStatus[website]))
# if all the networks are not down for the website
else:
# case where a down website is back up
- if self.connectionStatus[BLOCKCHAINS].completelyDown or (chaindIdsDown.len == 0 and self.connectionStatus[BLOCKCHAINS].chainIds.len != 0):
- self.connectionStatus[BLOCKCHAINS] = newConnectionStatus()
- self.events.emit(SIGNAL_CONNECTION_UPDATE, self.convertConnectionStatusToNetworkConnectionsArgs(BLOCKCHAINS, self.connectionStatus[BLOCKCHAINS]))
+ if self.connectionStatus[website].completelyDown or (chaindIdsDown.len == 0 and self.connectionStatus[website].chainIds.len != 0):
+ self.resetConnectionStatus(website)
+ self.events.emit(SIGNAL_CONNECTION_UPDATE, self.convertConnectionStatusToNetworkConnectionsArgs(website, self.connectionStatus[website]))
# 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.events.emit(SIGNAL_CONNECTION_UPDATE, self.convertConnectionStatusToNetworkConnectionsArgs(BLOCKCHAINS, self.connectionStatus[BLOCKCHAINS]))
+ self.updateConnectionStatus(website, ConnectionState.Failed, false, chaindIdsDown, at)
+ self.events.emit(SIGNAL_CONNECTION_UPDATE, self.convertConnectionStatusToNetworkConnectionsArgs(website, self.connectionStatus[website]))
proc blockchainsRetry*(self: Service) {.slot.} =
if(self.connectionStatus.hasKey(BLOCKCHAINS)):
@@ -202,12 +231,12 @@ QtObject:
if(self.connectionStatus.hasKey(COLLECTIBLES)):
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())
+ discard collectibles_backend.refetchOwnedCollectibles()
proc networkConnected*(self: Service, connected: bool) =
if connected:
self.walletService.reloadAccountTokens()
- self.events.emit(SIGNAL_REFRESH_COLLECTIBLES, Args())
+ discard collectibles_backend.refetchOwnedCollectibles()
else:
if(self.connectionStatus.hasKey(BLOCKCHAINS)):
self.connectionStatus[BLOCKCHAINS] = newConnectionStatus()
diff --git a/src/backend/collectibles.nim b/src/backend/collectibles.nim
index 70c0c7ac12..bd6eb411d0 100644
--- a/src/backend/collectibles.nim
+++ b/src/backend/collectibles.nim
@@ -138,3 +138,6 @@ rpc(filterOwnedCollectiblesAsync, "wallet"):
rpc(getCollectiblesDetailsAsync, "wallet"):
requestId: int32
uniqueIds: seq[CollectibleUniqueID]
+
+rpc(refetchOwnedCollectibles, "wallet"):
+ discard
diff --git a/src/backend/connection_status.nim b/src/backend/connection_status.nim
new file mode 100644
index 0000000000..ddfaef7329
--- /dev/null
+++ b/src/backend/connection_status.nim
@@ -0,0 +1,50 @@
+import json, strformat, tables
+
+const INVALID_TIMESTAMP* = -1
+
+type
+ # Mirrors services/wallet/connection/types.go StateValue
+ StateValue* {.pure.} = enum
+ Unknown,
+ Connected,
+ Disconnected
+
+ # Mirrors services/wallet/connection/types.go State
+ ConnectionState* = ref object of RootObj
+ value*: StateValue
+ lastCheckedAt*: int
+ lastSuccessAt*: int
+
+ # Mirrors services/wallet/connection/status_notifier.go StatusNotification
+ ConnectionStatusNotification* = Table[string, ConnectionState]
+
+# ConnectionState
+proc initConnectionState*(value: StateValue, lastCheckedAt: int = INVALID_TIMESTAMP, lastSuccessAt: int = INVALID_TIMESTAMP): ConnectionState =
+ result = ConnectionState()
+ result.value = value
+ result.lastCheckedAt = lastCheckedAt
+ result.lastSuccessAt = lastSuccessAt
+
+proc `$`*(self: ConnectionState): string =
+ return fmt"""ConnectionState(
+ value:{self.value},
+ lastCheckedAt:{self.lastCheckedAt},
+ lastSuccessAt:{self.lastSuccessAt}
+ )"""
+
+proc fromJson*(t: JsonNode, T: typedesc[ConnectionState]): ConnectionState {.inline.} =
+ result = ConnectionState()
+ result.value = StateValue(t["value"].getInt())
+ result.lastCheckedAt = t["last_checked_at"].getInt()
+ result.lastSuccessAt = t["last_success_at"].getInt()
+
+# ConnectionStatusNotification
+proc initCustomStatusNotification*(): ConnectionStatusNotification =
+ result = initTable[string, ConnectionState]()
+
+proc fromJson*(t: JsonNode, T: typedesc[ConnectionStatusNotification]): ConnectionStatusNotification {.inline.} =
+ result = initCustomStatusNotification()
+ if t.kind != JNull:
+ for k, v in t.pairs:
+ if v.kind != JNull:
+ result[k] = fromJson(v, ConnectionState)
diff --git a/ui/app/mainui/AppMain.qml b/ui/app/mainui/AppMain.qml
index 98f4fa769c..0978cf37d2 100644
--- a/ui/app/mainui/AppMain.qml
+++ b/ui/app/mainui/AppMain.qml
@@ -925,21 +925,49 @@ Item {
objectName: "walletCollectiblesConnectionBanner"
Layout.fillWidth: true
websiteDown: Constants.walletConnections.collectibles
- withCache: networkConnectionStore.collectiblesCache
+ withCache: lastCheckedAtUnix > 0
networkConnectionStore: appMain.networkConnectionStore
+ tooltipMessage: {
+ if(withCache)
+ return qsTr("Collectibles providers are currently unavailable for %1. Collectibles for those chains are as of %2.").arg(jointChainIdString).arg(lastCheckedAt)
+ else
+ return qsTr("Collectibles providers are currently unavailable for %1.").arg(jointChainIdString)
+ }
toastText: {
switch(connectionState) {
case Constants.ConnectionStatus.Success:
- return qsTr("Opensea connection successful")
+ return qsTr("Collectibles providers connection successful")
case Constants.ConnectionStatus.Failure:
- if(withCache){
- return qsTr("Opensea down. Collectibles are as of %1.").arg(lastCheckedAt)
+ if(completelyDown) {
+ if(withCache)
+ return qsTr("Collectibles providers down. Collectibles are as of %1.").arg(lastCheckedAt)
+ else
+ return qsTr("Collectibles providers down. Collectibles cannot be retrieved.")
}
- else {
- return qsTr("Opensea down.")
+ else if(chainIdsDown.length > 0) {
+ if(chainIdsDown.length > 2) {
+ if(withCache)
+ return qsTr("Collectibles providers down for multiple chains. Collectibles for these chains are as of %1.".arg(lastCheckedAt))
+ else
+ return qsTr("Collectibles providers down for multiple chains. Collectibles for these chains cannot be retrieved.")
+ }
+ else if(chainIdsDown.length === 1) {
+ if(withCache)
+ return qsTr("Collectibles providers down for %1. Collectibles for this chain are as of %2.").arg(jointChainIdString).arg(lastCheckedAt)
+ else
+ return qsTr("Collectibles providers down for %1. Collectibles for this chain cannot be retrieved.").arg(jointChainIdString)
+ }
+ else {
+ if(withCache)
+ return qsTr("Collectibles providers down for %1. Collectibles for these chains are as of %2.").arg(jointChainIdString).arg(lastCheckedAt)
+ else
+ return qsTr("Collectibles providers down for %1. Collectibles for these chains cannot be retrieved.").arg(jointChainIdString)
+ }
}
+ else
+ return ""
case Constants.ConnectionStatus.Retrying:
- return qsTr("Retrying connection to Opensea...")
+ return qsTr("Retrying connection to collectibles providers...")
default:
return ""
}
diff --git a/ui/imports/shared/panels/ConnectionWarnings.qml b/ui/imports/shared/panels/ConnectionWarnings.qml
index 10f9dd12e2..c13f5cb788 100644
--- a/ui/imports/shared/panels/ConnectionWarnings.qml
+++ b/ui/imports/shared/panels/ConnectionWarnings.qml
@@ -15,6 +15,7 @@ Loader {
property int connectionState: -1
property var chainIdsDown: []
property bool completelyDown: false
+ property double lastCheckedAtUnix: -1
property string lastCheckedAt
property bool withCache: false
property string tooltipMessage
@@ -57,12 +58,13 @@ Loader {
Connections {
target: networkConnectionStore.networkConnectionModuleInst
- function onNetworkConnectionStatusUpdate(website: string, completelyDown: bool, connectionState: int, chainIds: string, lastCheckedAt: int) {
+ function onNetworkConnectionStatusUpdate(website: string, completelyDown: bool, connectionState: int, chainIds: string, lastCheckedAtUnix: double) {
if (website === websiteDown) {
root.connectionState = connectionState
root.chainIdsDown = chainIds.split(";")
root.completelyDown = completelyDown
- root.lastCheckedAt = LocaleUtils.formatDateTime(new Date(lastCheckedAt*1000))
+ root.lastCheckedAtUnix = lastCheckedAtUnix
+ root.lastCheckedAt = LocaleUtils.formatDateTime(new Date(lastCheckedAtUnix*1000))
root.updateBanner()
}
}
diff --git a/ui/imports/shared/stores/NetworkConnectionStore.qml b/ui/imports/shared/stores/NetworkConnectionStore.qml
index 7cb672bb7b..63d605f956 100644
--- a/ui/imports/shared/stores/NetworkConnectionStore.qml
+++ b/ui/imports/shared/stores/NetworkConnectionStore.qml
@@ -13,7 +13,6 @@ QtObject {
readonly property bool balanceCache: walletSectionAssets.hasBalanceCache
readonly property bool marketValuesCache: walletSectionAssets.hasMarketValuesCache
- readonly property bool collectiblesCache: false // TODO: Issue #11636
readonly property var blockchainNetworksDown: !!networkConnectionModule.blockchainNetworkConnection.chainIds ? networkConnectionModule.blockchainNetworkConnection.chainIds.split(";") : []
readonly property bool atleastOneBlockchainNetworkAvailable: blockchainNetworksDown.length < networksModule.all.count
diff --git a/vendor/status-go b/vendor/status-go
index 2afe5a269d..bd6f9b098b 160000
--- a/vendor/status-go
+++ b/vendor/status-go
@@ -1 +1 @@
-Subproject commit 2afe5a269de11bad5412a64e27d33bd49a28d588
+Subproject commit bd6f9b098b018aba59d89d40343e4aee09e0531e