feat(@desktop/communities): Deploy Owner and Master tokens flow.

Issue #11250
This commit is contained in:
Michal Iskierko 2023-07-11 15:23:00 +02:00 committed by Michał Iskierko
parent 7a1500a365
commit 603d4dd4d8
19 changed files with 521 additions and 100 deletions

View File

@ -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

View File

@ -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)

View File

@ -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")

View File

@ -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:

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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")

View File

@ -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 != "":

View File

@ -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)

View File

@ -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)
arg.finish(output)

View File

@ -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(),

View File

@ -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

View File

@ -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

View File

@ -20,6 +20,7 @@ type
AirdropCommunityToken = "AirdropCommunityToken"
RemoteDestructCollectible = "RemoteDestructCollectible"
BurnCommunityToken = "BurnCommunityToken"
DeployOwnerToken = "DeployOwnerToken"
proc event*(self:PendingTransactionTypeDto):string =
result = "transaction:" & $self

View File

@ -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)
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)

View File

@ -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: {

View File

@ -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 {

View File

@ -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) {