From 603d4dd4d80d0e4109dc651381681efe316bdc61 Mon Sep 17 00:00:00 2001 From: Michal Iskierko Date: Tue, 11 Jul 2023 15:23:00 +0200 Subject: [PATCH] feat(@desktop/communities): Deploy Owner and Master tokens flow. Issue #11250 --- src/app/modules/main/communities/module.nim | 2 +- .../main/communities/tokens/controller.nim | 33 +- .../main/communities/tokens/io_interface.nim | 12 +- .../communities/tokens/models/token_model.nim | 17 ++ .../main/communities/tokens/module.nim | 57 +++- .../modules/main/communities/tokens/view.nim | 15 +- src/app/modules/main/controller.nim | 12 +- src/app/modules/main/io_interface.nim | 6 + src/app/modules/main/module.nim | 17 +- .../modules/shared_models/section_item.nim | 3 + .../service/community_tokens/async_tasks.nim | 33 +- .../community_tokens/dto/community_token.nim | 17 +- .../dto/deployment_parameters.nim | 6 +- .../service/community_tokens/service.nim | 282 ++++++++++++++---- src/app_service/service/transaction/dto.nim | 1 + src/backend/community_tokens.nim | 36 ++- .../panels/MintTokensSettingsPanel.qml | 3 +- .../views/CommunitySettingsView.qml | 47 ++- .../shared/stores/CommunityTokensStore.qml | 22 +- 19 files changed, 521 insertions(+), 100 deletions(-) diff --git a/src/app/modules/main/communities/module.nim b/src/app/modules/main/communities/module.nim index 9df0ffa274..56867239fa 100644 --- a/src/app/modules/main/communities/module.nim +++ b/src/app/modules/main/communities/module.nim @@ -76,7 +76,7 @@ proc newModule*( tokensService, chatService, ) - result.communityTokensModule = community_tokens_module.newCommunityTokensModule(result, events, communityTokensService, transactionService, networksService) + result.communityTokensModule = community_tokens_module.newCommunityTokensModule(result, events, communityTokensService, transactionService, networksService, communityService) result.moduleLoaded = false result.curatedCommunitiesLoaded = false diff --git a/src/app/modules/main/communities/tokens/controller.nim b/src/app/modules/main/communities/tokens/controller.nim index a4ee21e39c..65052fb09f 100644 --- a/src/app/modules/main/communities/tokens/controller.nim +++ b/src/app/modules/main/communities/tokens/controller.nim @@ -4,6 +4,7 @@ import ./io_interface as community_tokens_module_interface import ../../../../../app_service/service/community_tokens/service as community_tokens_service import ../../../../../app_service/service/transaction/service as transaction_service import ../../../../../app_service/service/network/service as networks_service +import ../../../../../app_service/service/community/service as community_service import ../../../../../app_service/service/community/dto/community import ../../../../core/signals/types import ../../../../core/eventemitter @@ -19,13 +20,15 @@ type communityTokensService: community_tokens_service.Service transactionService: transaction_service.Service networksService: networks_service.Service + communityService: community_service.Service proc newCommunityTokensController*( communityTokensModule: community_tokens_module_interface.AccessInterface, events: EventEmitter, communityTokensService: community_tokens_service.Service, transactionService: transaction_service.Service, - networksService: networks_service.Service + networksService: networks_service.Service, + communityService: community_service.Service ): Controller = result = Controller() result.communityTokensModule = communityTokensModule @@ -33,6 +36,7 @@ proc newCommunityTokensController*( result.communityTokensService = communityTokensService result.transactionService = transactionService result.networksService = networksService + result.communityService = communityService proc delete*(self: Controller) = discard @@ -59,8 +63,14 @@ proc init*(self: Controller) = let args = CommunityTokenDeploymentArgs(e) self.communityTokensModule.onCommunityTokenDeployStateChanged(args.communityToken.communityId, args.communityToken.chainId, args.transactionHash, args.communityToken.deployState) self.events.on(SIGNAL_COMMUNITY_TOKEN_DEPLOY_STATUS) do(e: Args): - let args = CommunityTokenDeployedStatusArgs(e) + let args = OwnerTokenDeployedStatusArgs(e) self.communityTokensModule.onCommunityTokenDeployStateChanged(args.communityId, args.chainId, args.transactionHash, args.deployState) + self.events.on(SIGNAL_OWNER_TOKEN_DEPLOYMENT_STARTED) do(e: Args): + let args = OwnerTokenDeploymentArgs(e) + self.communityTokensModule.onOwnerTokenDeployStarted(args.ownerToken.communityId, args.ownerToken.chainId, args.transactionHash) + self.events.on(SIGNAL_OWNER_TOKEN_DEPLOY_STATUS) do(e: Args): + let args = OwnerTokenDeployedStatusArgs(e) + self.communityTokensModule.onOwnerTokenDeployStateChanged(args.communityId, args.chainId, args.transactionHash, args.deployState) self.events.on(SIGNAL_REMOTE_DESTRUCT_STATUS) do(e: Args): let args = RemoteDestructArgs(e) self.communityTokensModule.onRemoteDestructStateChanged(args.communityToken.communityId, args.communityToken.name, args.communityToken.chainId, args.transactionHash, args.status) @@ -74,6 +84,13 @@ proc init*(self: Controller) = proc deployContract*(self: Controller, communityId: string, addressFrom: string, password: string, deploymentParams: DeploymentParameters, tokenMetadata: CommunityTokensMetadataDto, tokenImageCropInfoJson: string, chainId: int) = self.communityTokensService.deployContract(communityId, addressFrom, password, deploymentParams, tokenMetadata, tokenImageCropInfoJson, chainId) +proc deployOwnerContracts*(self: Controller, communityId: string, addressFrom: string, password: string, + ownerDeploymentParams: DeploymentParameters, ownerTokenMetadata: CommunityTokensMetadataDto, + masterDeploymentParams: DeploymentParameters, masterTokenMetadata: CommunityTokensMetadataDto, + tokenImageCropInfoJson: string, chainId: int) = + self.communityTokensService.deployOwnerContracts(communityId, addressFrom, password, ownerDeploymentParams, ownerTokenMetadata, + masterDeploymentParams, masterTokenMetadata, tokenImageCropInfoJson, chainId) + proc removeCommunityToken*(self: Controller, communityId: string, chainId: int, address: string) = self.communityTokensService.removeCommunityToken(communityId, chainId, address) @@ -99,6 +116,9 @@ proc getCommunityTokens*(self: Controller, communityId: string): seq[CommunityTo proc computeDeployFee*(self: Controller, chainId: int, accountAddress: string, tokenType: TokenType) = self.communityTokensService.computeDeployFee(chainId, accountAddress, tokenType) +proc computeDeployOwnerContractsFee*(self: Controller, chainId: int, accountAddress: string) = + self.communityTokensService.computeDeployOwnerContractsFee(chainId, accountAddress) + proc computeSelfDestructFee*(self: Controller, walletAndAmountList: seq[WalletAndAmount], contractUniqueKey: string) = self.communityTokensService.computeSelfDestructFee(walletAndAmountList, contractUniqueKey) @@ -110,3 +130,12 @@ proc computeBurnFee*(self: Controller, contractUniqueKey: string, amount: Uint25 proc getNetwork*(self:Controller, chainId: int): NetworkDto = self.networksService.getNetwork(chainId) + +proc getOwnerToken*(self: Controller, communityId: string): CommunityTokenDto = + return self.communityTokensService.getOwnerToken(communityId) + +proc getMasterToken*(self: Controller, communityId: string): CommunityTokenDto = + return self.communityTokensService.getMasterToken(communityId) + +proc getCommunityById*(self: Controller, communityId: string): CommunityDto = + return self.communityService.getCommunityById(communityId) \ No newline at end of file diff --git a/src/app/modules/main/communities/tokens/io_interface.nim b/src/app/modules/main/communities/tokens/io_interface.nim index 50cc7712ed..0e6f4d8e3b 100644 --- a/src/app/modules/main/communities/tokens/io_interface.nim +++ b/src/app/modules/main/communities/tokens/io_interface.nim @@ -32,13 +32,17 @@ method deployAssets*(self: AccessInterface, communityId: string, address: string chainId: int, imageCropInfoJson: string) {.base.} = raise newException(ValueError, "No implementation available") +method deployOwnerToken*(self: AccessInterface, communityId: string, fromAddress: string, ownerName: string, ownerSymbol: string, ownerDescription: string, + masterName: string, masterSymbol: string, masterDescription: string, chainId: int, imageCropInfoJson: 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") -method computeDeployFee*(self: AccessInterface, chainId: int, accountAddress: string, tokenType: TokenType) {.base.} = +method computeDeployFee*(self: AccessInterface, chainId: int, accountAddress: string, tokenType: TokenType, isOwnerDeployment: bool) {.base.} = raise newException(ValueError, "No implementation available") method computeSelfDestructFee*(self: AccessInterface, collectiblesToBurnJsonString: string, contractUniqueKey: string) {.base.} = @@ -62,6 +66,12 @@ method onBurnFeeComputed*(self: AccessInterface, ethCurrency: CurrencyAmount, fi method onCommunityTokenDeployStateChanged*(self: AccessInterface, communityId: string, chainId: int, transactionHash: string, deployState: DeployState) {.base.} = raise newException(ValueError, "No implementation available") +method onOwnerTokenDeployStateChanged*(self: AccessInterface, communityId: string, chainId: int, transactionHash: string, deployState: DeployState) {.base.} = + raise newException(ValueError, "No implementation available") + +method onOwnerTokenDeployStarted*(self: AccessInterface, communityId: string, chainId: int, transactionHash: string) {.base.} = + raise newException(ValueError, "No implementation available") + method onRemoteDestructStateChanged*(self: AccessInterface, communityId: string, tokenName: string, chainId: int, transactionHash: string, status: ContractTransactionStatus) {.base.} = raise newException(ValueError, "No implementation available") diff --git a/src/app/modules/main/communities/tokens/models/token_model.nim b/src/app/modules/main/communities/tokens/models/token_model.nim index 76b1f193d6..bc5901eff5 100644 --- a/src/app/modules/main/communities/tokens/models/token_model.nim +++ b/src/app/modules/main/communities/tokens/models/token_model.nim @@ -26,10 +26,12 @@ type ChainIcon TokenOwnersModel AccountName + AccountAddress RemainingSupply Decimals BurnState RemotelyDestructState + PrivilegesLevel QtObject: type TokenModel* = ref object of QAbstractListModel @@ -55,6 +57,15 @@ QtObject: self.dataChanged(index, index, @[ModelRole.DeployState.int]) return + proc updateAddress*(self: TokenModel, chainId: int, oldContractAddress: string, newContractAddress: string) = + for i in 0 ..< self.items.len: + if((self.items[i].tokenDto.address == oldContractAddress) and (self.items[i].tokenDto.chainId == chainId)): + self.items[i].tokenDto.address = newContractAddress + let index = self.createIndex(i, 0, nil) + defer: index.delete + self.dataChanged(index, index, @[ModelRole.TokenAddress.int]) + return + proc updateBurnState*(self: TokenModel, chainId: int, contractAddress: string, burnState: ContractTransactionStatus) = for i in 0 ..< self.items.len: if((self.items[i].tokenDto.address == contractAddress) and (self.items[i].tokenDto.chainId == chainId)): @@ -166,10 +177,12 @@ QtObject: ModelRole.ChainIcon.int:"chainIcon", ModelRole.TokenOwnersModel.int:"tokenOwnersModel", ModelRole.AccountName.int:"accountName", + ModelRole.AccountAddress.int:"accountAddress", ModelRole.RemainingSupply.int:"remainingSupply", ModelRole.Decimals.int:"decimals", ModelRole.BurnState.int:"burnState", ModelRole.RemotelyDestructState.int:"remotelyDestructState", + ModelRole.PrivilegesLevel.int:"privilegesLevel" }.toTable method data(self: TokenModel, index: QModelIndex, role: int): QVariant = @@ -215,6 +228,8 @@ QtObject: result = newQVariant(item.tokenOwnersModel) of ModelRole.AccountName: result = newQVariant(item.accountName) + of ModelRole.AccountAddress: + result = newQVariant(item.tokenDto.deployer) of ModelRole.RemainingSupply: result = newQVariant(supplyByType(item.remainingSupply, item.tokenDto.tokenType)) of ModelRole.Decimals: @@ -224,6 +239,8 @@ QtObject: of ModelRole.RemotelyDestructState: let destructStatus = if len(item.remoteDestructedAddresses) > 0: ContractTransactionStatus.InProgress.int else: ContractTransactionStatus.Completed.int result = newQVariant(destructStatus) + of ModelRole.PrivilegesLevel: + result = newQVariant(item.tokenDto.privilegesLevel.int) proc `$`*(self: TokenModel): string = for i in 0 ..< self.items.len: diff --git a/src/app/modules/main/communities/tokens/module.nim b/src/app/modules/main/communities/tokens/module.nim index 64ce824297..6a6737f68a 100644 --- a/src/app/modules/main/communities/tokens/module.nim +++ b/src/app/modules/main/communities/tokens/module.nim @@ -3,6 +3,7 @@ import NimQml, json, stint, strutils, chronicles import ../../../../../app_service/service/community_tokens/service as community_tokens_service import ../../../../../app_service/service/transaction/service as transaction_service import ../../../../../app_service/service/network/service as networks_service +import ../../../../../app_service/service/community/service as community_service import ../../../../../app_service/service/community/dto/community import ../../../../../app_service/service/accounts/utils as utl import ../../../../../app_service/common/conversion @@ -22,6 +23,7 @@ type Airdrop = 2 SelfDestruct = 3 Burn = 4 + DeployOwnerToken = 5 type Module* = ref object of io_interface.AccessInterface @@ -42,18 +44,23 @@ type tempContractAction: ContractAction tempContractUniqueKey: string tempAmount: Uint256 + tempOwnerDeploymentParams: DeploymentParameters + tempMasterDeploymentParams: DeploymentParameters + tempOwnerTokenMetadata: CommunityTokensMetadataDto + tempMasterTokenMetadata: CommunityTokensMetadataDto proc newCommunityTokensModule*( parent: parent_interface.AccessInterface, events: EventEmitter, communityTokensService: community_tokens_service.Service, transactionService: transaction_service.Service, - networksService: networks_service.Service): Module = + networksService: networks_service.Service, + communityService: community_service.Service): Module = result = Module() result.parent = parent result.view = newView(result) result.viewVariant = newQVariant(result.view) - result.controller = controller.newCommunityTokensController(result, events, communityTokensService, transactionService, networksService) + result.controller = controller.newCommunityTokensController(result, events, communityTokensService, transactionService, networksService, communityService) method delete*(self: Module) = self.view.delete @@ -151,6 +158,13 @@ method burnTokens*(self: Module, communityId: string, contractUniqueKey: string, method deployCollectibles*(self: Module, communityId: string, fromAddress: string, name: string, symbol: string, description: string, supply: float64, infiniteSupply: bool, transferable: bool, selfDestruct: bool, chainId: int, imageCropInfoJson: string) = + let ownerToken = self.controller.getOwnerToken(communityId) + let masterToken = self.controller.getMasterToken(communityId) + + if not (ownerToken.address != "" and ownerToken.deployState == DeployState.Deployed and masterToken.address != "" and masterToken.deployState == DeployState.Deployed): + error "Owner token and master token not deployed" + return + self.tempAddressFrom = fromAddress self.tempCommunityId = communityId self.tempChainId = chainId @@ -161,12 +175,31 @@ method deployCollectibles*(self: Module, communityId: string, fromAddress: strin self.tempDeploymentParams.transferable = transferable self.tempDeploymentParams.remoteSelfDestruct = selfDestruct self.tempDeploymentParams.tokenUri = utl.changeCommunityKeyCompression(communityId) & "/" + self.tempDeploymentParams.ownerTokenAddress = ownerToken.address + self.tempDeploymentParams.masterTokenAddress = masterToken.address self.tempTokenMetadata.tokenType = TokenType.ERC721 self.tempTokenMetadata.description = description self.tempTokenImageCropInfoJson = imageCropInfoJson self.tempContractAction = ContractAction.Deploy self.authenticate() +method deployOwnerToken*(self: Module, communityId: string, fromAddress: string, ownerName: string, ownerSymbol: string, ownerDescription: string, + masterName: string, masterSymbol: string, masterDescription: string, chainId: int, imageCropInfoJson: string) = + self.tempAddressFrom = fromAddress + self.tempCommunityId = communityId + self.tempChainId = chainId + let communityDto = self.controller.getCommunityById(communityId) + let commName = communityDto.name + self.tempOwnerDeploymentParams = DeploymentParameters(name: "Owner-" & commName, symbol: "OWN" & commName[0 .. 2].toUpper, supply: stint.u256("1"), infiniteSupply: false, transferable: true, remoteSelfDestruct: false, tokenUri: utl.changeCommunityKeyCompression(communityId) & "/") + self.tempMasterDeploymentParams = DeploymentParameters(name: "TMaster-" & commName, symbol: "TM" & commName[0 .. 2].toUpper, infiniteSupply: true, transferable: false, remoteSelfDestruct: true, tokenUri: utl.changeCommunityKeyCompression(communityId) & "/") + self.tempOwnerTokenMetadata.description = ownerDescription + self.tempOwnerTokenMetadata.tokenType = TokenType.ERC721 + self.tempMasterTokenMetadata.description = masterDescription + self.tempMasterTokenMetadata.tokenType = TokenType.ERC721 + self.tempTokenImageCropInfoJson = imageCropInfoJson + self.tempContractAction = ContractAction.DeployOwnerToken + self.authenticate() + method deployAssets*(self: Module, communityId: string, fromAddress: string, name: string, symbol: string, description: string, supply: float64, infiniteSupply: bool, decimals: int, chainId: int, imageCropInfoJson: string) = self.tempAddressFrom = fromAddress @@ -201,6 +234,11 @@ method onUserAuthenticated*(self: Module, password: string) = self.controller.selfDestructCollectibles(self.tempCommunityId, password, self.tempWalletAndAmountList, self.tempContractUniqueKey) elif self.tempContractAction == ContractAction.Burn: self.controller.burnTokens(self.tempCommunityId, password, self.tempContractUniqueKey, self.tempAmount) + elif self.tempContractAction == ContractAction.DeployOwnerToken: + self.controller.deployOwnerContracts(self.tempCommunityId, self.tempAddressFrom, password, + self.tempOwnerDeploymentParams, self.tempOwnerTokenMetadata, + self.tempMasterDeploymentParams, self.tempMasterTokenMetadata, + self.tempTokenImageCropInfoJson, self.tempChainId) method onDeployFeeComputed*(self: Module, ethCurrency: CurrencyAmount, fiatCurrency: CurrencyAmount, errorCode: ComputeFeeErrorCode) = self.view.updateDeployFee(ethCurrency, fiatCurrency, errorCode.int) @@ -214,8 +252,11 @@ method onAirdropFeesComputed*(self: Module, args: AirdropFeesArgs) = method onBurnFeeComputed*(self: Module, ethCurrency: CurrencyAmount, fiatCurrency: CurrencyAmount, errorCode: ComputeFeeErrorCode) = self.view.updateBurnFee(ethCurrency, fiatCurrency, errorCode.int) -method computeDeployFee*(self: Module, chainId: int, accountAddress: string, tokenType: TokenType) = - self.controller.computeDeployFee(chainId, accountAddress, tokenType) +method computeDeployFee*(self: Module, chainId: int, accountAddress: string, tokenType: TokenType, isOwnerDeployment: bool) = + if isOwnerDeployment: + self.controller.computeDeployOwnerContractsFee(chainId, accountAddress) + else: + self.controller.computeDeployFee(chainId, accountAddress, tokenType) method computeSelfDestructFee*(self: Module, collectiblesToBurnJsonString: string, contractUniqueKey: string) = let walletAndAmountList = self.getWalletAndAmountListFromJson(collectiblesToBurnJsonString) @@ -237,6 +278,14 @@ method onCommunityTokenDeployStateChanged*(self: Module, communityId: string, ch let url = self.createUrl(chainId, transactionHash) self.view.emitDeploymentStateChanged(communityId, deployState.int, url) +method onOwnerTokenDeployStateChanged*(self: Module, communityId: string, chainId: int, transactionHash: string, deployState: DeployState) = + let url = self.createUrl(chainId, transactionHash) + self.view.emitOwnerTokenDeploymentStateChanged(communityId, deployState.int, url) + +method onOwnerTokenDeployStarted*(self: Module, communityId: string, chainId: int, transactionHash: string) = + let url = self.createUrl(chainId, transactionHash) + self.view.emitOwnerTokenDeploymentStarted(communityId, url) + method onRemoteDestructStateChanged*(self: Module, communityId: string, tokenName: string, chainId: int, transactionHash: string, status: ContractTransactionStatus) = let url = self.createUrl(chainId, transactionHash) self.view.emitRemoteDestructStateChanged(communityId, tokenName, status.int, url) diff --git a/src/app/modules/main/communities/tokens/view.nim b/src/app/modules/main/communities/tokens/view.nim index 62e4551d02..be0a4bc859 100644 --- a/src/app/modules/main/communities/tokens/view.nim +++ b/src/app/modules/main/communities/tokens/view.nim @@ -27,6 +27,9 @@ QtObject: proc deployAssets*(self: View, communityId: string, fromAddress: string, name: string, symbol: string, description: string, supply: float, infiniteSupply: bool, decimals: int, chainId: int, imageCropInfoJson: string) {.slot.} = self.communityTokensModule.deployAssets(communityId, fromAddress, name, symbol, description, supply, infiniteSupply, decimals, chainId, imageCropInfoJson) + proc deployOwnerToken*(self:View, communityId: string, fromAddress: string, ownerName: string, ownerSymbol: string, ownerDescription: string, masterName: string, masterSymbol: string, masterDescription: string, chainId: int, imageCropInfoJson: string) {.slot.} = + self.communityTokensModule.deployOwnerToken(communityId, fromAddress, ownerName, ownerSymbol, ownerDescription, masterName, masterSymbol, masterDescription, chainId, imageCropInfoJson) + proc removeCommunityToken*(self: View, communityId: string, chainId: int, address: string) {.slot.} = self.communityTokensModule.removeCommunityToken(communityId, chainId, address) @@ -47,8 +50,8 @@ QtObject: proc airdropFeesUpdated*(self: View, json: string) {.signal.} proc burnFeeUpdated*(self: View, ethCurrency: QVariant, fiatCurrency: QVariant, errorCode: int) {.signal.} - proc computeDeployFee*(self: View, chainId: int, accountAddress: string, tokenType: int) {.slot.} = - self.communityTokensModule.computeDeployFee(chainId, accountAddress, intToEnum(tokenType, TokenType.Unknown)) + proc computeDeployFee*(self: View, chainId: int, accountAddress: string, tokenType: int, isOwnerDeployment: bool) {.slot.} = + self.communityTokensModule.computeDeployFee(chainId, accountAddress, intToEnum(tokenType, TokenType.Unknown), isOwnerDeployment) proc computeSelfDestructFee*(self: View, collectiblesToBurnJsonString: string, contractUniqueKey: string) {.slot.} = self.communityTokensModule.computeSelfDestructFee(collectiblesToBurnJsonString, contractUniqueKey) @@ -83,3 +86,11 @@ QtObject: proc airdropStateChanged*(self: View, communityId: string, tokenName: string, chainName: string, status: int, url: string) {.signal.} proc emitAirdropStateChanged*(self: View, communityId: string, tokenName: string, chainName: string, status: int, url: string) = self.airdropStateChanged(communityId, tokenName, chainName, status, url) + + proc ownerTokenDeploymentStarted*(self: View, communityId: string, url: string) {.signal.} + proc emitOwnerTokenDeploymentStarted*(self: View, communityId: string, url: string) = + self.ownerTokenDeploymentStarted(communityId, url) + + proc ownerTokenDeploymentStateChanged*(self: View, communityId: string, status: int, url: string) {.signal.} + proc emitOwnerTokenDeploymentStateChanged*(self: View, communityId: string, status: int, url: string) = + self.ownerTokenDeploymentStateChanged(communityId, status, url) \ No newline at end of file diff --git a/src/app/modules/main/controller.nim b/src/app/modules/main/controller.nim index c858f2d052..8def4a132a 100644 --- a/src/app/modules/main/controller.nim +++ b/src/app/modules/main/controller.nim @@ -342,10 +342,18 @@ proc init*(self: Controller) = let args = CommunityTokenDeploymentArgs(e) self.delegate.onCommunityTokenDeploymentStarted(args.communityToken) + self.events.on(SIGNAL_OWNER_TOKEN_DEPLOYMENT_STARTED) do(e: Args): + let args = OwnerTokenDeploymentArgs(e) + self.delegate.onOwnerTokensDeploymentStarted(args.ownerToken, args.masterToken) + self.events.on(SIGNAL_COMMUNITY_TOKEN_DEPLOY_STATUS) do(e: Args): let args = CommunityTokenDeployedStatusArgs(e) self.delegate.onCommunityTokenDeployStateChanged(args.communityId, args.chainId, args.contractAddress, args.deployState) + self.events.on(SIGNAL_OWNER_TOKEN_DEPLOY_STATUS) do(e: Args): + let args = OwnerTokenDeployedStatusArgs(e) + self.delegate.onOwnerTokenDeployStateChanged(args.communityId, args.chainId, args.ownerContractAddress, args.masterContractAddress, args.deployState) + self.events.on(SIGNAL_COMMUNITY_TOKEN_REMOVED) do(e: Args): let args = CommunityTokenRemovedArgs(e) self.delegate.onCommunityTokenRemoved(args.communityId, args.chainId, args.contractAddress) @@ -499,8 +507,8 @@ proc getCommunityTokens*(self: Controller, communityId: string): seq[CommunityTo proc getCommunityTokenOwners*(self: Controller, communityId: string, chainId: int, contractAddress: string): seq[CollectibleOwner] = return self.communityTokensService.getCommunityTokenOwners(communityId, chainId, contractAddress) -proc getCommunityTokenOwnerName*(self: Controller, chainId: int, contractAddress: string): string = - return self.communityTokensService.contractOwnerName(chainId, contractAddress) +proc getCommunityTokenOwnerName*(self: Controller, contractOwnerAddress: string): string = + return self.communityTokensService.contractOwnerName(contractOwnerAddress) proc getCommunityTokenBurnState*(self: Controller, chainId: int, contractAddress: string): ContractTransactionStatus = return self.communityTokensService.getCommunityTokenBurnState(chainId, contractAddress) diff --git a/src/app/modules/main/io_interface.nim b/src/app/modules/main/io_interface.nim index bffd56ab0c..dd5c60e48e 100644 --- a/src/app/modules/main/io_interface.nim +++ b/src/app/modules/main/io_interface.nim @@ -291,12 +291,18 @@ method onSharedKeycarModuleKeycardSyncPurposeTerminated*(self: AccessInterface, method onCommunityTokenDeploymentStarted*(self: AccessInterface, communityToken: CommunityTokenDto) {.base.} = raise newException(ValueError, "No implementation available") +method onOwnerTokensDeploymentStarted*(self: AccessInterface, ownerToken: CommunityTokenDto, masterToken: CommunityTokenDto) {.base.} = + raise newException(ValueError, "No implementation available") + method onCommunityTokenOwnersFetched*(self: AccessInterface, communityId: string, chainId: int, contractAddress: string, owners: seq[CollectibleOwner]) {.base.} = raise newException(ValueError, "No implementation available") method onCommunityTokenDeployStateChanged*(self: AccessInterface, communityId: string, chainId: int, contractAddress: string, deployState: DeployState) {.base.} = raise newException(ValueError, "No implementation available") +method onOwnerTokenDeployStateChanged*(self: AccessInterface, communityId: string, chainId: int, ownerContractAddress: string, masterContractAddress: string, deployState: DeployState) {.base.} = + raise newException(ValueError, "No implementation available") + method onCommunityTokenSupplyChanged*(self: AccessInterface, communityId: string, chainId: int, contractAddress: string, supply: Uint256, remainingSupply: Uint256, destructedAmount: Uint256) {.base.} = raise newException(ValueError, "No implementation available") diff --git a/src/app/modules/main/module.nim b/src/app/modules/main/module.nim index e352530435..12cca0a51d 100644 --- a/src/app/modules/main/module.nim +++ b/src/app/modules/main/module.nim @@ -245,7 +245,7 @@ method delete*[T](self: Module[T]) = proc createTokenItem[T](self: Module[T], tokenDto: CommunityTokenDto) : TokenItem = let network = self.controller.getNetwork(tokenDto.chainId) let tokenOwners = self.controller.getCommunityTokenOwners(tokenDto.communityId, tokenDto.chainId, tokenDto.address) - let ownerAddressName = self.controller.getCommunityTokenOwnerName(tokenDto.chainId, tokenDto.address) + let ownerAddressName = if len(tokenDto.deployer) > 0: self.controller.getCommunityTokenOwnerName(tokenDto.deployer) else: "" let remainingSupply = if tokenDto.infiniteSupply: stint.parse("0", Uint256) else: self.controller.getRemainingSupply(tokenDto.chainId, tokenDto.address) let burnState = self.controller.getCommunityTokenBurnState(tokenDto.chainId, tokenDto.address) let remoteDestructedAddresses = self.controller.getRemoteDestructedAddresses(tokenDto.chainId, tokenDto.address) @@ -1049,6 +1049,12 @@ method onCommunityTokenDeploymentStarted*[T](self: Module[T], communityToken: Co if item.id != "": item.appendCommunityToken(self.createTokenItem(communityToken)) +method onOwnerTokensDeploymentStarted*[T](self: Module[T], ownerToken: CommunityTokenDto, masterToken: CommunityTokenDto) = + let item = self.view.model().getItemById(ownerToken.communityId) + if item.id != "": + item.appendCommunityToken(self.createTokenItem(ownerToken)) + item.appendCommunityToken(self.createTokenItem(masterToken)) + method onCommunityTokenRemoved*[T](self: Module[T], communityId: string, chainId: int, address: string) = let item = self.view.model().getItemById(communityId) if item.id != "": @@ -1064,6 +1070,15 @@ method onCommunityTokenDeployStateChanged*[T](self: Module[T], communityId: stri if item.id != "": item.updateCommunityTokenDeployState(chainId, contractAddress, deployState) +method onOwnerTokenDeployStateChanged*[T](self: Module[T], communityId: string, chainId: int, ownerContractAddress: string, masterContractAddress: string, deployState: DeployState) = + let item = self.view.model().getItemById(communityId) + if item.id != "": + # update temporary master contract address first + item.updateCommunityTokenAddress(chainId, temporaryMasterContractAddress(ownerContractAddress), masterContractAddress) + # then update states + item.updateCommunityTokenDeployState(chainId, ownerContractAddress, deployState) + item.updateCommunityTokenDeployState(chainId, masterContractAddress, deployState) + method onCommunityTokenSupplyChanged*[T](self: Module[T], communityId: string, chainId: int, contractAddress: string, supply: Uint256, remainingSupply: Uint256, destructedAmount: Uint256) = let item = self.view.model().getItemById(communityId) if item.id != "": diff --git a/src/app/modules/shared_models/section_item.nim b/src/app/modules/shared_models/section_item.nim index fa927937df..b55d444cf8 100644 --- a/src/app/modules/shared_models/section_item.nim +++ b/src/app/modules/shared_models/section_item.nim @@ -338,6 +338,9 @@ proc removeCommunityToken*(self: SectionItem, chainId: int, contractAddress: str proc updateCommunityTokenDeployState*(self: SectionItem, chainId: int, contractAddress: string, deployState: DeployState) {.inline.} = self.communityTokensModel.updateDeployState(chainId, contractAddress, deployState) +proc updateCommunityTokenAddress*(self: SectionItem, chainId: int, oldContractAddress: string, newContractAddress: string) {.inline.} = + self.communityTokensModel.updateAddress(chainId, oldContractAddress, newContractAddress) + proc updateCommunityTokenSupply*(self: SectionItem, chainId: int, contractAddress: string, supply: Uint256, destructedAmount: Uint256) {.inline.} = self.communityTokensModel.updateSupply(chainId, contractAddress, supply, destructedAmount) diff --git a/src/app_service/service/community_tokens/async_tasks.nim b/src/app_service/service/community_tokens/async_tasks.nim index 4ce57cd95d..62005d1c3d 100644 --- a/src/app_service/service/community_tokens/async_tasks.nim +++ b/src/app_service/service/community_tokens/async_tasks.nim @@ -17,6 +17,29 @@ proc tableToJsonArray[A, B](t: var Table[A, B]): JsonNode = }) return data +type + AsyncDeployOwnerContractsFeesArg = ref object of QObjectTaskArg + chainId: int + +const asyncGetDeployOwnerContractsFeesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} = + let arg = decode[AsyncDeployOwnerContractsFeesArg](argEncoded) + try: + var gasTable: Table[ContractTuple, int] # gas per contract + var feeTable: Table[int, SuggestedFeesDto] # fees for chain + let response = eth.suggestedFees(arg.chainId).result + feeTable[arg.chainId] = response.toSuggestedFeesDto() + let deployGas = community_tokens.deployOwnerTokenEstimate().result.getInt + gasTable[(arg.chainId, "")] = deployGas + arg.finish(%* { + "feeTable": tableToJsonArray(feeTable), + "gasTable": tableToJsonArray(gasTable), + "error": "", + }) + except Exception as e: + arg.finish(%* { + "error": e.msg, + }) + type AsyncGetDeployFeesArg = ref object of QObjectTaskArg chainId: int @@ -47,6 +70,7 @@ type chainId: int contractAddress: string tokenIds: seq[UInt256] + addressFrom: string const asyncGetRemoteBurnFeesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} = let arg = decode[AsyncGetRemoteBurnFees](argEncoded) @@ -54,7 +78,7 @@ const asyncGetRemoteBurnFeesTask: Task = proc(argEncoded: string) {.gcsafe, nimc var gasTable: Table[ContractTuple, int] # gas per contract var feeTable: Table[int, SuggestedFeesDto] # fees for chain let fee = eth.suggestedFees(arg.chainId).result.toSuggestedFeesDto() - let burnGas = community_tokens.estimateRemoteBurn(arg.chainId, arg.contractAddress, arg.tokenIds).result.getInt + let burnGas = community_tokens.estimateRemoteBurn(arg.chainId, arg.contractAddress, arg.addressFrom, arg.tokenIds).result.getInt feeTable[arg.chainId] = fee gasTable[(arg.chainId, arg.contractAddress)] = burnGas arg.finish(%* { @@ -71,6 +95,7 @@ type chainId: int contractAddress: string amount: Uint256 + addressFrom: string const asyncGetBurnFeesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} = let arg = decode[AsyncGetBurnFees](argEncoded) @@ -78,7 +103,7 @@ const asyncGetBurnFeesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} var gasTable: Table[ContractTuple, int] # gas per contract var feeTable: Table[int, SuggestedFeesDto] # fees for chain let fee = eth.suggestedFees(arg.chainId).result.toSuggestedFeesDto() - let burnGas = community_tokens.estimateBurn(arg.chainId, arg.contractAddress, arg.amount).result.getInt + let burnGas = community_tokens.estimateBurn(arg.chainId, arg.contractAddress, arg.addressFrom, arg.amount).result.getInt feeTable[arg.chainId] = fee gasTable[(arg.chainId, arg.contractAddress)] = burnGas arg.finish(%* { @@ -109,7 +134,7 @@ const asyncGetMintFeesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} # get gas for smart contract let gas = community_tokens.estimateMintTokens(chainId, - collectibleAndAmount.communityToken.address, + collectibleAndAmount.communityToken.address, collectibleAndAmount.communityToken.deployer, arg.walletAddresses, collectibleAndAmount.amount).result.getInt gasTable[(chainId, collectibleAndAmount.communityToken.address)] = gas arg.finish(%* { @@ -152,4 +177,4 @@ const fetchCollectibleOwnersTaskArg: Task = proc(argEncoded: string) {.gcsafe, n "result": "", "error": e.msg } - arg.finish(output) \ No newline at end of file + arg.finish(output) diff --git a/src/app_service/service/community_tokens/dto/community_token.nim b/src/app_service/service/community_tokens/dto/community_token.nim index 17eb3a49fb..8ca4c55977 100644 --- a/src/app_service/service/community_tokens/dto/community_token.nim +++ b/src/app_service/service/community_tokens/dto/community_token.nim @@ -10,6 +10,13 @@ type InProgress, Deployed +# determines what is the type of the token: owner, master or normal community contract +type + PrivilegesLevel* {.pure.} = enum + Owner, + Master, + Community + type CommunityTokenDto* = object tokenType*: TokenType @@ -27,6 +34,8 @@ type deployState*: DeployState image*: string decimals*: int + deployer*: string + privilegesLevel*: PrivilegesLevel proc toJsonNode*(self: CommunityTokenDto): JsonNode = result = %* { @@ -44,7 +53,9 @@ proc toJsonNode*(self: CommunityTokenDto): JsonNode = "chainId": self.chainId, "deployState": self.deployState.int, "image": self.image, - "decimals": self.decimals + "decimals": self.decimals, + "deployer": self.deployer, + "privilegesLevel": self.privilegesLevel.int, } proc toCommunityTokenDto*(jsonObj: JsonNode): CommunityTokenDto = @@ -70,6 +81,10 @@ proc toCommunityTokenDto*(jsonObj: JsonNode): CommunityTokenDto = result.deployState = intToEnum(deployStateInt, DeployState.Failed) discard jsonObj.getProp("image", result.image) discard jsonObj.getProp("decimals", result.decimals) + discard jsonObj.getProp("deployer", result.deployer) + var privilegesLevelInt: int + discard jsonObj.getProp("privilegesLevel", privilegesLevelInt) + result.privilegesLevel = intToEnum(privilegesLevelInt, PrivilegesLevel.Community) proc parseCommunityTokens*(response: RpcResponse[JsonNode]): seq[CommunityTokenDto] = result = map(response.result.getElems(), diff --git a/src/app_service/service/community_tokens/dto/deployment_parameters.nim b/src/app_service/service/community_tokens/dto/deployment_parameters.nim index 5467bf4c89..db4d616ba6 100644 --- a/src/app_service/service/community_tokens/dto/deployment_parameters.nim +++ b/src/app_service/service/community_tokens/dto/deployment_parameters.nim @@ -10,6 +10,8 @@ type remoteSelfDestruct*: bool tokenUri*: string decimals*: int + ownerTokenAddress*: string + masterTokenAddress*: string proc `%`*(x: DeploymentParameters): JsonNode = result = newJobject() @@ -21,5 +23,5 @@ proc `%`*(x: DeploymentParameters): JsonNode = result["remoteSelfDestruct"] = %x.remoteSelfDestruct result["tokenUri"] = %x.tokenUri result["decimals"] = %x.decimals - - + result["ownerTokenAddress"] = %x.ownerTokenAddress + result["masterTokenAddress"] = %x.masterTokenAddress \ No newline at end of file diff --git a/src/app_service/service/community_tokens/service.nim b/src/app_service/service/community_tokens/service.nim index d6689b3cd1..f8bfee3be2 100644 --- a/src/app_service/service/community_tokens/service.nim +++ b/src/app_service/service/community_tokens/service.nim @@ -72,11 +72,26 @@ type transactionHash*: string deployState*: DeployState +type + OwnerTokenDeployedStatusArgs* = ref object of Args + communityId*: string + chainId*: int + ownerContractAddress*: string + masterContractAddress*: string + transactionHash*: string + deployState*: DeployState + type CommunityTokenDeploymentArgs* = ref object of Args communityToken*: CommunityTokenDto transactionHash*: string +type + OwnerTokenDeploymentArgs* = ref object of Args + ownerToken*: CommunityTokenDto + masterToken*: CommunityTokenDto + transactionHash*: string + type CommunityTokenRemovedArgs* = ref object of Args communityId*: string @@ -109,6 +124,28 @@ proc `%`*(self: RemoteDestroyTransactionDetails): JsonNode = "addresses": self.addresses } +type + OwnerTokenDeploymentTransactionDetails* = object + ownerToken*: ContractTuple + masterToken*: ContractTuple + communityId*: string + +proc `%`*(self: OwnerTokenDeploymentTransactionDetails): JsonNode = + result = %* { + "ownerToken": %self.ownerToken, + "masterToken": %self.masterToken, + "communityId": self.communityId + } + +proc toOwnerTokenDeploymentTransactionDetails*(jsonObj: JsonNode): OwnerTokenDeploymentTransactionDetails = + result = OwnerTokenDeploymentTransactionDetails() + try: + result.ownerToken = (jsonObj["ownerToken"]["chainId"].getInt, jsonObj["ownerToken"]["address"].getStr) + result.masterToken = (jsonObj["masterToken"]["chainId"].getInt, jsonObj["masterToken"]["address"].getStr) + result.communityId = jsonObj["communityId"].getStr + except Exception as e: + error "Error parsing OwnerTokenDeploymentTransactionDetails json", msg=e.msg + proc toRemoteDestroyTransactionDetails*(json: JsonNode): RemoteDestroyTransactionDetails = return RemoteDestroyTransactionDetails(chainId: json["chainId"].getInt, contractAddress: json["contractAddress"].getStr, addresses: to(json["addresses"], seq[string])) @@ -175,7 +212,10 @@ const SIGNAL_BURN_STATUS* = "communityTokenBurnStatus" const SIGNAL_AIRDROP_STATUS* = "airdropStatus" const SIGNAL_REMOVE_COMMUNITY_TOKEN_FAILED* = "removeCommunityTokenFailed" const SIGNAL_COMMUNITY_TOKEN_REMOVED* = "communityTokenRemoved" +const SIGNAL_OWNER_TOKEN_DEPLOY_STATUS* = "ownerTokenDeployStatus" +const SIGNAL_OWNER_TOKEN_DEPLOYMENT_STARTED* = "ownerTokenDeploymentStarted" +const SIGNAL_DEPLOY_OWNER_TOKEN* = "deployOwnerToken" QtObject: type @@ -197,6 +237,12 @@ QtObject: tempGasTable: Table[ContractTuple, int] # gas per contract, filled during gas computation, used during operation (deployment, mint, burn) tempTokensAndAmounts: seq[CommunityTokenAndAmount] + tempDeploymentChainId: int + tempDeploymentCommunityId: string + tempDeploymentParams: DeploymentParameters + tempDeploymentCroppedImageJson: string + tempDeploymentAddressFrom: string + # Forward declaration proc fetchAllTokenOwners*(self: Service) proc getCommunityTokenOwners*(self: Service, communityId: string, chainId: int, contractAddress: string): seq[CollectibleOwner] @@ -258,6 +304,50 @@ QtObject: except Exception as e: error "Error processing Collectible deployment pending transaction event", msg=e.msg, receivedData + self.events.on(PendingTransactionTypeDto.DeployOwnerToken.event) do(e: Args): + var receivedData = TransactionMinedArgs(e) + try: + let deployState = if receivedData.success: DeployState.Deployed else: DeployState.Failed + let ownerTransactionDetails = toOwnerTokenDeploymentTransactionDetails(parseJson(receivedData.data)) + if not receivedData.success: + error "Owner contracts not deployed", chainId=ownerTransactionDetails.ownerToken.chainId, address=ownerTransactionDetails.ownerToken.address + var masterContractAddress = ownerTransactionDetails.masterToken.address + + try: + # get master token address from transaction logs + if receivedData.success: + let response = tokens_backend.getMasterTokenContractAddressFromHash(ownerTransactionDetails.masterToken.chainId, receivedData.transactionHash) + masterContractAddress = response.result.getStr() + if masterContractAddress == "": + raise newException(RpcException, "master contract address is empty") + + # update master token address + discard updateCommunityTokenAddress(ownerTransactionDetails.masterToken.chainId, ownerTransactionDetails.masterToken.address, masterContractAddress) + #update db state for owner and master token + discard updateCommunityTokenState(ownerTransactionDetails.ownerToken.chainId, ownerTransactionDetails.ownerToken.address, deployState) + discard updateCommunityTokenState(ownerTransactionDetails.masterToken.chainId, masterContractAddress, deployState) + # now add owner token to community and publish update + var response = tokens_backend.addCommunityToken(ownerTransactionDetails.communityId, ownerTransactionDetails.ownerToken.chainId, ownerTransactionDetails.ownerToken.address) + if response.error != nil: + let error = Json.decode($response.error, RpcError) + raise newException(RpcException, "error adding owner token: " & error.message) + + # now add master token to community and publish update + response = tokens_backend.addCommunityToken(ownerTransactionDetails.communityId, ownerTransactionDetails.masterToken.chainId, masterContractAddress) + if response.error != nil: + let error = Json.decode($response.error, RpcError) + raise newException(RpcException, "error adding master token: " & error.message) + except RpcException: + error "Error updating owner contracts state", message = getCurrentExceptionMsg() + + let data = OwnerTokenDeployedStatusArgs(communityId: ownerTransactionDetails.communityId, chainId: ownerTransactionDetails.ownerToken.chainId, + ownerContractAddress: ownerTransactionDetails.ownerToken.address, + masterContractAddress: masterContractAddress, + deployState: deployState, + transactionHash: receivedData.transactionHash) + self.events.emit(SIGNAL_OWNER_TOKEN_DEPLOY_STATUS, data) + except Exception as e: + error "Error processing Collectible deployment pending transaction event", msg=e.msg, receivedData self.events.on(PendingTransactionTypeDto.AirdropCommunityToken.event) do(e: Args): let receivedData = TransactionMinedArgs(e) @@ -316,6 +406,98 @@ QtObject: if suggestedFees.eip1559Enabled: $suggestedFees.maxPriorityFeePerGas else: "", if suggestedFees.eip1559Enabled: $suggestedFees.maxFeePerGasM else: "") + proc createCommunityToken(self: Service, deploymentParams: DeploymentParameters, tokenMetadata: CommunityTokensMetadataDto, + chainId: int, contractAddress: string, communityId: string, addressFrom: string, privilegesLevel: PrivilegesLevel): CommunityTokenDto = + result.tokenType = tokenMetadata.tokenType + result.communityId = communityId + result.address = contractAddress + result.name = deploymentParams.name + result.symbol = deploymentParams.symbol + result.description = tokenMetadata.description + result.supply = stint.parse($deploymentParams.supply, Uint256) + result.infiniteSupply = deploymentParams.infiniteSupply + result.transferable = deploymentParams.transferable + result.remoteSelfDestruct = deploymentParams.remoteSelfDestruct + result.tokenUri = deploymentParams.tokenUri + result.chainId = chainId + result.deployState = DeployState.InProgress + result.decimals = deploymentParams.decimals + result.deployer = addressFrom + result.privilegesLevel = privilegesLevel + + proc saveTokenToDbAndWatchTransaction*(self:Service, communityToken: CommunityTokenDto, croppedImageJson: string, + transactionHash: string, addressFrom: string, watchTransaction: bool) = + var croppedImage = croppedImageJson.parseJson + croppedImage{"imagePath"} = newJString(singletonInstance.utils.formatImagePath(croppedImage["imagePath"].getStr)) + + # save token to db + let communityTokenJson = tokens_backend.saveCommunityToken(communityToken, $croppedImage) + let addedCommunityToken = communityTokenJson.result.toCommunityTokenDto() + let data = CommunityTokenDeploymentArgs(communityToken: addedCommunityToken, transactionHash: transactionHash) + self.events.emit(SIGNAL_COMMUNITY_TOKEN_DEPLOYMENT_STARTED, data) + + if watchTransaction: + # observe transaction state + self.transactionService.watchTransaction( + transactionHash, + addressFrom, + addedCommunityToken.address, + $PendingTransactionTypeDto.DeployCommunityToken, + $addedCommunityToken.toJsonNode(), + addedCommunityToken.chainId, + ) + + proc temporaryMasterContractAddress*(ownerContractAddress: string): string = + return ownerContractAddress & "-master" + + proc deployOwnerContracts*(self: Service, communityId: string, addressFrom: string, password: string, + ownerDeploymentParams: DeploymentParameters, ownerTokenMetadata: CommunityTokensMetadataDto, + masterDeploymentParams: DeploymentParameters, masterTokenMetadata: CommunityTokensMetadataDto, + croppedImageJson: string, chainId: int) = + try: + let txData = self.buildTransactionDataDto(addressFrom, chainId, "") + if txData.source == parseAddress(ZERO_ADDRESS): + return + + let response = tokens_backend.deployOwnerToken(chainId, %ownerDeploymentParams, %masterDeploymentParams, %txData, password) + let ownerContractAddress = response.result["contractAddress"].getStr() + let transactionHash = response.result["transactionHash"].getStr() + debug "Deployed owner contract address ", ownerContractAddress=ownerContractAddress + debug "Deployment transaction hash ", transactionHash=transactionHash + + var ownerToken = self.createCommunityToken(ownerDeploymentParams, ownerTokenMetadata, chainId, ownerContractAddress, communityId, addressFrom, PrivilegesLevel.Owner) + var masterToken = self.createCommunityToken(masterDeploymentParams, masterTokenMetadata, chainId, temporaryMasterContractAddress(ownerContractAddress), communityId, addressFrom, PrivilegesLevel.Master) + + var croppedImage = croppedImageJson.parseJson + ownerToken.image = croppedImage{"imagePath"}.getStr + masterToken.image = croppedImage{"imagePath"}.getStr + + let ownerTokenJson = tokens_backend.saveCommunityToken(ownerToken, "") + let addedOwnerToken = ownerTokenJson.result.toCommunityTokenDto() + + let masterTokenJson = tokens_backend.saveCommunityToken(masterToken, "") + let addedMasterToken = masterTokenJson.result.toCommunityTokenDto() + + let data = OwnerTokenDeploymentArgs(ownerToken: addedOwnerToken, masterToken: addedMasterToken, transactionHash: transactionHash) + self.events.emit(SIGNAL_OWNER_TOKEN_DEPLOYMENT_STARTED, data) + + let transactionDetails = OwnerTokenDeploymentTransactionDetails(ownerToken: (chainId, addedOwnerToken.address), + masterToken: (chainId, addedMasterToken.address), communityId: addedOwnerToken.communityId) + + self.transactionService.watchTransaction( + transactionHash, + addressFrom, + addedOwnerToken.address, + $PendingTransactionTypeDto.DeployOwnerToken, + $(%transactionDetails), + chainId, + ) + except RpcException: + error "Error deploying owner contract", message = getCurrentExceptionMsg() + let data = OwnerTokenDeployedStatusArgs(communityId: communityId, + deployState: DeployState.Failed) + self.events.emit(SIGNAL_OWNER_TOKEN_DEPLOY_STATUS, data) + proc deployContract*(self: Service, communityId: string, addressFrom: string, password: string, deploymentParams: DeploymentParameters, tokenMetadata: CommunityTokensMetadataDto, croppedImageJson: string, chainId: int) = try: let txData = self.buildTransactionDataDto(addressFrom, chainId, "") @@ -337,42 +519,11 @@ QtObject: debug "Deployed contract address ", contractAddress=contractAddress debug "Deployment transaction hash ", transactionHash=transactionHash - var communityToken: CommunityTokenDto - communityToken.tokenType = tokenMetadata.tokenType - communityToken.communityId = communityId - communityToken.address = contractAddress - communityToken.name = deploymentParams.name - communityToken.symbol = deploymentParams.symbol - communityToken.description = tokenMetadata.description - communityToken.supply = stint.parse($deploymentParams.supply, Uint256) - communityToken.infiniteSupply = deploymentParams.infiniteSupply - communityToken.transferable = deploymentParams.transferable - communityToken.remoteSelfDestruct = deploymentParams.remoteSelfDestruct - communityToken.tokenUri = deploymentParams.tokenUri - communityToken.chainId = chainId - communityToken.deployState = DeployState.InProgress - communityToken.decimals = deploymentParams.decimals + var communityToken = self.createCommunityToken(deploymentParams, tokenMetadata, chainId, contractAddress, communityId, addressFrom, PrivilegesLevel.Community) - var croppedImage = croppedImageJson.parseJson - croppedImage{"imagePath"} = newJString(singletonInstance.utils.formatImagePath(croppedImage["imagePath"].getStr)) + self.saveTokenToDbAndWatchTransaction(communityToken, croppedImageJson, transactionHash, addressFrom, true) - # save token to db - let communityTokenJson = tokens_backend.saveCommunityToken(communityToken, $croppedImage) - communityToken = communityTokenJson.result.toCommunityTokenDto() - let data = CommunityTokenDeploymentArgs(communityToken: communityToken, transactionHash: transactionHash) - self.events.emit(SIGNAL_COMMUNITY_TOKEN_DEPLOYMENT_STARTED, data) - - # observe transaction state - self.transactionService.watchTransaction( - transactionHash, - addressFrom, - contractAddress, - $PendingTransactionTypeDto.DeployCommunityToken, - $communityToken.toJsonNode(), - chainId, - ) - - except RpcException as e: + except RpcException: error "Error deploying contract", message = getCurrentExceptionMsg() let data = CommunityTokenDeployedStatusArgs(communityId: communityId, deployState: DeployState.Failed) @@ -437,17 +588,9 @@ QtObject: except Exception: error "Error getting contract owner", message = getCurrentExceptionMsg() - proc contractOwner*(self: Service, chainId: int, contractAddress: string): string = + proc contractOwnerName*(self: Service, contractOwnerAddress: string): string = try: - let response = tokens_backend.contractOwner(chainId, contractAddress) - return response.result.getStr() - except RpcException: - error "Error getting contract owner", message = getCurrentExceptionMsg() - - proc contractOwnerName*(self: Service, chainId: int, contractAddress: string): string = - try: - let response = tokens_backend.contractOwner(chainId, contractAddress) - return self.walletAccountService.getAccountByAddress(response.result.getStr().toLower()).name + return self.walletAccountService.getAccountByAddress(contractOwnerAddress).name except RpcException: error "Error getting contract owner name", message = getCurrentExceptionMsg() @@ -457,6 +600,8 @@ QtObject: return stint.parse(response.result.getStr(), Uint256) except RpcException: error "Error getting remaining supply", message = getCurrentExceptionMsg() + # if there is an exception probably community token is not minted yet + return self.getCommunityToken(chainId, contractAddress).supply proc getRemoteDestructedAmount*(self: Service, chainId: int, contractAddress: string): Uint256 = try: @@ -471,7 +616,7 @@ QtObject: proc airdropTokens*(self: Service, communityId: string, password: string, collectiblesAndAmounts: seq[CommunityTokenAndAmount], walletAddresses: seq[string]) = try: for collectibleAndAmount in collectiblesAndAmounts: - let addressFrom = self.contractOwner(collectibleAndAmount.communityToken.chainId, collectibleAndAmount.communityToken.address) + let addressFrom = collectibleAndAmount.communityToken.deployer let txData = self.buildTransactionDataDto(addressFrom, collectibleAndAmount.communityToken.chainId, collectibleAndAmount.communityToken.address) if txData.source == parseAddress(ZERO_ADDRESS): return @@ -534,6 +679,20 @@ QtObject: except Exception as e: error "Error loading fees", msg = e.msg + proc computeDeployOwnerContractsFee*(self: Service, chainId: int, accountAddress: string) = + try: + self.tempAccountAddress = accountAddress + self.tempChainId = chainId + let arg = AsyncDeployOwnerContractsFeesArg( + tptr: cast[ByteAddress](asyncGetDeployOwnerContractsFeesTask), + vptr: cast[ByteAddress](self.vptr), + slot: "onDeployOwnerContractsFees", + chainId: chainId, + ) + self.threadpool.start(arg) + except Exception as e: + error "Error loading fees", msg = e.msg + proc findContractByUniqueId*(self: Service, contractUniqueKey: string): CommunityTokenDto = let allTokens = self.getAllCommunityTokens() for token in allTokens: @@ -573,7 +732,7 @@ QtObject: let tokenIds = self.getTokensToBurn(walletAndAmounts, contract) if len(tokenIds) == 0: return - let addressFrom = self.contractOwner(contract.chainId, contract.address) + let addressFrom = contract.deployer let txData = self.buildTransactionDataDto(addressFrom, contract.chainId, contract.address) debug "Remote destruct collectibles ", chainId=contract.chainId, address=contract.address, tokens=tokenIds let response = tokens_backend.remoteBurn(contract.chainId, contract.address, %txData, password, tokenIds) @@ -602,7 +761,7 @@ QtObject: proc computeSelfDestructFee*(self: Service, walletAndAmountList: seq[WalletAndAmount], contractUniqueKey: string) = try: let contract = self.findContractByUniqueId(contractUniqueKey) - self.tempAccountAddress = self.contractOwner(contract.chainId, contract.address) + self.tempAccountAddress = contract.deployer self.tempChainId = contract.chainId let tokenIds = self.getTokensToBurn(walletAndAmountList, contract) if len(tokenIds) == 0: @@ -614,7 +773,8 @@ QtObject: slot: "onSelfDestructFees", chainId: contract.chainId, contractAddress: contract.address, - tokenIds: tokenIds + tokenIds: tokenIds, + addressFrom: contract.deployer ) self.threadpool.start(arg) except Exception as e: @@ -639,7 +799,7 @@ QtObject: proc burnTokens*(self: Service, communityId: string, password: string, contractUniqueKey: string, amount: Uint256) = try: var contract = self.findContractByUniqueId(contractUniqueKey) - let addressFrom = self.contractOwner(contract.chainId, contract.address) + let addressFrom = contract.deployer let txData = self.buildTransactionDataDto(addressFrom, contract.chainId, contract.address) debug "Burn tokens ", chainId=contract.chainId, address=contract.address, amount=amount let response = tokens_backend.burn(contract.chainId, contract.address, %txData, password, amount) @@ -665,7 +825,7 @@ QtObject: proc computeBurnFee*(self: Service, contractUniqueKey: string, amount: Uint256) = try: let contract = self.findContractByUniqueId(contractUniqueKey) - self.tempAccountAddress = self.contractOwner(contract.chainId, contract.address) + self.tempAccountAddress = contract.deployer self.tempChainId = contract.chainId let arg = AsyncGetBurnFees( tptr: cast[ByteAddress](asyncGetBurnFeesTask), @@ -673,7 +833,8 @@ QtObject: slot: "onBurnFees", chainId: contract.chainId, contractAddress: contract.address, - amount: amount + amount: amount, + addressFrom: contract.deployer ) self.threadpool.start(arg) except Exception as e: @@ -754,6 +915,9 @@ QtObject: let data = self.createComputeFeeArgsWithError(getCurrentExceptionMsg()) self.events.emit(signalName, data) + proc onDeployOwnerContractsFees*(self:Service, response: string) {.slot.} = + self.parseFeeResponseAndEmitSignal(response, SIGNAL_COMPUTE_DEPLOY_FEE) + proc onSelfDestructFees*(self:Service, response: string) {.slot.} = self.parseFeeResponseAndEmitSignal(response, SIGNAL_COMPUTE_SELF_DESTRUCT_FEE) @@ -796,7 +960,7 @@ QtObject: let gasUnits = self.tempGasTable[(collectibleAndAmount.communityToken.chainId, collectibleAndAmount.communityToken.address)] let suggestedFees = self.tempFeeTable[collectibleAndAmount.communityToken.chainId] let ethValue = self.computeEthValue(gasUnits, suggestedFees) - let walletAddress = self.contractOwner(collectibleAndAmount.communityToken.chainId, collectibleAndAmount.communityToken.address) + let walletAddress = collectibleAndAmount.communityToken.deployer wholeEthCostForChainWallet[(collectibleAndAmount.communityToken.chainId, walletAddress)] = wholeEthCostForChainWallet.getOrDefault((collectibleAndAmount.communityToken.chainId, walletAddress), 0.0) + ethValue ethValuesForContracts[(collectibleAndAmount.communityToken.chainId, collectibleAndAmount.communityToken.address)] = ethValue @@ -807,7 +971,7 @@ QtObject: let contractTuple = (chainId: collectibleAndAmount.communityToken.chainId, address: collectibleAndAmount.communityToken.address) let ethValue = ethValuesForContracts[contractTuple] - let walletAddress = self.contractOwner(contractTuple.chainId, contractTuple.address) + let walletAddress = collectibleAndAmount.communityToken.deployer var balance = self.getWalletBalanceForChain(walletAddress, contractTuple.chainId) if balance < wholeEthCostForChainWallet[(contractTuple.chainId, walletAddress)]: # if wallet balance for this chain is less than the whole cost @@ -877,3 +1041,15 @@ QtObject: let allTokens = self.getAllCommunityTokens() for token in allTokens: self.fetchCommunityOwners(token) + + proc getOwnerToken*(self: Service, communityId: string): CommunityTokenDto = + let communityTokens = self.getCommunityTokens(communityId) + for token in communityTokens: + if token.privilegesLevel == PrivilegesLevel.Owner: + return token + + proc getMasterToken*(self: Service, communityId: string): CommunityTokenDto = + let communityTokens = self.getCommunityTokens(communityId) + for token in communityTokens: + if token.privilegesLevel == PrivilegesLevel.Master: + return token \ No newline at end of file diff --git a/src/app_service/service/transaction/dto.nim b/src/app_service/service/transaction/dto.nim index e54a4634f0..22fe5195cc 100644 --- a/src/app_service/service/transaction/dto.nim +++ b/src/app_service/service/transaction/dto.nim @@ -20,6 +20,7 @@ type AirdropCommunityToken = "AirdropCommunityToken" RemoteDestructCollectible = "RemoteDestructCollectible" BurnCommunityToken = "BurnCommunityToken" + DeployOwnerToken = "DeployOwnerToken" proc event*(self:PendingTransactionTypeDto):string = result = "transaction:" & $self diff --git a/src/backend/community_tokens.nim b/src/backend/community_tokens.nim index 8a89ba1eff..c29c29d1f5 100644 --- a/src/backend/community_tokens.nim +++ b/src/backend/community_tokens.nim @@ -28,7 +28,7 @@ proc getAllCommunityTokens*(): RpcResponse[JsonNode] {.raises: [Exception].} = return core.callPrivateRPC("wakuext_getAllCommunityTokens", payload) proc saveCommunityToken*(token: CommunityTokenDto, croppedImageJson: string): RpcResponse[JsonNode] {.raises: [Exception].} = - let croppedImage = newCroppedImage(croppedImageJson) + let croppedImage = if len(croppedImageJson) > 0: newCroppedImage(croppedImageJson) else: nil let payload = %* [token.toJsonNode(), croppedImage] return core.callPrivateRPC("wakuext_saveCommunityToken", payload) @@ -40,6 +40,10 @@ proc updateCommunityTokenState*(chainId: int, contractAddress: string, deploySta let payload = %* [chainId, contractAddress, deployState.int] return core.callPrivateRPC("wakuext_updateCommunityTokenState", payload) +proc updateCommunityTokenAddress*(chainId: int, oldContractAddress: string, newContractAddress: string): RpcResponse[JsonNode] {.raises: [Exception].} = + let payload = %* [chainId, oldContractAddress, newContractAddress] + return core.callPrivateRPC("wakuext_updateCommunityTokenAddress", payload) + proc updateCommunityTokenSupply*(chainId: int, contractAddress: string, supply: Uint256): RpcResponse[JsonNode] {.raises: [Exception].} = let payload = %* [chainId, contractAddress, supply.toString(10)] return core.callPrivateRPC("wakuext_updateCommunityTokenSupply", payload) @@ -48,30 +52,26 @@ proc mintTokens*(chainId: int, contractAddress: string, txData: JsonNode, passwo let payload = %* [chainId, contractAddress, txData, utils.hashPassword(password), walletAddresses, amount.toString(10)] return core.callPrivateRPC("collectibles_mintTokens", payload) -proc estimateMintTokens*(chainId: int, contractAddress: string, walletAddresses: seq[string], amount: Uint256): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId, contractAddress, walletAddresses, amount.toString(10)] +proc estimateMintTokens*(chainId: int, contractAddress: string, fromAddress: string, walletAddresses: seq[string], amount: Uint256): RpcResponse[JsonNode] {.raises: [Exception].} = + let payload = %* [chainId, contractAddress, fromAddress, walletAddresses, amount.toString(10)] return core.callPrivateRPC("collectibles_estimateMintTokens", payload) proc remoteBurn*(chainId: int, contractAddress: string, txData: JsonNode, password: string, tokenIds: seq[UInt256]): RpcResponse[JsonNode] {.raises: [Exception].} = let payload = %* [chainId, contractAddress, txData, utils.hashPassword(password), tokenIds.map(x => x.toString(10))] return core.callPrivateRPC("collectibles_remoteBurn", payload) -proc estimateRemoteBurn*(chainId: int, contractAddress: string, tokenIds: seq[UInt256]): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId, contractAddress, tokenIds.map(x => x.toString(10))] +proc estimateRemoteBurn*(chainId: int, contractAddress: string, fromAddress: string, tokenIds: seq[UInt256]): RpcResponse[JsonNode] {.raises: [Exception].} = + let payload = %* [chainId, contractAddress, fromAddress, tokenIds.map(x => x.toString(10))] return core.callPrivateRPC("collectibles_estimateRemoteBurn", payload) proc burn*(chainId: int, contractAddress: string, txData: JsonNode, password: string, amount: Uint256): RpcResponse[JsonNode] {.raises: [Exception].} = let payload = %* [chainId, contractAddress, txData, utils.hashPassword(password), amount.toString(10)] return core.callPrivateRPC("collectibles_burn", payload) -proc estimateBurn*(chainId: int, contractAddress: string, amount: Uint256): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId, contractAddress, amount.toString(10)] +proc estimateBurn*(chainId: int, contractAddress: string, fromAddress: string, amount: Uint256): RpcResponse[JsonNode] {.raises: [Exception].} = + let payload = %* [chainId, contractAddress, fromAddress, amount.toString(10)] return core.callPrivateRPC("collectibles_estimateBurn", payload) -proc contractOwner*(chainId: int, contractAddress: string): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId, contractAddress] - return core.callPrivateRPC("collectibles_contractOwner", payload) - proc remainingSupply*(chainId: int, contractAddress: string): RpcResponse[JsonNode] {.raises: [Exception].} = let payload = %* [chainId, contractAddress] return core.callPrivateRPC("collectibles_remainingSupply", payload) @@ -86,4 +86,16 @@ proc deployAssetsEstimate*(): RpcResponse[JsonNode] {.raises: [Exception].} = proc remoteDestructedAmount*(chainId: int, contractAddress: string): RpcResponse[JsonNode] {.raises: [Exception].} = let payload = %*[chainId, contractAddress] - return core.callPrivateRPC("collectibles_remoteDestructedAmount", payload) \ No newline at end of file + return core.callPrivateRPC("collectibles_remoteDestructedAmount", payload) + +proc deployOwnerTokenEstimate*(): RpcResponse[JsonNode] {.raises: [Exception].} = + let payload = %*[] + return core.callPrivateRPC("collectibles_deployOwnerTokenEstimate", payload) + +proc deployOwnerToken*(chainId: int, ownerParams: JsonNode, masterParams: JsonNode, txData: JsonNode, password: string): RpcResponse[JsonNode] {.raises: [Exception].} = + let payload = %*[chainId, ownerParams, masterParams, txData, utils.hashPassword(password)] + return core.callPrivateRPC("collectibles_deployOwnerToken", payload) + +proc getMasterTokenContractAddressFromHash*(chainId: int, transactionHash: string): RpcResponse[JsonNode] {.raises: [Exception].} = + let payload = %*[chainId, transactionHash] + return core.callPrivateRPC("collectibles_getMasterTokenContractAddressFromHash", payload) \ No newline at end of file diff --git a/ui/app/AppLayouts/Communities/panels/MintTokensSettingsPanel.qml b/ui/app/AppLayouts/Communities/panels/MintTokensSettingsPanel.qml index b28fb9ee87..60f3eb742d 100644 --- a/ui/app/AppLayouts/Communities/panels/MintTokensSettingsPanel.qml +++ b/ui/app/AppLayouts/Communities/panels/MintTokensSettingsPanel.qml @@ -793,8 +793,7 @@ StackView { token.type: model.tokenType token.burnState: model.burnState token.remotelyDestructState: model.remotelyDestructState - // TODO: Backend - //token.accountAddress: model.accountAddress + token.accountAddress: model.accountAddress } onCountChanged: { diff --git a/ui/app/AppLayouts/Communities/views/CommunitySettingsView.qml b/ui/app/AppLayouts/Communities/views/CommunitySettingsView.qml index 3009154dd5..f927ce679e 100644 --- a/ui/app/AppLayouts/Communities/views/CommunitySettingsView.qml +++ b/ui/app/AppLayouts/Communities/views/CommunitySettingsView.qml @@ -360,7 +360,7 @@ StatusSectionLayout { isFeeLoading = true communityTokensStore.computeDeployFee( - chainId, accountAddress, tokenType) + chainId, accountAddress, tokenType, !(mintPanel.isOwnerTokenDeployed && mintPanel.isTMasterTokenDeployed)) } onBurnFeesRequested: { @@ -613,22 +613,24 @@ StatusSectionLayout { StatusQUtils.ModelUtils.contains(model, "name", PermissionsHelpers.tMasterTokenNameTag + root.communityName) } - function reviewTokenDeployState(tagType, isOwner, deployState) { - const index = StatusQUtils.ModelUtils.indexOf(model, "name", tagType + root.communityName) + function reviewTokenDeployState(isOwner, deployState) { + const privileges = isOwner ? Constants.TokenPrivilegesLevel.Owner : Constants.TokenPrivilegesLevel.TMaster + const index = StatusQUtils.ModelUtils.indexOf(model, "privilegesLevel", privileges) if(index === -1) return false const token = StatusQUtils.ModelUtils.get(model, index) - // Some assertions: - if(!token.isPrivilegedToken) + if(isOwner && token.privilegesLevel !== Constants.TokenPrivilegesLevel.Owner) + return false + if(!isOwner && token.privilegesLevel !== Constants.TokenPrivilegesLevel.TMaster) return false if(token.isOwner !== isOwner) return false // Deploy state check: - return token.deployState !== deployState + return token.deployState === deployState } model: root.community.communityTokens @@ -822,6 +824,39 @@ StatusSectionLayout { Global.displayToastMessage(title, url === "" ? qsTr("Something went wrong") : qsTr("View on etherscan"), "", loading, type, url) } + + function onOwnerTokenDeploymentStateChanged(communityId, status, url) { + if (root.community.id !== communityId) + return + + if (status === Constants.ContractTransactionStatus.Completed) + { + let title1 = qsTr("%1 Owner and TokenMaster tokens minting complete").arg(community.name) + let title2 = qsTr("%1 Owner token airdropped to you").arg(community.name) + let title3 = qsTr("%1 Owner and TokenMaster permissions created").arg(community.name) + let type = Constants.ephemeralNotificationType.normal + + Global.displayToastMessage(title1, url, "", true, type, url) + Global.displayToastMessage(title2, url, "", true, type, url) + Global.displayToastMessage(title3, url, "", true, type, url) + } else if (status === Constants.ContractTransactionStatus.Failed) { + let title = qsTr("%1 Owner and TokenMaster tokens minting failed").arg(community.name) + let type = Constants.ephemeralNotificationType.normal + Global.displayToastMessage(title, url, "", true, type, url) + } + } + + function onOwnerTokenDeploymentStarted(communityId, url) { + if (root.community.id !== communityId) + return + + let title1 = qsTr("%1 Owner and TokenMaster tokens are being minted...").arg(community.name) + let title2 = qsTr("Airdropping %1 Owner token to you...").arg(community.name) + let type = Constants.ephemeralNotificationType.normal + + Global.displayToastMessage(title1, url, "", true, type, url) + Global.displayToastMessage(title2, url, "", true, type, url) + } } Connections { diff --git a/ui/imports/shared/stores/CommunityTokensStore.qml b/ui/imports/shared/stores/CommunityTokensStore.qml index df9bff6375..50a72b6daf 100644 --- a/ui/imports/shared/stores/CommunityTokensStore.qml +++ b/ui/imports/shared/stores/CommunityTokensStore.qml @@ -18,9 +18,11 @@ QtObject { signal burnFeeUpdated(var ethCurrency, var fiatCurrency, int error) signal deploymentStateChanged(string communityId, int status, string url) + signal ownerTokenDeploymentStateChanged(string communityId, int status, string url) signal remoteDestructStateChanged(string communityId, string tokenName, int status, string url) signal burnStateChanged(string communityId, string tokenName, int status, string url) signal airdropStateChanged(string communityId, string tokenName, string chainName, int status, string url) + signal ownerTokenDeploymentStarted(string communityId, string url) // Minting tokens: function deployCollectible(communityId, collectibleItem) @@ -48,11 +50,9 @@ QtObject { function deployOwnerToken(communityId, ownerToken, tMasterToken) { - // NOTE for backend team: `ownerToken` and `tMasterToken` can be used to do an assertion before the deployment process starts, since - // the objects have been created to display the token details to the user and must be the same than backend builds. - // TODO: Backend will need to check if the ownerToken or tMasterToken have a valid tokenKey, so it means a deployment retry, - // otherwise, it is a new deployment. - console.log("TODO: Backend Owner and Token Master token deployment!") + const jsonArtworkFile = Utils.getImageAndCropInfoJson(ownerToken.artworkSource, ownerToken.artworkCropRect) + communityTokensModuleInst.deployOwnerToken(communityId, ownerToken.accountAddress, ownerToken.name, ownerToken.symbol, ownerToken.description, + tMasterToken.name, tMasterToken.symbol, tMasterToken.description, ownerToken.chainId, jsonArtworkFile) } function deleteToken(communityId, contractUniqueKey) { @@ -79,6 +79,14 @@ QtObject { root.deploymentStateChanged(communityId, status, url) } + function onOwnerTokenDeploymentStateChanged(communityId, status, url) { + root.ownerTokenDeploymentStateChanged(communityId, status, url) + } + + function onOwnerTokenDeploymentStarted(communityId, url) { + root.ownerTokenDeploymentStarted(communityId, url) + } + function onRemoteDestructStateChanged(communityId, tokenName, status, url) { root.remoteDestructStateChanged(communityId, tokenName, status, url) } @@ -96,8 +104,8 @@ QtObject { } } - function computeDeployFee(chainId, accountAddress, tokenType) { - communityTokensModuleInst.computeDeployFee(chainId, accountAddress, tokenType) + function computeDeployFee(chainId, accountAddress, tokenType, isOwnerDeployment) { + communityTokensModuleInst.computeDeployFee(chainId, accountAddress, tokenType, isOwnerDeployment) } function computeSelfDestructFee(selfDestructTokensList, tokenKey, accountAddress) {