feat(@wallet/desktop): implement generalized collectibles api
This commit is contained in:
parent
4239f77941
commit
c04bf2ef9e
|
@ -19,7 +19,7 @@ QtObject:
|
|||
type
|
||||
CollectibleDetailsEntry* = ref object of QObject
|
||||
id: backend.CollectibleUniqueID
|
||||
data: backend.CollectibleDetails
|
||||
data: backend.Collectible
|
||||
extradata: ExtraData
|
||||
traits: TraitModel
|
||||
|
||||
|
@ -29,13 +29,15 @@ QtObject:
|
|||
proc delete*(self: CollectibleDetailsEntry) =
|
||||
self.QObject.delete
|
||||
|
||||
proc newCollectibleDetailsFullEntry*(data: backend.CollectibleDetails, extradata: ExtraData): CollectibleDetailsEntry =
|
||||
proc newCollectibleDetailsFullEntry*(data: backend.Collectible, extradata: ExtraData): CollectibleDetailsEntry =
|
||||
new(result, delete)
|
||||
result.id = data.id
|
||||
result.data = data
|
||||
result.extradata = extradata
|
||||
result.traits = newTraitModel()
|
||||
result.traits.setItems(data.traits)
|
||||
if isSome(data.collectibleData) and isSome(data.collectibleData.get().traits):
|
||||
let traits = data.collectibleData.get().traits.get()
|
||||
result.traits.setItems(traits)
|
||||
result.setup()
|
||||
|
||||
proc newCollectibleDetailsBasicEntry*(id: backend.CollectibleUniqueID, extradata: ExtraData): CollectibleDetailsEntry =
|
||||
|
@ -64,6 +66,24 @@ QtObject:
|
|||
traits:{self.traits}
|
||||
)"""
|
||||
|
||||
proc hasCollectibleData(self: CollectibleDetailsEntry): bool =
|
||||
return self.data != nil and isSome(self.data.collectibleData)
|
||||
|
||||
proc getCollectibleData(self: CollectibleDetailsEntry): backend.CollectibleData =
|
||||
return self.data.collectibleData.get()
|
||||
|
||||
proc hasCollectionData(self: CollectibleDetailsEntry): bool =
|
||||
return self.data != nil and isSome(self.data.collectionData)
|
||||
|
||||
proc getCollectionData(self: CollectibleDetailsEntry): backend.CollectionData =
|
||||
return self.data.collectionData.get()
|
||||
|
||||
proc hasCommunityData(self: CollectibleDetailsEntry): bool =
|
||||
return self.data != nil and isSome(self.data.communityData)
|
||||
|
||||
proc getCommunityData(self: CollectibleDetailsEntry): backend.CommunityData =
|
||||
return self.data.communityData.get()
|
||||
|
||||
proc getChainID*(self: CollectibleDetailsEntry): int {.slot.} =
|
||||
return self.id.contractID.chainID
|
||||
|
||||
|
@ -83,66 +103,68 @@ QtObject:
|
|||
read = getTokenID
|
||||
|
||||
proc getName*(self: CollectibleDetailsEntry): string {.slot.} =
|
||||
if self.data == nil:
|
||||
if not self.hasCollectibleData():
|
||||
return ""
|
||||
return self.data.name
|
||||
return self.data.collectibleData.get().name
|
||||
|
||||
QtProperty[string] name:
|
||||
read = getName
|
||||
|
||||
proc getImageURL*(self: CollectibleDetailsEntry): string {.slot.} =
|
||||
if self.data == nil:
|
||||
if not self.hasCollectibleData() or isNone(self.getCollectibleData().imageUrl):
|
||||
return ""
|
||||
return self.data.imageUrl
|
||||
return self.getCollectibleData().imageUrl.get()
|
||||
|
||||
QtProperty[string] imageUrl:
|
||||
read = getImageURL
|
||||
|
||||
proc getMediaURL*(self: CollectibleDetailsEntry): string {.slot.} =
|
||||
if self.data == nil:
|
||||
if not self.hasCollectibleData() or isNone(self.getCollectibleData().animationUrl):
|
||||
return ""
|
||||
return self.data.animationUrl
|
||||
return self.getCollectibleData().animationUrl.get()
|
||||
|
||||
QtProperty[string] mediaUrl:
|
||||
read = getMediaURL
|
||||
|
||||
proc getMediaType*(self: CollectibleDetailsEntry): string {.slot.} =
|
||||
if self.data == nil:
|
||||
if not self.hasCollectibleData() or isNone(self.getCollectibleData().animationMediaType):
|
||||
return ""
|
||||
return self.data.animationMediaType
|
||||
return self.getCollectibleData().animationMediaType.get()
|
||||
|
||||
QtProperty[string] mediaType:
|
||||
read = getMediaType
|
||||
|
||||
proc getBackgroundColor*(self: CollectibleDetailsEntry): string {.slot.} =
|
||||
var color = "transparent"
|
||||
if self.data != nil and self.data.backgroundColor != "":
|
||||
color = "#" & self.data.backgroundColor
|
||||
if self.hasCollectibleData() and isSome(self.getCollectibleData().backgroundColor):
|
||||
let backgroundColor = self.getCollectibleData().backgroundColor.get()
|
||||
if backgroundColor != "":
|
||||
color = "#" & backgroundColor
|
||||
return color
|
||||
|
||||
QtProperty[string] backgroundColor:
|
||||
read = getBackgroundColor
|
||||
|
||||
proc getCollectionName*(self: CollectibleDetailsEntry): string {.slot.} =
|
||||
if self.data == nil:
|
||||
return ""
|
||||
return self.data.collectionName
|
||||
|
||||
QtProperty[string] collectionName:
|
||||
read = getCollectionName
|
||||
|
||||
proc getDescription*(self: CollectibleDetailsEntry): string {.slot.} =
|
||||
if self.data == nil:
|
||||
if not self.hasCollectibleData() or isNone(self.getCollectibleData().description):
|
||||
return ""
|
||||
return self.data.description
|
||||
return self.getCollectibleData().description.get()
|
||||
|
||||
QtProperty[string] description:
|
||||
read = getDescription
|
||||
|
||||
proc getCollectionImageURL*(self: CollectibleDetailsEntry): string {.slot.} =
|
||||
if self.data == nil:
|
||||
proc getCollectionName*(self: CollectibleDetailsEntry): string {.slot.} =
|
||||
if not self.hasCollectionData():
|
||||
return ""
|
||||
return self.data.collectionImageUrl
|
||||
return self.getCollectionData().name
|
||||
|
||||
QtProperty[string] collectionName:
|
||||
read = getCollectionName
|
||||
|
||||
proc getCollectionImageURL*(self: CollectibleDetailsEntry): string {.slot.} =
|
||||
if not self.hasCollectionData():
|
||||
return ""
|
||||
return self.getCollectionData().imageUrl
|
||||
|
||||
QtProperty[string] collectionImageUrl:
|
||||
read = getCollectionImageURL
|
||||
|
@ -160,45 +182,45 @@ QtObject:
|
|||
read = getNetworkShortName
|
||||
|
||||
proc getCommunityId*(self: CollectibleDetailsEntry): string {.slot.} =
|
||||
if self.data == nil or isNone(self.data.communityInfo):
|
||||
if not self.hasCommunityData():
|
||||
return ""
|
||||
return self.data.communityInfo.get().communityId
|
||||
return self.getCommunityData().id
|
||||
|
||||
QtProperty[string] communityId:
|
||||
read = getCommunityId
|
||||
|
||||
proc getCommunityName*(self: CollectibleDetailsEntry): string {.slot.} =
|
||||
if self.data == nil or isNone(self.data.communityInfo):
|
||||
if not self.hasCommunityData():
|
||||
return ""
|
||||
return self.data.communityInfo.get().communityName
|
||||
return self.getCommunityData().name
|
||||
|
||||
QtProperty[string] communityName:
|
||||
read = getCommunityName
|
||||
|
||||
proc getCommunityColor*(self: CollectibleDetailsEntry): string {.slot.} =
|
||||
if self.data == nil or isNone(self.data.communityInfo):
|
||||
if not self.hasCommunityData():
|
||||
return ""
|
||||
return self.data.communityInfo.get().communityColor
|
||||
return self.getCommunityData().color
|
||||
|
||||
QtProperty[string] communityColor:
|
||||
read = getCommunityColor
|
||||
|
||||
proc getCommunityImage*(self: CollectibleDetailsEntry): string {.slot.} =
|
||||
if self.data == nil or isNone(self.data.communityInfo):
|
||||
return ""
|
||||
return self.data.communityInfo.get().communityImage
|
||||
|
||||
QtProperty[string] communityImage:
|
||||
read = getCommunityImage
|
||||
|
||||
proc getCommunityPrivilegesLevel*(self: CollectibleDetailsEntry): int {.slot.} =
|
||||
if self.data == nil or isNone(self.data.communityInfo):
|
||||
if not self.hasCommunityData():
|
||||
return PrivilegesLevel.Community.int
|
||||
return int(self.data.communityInfo.get().privilegesLevel)
|
||||
return int(self.getCommunityData().privilegesLevel)
|
||||
|
||||
QtProperty[int] communityPrivilegesLevel:
|
||||
read = getCommunityPrivilegesLevel
|
||||
|
||||
proc getCommunityImage*(self: CollectibleDetailsEntry): string {.slot.} =
|
||||
if not self.hasCommunityData() or isNone(self.getCommunityData().imageUrl):
|
||||
return ""
|
||||
return self.getCommunityData().imageUrl.get()
|
||||
|
||||
QtProperty[string] communityImage:
|
||||
read = getCommunityImage
|
||||
|
||||
proc getNetworkColor*(self: CollectibleDetailsEntry): string {.slot.} =
|
||||
return self.extradata.networkColor
|
||||
|
||||
|
|
|
@ -3,36 +3,62 @@ import backend/collectibles as backend
|
|||
import collectibles_item
|
||||
import ../../../app_service/service/community_tokens/dto/community_token
|
||||
|
||||
proc collectibleToItem*(c: backend.CollectibleHeader, isPinned: bool = false) : Item =
|
||||
var mediaUrl = c.animationUrl
|
||||
var mediaType = c.animationMediaType
|
||||
if mediaUrl == "":
|
||||
mediaUrl = c.imageUrl
|
||||
mediaType = "image"
|
||||
proc collectibleToItem*(c: backend.Collectible, isPinned: bool = false) : Item =
|
||||
var collectibleName = ""
|
||||
var collectibleDescription = ""
|
||||
var collectibleMediaUrl = ""
|
||||
var collectibleMediaType = ""
|
||||
var collectibleImageUrl = ""
|
||||
var collectibleBackgroundColor = ""
|
||||
if isSome(c.collectibleData):
|
||||
let collectibleData = c.collectibleData.get()
|
||||
collectibleName = collectibleData.name
|
||||
if isSome(collectibleData.description):
|
||||
collectibleDescription = collectibleData.description.get()
|
||||
if isSome(collectibleData.animationUrl):
|
||||
collectibleMediaUrl = collectibleData.animationUrl.get()
|
||||
if isSome(collectibleData.animationMediaType):
|
||||
collectibleMediaType = collectibleData.animationMediaType.get()
|
||||
if isSome(collectibleData.imageUrl):
|
||||
collectibleImageUrl = collectibleData.imageUrl.get()
|
||||
if isSome(collectibleData.backgroundColor):
|
||||
collectibleBackgroundColor = collectibleData.backgroundColor.get()
|
||||
if collectibleMediaUrl == "":
|
||||
collectibleMediaUrl = collectibleImageUrl
|
||||
collectibleMediaType = "image"
|
||||
|
||||
var collectionName = ""
|
||||
var collectionSlug = ""
|
||||
var collectionImageUrl = ""
|
||||
if isSome(c.collectionData):
|
||||
let collectionData = c.collectionData.get()
|
||||
collectionName = collectionData.name
|
||||
collectionSlug = collectionData.slug
|
||||
collectionImageUrl = collectionData.imageUrl
|
||||
|
||||
var communityId = ""
|
||||
var communityName = ""
|
||||
var communityColor = ""
|
||||
var communityPrivilegesLevel = PrivilegesLevel.Community.int
|
||||
if isSome(c.communityHeader):
|
||||
let communityHeader = c.communityHeader.get()
|
||||
communityId = communityHeader.communityId
|
||||
communityName = communityHeader.communityName
|
||||
communityColor = communityHeader.communityColor
|
||||
communityPrivilegesLevel = int(communityHeader.privilegesLevel)
|
||||
if isSome(c.communityData):
|
||||
let communityData = c.communityData.get()
|
||||
communityId = communityData.id
|
||||
communityName = communityData.name
|
||||
communityColor = communityData.color
|
||||
communityPrivilegesLevel = int(communityData.privilegesLevel)
|
||||
|
||||
return initItem(
|
||||
c.id.contractID.chainID,
|
||||
c.id.contractID.address,
|
||||
c.id.tokenID,
|
||||
c.name,
|
||||
mediaUrl,
|
||||
mediaType,
|
||||
c.imageUrl,
|
||||
c.backgroundColor,
|
||||
c.collectionName,
|
||||
c.collectionSlug,
|
||||
c.collectionImageUrl,
|
||||
collectibleName,
|
||||
collectibleMediaUrl,
|
||||
collectibleMediaType,
|
||||
collectibleImageUrl,
|
||||
collectibleBackgroundColor,
|
||||
collectionName,
|
||||
collectionSlug,
|
||||
collectionImageUrl,
|
||||
isPinned,
|
||||
communityId,
|
||||
communityName,
|
||||
|
|
|
@ -21,6 +21,8 @@ QtObject:
|
|||
|
||||
requestId: int32
|
||||
|
||||
dataType: backend_collectibles.CollectibleDataType
|
||||
|
||||
proc setup(self: Controller) =
|
||||
self.QObject.setup
|
||||
|
||||
|
@ -62,7 +64,7 @@ QtObject:
|
|||
proc processGetCollectiblesDetailsResponse(self: Controller, response: JsonNode) =
|
||||
defer: self.setIsDetailedEntryLoading(false)
|
||||
|
||||
let res = fromJson(response, backend_collectibles.GetCollectiblesDetailsResponse)
|
||||
let res = fromJson(response, backend_collectibles.GetCollectiblesByUniqueIDResponse)
|
||||
|
||||
if res.errorCode != ErrorCodeSuccess:
|
||||
error "error fetching collectible details: ", res.errorCode
|
||||
|
@ -93,7 +95,7 @@ QtObject:
|
|||
self.detailedEntry = newCollectibleDetailsBasicEntry(id, extradata)
|
||||
self.detailedEntryChanged()
|
||||
|
||||
let response = backend_collectibles.getCollectiblesDetailsAsync(self.requestId, @[id])
|
||||
let response = backend_collectibles.getCollectiblesByUniqueIDAsync(self.requestId, @[id], self.dataType)
|
||||
if response.error != nil:
|
||||
self.setIsDetailedEntryLoading(false)
|
||||
error "error fetching collectible details: ", response.error
|
||||
|
@ -106,12 +108,15 @@ QtObject:
|
|||
|
||||
proc newController*(requestId: int32,
|
||||
networkService: network_service.Service,
|
||||
events: EventEmitter
|
||||
events: EventEmitter,
|
||||
dataType: backend_collectibles.CollectibleDataType = backend_collectibles.CollectibleDataType.Details
|
||||
): Controller =
|
||||
new(result, delete)
|
||||
|
||||
result.requestId = requestId
|
||||
|
||||
result.dataType = dataType
|
||||
|
||||
result.networkService = networkService
|
||||
|
||||
result.detailedEntry = newCollectibleDetailsEmptyEntry()
|
||||
|
|
|
@ -29,6 +29,9 @@ QtObject:
|
|||
requestId: int32
|
||||
autofetch: bool
|
||||
|
||||
dataType: backend_collectibles.CollectibleDataType
|
||||
fetchCriteria: backend_collectibles.FetchCriteria
|
||||
|
||||
proc setup(self: Controller) =
|
||||
self.QObject.setup
|
||||
|
||||
|
@ -112,17 +115,17 @@ QtObject:
|
|||
offset = self.model.getCollectiblesCount()
|
||||
self.fetchFromStart = false
|
||||
|
||||
let response = backend_collectibles.filterOwnedCollectiblesAsync(self.requestId, self.chainIds, self.addresses, self.filter, offset, FETCH_BATCH_COUNT_DEFAULT)
|
||||
let response = backend_collectibles.getOwnedCollectiblesAsync(self.requestId, self.chainIds, self.addresses, self.filter, offset, FETCH_BATCH_COUNT_DEFAULT, self.dataType, self.fetchCriteria)
|
||||
if response.error != nil:
|
||||
self.model.setIsFetching(false)
|
||||
self.model.setIsError(true)
|
||||
self.fetchFromStart = true
|
||||
error "error fetching collectibles entries: ", response.error
|
||||
|
||||
proc processFilterOwnedCollectiblesResponse(self: Controller, response: JsonNode) =
|
||||
proc processGetOwnedCollectiblesResponse(self: Controller, response: JsonNode) =
|
||||
defer: self.model.setIsFetching(false)
|
||||
|
||||
let res = fromJson(response, backend_collectibles.FilterOwnedCollectiblesResponse)
|
||||
let res = fromJson(response, backend_collectibles.GetOwnedCollectiblesResponse)
|
||||
|
||||
let isError = res.errorCode != backend_collectibles.ErrorCodeSuccess
|
||||
|
||||
|
@ -150,7 +153,7 @@ QtObject:
|
|||
|
||||
proc setupEventHandlers(self: Controller) =
|
||||
self.eventsHandler.onOwnedCollectiblesFilteringDone(proc (jsonObj: JsonNode) =
|
||||
self.processFilterOwnedCollectiblesResponse(jsonObj)
|
||||
self.processGetOwnedCollectiblesResponse(jsonObj)
|
||||
)
|
||||
|
||||
self.eventsHandler.onCollectiblesOwnershipUpdateStarted(proc (address: string, chainID: int) =
|
||||
|
@ -170,12 +173,20 @@ QtObject:
|
|||
self.eventsHandler.onCollectiblesOwnershipUpdateFinishedWithError(proc (address: string, chainID: int) =
|
||||
self.setOwnershipState(address, chainID, OwnershipStateError)
|
||||
)
|
||||
|
||||
proc newController*(requestId: int32, autofetch: bool, events: EventEmitter): Controller =
|
||||
proc newController*(
|
||||
requestId: int32,
|
||||
events: EventEmitter,
|
||||
autofetch: bool = true,
|
||||
dataType: backend_collectibles.CollectibleDataType = backend_collectibles.CollectibleDataType.Header,
|
||||
fetchCriteria: backend_collectibles.FetchCriteria = backend_collectibles.FetchCriteria(
|
||||
fetchType: backend_collectibles.FetchType.NeverFetch,
|
||||
)): Controller =
|
||||
new(result, delete)
|
||||
|
||||
result.requestId = requestId
|
||||
result.autofetch = autofetch
|
||||
result.dataType = dataType
|
||||
result.fetchCriteria = fetchCriteria
|
||||
|
||||
result.model = newModel()
|
||||
result.fetchFromStart = true
|
||||
|
|
|
@ -279,13 +279,18 @@ QtObject:
|
|||
let dataMessageJson = parseJson(jsonMessage)
|
||||
let tokenDataPayload = fromJson(dataMessageJson, CommunityCollectiblesReceivedPayload)
|
||||
for coll in tokenDataPayload.collectibles:
|
||||
let privilegesLevel = coll.communityHeader.privilegesLevel
|
||||
let communityId = coll.communityHeader.communityId
|
||||
if not coll.communityData.isSome():
|
||||
continue
|
||||
let id = coll.id
|
||||
let communityData = coll.communityData.get()
|
||||
|
||||
let privilegesLevel = communityData.privilegesLevel
|
||||
let communityId = communityData.id
|
||||
let community = self.communityService.getCommunityById(communityId)
|
||||
if privilegesLevel == PrivilegesLevel.Owner and not community.isOwner():
|
||||
let communityName = coll.communityHeader.communityName
|
||||
let chainId = coll.id.contractID.chainID
|
||||
let contractAddress = coll.id.contractID.address
|
||||
let communityName = communityData.name
|
||||
let chainId = id.contractID.chainID
|
||||
let contractAddress = id.contractID.address
|
||||
debug "received owner token", contractAddress=contractAddress, chainId=chainId
|
||||
let tokenReceivedArgs = OwnerTokenReceivedArgs(communityId: communityId, communityName: communityName, chainId: chainId, contractAddress: contractAddress)
|
||||
self.events.emit(SIGNAL_OWNER_TOKEN_RECEIVED, tokenReceivedArgs)
|
||||
|
|
|
@ -45,21 +45,21 @@ type
|
|||
state*: OwnershipState
|
||||
timestamp*: int
|
||||
|
||||
# Mirrors services/wallet/collectibles/service.go FilterOwnedCollectiblesResponse
|
||||
FilterOwnedCollectiblesResponse* = object
|
||||
collectibles*: seq[CollectibleHeader]
|
||||
# Mirrors services/wallet/collectibles/service.go GetOwnedCollectiblesResponse
|
||||
GetOwnedCollectiblesResponse* = object
|
||||
collectibles*: seq[Collectible]
|
||||
offset*: int
|
||||
hasMore*: bool
|
||||
ownershipStatus*: Table[string, Table[int, OwnershipStatus]]
|
||||
errorCode*: ErrorCode
|
||||
|
||||
# Mirrors services/wallet/collectibles/service.go GetCollectiblesDetailsResponse
|
||||
GetCollectiblesDetailsResponse* = object
|
||||
collectibles*: seq[CollectibleDetails]
|
||||
# Mirrors services/wallet/collectibles/service.go GetCollectiblesByUniqueIDResponse
|
||||
GetCollectiblesByUniqueIDResponse* = object
|
||||
collectibles*: seq[Collectible]
|
||||
errorCode*: ErrorCode
|
||||
|
||||
CommunityCollectiblesReceivedPayload* = object
|
||||
collectibles*: seq[CommunityCollectibleHeader]
|
||||
collectibles*: seq[Collectible]
|
||||
|
||||
# see status-go/services/wallet/collectibles/filter.go FilterCommunityType
|
||||
FilterCommunityType* {.pure.} = enum
|
||||
|
@ -72,6 +72,15 @@ type
|
|||
communityPrivilegesLevels*: seq[int]
|
||||
filterCommunity*: FilterCommunityType
|
||||
|
||||
# see status-go/services/wallet/collectibles/service.go FetchType
|
||||
FetchType* {.pure.} = enum
|
||||
NeverFetch, AlwaysFetch, FetchIfNotCached, FetchIfCacheOld
|
||||
|
||||
# see status-go/services/wallet/collectibles/service.go FetchCriteria
|
||||
FetchCriteria* = object
|
||||
fetchType*: FetchType
|
||||
maxCacheAgeSeconds*: int
|
||||
|
||||
# CollectibleOwnershipState
|
||||
proc `$`*(self: OwnershipStatus): string =
|
||||
return fmt"""OwnershipStatus(
|
||||
|
@ -115,14 +124,36 @@ proc `%`*(t: CollectibleFilter): JsonNode {.inline.} =
|
|||
proc `%`*(t: ref CollectibleFilter): JsonNode {.inline.} =
|
||||
return %(t[])
|
||||
|
||||
# CollectibleDataType
|
||||
proc `%`*(t: CollectibleDataType): JsonNode {.inline.} =
|
||||
result = %(t.int)
|
||||
|
||||
proc `%`*(t: ref CollectibleDataType): JsonNode {.inline.} =
|
||||
return %(t[])
|
||||
|
||||
# FetchCriteria
|
||||
proc `$`*(self: FetchCriteria): string =
|
||||
return fmt"""FetchCriteria(
|
||||
fetchType:{self.fetchType},
|
||||
maxCacheAgeSeconds:{self.maxCacheAgeSeconds}
|
||||
"""
|
||||
|
||||
proc `%`*(t: FetchCriteria): JsonNode {.inline.} =
|
||||
result = newJObject()
|
||||
result["fetch_type"] = %(t.fetchType.int)
|
||||
result["max_cache_age_seconds"] = %(t.maxCacheAgeSeconds)
|
||||
|
||||
proc `%`*(t: ref FetchCriteria): JsonNode {.inline.} =
|
||||
return %(t[])
|
||||
|
||||
# Responses
|
||||
proc fromJson*(e: JsonNode, T: typedesc[FilterOwnedCollectiblesResponse]): FilterOwnedCollectiblesResponse {.inline.} =
|
||||
var collectibles: seq[CollectibleHeader]
|
||||
proc fromJson*(e: JsonNode, T: typedesc[GetOwnedCollectiblesResponse]): GetOwnedCollectiblesResponse {.inline.} =
|
||||
var collectibles: seq[Collectible]
|
||||
if e.hasKey("collectibles"):
|
||||
let jsonCollectibles = e["collectibles"]
|
||||
collectibles = newSeq[CollectibleHeader](jsonCollectibles.len)
|
||||
for i in 0 ..< jsonCollectibles.len:
|
||||
collectibles[i] = fromJson(jsonCollectibles[i], CollectibleHeader)
|
||||
for jsonCollectible in jsonCollectibles.getElems():
|
||||
let collectible = fromJson(jsonCollectible, Collectible)
|
||||
collectibles.add(collectible)
|
||||
|
||||
var ownershipStatus = initTable[string, Table[int, OwnershipStatus]]()
|
||||
if e.hasKey("ownershipStatus"):
|
||||
|
@ -142,12 +173,10 @@ proc fromJson*(e: JsonNode, T: typedesc[FilterOwnedCollectiblesResponse]): Filte
|
|||
errorCode: ErrorCode(e["errorCode"].getInt())
|
||||
)
|
||||
|
||||
proc fromJson*(e: JsonNode, T: typedesc[GetCollectiblesDetailsResponse]): GetCollectiblesDetailsResponse {.inline.} =
|
||||
var collectibles: seq[CollectibleDetails] = @[]
|
||||
if e.hasKey("collectibles"):
|
||||
let jsonCollectibles = e["collectibles"]
|
||||
for item in jsonCollectibles.getElems():
|
||||
collectibles.add(fromJson(item, CollectibleDetails))
|
||||
proc fromJson*(e: JsonNode, T: typedesc[GetCollectiblesByUniqueIDResponse]): GetCollectiblesByUniqueIDResponse {.inline.} =
|
||||
var collectibles: seq[Collectible] = @[]
|
||||
for item in e["collectibles"].getElems():
|
||||
collectibles.add(fromJson(item, Collectible))
|
||||
|
||||
result = T(
|
||||
collectibles: collectibles,
|
||||
|
@ -155,9 +184,9 @@ proc fromJson*(e: JsonNode, T: typedesc[GetCollectiblesDetailsResponse]): GetCol
|
|||
)
|
||||
|
||||
proc fromJson*(e: JsonNode, T: typedesc[CommunityCollectiblesReceivedPayload]): CommunityCollectiblesReceivedPayload {.inline.} =
|
||||
var collectibles: seq[CommunityCollectibleHeader] = @[]
|
||||
var collectibles: seq[Collectible] = @[]
|
||||
for item in e.getElems():
|
||||
collectibles.add(fromJson(item, CommunityCollectibleHeader))
|
||||
collectibles.add(fromJson(item, Collectible))
|
||||
|
||||
result = T(
|
||||
collectibles: collectibles
|
||||
|
@ -183,17 +212,20 @@ rpc(getCollectibleOwnersByContractAddress, "wallet"):
|
|||
chainId: int
|
||||
contractAddress: string
|
||||
|
||||
rpc(filterOwnedCollectiblesAsync, "wallet"):
|
||||
rpc(getOwnedCollectiblesAsync, "wallet"):
|
||||
requestId: int32
|
||||
chainIDs: seq[int]
|
||||
addresses: seq[string]
|
||||
filter: CollectibleFilter
|
||||
offset: int
|
||||
limit: int
|
||||
dataType: CollectibleDataType
|
||||
fetchCriteria: FetchCriteria
|
||||
|
||||
rpc(getCollectiblesDetailsAsync, "wallet"):
|
||||
rpc(getCollectiblesByUniqueIDAsync, "wallet"):
|
||||
requestId: int32
|
||||
uniqueIds: seq[CollectibleUniqueID]
|
||||
dataType: CollectibleDataType
|
||||
|
||||
rpc(refetchOwnedCollectibles, "wallet"):
|
||||
discard
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
import json, strformat
|
||||
import json, strformat, json_serialization
|
||||
import stint, Tables, options
|
||||
import community_tokens_types
|
||||
|
||||
const communityHeaderField = "community_header"
|
||||
const communityInfoField = "community_info"
|
||||
|
||||
type
|
||||
# Mirrors services/wallet/thirdparty/collectible_types.go ContractID
|
||||
ContractID* = ref object of RootObj
|
||||
|
@ -16,6 +13,10 @@ type
|
|||
contractID*: ContractID
|
||||
tokenID*: UInt256
|
||||
|
||||
# see status-go/services/wallet/collectibles/service.go CollectibleDataType
|
||||
CollectibleDataType* {.pure.} = enum
|
||||
UniqueID, Header, Details, CommunityHeader
|
||||
|
||||
# Mirrors services/wallet/thirdparty/collectible_types.go CollectibleTrait
|
||||
CollectibleTrait* = ref object of RootObj
|
||||
trait_type*: string
|
||||
|
@ -23,82 +24,33 @@ type
|
|||
display_type*: string
|
||||
max_value*: string
|
||||
|
||||
# Mirrors services/wallet/thirdparty/collectible_types.go CollectionTrait
|
||||
CollectionTrait* = ref object of RootObj
|
||||
min*: float
|
||||
max*: float
|
||||
CollectibleData* = ref object of RootObj
|
||||
name*: string
|
||||
description*: Option[string]
|
||||
imageUrl*: Option[string]
|
||||
animationUrl*: Option[string]
|
||||
animationMediaType*: Option[string]
|
||||
traits*: Option[seq[CollectibleTrait]]
|
||||
backgroundColor*: Option[string]
|
||||
|
||||
# Mirrors services/wallet/thirdparty/collectible_types.go CollectionData
|
||||
CollectionData* = ref object of RootObj
|
||||
name*: string
|
||||
slug*: string
|
||||
imageUrl*: string
|
||||
traits*: Table[string, CollectionTrait]
|
||||
|
||||
# Mirrors services/wallet/thirdparty/collectible_types.go CollectibleData
|
||||
CollectibleData* = ref object of RootObj
|
||||
id* : CollectibleUniqueID
|
||||
communityId*: string
|
||||
CommunityData* = ref object of RootObj
|
||||
id*: string
|
||||
name*: string
|
||||
description*: string
|
||||
permalink*: string
|
||||
imageUrl*: string
|
||||
animationUrl*: string
|
||||
animationMediaType*: string
|
||||
traits*: seq[CollectibleTrait]
|
||||
backgroundColor*: string
|
||||
tokenUri*: string
|
||||
collectionData*: CollectionData
|
||||
|
||||
# Mirrors services/wallet/collectibles/types.go CommunityHeader
|
||||
CollectibleCommunityHeader* = ref object of RootObj
|
||||
communityId*: string
|
||||
communityName*: string
|
||||
communityColor*: string
|
||||
color*: string
|
||||
privilegesLevel*: PrivilegesLevel
|
||||
imageUrl*: Option[string]
|
||||
|
||||
# Mirrors services/wallet/collectibles/types.go CollectibleHeader
|
||||
CollectibleHeader* = ref object of RootObj
|
||||
Collectible* = ref object of RootObj
|
||||
dataType*: CollectibleDataType
|
||||
id* : CollectibleUniqueID
|
||||
name*: string
|
||||
imageUrl*: string
|
||||
animationUrl*: string
|
||||
animationMediaType*: string
|
||||
backgroundColor*: string
|
||||
collectionName*: string
|
||||
collectionSlug*: string
|
||||
collectionImageUrl*: string
|
||||
communityHeader*: Option[CollectibleCommunityHeader]
|
||||
|
||||
# Mirrors services/wallet/thirdparty/collectible_types.go CollectiblesCommunityInfo
|
||||
CollectibleCommunityInfo* = ref object of RootObj
|
||||
communityId*: string
|
||||
communityName*: string
|
||||
communityColor*: string
|
||||
communityImage*: string
|
||||
privilegesLevel*: PrivilegesLevel
|
||||
|
||||
# Mirrors services/wallet/collectibles/types.go CollectibleDetails
|
||||
CollectibleDetails* = ref object of RootObj
|
||||
id* : CollectibleUniqueID
|
||||
name*: string
|
||||
description*: string
|
||||
imageUrl*: string
|
||||
animationUrl*: string
|
||||
animationMediaType*: string
|
||||
traits*: seq[CollectibleTrait]
|
||||
backgroundColor*: string
|
||||
tokenUri*: string
|
||||
collectionName*: string
|
||||
collectionSlug*: string
|
||||
collectionImageUrl*: string
|
||||
communityInfo*: Option[CollectibleCommunityInfo]
|
||||
|
||||
# Mirrors services/wallet/collectibles/types.go CommunityCollectibleHeader
|
||||
CommunityCollectibleHeader* = ref object of RootObj
|
||||
id* : CollectibleUniqueID
|
||||
name*: string
|
||||
communityHeader*: CollectibleCommunityHeader
|
||||
collectibleData*: Option[CollectibleData]
|
||||
collectionData*: Option[CollectionData]
|
||||
communityData*: Option[CommunityData]
|
||||
|
||||
# Mirrors services/wallet/thirdparty/collectible_types.go TokenBalance
|
||||
CollectibleBalance* = ref object
|
||||
|
@ -191,209 +143,140 @@ proc fromJson*(t: JsonNode, T: typedesc[ref CollectibleTrait]): ref CollectibleT
|
|||
result = new(CollectibleTrait)
|
||||
result[] = fromJson(t, CollectibleTrait)
|
||||
|
||||
# CollectionTrait
|
||||
proc `$`*(self: CollectionTrait): string =
|
||||
return fmt"""CollectionTrait(
|
||||
min:{self.min},
|
||||
max:{self.max}
|
||||
)"""
|
||||
|
||||
proc fromJson*(t: JsonNode, T: typedesc[CollectionTrait]): CollectionTrait {.inline.} =
|
||||
result = CollectionTrait()
|
||||
result.min = t["min"].getFloat()
|
||||
result.max = t["max"].getFloat()
|
||||
|
||||
proc fromJson*(t: JsonNode, T: typedesc[ref CollectionTrait]): ref CollectionTrait {.inline.} =
|
||||
result = new(CollectionTrait)
|
||||
result[] = fromJson(t, CollectionTrait)
|
||||
|
||||
# CollectionData
|
||||
proc `$`*(self: CollectionData): string =
|
||||
return fmt"""CollectionData(
|
||||
name:{self.name},
|
||||
slug:{self.slug},
|
||||
imageUrl:{self.imageUrl},
|
||||
traits:{self.traits}
|
||||
imageUrl:{self.imageUrl}
|
||||
)"""
|
||||
|
||||
proc getCollectionTraits*(t: JsonNode): Table[string, CollectionTrait] =
|
||||
var traitList: Table[string, CollectionTrait] = initTable[string, CollectionTrait]()
|
||||
for key, value in t{"traits"}.getFields():
|
||||
traitList[key] = fromJson(value, CollectionTrait)
|
||||
return traitList
|
||||
|
||||
proc fromJson*(t: JsonNode, T: typedesc[CollectionData]): CollectionData {.inline.} =
|
||||
proc fromJson*(t: JsonNode, T: typedesc[CollectionData]): CollectionData =
|
||||
result = CollectionData()
|
||||
result.name = t["name"].getStr()
|
||||
result.slug = t["slug"].getStr()
|
||||
result.imageUrl = t["image_url"].getStr()
|
||||
result.traits = getCollectionTraits(t["traits"])
|
||||
|
||||
proc fromJson*(t: JsonNode, T: typedesc[ref CollectionData]): ref CollectionData {.inline.} =
|
||||
proc fromJson*(t: JsonNode, T: typedesc[ref CollectionData]): ref CollectionData =
|
||||
result = new(CollectionData)
|
||||
result[] = fromJson(t, CollectionData)
|
||||
|
||||
# CollectibleData
|
||||
proc `$`*(self: CollectibleData): string =
|
||||
return fmt"""CollectibleData(
|
||||
id:{self.id},
|
||||
communityId:{self.communityId},
|
||||
name:{self.name},
|
||||
description:{self.description},
|
||||
permalink:{self.permalink},
|
||||
imageUrl:{self.imageUrl},
|
||||
animationUrl:{self.animationUrl},
|
||||
animationMediaType:{self.animationMediaType},
|
||||
traits:{self.traits},
|
||||
backgroundColor:{self.backgroundColor},
|
||||
tokenUri:{self.tokenUri},
|
||||
backgroundColor:{self.backgroundColor}
|
||||
)"""
|
||||
|
||||
proc getCollectibleTraits*(t: JsonNode): seq[CollectibleTrait] =
|
||||
proc getCollectibleTraits*(t: JsonNode): Option[seq[CollectibleTrait]] =
|
||||
var traitList: seq[CollectibleTrait] = @[]
|
||||
for item in t.getElems():
|
||||
traitList.add(fromJson(item, CollectibleTrait))
|
||||
return traitList
|
||||
if traitList.len == 0:
|
||||
return none(seq[CollectibleTrait])
|
||||
else:
|
||||
return some(traitList)
|
||||
|
||||
proc fromJson*(t: JsonNode, T: typedesc[CollectibleData]): CollectibleData {.inline.} =
|
||||
proc fromJson*(t: JsonNode, T: typedesc[CollectibleData]): CollectibleData =
|
||||
result = CollectibleData()
|
||||
result.id = fromJson(t["id"], CollectibleUniqueID)
|
||||
result.communityId = t["community_id"].getStr()
|
||||
|
||||
result.name = t["name"].getStr()
|
||||
result.description = t["description"].getStr()
|
||||
result.permalink = t["permalink"].getStr()
|
||||
result.imageUrl = t["image_url"].getStr()
|
||||
result.animationUrl = t["animation_url"].getStr()
|
||||
result.animationMediaType = t["animation_media_type"].getStr()
|
||||
result.traits = getCollectibleTraits(t["traits"])
|
||||
result.backgroundColor = t["background_color"].getStr()
|
||||
result.tokenUri = t["token_uri"].getStr()
|
||||
let descriptionNode = t{"description"}
|
||||
if descriptionNode != nil and descriptionNode.kind != JNull:
|
||||
result.description = some(descriptionNode.getStr())
|
||||
else:
|
||||
result.description = none(string)
|
||||
let imageUrlNode = t{"image_url"}
|
||||
if imageUrlNode != nil and imageUrlNode.kind != JNull:
|
||||
result.imageUrl = some(imageUrlNode.getStr())
|
||||
else:
|
||||
result.imageUrl = none(string)
|
||||
let animationUrlNode = t{"animation_url"}
|
||||
if animationUrlNode != nil and animationUrlNode.kind != JNull:
|
||||
result.animationUrl = some(animationUrlNode.getStr())
|
||||
else:
|
||||
result.animationUrl = none(string)
|
||||
let animationMediaTypeNode = t{"animation_media_type"}
|
||||
if animationMediaTypeNode != nil and animationMediaTypeNode.kind != JNull:
|
||||
result.animationMediaType = some(animationMediaTypeNode.getStr())
|
||||
else:
|
||||
result.animationMediaType = none(string)
|
||||
result.traits = getCollectibleTraits(t{"traits"})
|
||||
let backgroundColorNode = t{"background_color"}
|
||||
if backgroundColorNode != nil and backgroundColorNode.kind != JNull:
|
||||
result.backgroundColor = some(backgroundColorNode.getStr())
|
||||
else:
|
||||
result.backgroundColor = none(string)
|
||||
|
||||
proc fromJson*(t: JsonNode, T: typedesc[ref CollectibleData]): ref CollectibleData {.inline.} =
|
||||
result = new(CollectibleData)
|
||||
result[] = fromJson(t, CollectibleData)
|
||||
|
||||
# CollectibleCommunityHeader
|
||||
proc `$`*(self: CollectibleCommunityHeader): string =
|
||||
return fmt"""CollectibleCommunityHeader(
|
||||
communityId:{self.communityId},
|
||||
communityName:{self.communityName},
|
||||
communityColor:{self.communityColor},
|
||||
privilegesLevel:{self.privilegesLevel}
|
||||
# CommunityData
|
||||
proc `$`*(self: CommunityData): string =
|
||||
return fmt"""CommunityData(
|
||||
id:{self.id},
|
||||
name:{self.name},
|
||||
color:{self.color},
|
||||
privilegesLevel:{self.privilegesLevel},
|
||||
imageUrl:{self.imageUrl}
|
||||
)"""
|
||||
|
||||
proc fromJson*(t: JsonNode, T: typedesc[CollectibleCommunityHeader]): CollectibleCommunityHeader {.inline.} =
|
||||
result = CollectibleCommunityHeader()
|
||||
result.communityId = t["community_id"].getStr
|
||||
result.communityName = t["community_name"].getStr
|
||||
result.communityColor = t["community_color"].getStr
|
||||
proc fromJson*(t: JsonNode, T: typedesc[CommunityData]): CommunityData =
|
||||
result = CommunityData()
|
||||
result.id = t["id"].getStr
|
||||
result.name = t["name"].getStr
|
||||
result.color = t["color"].getStr
|
||||
result.privilegesLevel = PrivilegesLevel(t["privileges_level"].getInt)
|
||||
let imageUrlNode = t{"image_url"}
|
||||
if imageUrlNode != nil and imageUrlNode.kind != JNull:
|
||||
result.imageUrl = some(imageUrlNode.getStr())
|
||||
else:
|
||||
result.imageUrl = none(string)
|
||||
|
||||
proc fromJson*(t: JsonNode, T: typedesc[ref CollectibleCommunityHeader]): ref CollectibleCommunityHeader {.inline.} =
|
||||
result = new(CollectibleCommunityHeader)
|
||||
result[] = fromJson(t, CollectibleCommunityHeader)
|
||||
proc fromJson*(t: JsonNode, T: typedesc[ref CommunityData]): ref CommunityData {.inline.} =
|
||||
result = new(CommunityData)
|
||||
result[] = fromJson(t, CommunityData)
|
||||
|
||||
# CollectibleHeader
|
||||
proc `$`*(self: CollectibleHeader): string =
|
||||
return fmt"""CollectibleHeader(
|
||||
# Collectible
|
||||
proc `$`*(self: Collectible): string =
|
||||
return fmt"""Collectible(
|
||||
dataType:{self.dataType},
|
||||
id:{self.id},
|
||||
name:{self.name},
|
||||
imageUrl:{self.imageUrl},
|
||||
animationUrl:{self.animationUrl},
|
||||
animationMediaType:{self.animationMediaType},
|
||||
backgroundColor:{self.backgroundColor},
|
||||
collectionName:{self.collectionName},
|
||||
collectionSlug:{self.collectionSlug},
|
||||
collectionImageUrl:{self.collectionImageUrl},
|
||||
communityHeader:{self.communityHeader}
|
||||
collectibleData:{self.collectibleData},
|
||||
collectionData:{self.collectionData},
|
||||
communityData:{self.communityData}
|
||||
)"""
|
||||
|
||||
proc fromJson*(t: JsonNode, T: typedesc[CollectibleHeader]): CollectibleHeader {.inline.} =
|
||||
result = CollectibleHeader()
|
||||
proc fromJson*(t: JsonNode, T: typedesc[Collectible]): Collectible {.inline.} =
|
||||
result = Collectible()
|
||||
result.dataType = t["data_type"].getInt().CollectibleDataType
|
||||
result.id = fromJson(t["id"], CollectibleUniqueID)
|
||||
result.name = t["name"].getStr()
|
||||
result.imageUrl = t["image_url"].getStr()
|
||||
result.animationUrl = t["animation_url"].getStr()
|
||||
result.animationMediaType = t["animation_media_type"].getStr()
|
||||
result.backgroundColor = t["background_color"].getStr()
|
||||
result.collectionName = t["collection_name"].getStr()
|
||||
result.collectionSlug = t["collection_slug"].getStr()
|
||||
result.collectionImageUrl = t["collection_image_url"].getStr()
|
||||
if t.contains(communityHeaderField) and t[communityHeaderField].kind != JNull:
|
||||
result.communityHeader = some(fromJson(t[communityHeaderField], CollectibleCommunityHeader))
|
||||
let collectibleDataNode = t{"collectible_data"}
|
||||
if collectibleDataNode != nil and collectibleDataNode.kind != JNull:
|
||||
result.collectibleData = some(fromJson(collectibleDataNode, CollectibleData))
|
||||
else:
|
||||
result.collectibleData = none(CollectibleData)
|
||||
let collectionDataNode = t{"collection_data"}
|
||||
if collectionDataNode != nil and collectionDataNode.kind != JNull:
|
||||
result.collectionData = some(fromJson(collectionDataNode, CollectionData))
|
||||
else:
|
||||
result.collectionData = none(CollectionData)
|
||||
let communityDataNode = t{"community_data"}
|
||||
if communityDataNode != nil and communityDataNode.kind != JNull:
|
||||
result.communityData = some(fromJson(communityDataNode, CommunityData))
|
||||
else:
|
||||
result.communityData = none(CommunityData)
|
||||
|
||||
# CollectibleCommunityInfo
|
||||
proc `$`*(self: CollectibleCommunityInfo): string =
|
||||
return fmt"""CollectibleCommunityInfo(
|
||||
communityId:{self.communityId},
|
||||
communityName:{self.communityName},
|
||||
communityColor:{self.communityColor},
|
||||
communityImage:{self.communityImage},
|
||||
privilegesLevel:{self.privilegesLevel}
|
||||
)"""
|
||||
|
||||
proc fromJson*(t: JsonNode, T: typedesc[CollectibleCommunityInfo]): CollectibleCommunityInfo {.inline.} =
|
||||
result = CollectibleCommunityInfo()
|
||||
result.communityId = t["community_id"].getStr
|
||||
result.communityName = t["community_name"].getStr
|
||||
result.communityColor = t["community_color"].getStr
|
||||
result.communityImage = t["community_image"].getStr
|
||||
result.privilegesLevel = PrivilegesLevel(t["privileges_level"].getInt)
|
||||
|
||||
proc fromJson*(t: JsonNode, T: typedesc[ref CollectibleCommunityInfo]): ref CollectibleCommunityInfo {.inline.} =
|
||||
result = new(CollectibleCommunityInfo)
|
||||
result[] = fromJson(t, CollectibleCommunityInfo)
|
||||
|
||||
# CollectibleDetails
|
||||
proc `$`*(self: CollectibleDetails): string =
|
||||
return fmt"""CollectibleDetails(
|
||||
id:{self.id},
|
||||
name:{self.name},
|
||||
description:{self.description},
|
||||
imageUrl:{self.imageUrl},
|
||||
animationUrl:{self.animationUrl},
|
||||
animationMediaType:{self.animationMediaType},
|
||||
traits:{self.traits},
|
||||
backgroundColor:{self.backgroundColor},
|
||||
collectionName:{self.collectionName},
|
||||
collectionSlug:{self.collectionSlug},
|
||||
collectionImageUrl:{self.collectionImageUrl},
|
||||
communityInfo:{self.communityInfo}
|
||||
)"""
|
||||
|
||||
proc fromJson*(t: JsonNode, T: typedesc[CollectibleDetails]): CollectibleDetails {.inline.} =
|
||||
result = CollectibleDetails()
|
||||
result.id = fromJson(t["id"], CollectibleUniqueID)
|
||||
result.name = t["name"].getStr()
|
||||
result.description = t["description"].getStr()
|
||||
result.imageUrl = t["image_url"].getStr()
|
||||
result.animationUrl = t["animation_url"].getStr()
|
||||
result.animationMediaType = t["animation_media_type"].getStr()
|
||||
result.traits = getCollectibleTraits(t["traits"])
|
||||
result.backgroundColor = t["background_color"].getStr()
|
||||
result.collectionName = t["collection_name"].getStr()
|
||||
result.collectionSlug = t["collection_slug"].getStr()
|
||||
result.collectionImageUrl = t["collection_image_url"].getStr()
|
||||
if t.contains(communityInfoField) and t[communityInfoField].kind != JNull:
|
||||
result.communityInfo = some(fromJson(t[communityInfoField], CollectibleCommunityInfo))
|
||||
|
||||
proc fromJson*(t: JsonNode, T: typedesc[ref CollectibleDetails]): ref CollectibleDetails {.inline.} =
|
||||
result = new(CollectibleDetails)
|
||||
result[] = fromJson(t, CollectibleDetails)
|
||||
|
||||
# CommunityCollectibleHeader
|
||||
proc `$`*(self: CommunityCollectibleHeader): string =
|
||||
return fmt"""CommunityCollectibleHeader(
|
||||
id:{self.id},
|
||||
name:{self.name},
|
||||
communityHeader:{self.communityHeader}
|
||||
)"""
|
||||
|
||||
proc fromJson*(t: JsonNode, T: typedesc[CommunityCollectibleHeader]): CommunityCollectibleHeader {.inline.} =
|
||||
result = CommunityCollectibleHeader()
|
||||
result.id = fromJson(t["id"], CollectibleUniqueID)
|
||||
result.name = t["name"].getStr()
|
||||
result.communityHeader = fromJson(t[communityHeaderField], CollectibleCommunityHeader)
|
||||
proc toIds(self: seq[Collectible]): seq[CollectibleUniqueID] =
|
||||
result = @[]
|
||||
for c in self:
|
||||
result.add(c.id)
|
||||
|
||||
# CollectibleBalance
|
||||
proc `$`*(self: CollectibleBalance): string =
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit a51f8aa13c20609c894ea36a9469ce3f57645657
|
||||
Subproject commit c88ab45d769d790fc24ff45518e4a818f90bcbb0
|
Loading…
Reference in New Issue