fix(@desktop/wallet): properly handle tokenID 0 when filtering activity by collectibles
Fixes #13660
This commit is contained in:
parent
a27e447f11
commit
d22ac0dfed
|
@ -9,6 +9,7 @@ import collectibles_model
|
|||
import collectibles_item
|
||||
import events_handler
|
||||
import status
|
||||
import utils
|
||||
|
||||
import web3/conversions
|
||||
|
||||
|
@ -36,9 +37,6 @@ const FETCH_BATCH_COUNT_DEFAULT = 10
|
|||
const FETCH_RECIPIENTS_BATCH_COUNT_DEFAULT = 2000
|
||||
const FETCH_COLLECTIBLES_BATCH_COUNT_DEFAULT = 2000
|
||||
|
||||
type
|
||||
CollectiblesToTokenConverter* = proc (id: string): backend_activity.Token
|
||||
|
||||
QtObject:
|
||||
type
|
||||
Controller* = ref object of QObject
|
||||
|
@ -65,8 +63,6 @@ QtObject:
|
|||
|
||||
requestId: int32
|
||||
|
||||
collectiblesToTokenConverter: CollectiblesToTokenConverter
|
||||
|
||||
proc setup(self: Controller) =
|
||||
self.QObject.setup
|
||||
|
||||
|
@ -311,8 +307,7 @@ QtObject:
|
|||
currencyService: currency_service.Service,
|
||||
tokenService: token_service.Service,
|
||||
savedAddressService: saved_address_service.Service,
|
||||
events: EventEmitter,
|
||||
collectiblesConverter: CollectiblesToTokenConverter): Controller =
|
||||
events: EventEmitter): Controller =
|
||||
new(result, delete)
|
||||
|
||||
result.requestId = requestId
|
||||
|
@ -334,8 +329,6 @@ QtObject:
|
|||
result.allAddressesSelected = false
|
||||
result.chainIds = @[]
|
||||
|
||||
result.collectiblesToTokenConverter = collectiblesConverter
|
||||
|
||||
result.setup()
|
||||
|
||||
result.setupEventHandlers(events)
|
||||
|
@ -373,8 +366,12 @@ QtObject:
|
|||
var collectibles = newSeq[backend_activity.Token]()
|
||||
for i in 0 ..< collectiblesJson.len:
|
||||
let uid = collectiblesJson[i].getStr()
|
||||
let token = self.collectiblesToTokenConverter(uid)
|
||||
collectibles.add(token)
|
||||
# TODO: We need the token type here, which is not part of the uid.
|
||||
# We currently don't support filtering ERC1155 tokens anyway, so it's not an issue.
|
||||
# When we have a split model for all collectibles metadata, get the entry from there
|
||||
# to get the token type. Perhaps also add an "UnknownCollectible" TokenType that includes
|
||||
# both ERC721 and ERC1155?
|
||||
collectibles.add(collectibleUidToActivityToken(uid, TokenType.ERC721))
|
||||
|
||||
self.currentActivityFilter.collectibles = collectibles
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
import stint, chronicles
|
||||
|
||||
import backend/collectibles_types as backend_collectibles
|
||||
import backend/activity as backend_activity
|
||||
import app_service/common/types
|
||||
import web3/ethtypes as eth
|
||||
|
||||
proc collectibleUidToActivityToken*(uid: string, tokenType: TokenType): backend_activity.Token =
|
||||
try:
|
||||
let id = uid.toCollectibleUniqueID()
|
||||
result.tokenType = tokenType
|
||||
result.chainId = backend_activity.ChainId(id.contractID.chainID)
|
||||
let contractAddress = id.contractID.address
|
||||
if len(contractAddress) > 0:
|
||||
var address: eth.Address
|
||||
address = eth.fromHex(eth.Address, contractAddress)
|
||||
result.address = some(address)
|
||||
result.tokenId = some(backend_activity.TokenId("0x" & stint.toHex(id.tokenId)))
|
||||
except:
|
||||
error "Invalid collectible uid: ", uid
|
|
@ -129,7 +129,7 @@ proc newModule*(
|
|||
result.assetsModule = assets_module.newModule(result, events, walletAccountService, networkService, tokenService,
|
||||
currencyService)
|
||||
result.sendModule = send_module.newModule(result, events, walletAccountService, networkService, currencyService,
|
||||
transactionService, keycardService)
|
||||
transactionService, keycardService)
|
||||
result.savedAddressesModule = saved_addresses_module.newModule(result, events, savedAddressService)
|
||||
result.buySellCryptoModule = buy_sell_crypto_module.newModule(result, events, transactionService)
|
||||
result.overviewModule = overview_module.newModule(result, events, walletAccountService, currencyService)
|
||||
|
@ -137,12 +137,10 @@ proc newModule*(
|
|||
result.networksService = networkService
|
||||
|
||||
result.transactionService = transactionService
|
||||
let collectiblesToTokenConverter = proc(id: string): backend_activity.Token =
|
||||
return allCollectiblesModule.getAllCollectiblesModel().getActivityToken(id)
|
||||
result.activityController = activityc.newController(int32(ActivityID.History), currencyService, tokenService,
|
||||
savedAddressService, events, collectiblesToTokenConverter)
|
||||
savedAddressService, events)
|
||||
result.tmpActivityController = activityc.newController(int32(ActivityID.Temporary), currencyService, tokenService,
|
||||
savedAddressService, events, collectiblesToTokenConverter)
|
||||
savedAddressService, events)
|
||||
result.collectibleDetailsController = collectible_detailsc.newController(int32(backend_collectibles.CollectiblesRequestID.WalletAccount), networkService, events)
|
||||
result.filter = initFilter(result.controller)
|
||||
|
||||
|
|
|
@ -59,9 +59,6 @@ QtObject:
|
|||
generatedCollectionId:{self.generatedCollectionId}
|
||||
)"""
|
||||
|
||||
proc getCollectibleUniqueID*(self: CollectiblesEntry): backend.CollectibleUniqueID =
|
||||
return self.id
|
||||
|
||||
proc hasCollectibleData(self: CollectiblesEntry): bool =
|
||||
return self.data != nil and isSome(self.data.collectibleData)
|
||||
|
||||
|
@ -108,18 +105,18 @@ QtObject:
|
|||
read = getTokenIDAsString
|
||||
|
||||
# Unique ID to identify collectible, generated by us
|
||||
proc getID*(self: CollectiblesEntry): string =
|
||||
proc getID*(self: CollectiblesEntry): backend.CollectibleUniqueID =
|
||||
return self.id
|
||||
|
||||
proc getIDAsString*(self: CollectiblesEntry): string =
|
||||
return self.generatedId
|
||||
|
||||
proc generateId*(self: CollectiblesEntry): string =
|
||||
return fmt"{self.getChainId}+{self.getContractAddress}+{self.getTokenID}"
|
||||
|
||||
# Unique ID to identify collection, generated by us
|
||||
proc getCollectionID*(self: CollectiblesEntry): string =
|
||||
return self.generatedCollectionId
|
||||
proc getCollectionID*(self: CollectiblesEntry): backend.ContractID =
|
||||
return self.id.contractID
|
||||
|
||||
proc generateCollectionId*(self: CollectiblesEntry): string =
|
||||
return fmt"{self.getChainId}+{self.getContractAddress}"
|
||||
proc getCollectionIDAsString*(self: CollectiblesEntry): string =
|
||||
return self.generatedCollectionId
|
||||
|
||||
proc nameChanged*(self: CollectiblesEntry) {.signal.}
|
||||
proc getName*(self: CollectiblesEntry): string {.slot.} =
|
||||
|
@ -341,8 +338,8 @@ QtObject:
|
|||
result.id = data.id
|
||||
result.setData(data)
|
||||
result.extradata = extradata
|
||||
result.generatedId = result.generateId()
|
||||
result.generatedCollectionId = result.generateCollectionId()
|
||||
result.generatedId = result.id.toString()
|
||||
result.generatedCollectionId = result.id.contractID.toString()
|
||||
result.setup()
|
||||
|
||||
proc newCollectibleDetailsBasicEntry*(id: backend.CollectibleUniqueID, extradata: ExtraData): CollectiblesEntry =
|
||||
|
@ -351,8 +348,8 @@ QtObject:
|
|||
result.extradata = extradata
|
||||
result.traits = newTraitModel()
|
||||
result.ownership = newOwnershipModel()
|
||||
result.generatedId = result.generateId()
|
||||
result.generatedCollectionId = result.generateCollectionId()
|
||||
result.generatedId = result.id.toString()
|
||||
result.generatedCollectionId = result.id.contractID.toString()
|
||||
result.setup()
|
||||
|
||||
proc newCollectibleDetailsEmptyEntry*(): CollectiblesEntry =
|
||||
|
|
|
@ -2,9 +2,7 @@ import NimQml, Tables, strutils, strformat, sequtils, stint, json
|
|||
import logging
|
||||
|
||||
import ./collectibles_entry
|
||||
import web3/ethtypes as eth
|
||||
import backend/collectibles as backend_collectibles
|
||||
import backend/activity as backend_activity
|
||||
import app_service/common/utils as common_utils
|
||||
import app_service/common/types
|
||||
|
||||
|
@ -164,7 +162,7 @@ QtObject:
|
|||
let item = self.items[index.row]
|
||||
case enumRole:
|
||||
of CollectibleRole.Uid:
|
||||
result = newQVariant(item.getID())
|
||||
result = newQVariant(item.getIDAsString())
|
||||
of CollectibleRole.ChainId:
|
||||
result = newQVariant(item.getChainID())
|
||||
of CollectibleRole.ContractAddress:
|
||||
|
@ -182,7 +180,7 @@ QtObject:
|
|||
of CollectibleRole.BackgroundColor:
|
||||
result = newQVariant(item.getBackgroundColor())
|
||||
of CollectibleRole.CollectionUid:
|
||||
result = newQVariant(item.getCollectionID())
|
||||
result = newQVariant(item.getCollectionIDAsString())
|
||||
of CollectibleRole.CollectionName:
|
||||
result = newQVariant(item.getCollectionName())
|
||||
of CollectibleRole.CollectionSlug:
|
||||
|
@ -205,7 +203,7 @@ QtObject:
|
|||
return
|
||||
let item = self.items[index]
|
||||
case column:
|
||||
of "uid": result = item.getID()
|
||||
of "uid": result = item.getIDAsString()
|
||||
of "chainId": result = $item.getChainID()
|
||||
of "contractAddress": result = item.getContractAddress()
|
||||
of "tokenId": result = item.getTokenIDAsString()
|
||||
|
@ -214,7 +212,7 @@ QtObject:
|
|||
of "mediaType": result = item.getMediaType()
|
||||
of "imageUrl": result = item.getImageURL()
|
||||
of "backgroundColor": result = item.getBackgroundColor()
|
||||
of "collectionUid": result = item.getCollectionID()
|
||||
of "collectionUid": result = item.getCollectionIDAsString()
|
||||
of "collectionName": result = item.getCollectionName()
|
||||
of "collectionSlug": result = item.getCollectionSlug()
|
||||
of "isLoading": result = $false
|
||||
|
@ -271,12 +269,12 @@ QtObject:
|
|||
|
||||
var newTable = initTable[string, int](len(newItems))
|
||||
for i in 0 ..< len(newItems):
|
||||
newTable.add(newItems[i].getID(), i)
|
||||
newTable.add(newItems[i].getIDAsString(), i)
|
||||
|
||||
# Needs to be built in sequential index order
|
||||
var oldIndicesToRemove: seq[int] = @[]
|
||||
for idx in 0 ..< len(self.items):
|
||||
let uid = self.items[idx].getID()
|
||||
let uid = self.items[idx].getIDAsString()
|
||||
if not newTable.hasKey(uid):
|
||||
# Item in old list but not in new -> Must remove
|
||||
oldIndicesToRemove.add(idx)
|
||||
|
@ -303,7 +301,7 @@ QtObject:
|
|||
|
||||
proc getItemById*(self: Model, id: string): CollectiblesEntry =
|
||||
for item in self.items:
|
||||
if(cmpIgnoreCase(item.getID(), id) == 0):
|
||||
if(cmpIgnoreCase(item.getIDAsString(), id) == 0):
|
||||
return item
|
||||
return nil
|
||||
|
||||
|
@ -343,45 +341,20 @@ QtObject:
|
|||
|
||||
proc getImageUrl*(self: Model, id: string): string {.slot.} =
|
||||
for item in self.items:
|
||||
if(cmpIgnoreCase(item.getId(), id) == 0):
|
||||
if(cmpIgnoreCase(item.getIDAsString(), id) == 0):
|
||||
return item.getImageUrl()
|
||||
return ""
|
||||
|
||||
proc getName*(self: Model, id: string): string {.slot.} =
|
||||
for item in self.items:
|
||||
if(cmpIgnoreCase(item.getId(), id) == 0):
|
||||
if(cmpIgnoreCase(item.getIDAsString(), id) == 0):
|
||||
return item.getName()
|
||||
return ""
|
||||
|
||||
proc getActivityToken*(self: Model, id: string): backend_activity.Token =
|
||||
for item in self.items:
|
||||
if(cmpIgnoreCase(item.getID(), id) == 0):
|
||||
result.tokenType = TokenType.ERC721
|
||||
result.chainId = backend_activity.ChainId(item.getChainID())
|
||||
var contract = item.getContractAddress()
|
||||
if len(contract) > 0:
|
||||
var address: eth.Address
|
||||
address = eth.fromHex(eth.Address, contract)
|
||||
result.address = some(address)
|
||||
var tokenId = item.getTokenID()
|
||||
if tokenId > 0:
|
||||
result.tokenId = some(backend_activity.TokenId("0x" & stint.toHex(tokenId)))
|
||||
return result
|
||||
|
||||
# Fallback, use data from id
|
||||
var parts = id.split("+")
|
||||
if len(parts) == 3:
|
||||
result.chainId = backend_activity.ChainId(parseInt(parts[0]))
|
||||
result.address = some(eth.fromHex(eth.Address, parts[1]))
|
||||
var tokenIdInt = u256(parseInt(parts[2]))
|
||||
result.tokenId = some(backend_activity.TokenId("0x" & stint.toHex(tokenIdInt)))
|
||||
|
||||
return result
|
||||
|
||||
proc getUidForData*(self: Model, tokenId: string, tokenAddress: string, chainId: int): string {.slot.} =
|
||||
for item in self.items:
|
||||
if(cmpIgnoreCase(item.getTokenIDAsString(), tokenId) == 0 and cmpIgnoreCase(item.getContractAddress(), tokenAddress) == 0):
|
||||
return item.getID()
|
||||
if(cmpIgnoreCase(item.getTokenIDAsString(), tokenId) == 0 and cmpIgnoreCase(item.getContractAddress(), tokenAddress) == 0) and item.getChainID() == chainId:
|
||||
return item.getIDAsString()
|
||||
# Fallback, create uid from data, because it still might not be fetched
|
||||
if chainId > 0 and len(tokenAddress) > 0 and len(tokenId) > 0:
|
||||
return $chainId & "+" & tokenAddress & "+" & tokenId
|
||||
|
|
|
@ -125,7 +125,7 @@ QtObject:
|
|||
var collectiblesPerCollection = initTable[string, seq[flat_item.CollectiblesEntry]]()
|
||||
|
||||
for item in items:
|
||||
let collectionId = item.getCollectionID()
|
||||
let collectionId = item.getCollectionIDAsString()
|
||||
if not collectiblesPerCollection.hasKey(collectionId):
|
||||
collectiblesPerCollection[collectionId] = @[]
|
||||
collectiblesPerCollection[collectionId].add(item)
|
||||
|
|
|
@ -3,22 +3,22 @@ import ./collectibles_nested_item as nested_item
|
|||
|
||||
proc collectibleToCollectibleNestedItem*(flatItem: flat_item.CollectiblesEntry): nested_item.Item =
|
||||
return nested_item.initItem(
|
||||
flatItem.getID(),
|
||||
flatItem.getIDAsString(),
|
||||
flatItem.getChainID(),
|
||||
flatItem.getName(),
|
||||
flatItem.getImageURL(),
|
||||
flatItem.getCollectionID(),
|
||||
flatItem.getCollectionIDAsString(),
|
||||
flatItem.getCollectionName(),
|
||||
false
|
||||
)
|
||||
|
||||
proc collectibleToCollectionNestedItem*(flatItem: flat_item.CollectiblesEntry): nested_item.Item =
|
||||
return nested_item.initItem(
|
||||
flatItem.getCollectionID(),
|
||||
flatItem.getCollectionIDAsString(),
|
||||
flatItem.getChainID(),
|
||||
flatItem.getCollectionName(),
|
||||
flatItem.getCollectionImageURL(),
|
||||
flatItem.getCollectionID(),
|
||||
flatItem.getCollectionIDAsString(),
|
||||
flatItem.getCollectionName(),
|
||||
true
|
||||
)
|
||||
|
|
|
@ -9,7 +9,6 @@ import events_handler
|
|||
import app/core/eventemitter
|
||||
|
||||
import backend/collectibles as backend_collectibles
|
||||
import backend/activity as backend_activity
|
||||
import app_service/service/network/service as network_service
|
||||
|
||||
const FETCH_BATCH_COUNT_DEFAULT = 50
|
||||
|
@ -302,9 +301,6 @@ QtObject:
|
|||
|
||||
self.resetModel()
|
||||
|
||||
proc getActivityToken*(self: Controller, id: string): backend_activity.Token =
|
||||
return self.model.getActivityToken(id)
|
||||
|
||||
proc getItemForData*(self: Controller, tokenId: string, tokenAddress: string, chainId: int): CollectiblesEntry =
|
||||
let uid = self.model.getUidForData(tokenId, tokenAddress, chainId)
|
||||
return self.model.getItemById(uid)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import json, strformat, json_serialization
|
||||
import stint, Tables, options
|
||||
import stint, Tables, options, strutils
|
||||
import community_tokens_types
|
||||
|
||||
include app_service/common/json_utils
|
||||
|
@ -126,6 +126,13 @@ proc fromJson*(t: JsonNode, T: typedesc[ref ContractID]): ref ContractID {.inlin
|
|||
result = new(ContractID)
|
||||
result[] = fromJson(t, ContractID)
|
||||
|
||||
proc toString*(t: ContractID): string =
|
||||
return fmt"{t.chainID}+{t.address}"
|
||||
|
||||
proc toContractID*(t: string): ContractID =
|
||||
var parts = t.split("+")
|
||||
return ContractID(chainID: parts[0].parseInt(), address: parts[1])
|
||||
|
||||
# CollectibleUniqueID
|
||||
proc `$`*(self: CollectibleUniqueID): string =
|
||||
return fmt"""CollectibleUniqueID(
|
||||
|
@ -154,6 +161,19 @@ proc fromJson*(t: JsonNode, T: typedesc[ref CollectibleUniqueID]): ref Collectib
|
|||
result = new(CollectibleUniqueID)
|
||||
result[] = fromJson(t, CollectibleUniqueID)
|
||||
|
||||
proc toString*(t: CollectibleUniqueID): string =
|
||||
return fmt"{t.contractID.chainID}+{t.contractID.address}+{t.tokenID.toString()}"
|
||||
|
||||
proc toCollectibleUniqueID*(t: string): CollectibleUniqueID =
|
||||
var parts = t.split("+")
|
||||
return CollectibleUniqueID(
|
||||
contractID: ContractID(
|
||||
chainID: parts[0].parseInt(),
|
||||
address: parts[1]
|
||||
),
|
||||
tokenID: stint.parse(parts[2], UInt256)
|
||||
)
|
||||
|
||||
# CollectibleTrait
|
||||
proc `$`*(self: CollectibleTrait): string =
|
||||
return fmt"""CollectibleTrait(
|
||||
|
|
|
@ -41,3 +41,25 @@ suite "collectibles types":
|
|||
check(oldCommOwners[0].name == newCommOwners[0].name)
|
||||
check(oldCommOwners[0].imageSource == newCommOwners[0].imageSource)
|
||||
check(oldCommOwners[0].collectibleOwner.address == newCommOwners[0].collectibleOwner.address)
|
||||
|
||||
test "ContractID string conversion":
|
||||
|
||||
let oldContractID = ContractID(chainID: 321, address: "0x123")
|
||||
let contractIDString = oldContractID.toString()
|
||||
|
||||
let newContractID = contractIDString.toContractID()
|
||||
|
||||
check(oldContractID == newContractID)
|
||||
|
||||
test "CollectibleUniqueID string conversion":
|
||||
|
||||
let oldUniqueID = CollectibleUniqueID(
|
||||
contractID: ContractID(chainID: 321, address: "0x123"),
|
||||
tokenId: stint.u256(23)
|
||||
)
|
||||
let uniqueIDString = oldUniqueID.toString()
|
||||
|
||||
let newUniqueID = uniqueIDString.toCollectibleUniqueID()
|
||||
|
||||
check(oldUniqueID == newUniqueID)
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 972a4f9df9fdd0464d02e014fc65a9de70753b3c
|
||||
Subproject commit 54ea0981a5e1496c1358ea9dcc8c99ffc2098c73
|
Loading…
Reference in New Issue