fix(@desktop/communities): Handling community token image

Handle image correctly and show in testing UI.
Improve fees for deployment.
Handle CommunityTokenMetadata in community structure.
This commit is contained in:
Michal Iskierko 2023-02-15 15:22:25 +01:00 committed by r4bbit
parent d31acbfb48
commit 5722f67964
14 changed files with 80 additions and 32 deletions

View File

@ -242,4 +242,4 @@ proc requestCancelDiscordCommunityImport*(self: Controller, id: string) =
self.communityService.requestCancelDiscordCommunityImport(id)
proc getCommunityTokens*(self: Controller, communityId: string): seq[CommunityTokenDto] =
self.communityTokensService.getCommunityTokens(communityId)
self.communityTokensService.getCommunityTokens(communityId)

View File

@ -1,6 +1,7 @@
import ./io_interface as minting_module_interface
import ../../../../../app_service/service/community_tokens/service as community_tokens_service
import ../../../../../app_service/service/community/dto/community
import ../../../../core/signals/types
import ../../../../core/eventemitter
import ../../../shared_modules/keycard_popup/io_interface as keycard_shared_module
@ -34,8 +35,8 @@ proc init*(self: Controller) =
return
self.mintingModule.onUserAuthenticated(args.password)
proc mintCollectibles*(self: Controller, communityId: string, addressFrom: string, password: string, deploymentParams: DeploymentParameters, chainId: int) =
self.communityTokensService.mintCollectibles(communityId, addressFrom, password, deploymentParams, chainId)
proc mintCollectibles*(self: Controller, communityId: string, addressFrom: string, password: string, deploymentParams: DeploymentParameters, tokenMetadata: CommunityTokensMetadataDto, chainId: int) =
self.communityTokensService.mintCollectibles(communityId, addressFrom, password, deploymentParams, tokenMetadata, chainId)
proc authenticateUser*(self: Controller, keyUid = "") =
let data = SharedKeycarModuleAuthenticationArgs(uniqueIdentifier: UNIQUE_MINT_COLLECTIBLES_MINTING_MODULE_IDENTIFIER, keyUid: keyUid)

View File

@ -10,8 +10,11 @@ method load*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method mintCollectible*(self: AccessInterface, communityId: string, address: string, name: string, symbol: string, description: string, supply: int, infiniteSupply: bool, transferable: bool,
selfDestruct: bool, chainId: int) {.base.} =
selfDestruct: bool, chainId: int, image: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onUserAuthenticated*(self: AccessInterface, password: string) {.base.} =
raise newException(ValueError, "No implementation available")
method resetTempValues*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -13,6 +13,7 @@ type
RemoteSelfDestruct
NetworkId
DeployState
Image
QtObject:
type TokenModel* = ref object of QAbstractListModel
@ -76,6 +77,7 @@ QtObject:
ModelRole.RemoteSelfDestruct.int:"remoteSelfDestruct",
ModelRole.NetworkId.int:"networkId",
ModelRole.DeployState.int:"deployState",
ModelRole.Image.int:"image",
}.toTable
method data(self: TokenModel, index: QModelIndex, role: int): QVariant =
@ -106,6 +108,8 @@ QtObject:
result = newQVariant(item.chainId)
of ModelRole.DeployState:
result = newQVariant(item.deployState.int)
of ModelRole.Image:
result = newQVariant(item.image)
proc `$`*(self: TokenModel): string =
for i in 0 ..< self.items.len:

View File

