feat(@dekstop/wallet): support collectibles in activity tab
Fixes #8811
This commit is contained in:
parent
4ad4a7e2b5
commit
eed98809d1
|
@ -31,21 +31,21 @@ proc delete*(self: Controller) =
|
|||
discard
|
||||
|
||||
proc refreshCollections*(self: Controller, chainId: int, address: string) =
|
||||
let collections = self.collectibleService.getCollections(chainId, address)
|
||||
let collections = self.collectibleService.getOwnedCollections(chainId, address)
|
||||
self.delegate.setCollections(collections)
|
||||
|
||||
proc refreshCollectibles*(self: Controller, chainId: int, address: string, collectionSlug: string) =
|
||||
let collection = self.collectibleService.getCollection(chainId, address, collectionSlug)
|
||||
let collection = self.collectibleService.getOwnedCollection(chainId, address, collectionSlug)
|
||||
self.delegate.updateCollection(collection)
|
||||
|
||||
proc init*(self: Controller) =
|
||||
self.events.on(SIGNAL_COLLECTIONS_UPDATED) do(e:Args):
|
||||
let args = CollectionsUpdateArgs(e)
|
||||
self.events.on(SIGNAL_OWNED_COLLECTIONS_UPDATED) do(e:Args):
|
||||
let args = OwnedCollectionsUpdateArgs(e)
|
||||
self.refreshCollections(args.chainId, args.address)
|
||||
self.collectibleService.fetchAllCollectibles(args.chainId, args.address)
|
||||
self.collectibleService.fetchAllOwnedCollectibles(args.chainId, args.address)
|
||||
|
||||
self.events.on(SIGNAL_COLLECTIBLES_UPDATED) do(e:Args):
|
||||
let args = CollectiblesUpdateArgs(e)
|
||||
self.events.on(SIGNAL_OWNED_COLLECTIBLES_UPDATED) do(e:Args):
|
||||
let args = OwnedCollectiblesUpdateArgs(e)
|
||||
self.refreshCollectibles(args.chainId, args.address, args.collectionSlug)
|
||||
|
||||
proc getWalletAccount*(self: Controller, accountIndex: int): wallet_account_service.WalletAccountDto =
|
||||
|
@ -54,8 +54,8 @@ proc getWalletAccount*(self: Controller, accountIndex: int): wallet_account_serv
|
|||
proc getNetwork*(self: Controller): network_service.NetworkDto =
|
||||
return self.networkService.getNetworkForCollectibles()
|
||||
|
||||
proc fetchCollections*(self: Controller, chainId: int, address: string) =
|
||||
self.collectibleService.fetchCollections(chainId, address)
|
||||
proc fetchOwnedCollections*(self: Controller, chainId: int, address: string) =
|
||||
self.collectibleService.fetchOwnedCollections(chainId, address)
|
||||
|
||||
proc fetchCollectibles*(self: Controller, chainId: int, address: string, collectionSlug: string) =
|
||||
self.collectibleService.fetchCollectibles(chainId, address, collectionSlug)
|
||||
proc fetchOwnedCollectibles*(self: Controller, chainId: int, address: string, collectionSlug: string) =
|
||||
self.collectibleService.fetchOwnedCollectibles(chainId, address, collectionSlug)
|
||||
|
|
|
@ -30,5 +30,5 @@ method setCurrentAddress*(self: Controller, network: network_dto.NetworkDto, add
|
|||
self.address = address
|
||||
|
||||
proc update*(self: Controller, collectionSlug: string, id: int) =
|
||||
let collection = self.collectibleService.getCollection(self.network.chainId, self.address, collectionSlug)
|
||||
let collection = self.collectibleService.getOwnedCollection(self.network.chainId, self.address, collectionSlug)
|
||||
self.delegate.setData(collection.collection, collection.collectibles[id], self.network)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import NimQml, sequtils, sugar
|
||||
import NimQml, sequtils, sugar, stint
|
||||
|
||||
import ./io_interface
|
||||
import ../../../../../../app_service/service/network/dto as network_dto
|
||||
|
@ -20,6 +20,7 @@ QtObject:
|
|||
|
||||
name: string
|
||||
id: string
|
||||
tokenId: string
|
||||
description: string
|
||||
backgroundColor: string
|
||||
imageUrl: string
|
||||
|
@ -92,6 +93,15 @@ QtObject:
|
|||
read = getID
|
||||
notify = idChanged
|
||||
|
||||
proc getTokenID(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.tokenId)
|
||||
|
||||
proc tokenIdChanged(self: View) {.signal.}
|
||||
|
||||
QtProperty[QVariant] tokenId:
|
||||
read = getTokenID
|
||||
notify = tokenIdChanged
|
||||
|
||||
proc getDescription(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.description)
|
||||
|
||||
|
@ -206,6 +216,11 @@ QtObject:
|
|||
self.id = idString
|
||||
self.idChanged()
|
||||
|
||||
let tokenIdString = collectible.tokenId.toString()
|
||||
if (self.tokenId != tokenIdString):
|
||||
self.tokenId = tokenIdString
|
||||
self.tokenIdChanged()
|
||||
|
||||
if (self.description != collectible.description):
|
||||
self.description = collectible.description
|
||||
self.descriptionChanged()
|
||||
|
|
|
@ -16,13 +16,13 @@ method isLoaded*(self: AccessInterface): bool {.base.} =
|
|||
method switchAccount*(self: AccessInterface, accountIndex: int) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method fetchCollections*(self: AccessInterface) {.base.} =
|
||||
method fetchOwnedCollections*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method setCollections*(self: AccessInterface, collections: CollectionsData) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method fetchCollectibles*(self: AccessInterface, collectionSlug: string) {.base.} =
|
||||
method fetchOwnedCollectibles*(self: AccessInterface, collectionSlug: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method updateCollection*(self: AccessInterface, collection: CollectionData) {.base.} =
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import strformat
|
||||
import strformat, stint
|
||||
import ./collectible_trait_item
|
||||
|
||||
type
|
||||
Item* = object
|
||||
id: int
|
||||
tokenId: UInt256
|
||||
name: string
|
||||
imageUrl: string
|
||||
backgroundColor: string
|
||||
|
@ -15,6 +16,7 @@ type
|
|||
|
||||
proc initItem*(
|
||||
id: int,
|
||||
tokenId: UInt256,
|
||||
name: string,
|
||||
imageUrl: string,
|
||||
backgroundColor: string,
|
||||
|
@ -25,6 +27,7 @@ proc initItem*(
|
|||
stats: seq[CollectibleTrait]
|
||||
): Item =
|
||||
result.id = id
|
||||
result.tokenId = tokenId
|
||||
result.name = name
|
||||
result.imageUrl = imageUrl
|
||||
result.backgroundColor = if (backgroundColor == ""): "transparent" else: ("#" & backgroundColor)
|
||||
|
@ -35,11 +38,12 @@ proc initItem*(
|
|||
result.stats = stats
|
||||
|
||||
proc initItem*: Item =
|
||||
result = initItem(-1, "", "", "transparent", "Collectibles", "", @[], @[], @[])
|
||||
result = initItem(-1, u256(0), "", "", "transparent", "Collectibles", "", @[], @[], @[])
|
||||
|
||||
proc `$`*(self: Item): string =
|
||||
result = fmt"""Collectibles(
|
||||
id: {self.id},
|
||||
tokenId: {self.tokenId},
|
||||
name: {self.name},
|
||||
imageUrl: {self.imageUrl},
|
||||
backgroundColor: {self.backgroundColor},
|
||||
|
@ -50,6 +54,9 @@ proc `$`*(self: Item): string =
|
|||
proc getId*(self: Item): int =
|
||||
return self.id
|
||||
|
||||
proc getTokenId*(self: Item): UInt256 =
|
||||
return self.tokenId
|
||||
|
||||
proc getName*(self: Item): string =
|
||||
return self.name
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import NimQml, Tables, strutils, strformat, sequtils
|
||||
import NimQml, Tables, strutils, strformat, sequtils, stint
|
||||
|
||||
import ./collectibles_item, ./collectible_trait_model
|
||||
|
||||
type
|
||||
CollectibleRole* {.pure.} = enum
|
||||
Id = UserRole + 1,
|
||||
TokenId
|
||||
Name
|
||||
ImageUrl
|
||||
BackgroundColor
|
||||
|
@ -51,6 +52,7 @@ QtObject:
|
|||
method roleNames(self: Model): Table[int, string] =
|
||||
{
|
||||
CollectibleRole.Id.int:"id",
|
||||
CollectibleRole.TokenId.int:"tokenId",
|
||||
CollectibleRole.Name.int:"name",
|
||||
CollectibleRole.ImageUrl.int:"imageUrl",
|
||||
CollectibleRole.BackgroundColor.int:"backgroundColor",
|
||||
|
@ -74,6 +76,8 @@ QtObject:
|
|||
case enumRole:
|
||||
of CollectibleRole.Id:
|
||||
result = newQVariant(item.getId())
|
||||
of CollectibleRole.TokenId:
|
||||
result = newQVariant(item.getTokenId().toString())
|
||||
of CollectibleRole.Name:
|
||||
result = newQVariant(item.getName())
|
||||
of CollectibleRole.ImageUrl:
|
||||
|
|
|
@ -5,6 +5,7 @@ import collectibles_item, collectible_trait_item
|
|||
proc collectibleToItem*(c: CollectibleDto) : Item =
|
||||
return initItem(
|
||||
c.id,
|
||||
c.tokenId,
|
||||
c.name,
|
||||
c.imageUrl,
|
||||
c.backgroundColor,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import strformat
|
||||
import strformat, stint
|
||||
import ./collectibles_model as collectibles_model
|
||||
import ./collectibles_item as collectibles_item
|
||||
|
||||
|
@ -7,11 +7,11 @@ type
|
|||
name: string
|
||||
slug: string
|
||||
imageUrl: string
|
||||
ownedAssetCount: int
|
||||
ownedAssetCount: Uint256
|
||||
collectiblesLoaded*: bool
|
||||
collectiblesModel: collectibles_model.Model
|
||||
|
||||
proc initItem*(name, slug, imageUrl: string, ownedAssetCount: int, collectiblesLoaded: bool, collectibles: seq[collectibles_item.Item]): Item =
|
||||
proc initItem*(name, slug, imageUrl: string, ownedAssetCount: Uint256, collectiblesLoaded: bool, collectibles: seq[collectibles_item.Item]): Item =
|
||||
result.name = name
|
||||
result.slug = slug
|
||||
result.imageUrl = imageUrl
|
||||
|
@ -20,7 +20,7 @@ proc initItem*(name, slug, imageUrl: string, ownedAssetCount: int, collectiblesL
|
|||
result.collectiblesModel = collectibles_model.newModel(collectibles)
|
||||
|
||||
proc initItem*(): Item =
|
||||
result = initItem("", "", "", 0, false, @[])
|
||||
result = initItem("", "", "", u256(0), false, @[])
|
||||
|
||||
proc `$`*(self: Item): string =
|
||||
result = fmt"""CollectibleCollection(
|
||||
|
@ -41,7 +41,7 @@ proc getSlug*(self: Item): string =
|
|||
proc getImageUrl*(self: Item): string =
|
||||
return self.imageUrl
|
||||
|
||||
proc getOwnedAssetCount*(self: Item): int =
|
||||
proc getOwnedAssetCount*(self: Item): Uint256 =
|
||||
return self.ownedAssetCount
|
||||
|
||||
proc getCollectiblesLoaded*(self: Item): bool =
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import NimQml, Tables, strutils, strformat
|
||||
import NimQml, Tables, strutils, strformat, stint
|
||||
|
||||
import ./collections_item as collections_item
|
||||
|
||||
|
@ -81,7 +81,7 @@ QtObject:
|
|||
of CollectionRole.ImageUrl:
|
||||
result = newQVariant(item.getImageUrl())
|
||||
of CollectionRole.OwnedAssetCount:
|
||||
result = newQVariant(item.getOwnedAssetCount())
|
||||
result = newQVariant(item.getOwnedAssetCount().toString())
|
||||
of CollectionRole.CollectiblesLoaded:
|
||||
result = newQVariant(item.getCollectiblesLoaded())
|
||||
of CollectionRole.CollectiblesModel:
|
||||
|
|
|
@ -84,7 +84,7 @@ method switchAccount*(self: Module, accountIndex: int) =
|
|||
self.address = account.address
|
||||
|
||||
self.controller.refreshCollections(self.chainId, self.address)
|
||||
self.controller.fetchCollections(self.chainId, self.address)
|
||||
self.controller.fetchOwnedCollections(self.chainId, self.address)
|
||||
|
||||
self.currentCollectibleModule.setCurrentAddress(network, self.address)
|
||||
|
||||
|
@ -115,8 +115,8 @@ method updateCollection*(self: Module, collection: CollectionData) =
|
|||
collection.collectiblesLoaded
|
||||
)
|
||||
|
||||
method fetchCollections*(self: Module) =
|
||||
self.controller.fetchCollections(self.chainId, self.address)
|
||||
method fetchOwnedCollections*(self: Module) =
|
||||
self.controller.fetchOwnedCollections(self.chainId, self.address)
|
||||
|
||||
method fetchCollectibles*(self: Module, collectionSlug: string) =
|
||||
self.controller.fetchCollectibles(self.chainId, self.address, collectionSlug)
|
||||
method fetchOwnedCollectibles*(self: Module, collectionSlug: string) =
|
||||
self.controller.fetchOwnedCollectibles(self.chainId, self.address, collectionSlug)
|
||||
|
|
|
@ -42,11 +42,11 @@ QtObject:
|
|||
read = getFlatModel
|
||||
notify = flatModelChanged
|
||||
|
||||
proc fetchCollections*(self: View) {.slot.} =
|
||||
self.delegate.fetchCollections()
|
||||
proc fetchOwnedCollections*(self: View) {.slot.} =
|
||||
self.delegate.fetchOwnedCollections()
|
||||
|
||||
proc fetchCollectibles*(self: View, collectionSlug: string) {.slot.} =
|
||||
self.delegate.fetchCollectibles(collectionSlug)
|
||||
proc fetchOwnedCollectibles*(self: View, collectionSlug: string) {.slot.} =
|
||||
self.delegate.fetchOwnedCollectibles(collectionSlug)
|
||||
|
||||
proc setCollections*(self: View, collections: seq[collections_item.Item], collectionsLoaded: bool) =
|
||||
self.model.setCollections(collections, collectionsLoaded)
|
||||
|
|
|
@ -4,6 +4,7 @@ import ../../../../../app_service/service/transaction/service as transaction_ser
|
|||
import ../../../../../app_service/service/network/service as network_service
|
||||
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
import ../../../../../app_service/service/currency/service as currency_service
|
||||
import ../../../../../app_service/service/collectible/service as collectible_service
|
||||
import ../../../shared_modules/keycard_popup/io_interface as keycard_shared_module
|
||||
|
||||
import ../../../../core/[main]
|
||||
|
@ -66,7 +67,7 @@ proc init*(self: Controller) =
|
|||
self.events.on(SIGNAL_TRANSACTIONS_LOADED) do(e:Args):
|
||||
let args = TransactionsLoadedArgs(e)
|
||||
self.delegate.setHistoryFetchState(@[args.address], isFetching = false)
|
||||
self.delegate.setTrxHistoryResult(args.transactions, args.address, args.wasFetchMore)
|
||||
self.delegate.setTrxHistoryResult(args.transactions, args.collectibles, args.address, args.wasFetchMore)
|
||||
|
||||
self.events.on(SIGNAL_TRANSACTION_SENT) do(e:Args):
|
||||
self.delegate.transactionWasSent(TransactionSentArgs(e).result)
|
||||
|
@ -88,6 +89,10 @@ proc init*(self: Controller) =
|
|||
# TODO: Rebuild Transaction items
|
||||
discard
|
||||
|
||||
self.events.on(SIGNAL_COLLECTIBLES_UPDATED) do(e:Args):
|
||||
# TODO: Refresh collectible data in Transaction items
|
||||
discard
|
||||
|
||||
proc watchPendingTransactions*(self: Controller): seq[TransactionDto] =
|
||||
return self.transactionService.watchPendingTransactions()
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import stint
|
||||
import ../../../../../app_service/service/wallet_account/dto as WalletDto
|
||||
import ../../../../../app_service/service/collectible/dto as CollectibleDto
|
||||
import ../../../../../app_service/service/transaction/dto
|
||||
export TransactionDto
|
||||
export TransactionDto, CollectibleDto
|
||||
|
||||
type
|
||||
AccessInterface* {.pure inheritable.} = ref object of RootObj
|
||||
|
@ -28,7 +29,7 @@ method getAccountByAddress*(self: AccessInterface, address: string): WalletAccou
|
|||
method loadTransactions*(self: AccessInterface, address: string, toBlock: string, limit: int, loadMore: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method setTrxHistoryResult*(self: AccessInterface, transactions: seq[TransactionDto], address: string, wasFetchMore: bool) {.base.} =
|
||||
method setTrxHistoryResult*(self: AccessInterface, transactions: seq[TransactionDto], collectibles: seq[CollectibleDto], address: string, wasFetchMore: bool) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method setHistoryFetchState*(self: AccessInterface, addresses: seq[string], isFetching: bool) {.base.} =
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import strformat
|
||||
import strformat, stint
|
||||
import ../../../shared_models/currency_amount
|
||||
|
||||
type
|
||||
Item* = object
|
||||
id: string
|
||||
typ: string
|
||||
txType: string
|
||||
address: string
|
||||
blockNumber: string
|
||||
blockHash: string
|
||||
|
@ -14,7 +14,6 @@ type
|
|||
gasUsed: int
|
||||
nonce: string
|
||||
txStatus: string
|
||||
value: CurrencyAmount
|
||||
fro: string
|
||||
to: string
|
||||
contract: string
|
||||
|
@ -25,15 +24,22 @@ type
|
|||
txHash: string
|
||||
multiTransactionID: int
|
||||
isTimeStamp: bool
|
||||
isNFT: bool
|
||||
baseGasFees: CurrencyAmount
|
||||
totalFees: CurrencyAmount
|
||||
maxTotalFees: CurrencyAmount
|
||||
symbol: string
|
||||
loadingTransaction: bool
|
||||
# Applies only to isNFT == false
|
||||
value: CurrencyAmount
|
||||
symbol: string
|
||||
# Applies only to isNFT == true
|
||||
tokenID: UInt256
|
||||
nftName: string
|
||||
nftImageUrl: string
|
||||
|
||||
proc initItem*(
|
||||
id: string,
|
||||
typ: string,
|
||||
txType: string,
|
||||
address: string,
|
||||
blockNumber: string,
|
||||
blockHash: string,
|
||||
|
@ -61,7 +67,7 @@ proc initItem*(
|
|||
loadingTransaction: bool = false
|
||||
): Item =
|
||||
result.id = id
|
||||
result.typ = typ
|
||||
result.txType = txType
|
||||
result.address = address
|
||||
result.blockNumber = blockNumber
|
||||
result.blockHash = blockHash
|
||||
|
@ -82,12 +88,73 @@ proc initItem*(
|
|||
result.txHash = txHash
|
||||
result.multiTransactionID = multiTransactionID
|
||||
result.isTimeStamp = isTimeStamp
|
||||
result.isNFT = false
|
||||
result.baseGasFees = baseGasFees
|
||||
result.totalFees = totalFees
|
||||
result.maxTotalFees = maxTotalFees
|
||||
result.symbol = symbol
|
||||
result.loadingTransaction = loadingTransaction
|
||||
|
||||
proc initNFTItem*(
|
||||
id: string,
|
||||
txType: string,
|
||||
address: string,
|
||||
blockNumber: string,
|
||||
blockHash: string,
|
||||
timestamp: int,
|
||||
gasPrice: CurrencyAmount,
|
||||
gasLimit: int,
|
||||
gasUsed: int,
|
||||
nonce: string,
|
||||
txStatus: string,
|
||||
fro: string,
|
||||
to: string,
|
||||
contract: string,
|
||||
chainId: int,
|
||||
maxFeePerGas: CurrencyAmount,
|
||||
maxPriorityFeePerGas: CurrencyAmount,
|
||||
input: string,
|
||||
txHash: string,
|
||||
multiTransactionID: int,
|
||||
baseGasFees: CurrencyAmount,
|
||||
totalFees: CurrencyAmount,
|
||||
maxTotalFees: CurrencyAmount,
|
||||
tokenID: UInt256,
|
||||
nftName: string,
|
||||
nftImageUrl: string,
|
||||
loadingTransaction: bool = false
|
||||
): Item =
|
||||
result.id = id
|
||||
result.txType = txType
|
||||
result.address = address
|
||||
result.blockNumber = blockNumber
|
||||
result.blockHash = blockHash
|
||||
result.timestamp = timestamp
|
||||
result.gasPrice = gasPrice
|
||||
result.gasLimit = gasLimit
|
||||
result.gasUsed = gasUsed
|
||||
result.nonce = nonce
|
||||
result.txStatus = txStatus
|
||||
result.value = newCurrencyAmount()
|
||||
result.fro = fro
|
||||
result.to = to
|
||||
result.contract = contract
|
||||
result.chainId = chainId
|
||||
result.maxFeePerGas = maxFeePerGas
|
||||
result.maxPriorityFeePerGas = maxPriorityFeePerGas
|
||||
result.input = input
|
||||
result.txHash = txHash
|
||||
result.multiTransactionID = multiTransactionID
|
||||
result.isTimeStamp = false
|
||||
result.isNFT = true
|
||||
result.baseGasFees = baseGasFees
|
||||
result.totalFees = totalFees
|
||||
result.maxTotalFees = maxTotalFees
|
||||
result.loadingTransaction = loadingTransaction
|
||||
result.tokenID = tokenID
|
||||
result.nftName = nftName
|
||||
result.nftImageUrl = nftImageUrl
|
||||
|
||||
proc initTimestampItem*(timestamp: int): Item =
|
||||
result.timestamp = timestamp
|
||||
result.gasPrice = newCurrencyAmount()
|
||||
|
@ -116,9 +183,9 @@ proc initLoadingItem*(): Item =
|
|||
result.loadingTransaction = true
|
||||
|
||||
proc `$`*(self: Item): string =
|
||||
result = fmt"""AllTokensItem(
|
||||
result = fmt"""TransactionsItem(
|
||||
id: {self.id},
|
||||
type: {self.typ},
|
||||
txType: {self.txType},
|
||||
address: {self.address},
|
||||
blockNumber: {self.blockNumber},
|
||||
blockHash: {self.blockHash},
|
||||
|
@ -139,18 +206,22 @@ proc `$`*(self: Item): string =
|
|||
txHash: {self.txHash},
|
||||
multiTransactionID: {self.multiTransactionID},
|
||||
isTimeStamp: {self.isTimeStamp},
|
||||
isNFT: {self.isNFT},
|
||||
baseGasFees: {self.baseGasFees},
|
||||
totalFees: {self.totalFees},
|
||||
maxTotalFees: {self.maxTotalFees},
|
||||
symbol: {self.symbol},
|
||||
loadingTransaction: {self.loadingTransaction},
|
||||
tokenID: {self.tokenID},
|
||||
nftName: {self.nftName},
|
||||
nftImageUrl: {self.nftImageUrl},
|
||||
]"""
|
||||
|
||||
proc getId*(self: Item): string =
|
||||
return self.id
|
||||
|
||||
proc getType*(self: Item): string =
|
||||
return self.typ
|
||||
return self.txType
|
||||
|
||||
proc getAddress*(self: Item): string =
|
||||
return self.address
|
||||
|
@ -212,6 +283,9 @@ proc getMultiTransactionID*(self: Item): int =
|
|||
proc getIsTimeStamp*(self: Item): bool =
|
||||
return self.isTimeStamp
|
||||
|
||||
proc getIsNFT*(self: Item): bool =
|
||||
return self.isNFT
|
||||
|
||||
proc getBaseGasFees*(self: Item): CurrencyAmount =
|
||||
return self.baseGasFees
|
||||
|
||||
|
@ -226,3 +300,12 @@ proc getSymbol*(self: Item): string =
|
|||
|
||||
proc getLoadingTransaction*(self: Item): bool =
|
||||
return self.loadingTransaction
|
||||
|
||||
proc getTokenID*(self: Item): UInt256 =
|
||||
return self.tokenID
|
||||
|
||||
proc getNFTName*(self: Item): string =
|
||||
return self.nftName
|
||||
|
||||
proc getNFTImageURL*(self: Item): string =
|
||||
return self.nftImageUrl
|
||||
|
|
|
@ -16,7 +16,6 @@ type
|
|||
GasUsed
|
||||
Nonce
|
||||
TxStatus
|
||||
Value
|
||||
From
|
||||
To
|
||||
Contract
|
||||
|
@ -27,11 +26,18 @@ type
|
|||
TxHash
|
||||
MultiTransactionID
|
||||
IsTimeStamp
|
||||
IsNFT
|
||||
BaseGasFees
|
||||
TotalFees
|
||||
MaxTotalFees
|
||||
Symbol
|
||||
LoadingTransaction
|
||||
# Applies only to IsNFT == false
|
||||
Value
|
||||
Symbol
|
||||
# Applies only to IsNFT == true
|
||||
TokenID
|
||||
NFTName
|
||||
NFTImageURL
|
||||
|
||||
QtObject:
|
||||
type
|
||||
|
@ -93,11 +99,15 @@ QtObject:
|
|||
ModelRole.TxHash.int:"txHash",
|
||||
ModelRole.MultiTransactionID.int:"multiTransactionID",
|
||||
ModelRole.IsTimeStamp.int: "isTimeStamp",
|
||||
ModelRole.IsNFT.int: "isNFT",
|
||||
ModelRole.BaseGasFees.int: "baseGasFees",
|
||||
ModelRole.TotalFees.int: "totalFees",
|
||||
ModelRole.MaxTotalFees.int: "maxTotalFees",
|
||||
ModelRole.Symbol.int: "symbol",
|
||||
ModelRole.LoadingTransaction.int: "loadingTransaction"
|
||||
ModelRole.LoadingTransaction.int: "loadingTransaction",
|
||||
ModelRole.TokenID.int: "tokenID",
|
||||
ModelRole.NFTName.int: "nftName",
|
||||
ModelRole.NFTImageURL.int: "nftImageUrl"
|
||||
}.toTable
|
||||
|
||||
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
||||
|
@ -154,7 +164,9 @@ QtObject:
|
|||
of ModelRole.MultiTransactionID:
|
||||
result = newQVariant(item.getMultiTransactionID())
|
||||
of ModelRole.IsTimeStamp:
|
||||
result = newQVariant(item.getIsTimeStamp())
|
||||
result = newQVariant(item.getIsTimeStamp())
|
||||
of ModelRole.IsNFT:
|
||||
result = newQVariant(item.getIsNFT())
|
||||
of ModelRole.BaseGasFees:
|
||||
result = newQVariant(item.getBaseGasFees())
|
||||
of ModelRole.TotalFees:
|
||||
|
@ -165,6 +177,12 @@ QtObject:
|
|||
result = newQVariant(item.getSymbol())
|
||||
of ModelRole.LoadingTransaction:
|
||||
result = newQVariant(item.getLoadingTransaction())
|
||||
of ModelRole.TokenID:
|
||||
result = newQVariant(item.getTokenID().toString())
|
||||
of ModelRole.NFTName:
|
||||
result = newQVariant(item.getNFTName())
|
||||
of ModelRole.NFTImageURL:
|
||||
result = newQVariant(item.getNFTImageURL())
|
||||
|
||||
proc setItems*(self: Model, items: seq[Item]) =
|
||||
self.beginResetModel()
|
||||
|
|
|
@ -4,10 +4,12 @@ import ./io_interface, ./view, ./controller, ./item, ./utils
|
|||
import ../io_interface as delegate_interface
|
||||
import ../../../../global/global_singleton
|
||||
import ../../../../core/eventemitter
|
||||
import ../../../../../app_service/common/wallet_constants
|
||||
import ../../../../../app_service/service/transaction/service as transaction_service
|
||||
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
|
||||
import ../../../../../app_service/service/network/service as network_service
|
||||
import ../../../../../app_service/service/currency/service as currency_service
|
||||
import ../../../../../app_service/service/collectible/service as collectible_service
|
||||
|
||||
export io_interface
|
||||
|
||||
|
@ -70,17 +72,24 @@ proc getResolvedSymbol*(self: Module, transaction: TransactionDto): string =
|
|||
else:
|
||||
result = "ETH"
|
||||
|
||||
proc transactionsToItems(self: Module, transactions: seq[TransactionDto]) : seq[Item] =
|
||||
proc transactionsToItems(self: Module, transactions: seq[TransactionDto], collectibles: seq[CollectibleDto]) : seq[Item] =
|
||||
let gweiFormat = self.controller.getCurrencyFormat("Gwei")
|
||||
let ethFormat = self.controller.getCurrencyFormat("ETH")
|
||||
|
||||
transactions.map(t => (block:
|
||||
if t.typeValue == ERC721_TRANSACTION_TYPE:
|
||||
for c in collectibles:
|
||||
if c.tokenId == t.tokenId and c.address == t.contract:
|
||||
# Found matching collectible
|
||||
return transactionToNFTItem(t, c, ethFormat, gweiFormat)
|
||||
# Could not find matching collectible, use empty one
|
||||
return transactionToNFTItem(t, newCollectibleDto(), ethFormat, gweiFormat)
|
||||
let resolvedSymbol = self.getResolvedSymbol(t)
|
||||
transactionToItem(t, resolvedSymbol, self.controller.getCurrencyFormat(resolvedSymbol), ethFormat, gweiFormat)
|
||||
return transactionToItem(t, resolvedSymbol, self.controller.getCurrencyFormat(resolvedSymbol), ethFormat, gweiFormat)
|
||||
))
|
||||
|
||||
proc setPendingTx(self: Module) =
|
||||
self.view.setPendingTx(self.transactionsToItems(self.controller.watchPendingTransactions()))
|
||||
self.view.setPendingTx(self.transactionsToItems(self.controller.watchPendingTransactions(), @[]))
|
||||
|
||||
method viewDidLoad*(self: Module) =
|
||||
let accounts = self.getWalletAccounts()
|
||||
|
@ -109,8 +118,8 @@ method loadTransactions*(self: Module, address: string, toBlock: string = "0x0",
|
|||
|
||||
self.controller.loadTransactions(address, toBlockParsed, txLimit, loadMore)
|
||||
|
||||
method setTrxHistoryResult*(self: Module, transactions: seq[TransactionDto], address: string, wasFetchMore: bool) =
|
||||
self.view.setTrxHistoryResult(self.transactionsToItems(transactions), address, wasFetchMore)
|
||||
method setTrxHistoryResult*(self: Module, transactions: seq[TransactionDto], collectibles: seq[CollectibleDto], address: string, wasFetchMore: bool) =
|
||||
self.view.setTrxHistoryResult(self.transactionsToItems(transactions, collectibles), address, wasFetchMore)
|
||||
|
||||
method setHistoryFetchState*(self: Module, addresses: seq[string], isFetching: bool) =
|
||||
self.view.setHistoryFetchStateForAccounts(addresses, isFetching)
|
||||
|
@ -168,7 +177,7 @@ method onUserAuthenticated*(self: Module, password: string) =
|
|||
|
||||
method transactionWasSent*(self: Module, result: string) =
|
||||
self.view.transactionWasSent(result)
|
||||
self.view.setPendingTx(self.transactionsToItems(self.controller.getPendingTransactions()))
|
||||
self.view.setPendingTx(self.transactionsToItems(self.controller.getPendingTransactions(), @[]))
|
||||
|
||||
method suggestedFees*(self: Module, chainId: int): string =
|
||||
return self.controller.suggestedFees(chainId)
|
||||
|
|
|
@ -3,6 +3,7 @@ import ../../../../global/global_singleton
|
|||
|
||||
import ../../../../../app_service/service/transaction/dto
|
||||
import ../../../../../app_service/service/currency/dto as currency_dto
|
||||
import ../../../../../app_service/service/collectible/dto as collectible_dto
|
||||
import ../../../shared_models/currency_amount
|
||||
import ../../../shared_models/currency_amount_utils
|
||||
|
||||
|
@ -49,3 +50,33 @@ proc transactionToItem*(t: TransactionDto, resolvedSymbol: string, tokenFormat:
|
|||
hex2GweiCurrencyAmount(t.maxTotalFees, gweiFormat),
|
||||
resolvedSymbol
|
||||
)
|
||||
|
||||
proc transactionToNFTItem*(t: TransactionDto, c: CollectibleDto, ethFormat: CurrencyFormatDto, gweiFormat: CurrencyFormatDto): Item =
|
||||
return initNFTItem(
|
||||
t.id,
|
||||
t.typeValue,
|
||||
t.address,
|
||||
t.blockNumber,
|
||||
t.blockHash,
|
||||
toInt(t.timestamp),
|
||||
hex2EthCurrencyAmount(t.gasPrice, ethFormat),
|
||||
parseInt(singletonInstance.utils.hex2Dec(t.gasLimit)),
|
||||
parseInt(singletonInstance.utils.hex2Dec(t.gasUsed)),
|
||||
t.nonce,
|
||||
t.txStatus,
|
||||
t.fromAddress,
|
||||
t.to,
|
||||
t.contract,
|
||||
t.chainId,
|
||||
hex2GweiCurrencyAmount(t.maxFeePerGas, gweiFormat),
|
||||
hex2GweiCurrencyAmount(t.maxPriorityFeePerGas, gweiFormat),
|
||||
t.input,
|
||||
t.txHash,
|
||||
t.multiTransactionID,
|
||||
hex2GweiCurrencyAmount(t.baseGasFees, gweiFormat),
|
||||
hex2GweiCurrencyAmount(t.totalFees, gweiFormat),
|
||||
hex2GweiCurrencyAmount(t.maxTotalFees, gweiFormat),
|
||||
t.tokenId,
|
||||
c.name,
|
||||
c.imageUrl
|
||||
)
|
|
@ -0,0 +1,3 @@
|
|||
const ETH_TRANSACTION_TYPE* = "eth"
|
||||
const ERC20_TRANSACTION_TYPE* = "erc20"
|
||||
const ERC721_TRANSACTION_TYPE* = "erc721"
|
|
@ -1,32 +1,32 @@
|
|||
type
|
||||
FetchCollectionsTaskArg = ref object of QObjectTaskArg
|
||||
FetchOwnedCollectionsTaskArg = ref object of QObjectTaskArg
|
||||
chainId*: int
|
||||
address*: string
|
||||
|
||||
const fetchCollectionsTaskArg: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[FetchCollectionsTaskArg](argEncoded)
|
||||
const fetchOwnedCollectionsTaskArg: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[FetchOwnedCollectionsTaskArg](argEncoded)
|
||||
let output = %* {
|
||||
"chainId": arg.chainId,
|
||||
"address": arg.address,
|
||||
"collections": ""
|
||||
}
|
||||
try:
|
||||
let response = backend.getOpenseaCollectionsByOwner(arg.chainId, arg.address)
|
||||
let response = collectibles.getOpenseaCollectionsByOwner(arg.chainId, arg.address)
|
||||
output["collections"] = response.result
|
||||
except Exception as e:
|
||||
let errDesription = e.msg
|
||||
error "error fetchCollectionsTaskArg: ", errDesription
|
||||
error "error fetchOwnedCollectionsTaskArg: ", errDesription
|
||||
arg.finish(output)
|
||||
|
||||
type
|
||||
FetchCollectiblesTaskArg = ref object of QObjectTaskArg
|
||||
FetchOwnedCollectiblesTaskArg = ref object of QObjectTaskArg
|
||||
chainId*: int
|
||||
address*: string
|
||||
collectionSlug: string
|
||||
limit: int
|
||||
|
||||
const fetchCollectiblesTaskArg: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[FetchCollectiblesTaskArg](argEncoded)
|
||||
const fetchOwnedCollectiblesTaskArg: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[FetchOwnedCollectiblesTaskArg](argEncoded)
|
||||
let output = %* {
|
||||
"chainId": arg.chainId,
|
||||
"address": arg.address,
|
||||
|
@ -34,7 +34,27 @@ const fetchCollectiblesTaskArg: Task = proc(argEncoded: string) {.gcsafe, nimcal
|
|||
"collectibles": ""
|
||||
}
|
||||
try:
|
||||
let response = backend.getOpenseaAssetsByOwnerAndCollection(arg.chainId, arg.address, arg.collectionSlug, arg.limit)
|
||||
let response = collectibles.getOpenseaAssetsByOwnerAndCollection(arg.chainId, arg.address, arg.collectionSlug, arg.limit)
|
||||
output["collectibles"] = response.result
|
||||
except Exception as e:
|
||||
let errDesription = e.msg
|
||||
error "error fetchOwnedCollectiblesTaskArg: ", errDesription
|
||||
arg.finish(output)
|
||||
|
||||
type
|
||||
FetchCollectiblesTaskArg = ref object of QObjectTaskArg
|
||||
chainId*: int
|
||||
ids*: seq[collectibles.NFTUniqueID]
|
||||
limit: int
|
||||
|
||||
const fetchCollectiblesTaskArg: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[FetchCollectiblesTaskArg](argEncoded)
|
||||
let output = %* {
|
||||
"chainId": arg.chainId,
|
||||
"collectibles": ""
|
||||
}
|
||||
try:
|
||||
let response = collectibles.getOpenseaAssetsByNFTUniqueID(arg.chainId, arg.ids, arg.limit)
|
||||
output["collectibles"] = response.result
|
||||
except Exception as e:
|
||||
let errDesription = e.msg
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import json, Tables, strformat, strutils
|
||||
import json, Tables, stint, strformat, strutils
|
||||
|
||||
|
||||
type CollectibleTraitType* {.pure.} = enum
|
||||
|
@ -11,7 +11,7 @@ type CollectionTrait* = ref object
|
|||
|
||||
type CollectionDto* = ref object
|
||||
name*, slug*, imageUrl*: string
|
||||
ownedAssetCount*: int
|
||||
ownedAssetCount*: Uint256
|
||||
trait*: Table[string, CollectionTrait]
|
||||
|
||||
type CollectibleTrait* = ref object
|
||||
|
@ -19,9 +19,18 @@ type CollectibleTrait* = ref object
|
|||
|
||||
type CollectibleDto* = ref object
|
||||
id*: int
|
||||
tokenId*: Uint256
|
||||
name*, description*, permalink*, imageThumbnailUrl*, imageUrl*, address*, backgroundColor*: string
|
||||
properties*, rankings*, statistics*: seq[CollectibleTrait]
|
||||
|
||||
proc newCollectibleDto*: CollectibleDto =
|
||||
return CollectibleDto(
|
||||
id: -1
|
||||
)
|
||||
|
||||
proc isValid*(self: CollectibleDto): bool =
|
||||
return self.id >= 0
|
||||
|
||||
proc isNumeric(s: string): bool =
|
||||
try:
|
||||
discard s.parseFloat()
|
||||
|
@ -33,7 +42,7 @@ proc `$`*(self: CollectionDto): string =
|
|||
return fmt"CollectionDto(name:{self.name}, slug:{self.slug}, owned asset count:{self.ownedAssetCount})"
|
||||
|
||||
proc `$`*(self: CollectibleDto): string =
|
||||
return fmt"CollectibleDto(id:{self.id}, name:{self.name}, description:{self.description}, permalink:{self.permalink}, address:{self.address}, imageUrl: {self.imageUrl}, imageThumbnailUrl: {self.imageThumbnailUrl}, backgroundColor: {self.backgroundColor})"
|
||||
return fmt"CollectibleDto(id:{self.id}, token_id:{self.tokenId}, name:{self.name}, description:{self.description}, permalink:{self.permalink}, address:{self.address}, imageUrl: {self.imageUrl}, imageThumbnailUrl: {self.imageThumbnailUrl}, backgroundColor: {self.backgroundColor})"
|
||||
|
||||
proc getCollectionTraits*(jsonCollection: JsonNode): Table[string, CollectionTrait] =
|
||||
var traitList: Table[string, CollectionTrait] = initTable[string, CollectionTrait]()
|
||||
|
@ -46,7 +55,7 @@ proc toCollectionDto*(jsonCollection: JsonNode): CollectionDto =
|
|||
name: jsonCollection{"name"}.getStr,
|
||||
slug: jsonCollection{"slug"}.getStr,
|
||||
imageUrl: jsonCollection{"image_url"}.getStr,
|
||||
ownedAssetCount: jsonCollection{"owned_asset_count"}.getInt,
|
||||
ownedAssetCount: stint.parse(jsonCollection{"owned_asset_count"}.getStr, Uint256),
|
||||
trait: getCollectionTraits(jsonCollection)
|
||||
)
|
||||
|
||||
|
@ -70,6 +79,7 @@ proc getTrait*(jsonAsset: JsonNode, traitType: CollectibleTraitType): seq[Collec
|
|||
proc toCollectibleDto*(jsonAsset: JsonNode): CollectibleDto =
|
||||
return CollectibleDto(
|
||||
id: jsonAsset{"id"}.getInt,
|
||||
tokenId: stint.parse(jsonAsset{"token_id"}.getStr, Uint256),
|
||||
name: jsonAsset{"name"}.getStr,
|
||||
description: jsonAsset{"description"}.getStr,
|
||||
permalink: jsonAsset{"permalink"}.getStr,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import NimQml, Tables, chronicles, sequtils, json, sugar
|
||||
import NimQml, Tables, chronicles, sequtils, json, sugar, stint, hashes
|
||||
import ../../../app/core/eventemitter
|
||||
import ../../../app/core/tasks/[qt, threadpool]
|
||||
|
||||
import dto
|
||||
import ../network/service as network_service
|
||||
|
||||
import ../../../backend/backend
|
||||
import ../../../backend/collectibles as collectibles
|
||||
|
||||
include ../../common/json_utils
|
||||
include async_tasks
|
||||
|
@ -16,25 +16,35 @@ logScope:
|
|||
topics = "collectible-service"
|
||||
|
||||
# Signals which may be emitted by this service:
|
||||
const SIGNAL_COLLECTIONS_UPDATE_STARTED* = "collectionsUpdateStarted"
|
||||
const SIGNAL_COLLECTIONS_UPDATED* = "collectionsUpdated"
|
||||
const SIGNAL_COLLECTIBLES_UPDATE_STARTED* = "collectiblesUpdateStarted"
|
||||
const SIGNAL_OWNED_COLLECTIONS_UPDATED* = "ownedCollectionsUpdated"
|
||||
const SIGNAL_OWNED_COLLECTIBLES_UPDATED* = "ownedCollectiblesUpdated"
|
||||
const SIGNAL_COLLECTIBLES_UPDATED* = "collectiblesUpdated"
|
||||
|
||||
# Maximum number of collectibles to be fetched at a time
|
||||
const limit = 200
|
||||
|
||||
# Unique identifier for collectible in a specific chain
|
||||
type
|
||||
CollectionsUpdateArgs* = ref object of Args
|
||||
UniqueID* = object
|
||||
contractAddress*: string
|
||||
tokenId*: UInt256
|
||||
|
||||
type
|
||||
OwnedCollectionsUpdateArgs* = ref object of Args
|
||||
chainId*: int
|
||||
address*: string
|
||||
|
||||
type
|
||||
CollectiblesUpdateArgs* = ref object of Args
|
||||
OwnedCollectiblesUpdateArgs* = ref object of Args
|
||||
chainId*: int
|
||||
address*: string
|
||||
collectionSlug*: string
|
||||
|
||||
type
|
||||
CollectiblesUpdateArgs* = ref object of Args
|
||||
chainId*: int
|
||||
ids*: seq[UniqueID]
|
||||
|
||||
type
|
||||
CollectionData* = ref object
|
||||
collection*: CollectionDto
|
||||
|
@ -63,13 +73,18 @@ type
|
|||
type
|
||||
ChainsData* = TableRef[int, AdressesData] # [chainId, AdressesData]
|
||||
|
||||
proc hash(x: UniqueID): Hash =
|
||||
result = x.contractAddress.hash !& x.tokenId.hash
|
||||
result = !$result
|
||||
|
||||
QtObject:
|
||||
type
|
||||
Service* = ref object of QObject
|
||||
events: EventEmitter
|
||||
threadpool: ThreadPool
|
||||
networkService: network_service.Service
|
||||
data: ChainsData
|
||||
ownershipData: ChainsData
|
||||
data: TableRef[int, TableRef[UniqueID, CollectibleDto]] # [chainId, [UniqueID, CollectibleDto]]
|
||||
|
||||
proc delete*(self: Service) =
|
||||
self.QObject.delete
|
||||
|
@ -84,22 +99,23 @@ QtObject:
|
|||
result.events = events
|
||||
result.threadpool = threadpool
|
||||
result.networkService = networkService
|
||||
result.data = newTable[int, AdressesData]()
|
||||
result.ownershipData = newTable[int, AdressesData]()
|
||||
result.data = newTable[int, TableRef[UniqueID, CollectibleDto]]()
|
||||
|
||||
proc init*(self: Service) =
|
||||
discard
|
||||
|
||||
proc insertAddressIfNeeded*(self: Service, chainId: int, address: string) =
|
||||
if not self.data.hasKey(chainId):
|
||||
self.data[chainId] = newTable[string, CollectionsData]()
|
||||
if not self.ownershipData.hasKey(chainId):
|
||||
self.ownershipData[chainId] = newTable[string, CollectionsData]()
|
||||
|
||||
let chainData = self.data[chainId]
|
||||
let chainData = self.ownershipData[chainId]
|
||||
if not chainData.hasKey(address):
|
||||
chainData[address] = newCollectionsData()
|
||||
|
||||
proc setCollections*(self: Service, chainId: int, address: string, collections: seq[CollectionDto]) =
|
||||
proc updateOwnedCollectionsCache*(self: Service, chainId: int, address: string, collections: seq[CollectionDto]) =
|
||||
try:
|
||||
let oldAddressData = self.data[chainId][address]
|
||||
let oldAddressData = self.ownershipData[chainId][address]
|
||||
|
||||
# Start with empty object. Only add newly received collections, so removed ones are discarded
|
||||
let newAddressData = newCollectionsData()
|
||||
|
@ -113,46 +129,105 @@ QtObject:
|
|||
newCollection.collectibles = oldCollection.collectibles
|
||||
|
||||
newAddressData.collectionsLoaded = true
|
||||
self.data[chainId][address] = newAddressData
|
||||
self.ownershipData[chainId][address] = newAddressData
|
||||
|
||||
var data = OwnedCollectionsUpdateArgs()
|
||||
data.chainId = chainId
|
||||
data.address = address
|
||||
|
||||
self.events.emit(SIGNAL_OWNED_COLLECTIONS_UPDATED, data)
|
||||
|
||||
except Exception as e:
|
||||
let errDesription = e.msg
|
||||
error "error: ", errDesription
|
||||
|
||||
proc setCollectibles*(self: Service, chainId: int, address: string, collectionSlug: string, collectibles: seq[CollectibleDto]) =
|
||||
proc updateOwnedCollectiblesCache*(self: Service, chainId: int, address: string, collectionSlug: string, collectibles: seq[CollectibleDto]) =
|
||||
try:
|
||||
let collection = self.data[chainId][address].collections[collectionSlug]
|
||||
let collection = self.ownershipData[chainId][address].collections[collectionSlug]
|
||||
collection.collectibles.clear()
|
||||
|
||||
for collectible in collectibles:
|
||||
collection.collectibles[collectible.id] = collectible
|
||||
collection.collectiblesLoaded = true
|
||||
|
||||
var data = OwnedCollectiblesUpdateArgs()
|
||||
data.chainId = chainId
|
||||
data.address = address
|
||||
data.collectionSlug = collectionSlug
|
||||
self.events.emit(SIGNAL_OWNED_COLLECTIBLES_UPDATED, data)
|
||||
except Exception as e:
|
||||
let errDesription = e.msg
|
||||
error "error: ", errDesription
|
||||
|
||||
proc getCollections*(self: Service, chainId: int, address: string) : CollectionsData =
|
||||
proc updateCollectiblesCache*(self: Service, chainId: int, collectibles: seq[CollectibleDto]) =
|
||||
if not self.data.hasKey(chainId):
|
||||
self.data[chainId] = newTable[UniqueID, CollectibleDto]()
|
||||
|
||||
var data = CollectiblesUpdateArgs()
|
||||
data.chainId = chainId
|
||||
|
||||
for collectible in collectibles:
|
||||
let id = UniqueID(
|
||||
contractAddress: collectible.address,
|
||||
tokenId: collectible.tokenId
|
||||
)
|
||||
self.data[chainId][id] = collectible
|
||||
data.ids.add(id)
|
||||
|
||||
self.events.emit(SIGNAL_COLLECTIBLES_UPDATED, data)
|
||||
|
||||
proc getOwnedCollections*(self: Service, chainId: int, address: string) : CollectionsData =
|
||||
try:
|
||||
return self.data[chainId][address]
|
||||
return self.ownershipData[chainId][address]
|
||||
except:
|
||||
discard
|
||||
return newCollectionsData()
|
||||
|
||||
proc getCollection*(self: Service, chainId: int, address: string, collectionSlug: string) : CollectionData =
|
||||
proc getOwnedCollection*(self: Service, chainId: int, address: string, collectionSlug: string) : CollectionData =
|
||||
try:
|
||||
return self.data[chainId][address].collections[collectionSlug]
|
||||
return self.ownershipData[chainId][address].collections[collectionSlug]
|
||||
except:
|
||||
discard
|
||||
return newCollectionData(CollectionDto())
|
||||
|
||||
proc getCollectible*(self: Service, chainId: int, address: string, collectionSlug: string, collectibleId: int) : CollectibleDto =
|
||||
proc getCollectible*(self: Service, chainId: int, id: UniqueID) : CollectibleDto =
|
||||
try:
|
||||
return self.data[chainId][address].collections[collectionSlug].collectibles[collectibleId]
|
||||
return self.data[chainId][id]
|
||||
except:
|
||||
discard
|
||||
return CollectibleDto()
|
||||
return newCollectibleDto()
|
||||
|
||||
proc onRxCollections*(self: Service, response: string) {.slot.} =
|
||||
var data = CollectionsUpdateArgs()
|
||||
proc onRxCollectibles*(self: Service, response: string) {.slot.} =
|
||||
try:
|
||||
let responseObj = response.parseJson
|
||||
if (responseObj.kind == JObject):
|
||||
let chainIdJson = responseObj["chainId"]
|
||||
let collectiblesJson = responseObj["collectibles"]
|
||||
|
||||
if (chainIdJson.kind == JInt and
|
||||
collectiblesJson.kind == JArray):
|
||||
let chainId = chainIdJson.getInt()
|
||||
let collectibles = map(collectiblesJson.getElems(), proc(x: JsonNode): CollectibleDto = x.toCollectibleDto())
|
||||
self.updateCollectiblesCache(chainId, collectibles)
|
||||
except Exception as e:
|
||||
let errDescription = e.msg
|
||||
error "error onRxCollectibles: ", errDescription
|
||||
|
||||
proc fetchCollectibles*(self: Service, chainId: int, ids: seq[UniqueID]) =
|
||||
let arg = FetchCollectiblesTaskArg(
|
||||
tptr: cast[ByteAddress](fetchCollectiblesTaskArg),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "onRxCollectibles",
|
||||
chainId: chainId,
|
||||
ids: ids.map(id => collectibles.NFTUniqueID(
|
||||
contractAddress: id.contractAddress,
|
||||
tokenID: id.tokenId.toString()
|
||||
)),
|
||||
limit: limit
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
|
||||
proc onRxOwnedCollections*(self: Service, response: string) {.slot.} =
|
||||
try:
|
||||
let responseObj = response.parseJson
|
||||
if (responseObj.kind == JObject):
|
||||
|
@ -162,38 +237,33 @@ QtObject:
|
|||
let validAccount = (chainIdJson.kind == JInt and
|
||||
addressJson.kind == JString)
|
||||
if (validAccount):
|
||||
data.chainId = chainIdJson.getInt()
|
||||
data.address = addressJson.getStr()
|
||||
let chainId = chainIdJson.getInt()
|
||||
let address = addressJson.getStr()
|
||||
|
||||
var collections: seq[CollectionDto]
|
||||
let collectionsJson = responseObj["collections"]
|
||||
if (collectionsJson.kind == JArray):
|
||||
collections = map(collectionsJson.getElems(), proc(x: JsonNode): CollectionDto = x.toCollectionDto())
|
||||
self.setCollections(data.chainId, data.address, collections)
|
||||
self.events.emit(SIGNAL_COLLECTIONS_UPDATED, data)
|
||||
|
||||
self.updateOwnedCollectionsCache(chainId, address, collections)
|
||||
except Exception as e:
|
||||
let errDescription = e.msg
|
||||
error "error onRxCollections: ", errDescription
|
||||
error "error onRxOwnedCollections: ", errDescription
|
||||
|
||||
proc fetchCollections*(self: Service, chainId: int, address: string) =
|
||||
proc fetchOwnedCollections*(self: Service, chainId: int, address: string) =
|
||||
self.insertAddressIfNeeded(chainId, address)
|
||||
|
||||
var data = CollectionsUpdateArgs()
|
||||
data.chainId = chainId
|
||||
data.address = address
|
||||
self.events.emit(SIGNAL_COLLECTIONS_UPDATE_STARTED, data)
|
||||
|
||||
let arg = FetchCollectionsTaskArg(
|
||||
tptr: cast[ByteAddress](fetchCollectionsTaskArg),
|
||||
let arg = FetchOwnedCollectionsTaskArg(
|
||||
tptr: cast[ByteAddress](fetchOwnedCollectionsTaskArg),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "onRxCollections",
|
||||
slot: "onRxOwnedCollections",
|
||||
chainId: chainId,
|
||||
address: address,
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
|
||||
proc onRxCollectibles*(self: Service, response: string) {.slot.} =
|
||||
var data = CollectiblesUpdateArgs()
|
||||
proc onRxOwnedCollectibles*(self: Service, response: string) {.slot.} =
|
||||
var data = OwnedCollectiblesUpdateArgs()
|
||||
try:
|
||||
let responseObj = response.parseJson
|
||||
if (responseObj.kind == JObject):
|
||||
|
@ -205,38 +275,32 @@ QtObject:
|
|||
addressJson.kind == JString and
|
||||
collectionSlugJson.kind == JString)
|
||||
if (validCollection):
|
||||
data.chainId = chainIdJson.getInt()
|
||||
data.address = addressJson.getStr()
|
||||
data.collectionSlug = collectionSlugJson.getStr()
|
||||
let chainId = chainIdJson.getInt()
|
||||
let address = addressJson.getStr()
|
||||
let collectionSlug = collectionSlugJson.getStr()
|
||||
|
||||
var collectibles: seq[CollectibleDto]
|
||||
let collectiblesJson = responseObj["collectibles"]
|
||||
if (collectiblesJson.kind == JArray):
|
||||
collectibles = map(collectiblesJson.getElems(), proc(x: JsonNode): CollectibleDto = x.toCollectibleDto())
|
||||
self.setCollectibles(data.chainId, data.address, data.collectionSlug, collectibles)
|
||||
self.events.emit(SIGNAL_COLLECTIBLES_UPDATED, data)
|
||||
self.updateOwnedCollectiblesCache(chainId, address, collectionSlug, collectibles)
|
||||
self.updateCollectiblesCache(data.chainId, collectibles)
|
||||
except Exception as e:
|
||||
let errDescription = e.msg
|
||||
error "error onRxCollectibles: ", errDescription
|
||||
error "error onRxOwnedCollectibles: ", errDescription
|
||||
|
||||
proc fetchCollectibles*(self: Service, chainId: int, address: string, collectionSlug: string) =
|
||||
proc fetchOwnedCollectibles*(self: Service, chainId: int, address: string, collectionSlug: string) =
|
||||
self.insertAddressIfNeeded(chainId, address)
|
||||
let collections = self.data[chainId][address].collections
|
||||
let collections = self.ownershipData[chainId][address].collections
|
||||
|
||||
if not collections.hasKey(collectionSlug):
|
||||
error "error fetchCollectibles: Attempting to fetch collectibles from unknown collection: ", collectionSlug
|
||||
error "error fetchOwnedCollectibles: Attempting to fetch collectibles from unknown collection: ", collectionSlug
|
||||
return
|
||||
|
||||
var data = CollectiblesUpdateArgs()
|
||||
data.chainId = chainId
|
||||
data.address = address
|
||||
data.collectionSlug = collectionSlug
|
||||
self.events.emit(SIGNAL_COLLECTIBLES_UPDATE_STARTED, data)
|
||||
|
||||
let arg = FetchCollectiblesTaskArg(
|
||||
tptr: cast[ByteAddress](fetchCollectiblesTaskArg),
|
||||
let arg = FetchOwnedCollectiblesTaskArg(
|
||||
tptr: cast[ByteAddress](fetchOwnedCollectiblesTaskArg),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "onRxCollectibles",
|
||||
slot: "onRxOwnedCollectibles",
|
||||
chainId: chainId,
|
||||
address: address,
|
||||
collectionSlug: collectionSlug,
|
||||
|
@ -244,10 +308,10 @@ QtObject:
|
|||
)
|
||||
self.threadpool.start(arg)
|
||||
|
||||
proc fetchAllCollectibles*(self: Service, chainId: int, address: string) =
|
||||
proc fetchAllOwnedCollectibles*(self: Service, chainId: int, address: string) =
|
||||
try:
|
||||
for collectionSlug, _ in self.data[chainId][address].collections:
|
||||
self.fetchCollectibles(chainId, address, collectionSlug)
|
||||
for collectionSlug, _ in self.ownershipData[chainId][address].collections:
|
||||
self.fetchOwnedCollectibles(chainId, address, collectionSlug)
|
||||
except Exception as e:
|
||||
let errDescription = e.msg
|
||||
error "error fetchAllCollectibles: ", errDescription
|
||||
error "error fetchAllOwnedCollectibles: ", errDescription
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
import stint
|
||||
import ../../common/conversion as service_conversion
|
||||
import ../../common/wallet_constants
|
||||
|
||||
proc sortAsc[T](t1, t2: T): int =
|
||||
if (t1.fromNetwork.chainId > t2.fromNetwork.chainId): return 1
|
||||
|
@ -16,21 +17,46 @@ type
|
|||
address: string
|
||||
toBlock: Uint256
|
||||
limit: int
|
||||
collectiblesLimit: int
|
||||
loadMore: bool
|
||||
allTxLoaded: bool
|
||||
|
||||
const loadTransactionsTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let
|
||||
arg = decode[LoadTransactionsTaskArg](argEncoded)
|
||||
limitAsHex = "0x" & eth_utils.stripLeadingZeros(arg.limit.toHex)
|
||||
response = transactions.getTransfersByAddress(arg.chainId, arg.address, arg.toBlock, limitAsHex, arg.loadMore).result
|
||||
output = %*{
|
||||
"address": arg.address,
|
||||
"chainId": arg.chainId,
|
||||
"history": response,
|
||||
"loadMore": arg.loadMore,
|
||||
"allTxLoaded": response.getElems().len < arg.limit
|
||||
}
|
||||
let arg = decode[LoadTransactionsTaskArg](argEncoded)
|
||||
let output = %* {
|
||||
"address": arg.address,
|
||||
"chainId": arg.chainId,
|
||||
"history": "",
|
||||
"collectibles": "",
|
||||
"loadMore": arg.loadMore,
|
||||
"allTxLoaded": ""
|
||||
}
|
||||
try:
|
||||
let limitAsHex = "0x" & eth_utils.stripLeadingZeros(arg.limit.toHex)
|
||||
let response = transactions.getTransfersByAddress(arg.chainId, arg.address, arg.toBlock, limitAsHex, arg.loadMore).result
|
||||
output["history"] = response
|
||||
output["allTxLoaded"] = %(response.getElems().len < arg.limit)
|
||||
|
||||
# Fetch collectibles for transactions
|
||||
var uniqueIds: seq[collectibles.NFTUniqueID] = @[]
|
||||
for txJson in response.getElems():
|
||||
let tx = txJson.toTransactionDto()
|
||||
if tx.typeValue == ERC721_TRANSACTION_TYPE:
|
||||
let nftId = collectibles.NFTUniqueID(
|
||||
contractAddress: tx.contract,
|
||||
tokenID: tx.tokenId.toString(10)
|
||||
)
|
||||
if not uniqueIds.any(x => (x == nftId)):
|
||||
uniqueIds.add(nftId)
|
||||
|
||||
if len(uniqueIds) > 0:
|
||||
let collectiblesResponse = collectibles.getOpenseaAssetsByNFTUniqueID(arg.chainId, uniqueIds, arg.collectiblesLimit).result
|
||||
output["collectibles"] = collectiblesResponse
|
||||
|
||||
except Exception as e:
|
||||
let errDesription = e.msg
|
||||
error "error loadTransactionsTask: ", errDesription
|
||||
|
||||
arg.finish(output)
|
||||
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ type
|
|||
nonce*: string
|
||||
txStatus*: string
|
||||
value*: string
|
||||
tokenId*: UInt256
|
||||
fromAddress*: string
|
||||
to*: string
|
||||
chainId*: int
|
||||
|
@ -77,6 +78,7 @@ proc getMaxTotalFees(maxFee: string, gasLimit: string): string =
|
|||
proc toTransactionDto*(jsonObj: JsonNode): TransactionDto =
|
||||
result = TransactionDto()
|
||||
result.timestamp = stint.fromHex(UInt256, jsonObj{"timestamp"}.getStr)
|
||||
result.tokenId = stint.fromHex(UInt256, jsonObj{"tokenId"}.getStr)
|
||||
discard jsonObj.getProp("id", result.id)
|
||||
discard jsonObj.getProp("type", result.typeValue)
|
||||
discard jsonObj.getProp("address", result.address)
|
||||
|
@ -101,10 +103,42 @@ proc toTransactionDto*(jsonObj: JsonNode): TransactionDto =
|
|||
result.totalFees = getTotalFees(result.maxPriorityFeePerGas, result.baseGasFees, result.gasUsed, result.maxFeePerGas)
|
||||
result.maxTotalFees = getMaxTotalFees(result.maxFeePerGas, result.gasLimit)
|
||||
|
||||
proc `$`*(self: TransactionDto): string =
|
||||
return fmt"""TransactionDto(
|
||||
id:{self.id},
|
||||
typeValue:{self.typeValue},
|
||||
address:{self.address},
|
||||
blockNumber:{self.blockNumber},
|
||||
blockHash:{self.blockHash},
|
||||
contract:{self.contract},
|
||||
timestamp:{self.timestamp},
|
||||
gasPrice:{self.gasPrice},
|
||||
gasLimit:{self.gasLimit},
|
||||
gasUsed:{self.gasUsed},
|
||||
nonce:{self.nonce},
|
||||
txStatus:{self.txStatus},
|
||||
value:{self.value},
|
||||
tokenId:{self.tokenId},
|
||||
fromAddress:{self.fromAddress},
|
||||
to:{self.to},
|
||||
chainId:{self.chainId},
|
||||
maxFeePerGas:{self.maxFeePerGas},
|
||||
maxPriorityFeePerGas:{self.maxPriorityFeePerGas},
|
||||
input:{self.input},
|
||||
txHash:{self.txHash},
|
||||
multiTransactionID:{self.multiTransactionID},
|
||||
baseGasFees:{self.baseGasFees},
|
||||
totalFees:{self.totalFees},
|
||||
maxTotalFees:{self.maxTotalFees},
|
||||
additionalData:{self.additionalData},
|
||||
symbol:{self.symbol}
|
||||
)"""
|
||||
|
||||
proc toPendingTransactionDto*(jsonObj: JsonNode): TransactionDto =
|
||||
result = TransactionDto()
|
||||
result.value = "0x" & toHex(toUInt256(parseFloat(jsonObj{"value"}.getStr)))
|
||||
result.timestamp = u256(jsonObj{"timestamp"}.getInt)
|
||||
result.tokenId = stint.fromHex(UInt256, jsonObj{"tokenId"}.getStr)
|
||||
discard jsonObj.getProp("hash", result.txHash)
|
||||
discard jsonObj.getProp("from", result.fromAddress)
|
||||
discard jsonObj.getProp("to", result.to)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import Tables, NimQml, chronicles, sequtils, sugar, stint, strutils, json, strformat, algorithm, math, random
|
||||
|
||||
import ../../../backend/collectibles as collectibles
|
||||
import ../../../backend/transactions as transactions
|
||||
import ../../../backend/backend
|
||||
import ../../../backend/eth
|
||||
|
@ -16,6 +17,7 @@ import ../wallet_account/service as wallet_account_service
|
|||
import ../network/service as network_service
|
||||
import ../token/service as token_service
|
||||
import ../settings/service as settings_service
|
||||
import ../collectible/dto
|
||||
import ../eth/dto/transaction as transaction_data_dto
|
||||
import ../eth/dto/[method_dto, coder, method_dto]
|
||||
import ./dto as transaction_dto
|
||||
|
@ -32,6 +34,9 @@ logScope:
|
|||
include async_tasks
|
||||
include ../../common/json_utils
|
||||
|
||||
# Maximum number of collectibles to be fetched at a time
|
||||
const collectiblesLimit = 200
|
||||
|
||||
# Signals which may be emitted by this service:
|
||||
const SIGNAL_TRANSACTIONS_LOADED* = "transactionsLoaded"
|
||||
const SIGNAL_TRANSACTION_SENT* = "transactionSent"
|
||||
|
@ -68,6 +73,7 @@ type
|
|||
type
|
||||
TransactionsLoadedArgs* = ref object of Args
|
||||
transactions*: seq[TransactionDto]
|
||||
collectibles*: seq[CollectibleDto]
|
||||
address*: string
|
||||
wasFetchMore*: bool
|
||||
allTxLoaded*: bool
|
||||
|
@ -200,16 +206,20 @@ QtObject:
|
|||
self.watchTransaction(tx.txHash, tx.fromAddress, tx.to, tx.typeValue, tx.input, tx.chainId, track = false)
|
||||
return pendingTransactions
|
||||
|
||||
proc setTrxHistoryResult*(self: Service, historyJSON: string) {.slot.} =
|
||||
proc onTransactionsLoaded*(self: Service, historyJSON: string) {.slot.} =
|
||||
let historyData = parseJson(historyJSON)
|
||||
let address = historyData["address"].getStr
|
||||
let chainID = historyData["chainId"].getInt
|
||||
let wasFetchMore = historyData["loadMore"].getBool
|
||||
let allTxLoaded = historyData["allTxLoaded"].getBool
|
||||
var transactions: seq[TransactionDto] = @[]
|
||||
var collectibles: seq[CollectibleDto] = @[]
|
||||
for tx in historyData["history"].getElems():
|
||||
transactions.add(tx.toTransactionDto())
|
||||
|
||||
for c in historyData["collectibles"].getElems():
|
||||
collectibles.add(c.toCollectibleDto())
|
||||
|
||||
if self.allTxLoaded.hasKey(address):
|
||||
self.allTxLoaded[address] = self.allTxLoaded[address] and allTxLoaded
|
||||
else:
|
||||
|
@ -218,6 +228,7 @@ QtObject:
|
|||
# emit event
|
||||
self.events.emit(SIGNAL_TRANSACTIONS_LOADED, TransactionsLoadedArgs(
|
||||
transactions: transactions,
|
||||
collectibles: collectibles,
|
||||
address: address,
|
||||
wasFetchMore: wasFetchMore
|
||||
))
|
||||
|
@ -244,9 +255,10 @@ QtObject:
|
|||
address: address,
|
||||
tptr: cast[ByteAddress](loadTransactionsTask),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "setTrxHistoryResult",
|
||||
slot: "onTransactionsLoaded",
|
||||
toBlock: toBlock,
|
||||
limit: limit,
|
||||
collectiblesLimit: collectiblesLimit,
|
||||
loadMore: loadMore,
|
||||
chainId: network.chainId,
|
||||
)
|
||||
|
|
|
@ -62,16 +62,6 @@ type
|
|||
rpc(clientVersion, "web3"):
|
||||
discard
|
||||
|
||||
rpc(getOpenseaCollectionsByOwner, "wallet"):
|
||||
chainId: int
|
||||
address: string
|
||||
|
||||
rpc(getOpenseaAssetsByOwnerAndCollection, "wallet"):
|
||||
chainId: int
|
||||
address: string
|
||||
collectionSlug: string
|
||||
limit: int
|
||||
|
||||
rpc(getEthereumChains, "wallet"):
|
||||
onlyEnabled: bool
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import json, json_serialization, strformat
|
||||
|
||||
import ./core, ./response_type
|
||||
from ./gen import rpc
|
||||
|
||||
type
|
||||
NFTUniqueID* = ref object of RootObj
|
||||
contractAddress* {.serializedFieldName("contract_address").}: string
|
||||
tokenID* {.serializedFieldName("token_id").}: string
|
||||
|
||||
proc `$`*(self: NFTUniqueID): string =
|
||||
return fmt"""NFTUniqueID(
|
||||
contractAddress:{self.contractAddress},
|
||||
tokenID:{self.tokenID}
|
||||
)"""
|
||||
|
||||
proc `==`*(a, b: NFTUniqueID): bool =
|
||||
result = a.contractAddress == b.contractAddress and
|
||||
a.tokenID == b.tokenID
|
||||
|
||||
rpc(getOpenseaCollectionsByOwner, "wallet"):
|
||||
chainId: int
|
||||
address: string
|
||||
|
||||
rpc(getOpenseaAssetsByOwnerAndCollection, "wallet"):
|
||||
chainId: int
|
||||
address: string
|
||||
collectionSlug: string
|
||||
limit: int
|
||||
|
||||
rpc(getOpenseaAssetsByNFTUniqueID, "wallet"):
|
||||
chainId: int
|
||||
uniqueIds: seq[NFTUniqueID]
|
||||
limit: int
|
|
@ -181,8 +181,8 @@ QtObject {
|
|||
return globalUtils.hex2Dec(value)
|
||||
}
|
||||
|
||||
function fetchCollectibles(slug) {
|
||||
walletSectionCollectibles.fetchCollectibles(slug)
|
||||
function fetchOwnedCollectibles(slug) {
|
||||
walletSectionCollectibles.fetchOwnedCollectibles(slug)
|
||||
}
|
||||
|
||||
function getCollectionMaxValue(traitType, value, maxValue, collectionIndex) {
|
||||
|
|
|
@ -29,6 +29,7 @@ Item {
|
|||
QtObject {
|
||||
id: d
|
||||
readonly property bool isIncoming: root.isTransactionValid ? root.transaction.to === currentAccount.address : false
|
||||
readonly property bool isNFT: root.isTransactionValid ? root.transaction.isNFT : false
|
||||
readonly property string savedAddressNameTo: root.isTransactionValid ? d.getNameForSavedWalletAddress(transaction.to) : ""
|
||||
readonly property string savedAddressNameFrom: root.isTransactionValid ? d.getNameForSavedWalletAddress(transaction.from): ""
|
||||
readonly property string from: root.isTransactionValid ? !!savedAddressNameFrom ? savedAddressNameFrom : Utils.compactAddress(transaction.from, 4): ""
|
||||
|
@ -72,9 +73,9 @@ Item {
|
|||
symbol: root.isTransactionValid ? transaction.symbol : ""
|
||||
transferStatus: root.isTransactionValid ? RootStore.hex2Dec(transaction.txStatus): ""
|
||||
shortTimeStamp: root.isTransactionValid ? LocaleUtils.formatTime(transaction.timestamp * 1000, Locale.ShortFormat): ""
|
||||
savedAddressName: root.isTransactionValid ? RootStore.getNameForSavedWalletAddress(transaction.to): ""
|
||||
title: d.isIncoming ? qsTr("Received %1 from %2").arg(RootStore.formatCurrencyAmount(cryptoValue, symbol)).arg(d.from) :
|
||||
qsTr("Sent %1 to %2").arg(RootStore.formatCurrencyAmount(cryptoValue, symbol)).arg(d.to)
|
||||
savedAddressNameTo: root.isTransactionValid ? RootStore.getNameForSavedWalletAddress(transaction.to): ""
|
||||
savedAddressNameFrom: root.isTransactionValid ? RootStore.getNameForSavedWalletAddress(transaction.from): ""
|
||||
isSummary: false
|
||||
sensor.enabled: false
|
||||
color: Theme.palette.statusListItem.backgroundColor
|
||||
state: "big"
|
||||
|
@ -153,9 +154,9 @@ Item {
|
|||
symbol: root.isTransactionValid ? transaction.symbol : ""
|
||||
transferStatus: root.isTransactionValid ? RootStore.hex2Dec(transaction.txStatus): ""
|
||||
shortTimeStamp: root.isTransactionValid ? LocaleUtils.formatTime(transaction.timestamp * 1000, Locale.ShortFormat): ""
|
||||
savedAddressName: root.isTransactionValid ? RootStore.getNameForSavedWalletAddress(transaction.to): ""
|
||||
title: d.isIncoming ? qsTr("Received %1 from %2").arg(RootStore.formatCurrencyAmount(cryptoValue, symbol)).arg(d.from) :
|
||||
qsTr("Sent %1 to %2").arg(RootStore.formatCurrencyAmount(cryptoValue, symbol)).arg(d.to)
|
||||
savedAddressNameTo: root.isTransactionValid ? RootStore.getNameForSavedWalletAddress(transaction.to): ""
|
||||
savedAddressNameFrom: root.isTransactionValid ? RootStore.getNameForSavedWalletAddress(transaction.from): ""
|
||||
isSummary: false
|
||||
sensor.enabled: false
|
||||
color: Theme.palette.statusListItem.backgroundColor
|
||||
border.width: 1
|
||||
|
@ -185,6 +186,12 @@ Item {
|
|||
primaryText: qsTr("Nonce")
|
||||
secondaryText: root.isTransactionValid ? RootStore.hex2Dec(root.transaction.nonce) : ""
|
||||
}
|
||||
InformationTile {
|
||||
maxWidth: parent.width
|
||||
primaryText: qsTr("TokenID")
|
||||
secondaryText: root.isTransactionValid ? root.transaction.tokenID : ""
|
||||
visible: root.isTransactionValid && d.isNFT
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,16 +27,54 @@ StatusListItem {
|
|||
property string networkColor
|
||||
property string networkName
|
||||
property string shortTimeStamp
|
||||
property string savedAddressName
|
||||
property string savedAddressNameTo
|
||||
property string savedAddressNameFrom
|
||||
property bool isSummary: false
|
||||
|
||||
readonly property bool isModelDataValid: modelData !== undefined && !!modelData
|
||||
readonly property bool isNFT: isModelDataValid && modelData.isNFT
|
||||
readonly property string name: isModelDataValid ?
|
||||
root.isNFT ?
|
||||
modelData.nftName ?
|
||||
modelData.nftName :
|
||||
"#" + modelData.tokenID :
|
||||
root.isSummary ? root.symbol : RootStore.formatCurrencyAmount(cryptoValue, symbol) :
|
||||
"N/A"
|
||||
|
||||
readonly property string image: isModelDataValid ?
|
||||
root.isNFT ?
|
||||
modelData.nftImageUrl ?
|
||||
modelData.nftImageUrl :
|
||||
"" :
|
||||
root.symbol ?
|
||||
Style.png("tokens/%1".arg(root.symbol)) :
|
||||
"" :
|
||||
""
|
||||
|
||||
readonly property string toAddress: !!savedAddressNameTo ?
|
||||
savedAddressNameTo :
|
||||
isModelDataValid ?
|
||||
Utils.compactAddress(modelData.to, 4) :
|
||||
""
|
||||
|
||||
readonly property string fromAddress: !!savedAddressNameFrom ?
|
||||
savedAddressNameFrom :
|
||||
isModelDataValid ?
|
||||
Utils.compactAddress(modelData.from, 4) :
|
||||
""
|
||||
state: "normal"
|
||||
asset.isImage: !loading
|
||||
asset.name: root.symbol ? Style.png("tokens/%1".arg(root.symbol)) : ""
|
||||
asset.name: root.image
|
||||
asset.isLetterIdenticon: loading
|
||||
title: modelData !== undefined && !!modelData ?
|
||||
isIncoming ? qsTr("Receive %1").arg(root.symbol) : !!savedAddressName ?
|
||||
qsTr("Send %1 to %2").arg(root.symbol).arg(savedAddressName) :
|
||||
qsTr("Send %1 to %2").arg(root.symbol).arg(Utils.compactAddress(modelData.to, 4)): ""
|
||||
title: root.isModelDataValid ?
|
||||
isIncoming ?
|
||||
isSummary ?
|
||||
qsTr("Receive %1").arg(root.name) :
|
||||
qsTr("Received %1 from %2").arg(root.name).arg(root.fromAddress):
|
||||
isSummary ?
|
||||
qsTr("Send %1 to %2").arg(root.name).arg(root.toAddress) :
|
||||
qsTr("Sent %1 to %2").arg(root.name).arg(root.toAddress) :
|
||||
""
|
||||
subTitle: shortTimeStamp
|
||||
inlineTagModel: 1
|
||||
inlineTagDelegate: InformationTag {
|
||||
|
@ -63,6 +101,7 @@ StatusListItem {
|
|||
}
|
||||
components: [
|
||||
ColumnLayout {
|
||||
visible: !root.isNFT
|
||||
Row {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
spacing: 4
|
||||
|
|
|
@ -110,7 +110,9 @@ ColumnLayout {
|
|||
symbol: modelDataValid && !!modelData.symbol ? modelData.symbol : ""
|
||||
transferStatus: modelDataValid ? RootStore.hex2Dec(modelData.txStatus) : ""
|
||||
shortTimeStamp: modelDataValid ? LocaleUtils.formatTime(modelData.timestamp * 1000, Locale.ShortFormat) : ""
|
||||
savedAddressName: modelDataValid ? RootStore.getNameForSavedWalletAddress(modelData.to) : ""
|
||||
savedAddressNameTo: modelDataValid ? RootStore.getNameForSavedWalletAddress(modelData.to) : ""
|
||||
savedAddressNameFrom: modelDataValid ? RootStore.getNameForSavedWalletAddress(modelData.from) : ""
|
||||
isSummary: true
|
||||
onClicked: launchTransactionDetail(modelData)
|
||||
loading: modelDataValid ? modelData.loadingTransaction : false
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 1b24342a75d99b8e2601d7639295899ea75b6fb3
|
||||
Subproject commit 3f3e8f8894dfd5c8a6124bce805d0bd708fb6433
|
Loading…
Reference in New Issue