diff --git a/src/app/wallet/view.nim b/src/app/wallet/view.nim index 9738874197..4c83f4127a 100644 --- a/src/app/wallet/view.nim +++ b/src/app/wallet/view.nim @@ -1,5 +1,6 @@ -import NimQml, Tables, strformat, strutils, chronicles -import ../../status/[status, wallet] +import NimQml, Tables, strformat, strutils, chronicles, json +import ../../status/[status, wallet, threads] +import ../../status/wallet/collectibles as status_collectibles import views/[asset_list, account_list, account_item, transaction_list, collectibles_list] QtObject: @@ -49,8 +50,6 @@ QtObject: read = getEtherscanLink notify = etherscanLinkChanged - proc currentAccountChanged*(self: WalletView) {.signal.} - proc setCurrentAssetList*(self: WalletView, assetList: seq[Asset]) proc currentCollectiblesListChanged*(self: WalletView) {.signal.} @@ -67,6 +66,10 @@ QtObject: write = setCurrentCollectiblesList notify = currentCollectiblesListChanged + proc loadCollectiblesForAccount*(self: WalletView, address: string) + + proc currentAccountChanged*(self: WalletView) {.signal.} + proc setCurrentAccountByIndex*(self: WalletView, index: int) {.slot.} = if(self.accounts.rowCount() == 0): return @@ -76,6 +79,11 @@ QtObject: self.currentAccountChanged() self.setCurrentAssetList(selectedAccount.assetList) + # Display currently known collectibles, and get latest from API/Contracts + self.setCurrentCollectiblesList(selectedAccount.collectibles) + self.loadCollectiblesForAccount(selectedAccount.address) + self.currentCollectiblesListChanged() + proc getCurrentAccount*(self: WalletView): QVariant {.slot.} = result = newQVariant(self.currentAccount) @@ -211,5 +219,23 @@ QtObject: proc loadTransactionsForAccount*(self: WalletView, address: string) {.slot.} = self.setCurrentTransactions(self.status.wallet.getTransfersByAddress(address)) + proc loadingCollectibles*(self: WalletView, isLoading: bool) {.signal.} + proc loadCollectiblesForAccount*(self: WalletView, address: string) {.slot.} = - self.setCurrentCollectiblesList(self.status.wallet.getAllCollectibles(address)) + self.loadingCollectibles(true) + spawnAndSend(self, "setCollectiblesResult ") do: + $(%*{ + "address": address, + "collectibles": status_collectibles.getAllCollectibles(address) + }) + + proc setCollectiblesResult(self: WalletView, collectiblesJSON: string) {.slot.} = + let collectibleData = parseJson(collectiblesJSON) + let collectibles = collectibleData["collectibles"].to(seq[Collectible]); + let address = collectibleData["address"].getStr + self.accounts.getAccount(self.accounts.getAccountindexByAddress(address)).collectibles = collectibles + if address == self.currentAccount.address: + self.setCurrentCollectiblesList(collectibles) + + self.loadingCollectibles(false) + diff --git a/src/status/libstatus/contracts.nim b/src/status/libstatus/contracts.nim index 14a6f91cb6..4a647ef42d 100644 --- a/src/status/libstatus/contracts.nim +++ b/src/status/libstatus/contracts.nim @@ -30,7 +30,7 @@ type PackData* = object price*: Stuint[256] # uint256 contentHash*: DynamicBytes[64] # bytes -let CONTRACTS: seq[Contract] = @[ +proc allContracts(): seq[Contract] = @[ Contract(name: "snt", network: Network.Mainnet, address: parseAddress("0x744d70fdbe2ba4cf95131626614a1763df805b9e"), methods: [ ("approveAndCall", Method(signature: "approveAndCall(address,uint256,bytes)")), @@ -100,7 +100,7 @@ let CONTRACTS: seq[Contract] = @[ ] proc getContract(network: Network, name: string): Contract = - let found = CONTRACTS.filter(contract => contract.name == name and contract.network == network) + let found = allContracts().filter(contract => contract.name == name and contract.network == network) result = if found.len > 0: found[0] else: nil proc getContract*(name: string): Contract = diff --git a/src/status/libstatus/settings.nim b/src/status/libstatus/settings.nim index 9aad246895..efaab23df8 100644 --- a/src/status/libstatus/settings.nim +++ b/src/status/libstatus/settings.nim @@ -1,28 +1,37 @@ import core, ./types, ../../signals/types as statusgo_types, ./accounts/constants, ./utils import json, tables, sugar, sequtils import json_serialization +import locks -var settings: JsonNode = %*{} -var dirty: bool = true +var settingsLock: Lock +initLock(settingsLock) + +var settings {.guard: settingsLock.} = %*{} +var dirty {.guard: settingsLock.} = true proc saveSetting*(key: Setting, value: string | JsonNode): StatusGoError = let response = callPrivateRPC("settings_saveSetting", %* [ key, value ]) - try: - result = Json.decode($response, StatusGoError) - except: - dirty = true + + withLock settingsLock: + try: + result = Json.decode($response, StatusGoError) + except: + dirty = true proc getWeb3ClientVersion*(): string = parseJson(callPrivateRPC("web3_clientVersion"))["result"].getStr proc getSettings*(useCached: bool = true): JsonNode = - if useCached and not dirty: - return settings - settings = callPrivateRPC("settings_getSettings").parseJSON()["result"] - dirty = false - result = settings + {.gcsafe.}: + withLock settingsLock: + if useCached and not dirty: + result = settings + else: + settings = callPrivateRPC("settings_getSettings").parseJSON()["result"] + dirty = false + result = settings proc getSetting*[T](name: Setting, defaultValue: T, useCached: bool = true): T = let settings: JsonNode = getSettings(useCached) diff --git a/src/status/wallet/collectibles.nim b/src/status/wallet/collectibles.nim index c3dceb50c1..d74dad7933 100644 --- a/src/status/wallet/collectibles.nim +++ b/src/status/wallet/collectibles.nim @@ -3,6 +3,7 @@ from eth/common/utils import parseAddress import ../libstatus/core as status import ../libstatus/contracts as contracts import eth/common/eth_types +import ../libstatus/types import account proc getTokenUri(contract: Contract, tokenId: int): string = diff --git a/ui/app/AppLayouts/Wallet/CollectiblesTab.qml b/ui/app/AppLayouts/Wallet/CollectiblesTab.qml index 833d850ac4..31e79be12b 100644 --- a/ui/app/AppLayouts/Wallet/CollectiblesTab.qml +++ b/ui/app/AppLayouts/Wallet/CollectiblesTab.qml @@ -4,9 +4,39 @@ import "../../../shared" Item { StyledText { - visible: walletModel.collectibles.rowCount() === 0 //% "No collectibles in this account" text: qsTrId("no-collectibles-in-this-account") + visible: walletModel.collectibles.rowCount() === 0 + } + + SVGImage { + id: loadingImg + visible: false + anchors.right: parent.right + anchors.rightMargin: Style.current.padding + anchors.top: parent.top + anchors.topMargin: Style.currentPadding + anchors.verticalCenter: txtPassword.verticalCenter + // TODO replace by a real loading image + source: "../../img/settings.svg" + width: 30 + height: 30 + fillMode: Image.Stretch + RotationAnimator { + target: loadingImg; + from: 0; + to: 360; + duration: 1200 + running: true + loops: Animation.Infinite + } + } + + Connections { + target: walletModel + onLoadingCollectibles: { + loadingImg.visible = isLoading + } } Component {