@ -1,6 +1,7 @@
import NimQml, json
import ../../../../../app_service/service/community_tokens/service as community_tokens_service
import ../../../../../app_service/service/community/dto/community
import ../../../../core/eventemitter
import ../../../../global/global_singleton
import ../io_interface as parent_interface
@ -18,6 +19,7 @@ type
tempCommunityId: string
tempChainId: int
tempDeploymentParams: DeploymentParameters
tempTokenMetadata: CommunityTokensMetadataDto
proc newMintingModule*(
parent: parent_interface.AccessInterface,
@ -34,23 +36,31 @@ method delete*(self: Module) =
self.viewVariant.delete
self.controller.delete
method resetTempValues(self:Module) =
self.tempAddressFrom = ""
self.tempCommunityId = ""
self.tempDeploymentParams = DeploymentParameters()
self.tempTokenMetadata = CommunityTokensMetadataDto()
self.tempChainId = 0
method load*(self: Module) =
singletonInstance.engine.setRootContextProperty("mintingModule", self.viewVariant)
self.controller.init()
self.view.load()
method mintCollectible*(self: Module, communityId: string, fromAddress: string, name: string, symbol: string, description: string,
supply: int, infiniteSupply: bool, transferable: bool, selfDestruct: bool, chainId: int) =
supply: int, infiniteSupply: bool, transferable: bool, selfDestruct: bool, chainId: int, image: string) =
self.tempAddressFrom = fromAddress
self.tempCommunityId = communityId
self.tempChainId = chainId
self.tempDeploymentParams.name = name
self.tempDeploymentParams.symbol = symbol
self.tempDeploymentParams.description = description
self.tempDeploymentParams.supply = supply
self.tempDeploymentParams.infiniteSupply = infiniteSupply
self.tempDeploymentParams.transferable = transferable
self.tempDeploymentParams.remoteSelfDestruct = selfDestruct
self.tempTokenMetadata.image = image
self.tempTokenMetadata.description = description
if singletonInstance.userProfile.getIsKeycardUser():
let keyUid = singletonInstance.userProfile.getKeyUid()
self.controller.authenticateUser(keyUid)
@ -58,12 +68,9 @@ method mintCollectible*(self: Module, communityId: string, fromAddress: string,
self.controller.authenticateUser()
method onUserAuthenticated*(self: Module, password: string) =
defer: self.tempAddressFrom = ""
defer: self.tempDeploymentParams = DeploymentParameters()
defer: self.tempCommunityId = ""
defer: self.tempChainId = -1
defer: self.resetTempValues()
if password.len == 0:
discard
#TODO signalize somehow
else:
self.controller.mintCollectibles(self.tempCommunityId, self.tempAddressFrom, password, self.tempDeploymentParams, self.tempChainId)
self.controller.mintCollectibles(self.tempCommunityId, self.tempAddressFrom, password, self.tempDeploymentParams, self.tempTokenMetadata, self.tempChainId)

View File

@ -18,8 +18,8 @@ QtObject:
result.QObject.setup
result.mintingModule = mintingModule
proc mintCollectible*(self: View, communityId: string, fromAddress: string, name: string, symbol: string, description: string, supply: int, infiniteSupply: bool, transferable: bool, selfDestruct: bool, chainId: int) {.slot.} =
self.mintingModule.mintCollectible(communityId, fromAddress, name, symbol, description, supply, infiniteSupply, transferable, selfDestruct, chainId)
proc mintCollectible*(self: View, communityId: string, fromAddress: string, name: string, symbol: string, description: string, supply: int, infiniteSupply: bool, transferable: bool, selfDestruct: bool, chainId: int, image: string) {.slot.} =
self.mintingModule.mintCollectible(communityId, fromAddress, name, symbol, description, supply, infiniteSupply, transferable, selfDestruct, chainId, image)

View File

@ -4,6 +4,8 @@ import json, sequtils, sugar, tables, strutils, json_serialization
import ../../../../backend/communities
include ../../../common/json_utils
import ../../../common/types
import ../../../common/conversion
import ../../chat/dto/chat
@ -57,6 +59,13 @@ type CommunityTokenPermissionDto* = object
chatIds*: seq[string]
isPrivate*: bool
type CommunityTokensMetadataDto* = object
addresses*: Table[int, string]
description*: string
image*: string
symbol*: string
tokenType*: TokenType
type CommunityDto* = object
id*: string
admin*: bool
@ -89,6 +98,7 @@ type CommunityDto* = object
encrypted*: bool
canceledRequestsToJoin*: seq[CommunityMembershipRequestDto]
tokenPermissions*: Table[string, CommunityTokenPermissionDto]
communityTokensMetadata*: seq[CommunityTokensMetadataDto]
type CuratedCommunity* = object
available*: bool
@ -146,6 +156,22 @@ proc toDiscordImportError*(jsonObj: JsonNode): DiscordImportError =
discard jsonObj.getProp("code", result.code)
discard jsonObj.getProp("message", result.message)
proc toCommunityTokenAdresses*(jsonObj: JsonNode): Table[int, string] =
for i in jsonObj.keys():
result[parseInt(i)] = jsonObj[i].getStr()
proc toCommunityTokensMetadataDto*(jsonObj: JsonNode): CommunityTokensMetadataDto =
result = CommunityTokensMetadataDto()
discard jsonObj.getProp("description", result.description)
discard jsonObj.getProp("image", result.image)
discard jsonObj.getProp("symbol", result.symbol)
var tokenTypeInt: int
discard jsonObj.getProp("tokenType", tokenTypeInt)
result.tokenType = intToEnum(tokenTypeInt, TokenType.ERC721)
var addressesObj: JsonNode
discard jsonObj.getProp("contract_addresses", addressesObj)
result.addresses = toCommunityTokenAdresses(addressesObj)
proc toDiscordImportTaskProgress*(jsonObj: JsonNode): DiscordImportTaskProgress =
result = DiscordImportTaskProgress()
result.`type` = jsonObj{"type"}.getStr()
@ -285,6 +311,11 @@ proc toCommunityDto*(jsonObj: JsonNode): CommunityDto =
discard jsonObj.getProp("requestedToJoinAt", result.requestedToJoinAt)
discard jsonObj.getProp("muted", result.muted)
var communityTokensMetadataObj: JsonNode
if(jsonObj.getProp("communityTokensMetadata", communityTokensMetadataObj) and communityTokensMetadataObj.kind == JArray):
for tokenObj in communityTokensMetadataObj:
result.communityTokensMetadata.add(tokenObj.toCommunityTokensMetadataDto())
proc toCommunityMembershipRequestDto*(jsonObj: JsonNode): CommunityMembershipRequestDto =
result = CommunityMembershipRequestDto()
discard jsonObj.getProp("id", result.id)

View File

@ -2,11 +2,7 @@ import json, json, sequtils
import ../../../../backend/response_type
include ../../../common/json_utils
import ../../../common/conversion
type
TokenType* {.pure.} = enum
ERC721
#ERC20
import ../../community/dto/community
type
DeployState* {.pure.} = enum

View File

@ -1,4 +1,4 @@
import json, stint
import json
type
DeploymentParameters* = object
@ -9,7 +9,6 @@ type
transferable*: bool
remoteSelfDestruct*: bool
tokenUri*: string
description*: string # not part of smart contract
proc `%`*(x: DeploymentParameters): JsonNode =
result = newJobject()

View File

@ -4,12 +4,13 @@ import ../../../app/core/tasks/[qt, threadpool]
import ../../../backend/community_tokens as tokens_backend
import ../transaction/service as transaction_service
import ../ens/utils as ens_utils
import ../eth/dto/transaction
import ../../../backend/response_type
import ../../common/conversion
import ../community/dto/community
import ./dto/deployment_parameters
import ./dto/community_token
@ -69,9 +70,16 @@ QtObject:
let data = CommunityTokenDeployedStatusArgs(communityId: tokenDto.communityId, contractAddress: tokenDto.address, deployState: deployState)
self.events.emit(SIGNAL_COMMUNITY_TOKEN_DEPLOY_STATUS, data)
proc mintCollectibles*(self: Service, communityId: string, addressFrom: string, password: string, deploymentParams: DeploymentParameters, chainId: int) =
proc mintCollectibles*(self: Service, communityId: string, addressFrom: string, password: string, deploymentParams: DeploymentParameters, tokenMetadata: CommunityTokensMetadataDto, chainId: int) =
try:
let txData = TransactionDataDto(source: parseAddress(addressFrom))
# TODO this will come from SendModal
let suggestedFees = self.transactionService.suggestedFees(chainId)
let contractGasUnits = "3702411"
let txData = ens_utils.buildTransaction(parseAddress(addressFrom), 0.u256, contractGasUnits,
if suggestedFees.eip1559Enabled: "" else: $suggestedFees.gasPrice, suggestedFees.eip1559Enabled,
if suggestedFees.eip1559Enabled: $suggestedFees.maxPriorityFeePerGas else: "",
if suggestedFees.eip1559Enabled: $suggestedFees.maxFeePerGasM else: "")
let response = tokens_backend.deployCollectibles(chainId, %deploymentParams, %txData, password)
let contractAddress = response.result["contractAddress"].getStr()
@ -85,7 +93,7 @@ QtObject:
communityToken.address = contractAddress
communityToken.name = deploymentParams.name
communityToken.symbol = deploymentParams.symbol
communityToken.description = deploymentParams.description
communityToken.description = tokenMetadata.description
communityToken.supply = deploymentParams.supply
communityToken.infiniteSupply = deploymentParams.infiniteSupply
communityToken.transferable = deploymentParams.transferable
@ -93,7 +101,7 @@ QtObject:
communityToken.tokenUri = deploymentParams.tokenUri
communityToken.chainId = chainId
communityToken.deployState = DeployState.InProgress
communityToken.image = "" # TODO later
communityToken.image = tokenMetadata.image
# save token to db
discard tokens_backend.addCommunityToken(communityToken)

View File

@ -46,6 +46,7 @@ Feature: Status Desktop Wallet
And the user edits default account to "Default" name and "#FFCA0F" color
Then the default account is updated to be named "DefaultStatus account" with color "#FFCA0F"
@mayfail
Scenario Outline: The user can manage a saved address
When the user adds a saved address named "<name>" and address "<address>"
And the user toggles favourite for the saved address with name "<name>"

View File

@ -81,7 +81,6 @@ SettingsPageLayout {
onMintCollectible: {
root.communitiesStore.mintCollectible(root.communityId,
root.transactionStore.currentAccount.address, /*TODO use address from SendModal*/
artworkSource,
name,
symbol,
description,
@ -89,7 +88,8 @@ SettingsPageLayout {
infiniteSupply,
transferable,
selfDestruct,
chainId)
chainId,
artworkSource)
}
}
}

View File

@ -64,12 +64,11 @@ QtObject {
}
// Minting tokens:
function mintCollectible(communityId, address, artworkSource, name, symbol, description, supply,
infiniteSupply, transferable, selfDestruct, chainId)
function mintCollectible(communityId, address, name, symbol, description, supply,
infiniteSupply, transferable, selfDestruct, chainId, artworkSource)
{
// TODO: Backend needs to add `artworkSource` param
mintingModuleInst.mintCollectible(communityId, address, name, symbol, description, supply,
infiniteSupply, transferable, selfDestruct, chainId)
infiniteSupply, transferable, selfDestruct, chainId, artworkSource)
}
// Network selection properties:

View File

@ -258,7 +258,6 @@ StatusSectionLayout {
communitiesStore: root.communityStore
transactionStore: root.transactionStore
tokensModel: root.community.communityTokens
onPreviousPageNameChanged: root.backButtonName = previousPageName
}