feat(@desktop/communities): Adjust owner and master tokens deployment flow to new API

Issue #11954
This commit is contained in:
Michal Iskierko 2023-08-30 09:20:28 +02:00 committed by Michał Iskierko
parent bfa2fe088c
commit 5981e946fd
16 changed files with 93 additions and 38 deletions

View File

@ -116,8 +116,8 @@ proc getCommunityTokens*(self: Controller, communityId: string): seq[CommunityTo
proc computeDeployFee*(self: Controller, chainId: int, accountAddress: string, tokenType: TokenType, requestId: string) =
self.communityTokensService.computeDeployFee(chainId, accountAddress, tokenType, requestId)
proc computeDeployOwnerContractsFee*(self: Controller, chainId: int, accountAddress: string, requestId: string) =
self.communityTokensService.computeDeployOwnerContractsFee(chainId, accountAddress, requestId)
proc computeDeployOwnerContractsFee*(self: Controller, chainId: int, accountAddress: string, communityId: string, ownerDeploymentParams: DeploymentParameters, masterDeploymentParams: DeploymentParameters, requestId: string) =
self.communityTokensService.computeDeployOwnerContractsFee(chainId, accountAddress, communityId, ownerDeploymentParams, masterDeploymentParams, requestId)
proc computeSelfDestructFee*(self: Controller, walletAndAmountList: seq[WalletAndAmount], contractUniqueKey: string, addressFrom: string, requestId: string) =
self.communityTokensService.computeSelfDestructFee(walletAndAmountList, contractUniqueKey, addressFrom, requestId)

View File

@ -42,7 +42,7 @@ method onUserAuthenticated*(self: AccessInterface, password: string) {.base.} =
method resetTempValues*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method computeDeployFee*(self: AccessInterface, chainId: int, accountAddress: string, tokenType: TokenType, isOwnerDeployment: bool, requestId: string) {.base.} =
method computeDeployFee*(self: AccessInterface, communityId: string, chainId: int, accountAddress: string, tokenType: TokenType, isOwnerDeployment: bool, requestId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method computeSelfDestructFee*(self: AccessInterface, collectiblesToBurnJsonString: string, contractUniqueKey: string, addressFrom: string, requestId: string) {.base.} =

View File

@ -173,6 +173,13 @@ method deployCollectibles*(self: Module, communityId: string, fromAddress: strin
self.tempContractAction = ContractAction.Deploy
self.authenticate()
proc createOwnerAndMasterDeploymentParams(self: Module, communityId: string): (DeploymentParameters, DeploymentParameters) =
let communityDto = self.controller.getCommunityById(communityId)
let commName = communityDto.name
let commNameShort = try: commName[0 .. 2].toUpper except: commName.toUpper
return (DeploymentParameters(name: "Owner-" & commName, symbol: "OWN" & commNameShort, supply: stint.u256("1"), infiniteSupply: false, transferable: true, remoteSelfDestruct: false, tokenUri: utl.changeCommunityKeyCompression(communityId) & "/"),
DeploymentParameters(name: "TMaster-" & commName, symbol: "TM" & commNameShort, infiniteSupply: true, transferable: false, remoteSelfDestruct: true, tokenUri: utl.changeCommunityKeyCompression(communityId) & "/"))
method deployOwnerToken*(self: Module, communityId: string, fromAddress: string, ownerName: string, ownerSymbol: string, ownerDescription: string,
masterName: string, masterSymbol: string, masterDescription: string, chainId: int, imageCropInfoJson: string) =
let ownerToken = self.controller.getOwnerToken(communityId)
@ -185,11 +192,7 @@ method deployOwnerToken*(self: Module, communityId: string, fromAddress: string,
self.tempAddressFrom = fromAddress
self.tempCommunityId = communityId
self.tempChainId = chainId
let communityDto = self.controller.getCommunityById(communityId)
let commName = communityDto.name
let commNameShort = try: commName[0 .. 2].toUpper except: commName.toUpper
self.tempOwnerDeploymentParams = DeploymentParameters(name: "Owner-" & commName, symbol: "OWN" & commNameShort, supply: stint.u256("1"), infiniteSupply: false, transferable: true, remoteSelfDestruct: false, tokenUri: utl.changeCommunityKeyCompression(communityId) & "/")
self.tempMasterDeploymentParams = DeploymentParameters(name: "TMaster-" & commName, symbol: "TM" & commNameShort, infiniteSupply: true, transferable: false, remoteSelfDestruct: true, tokenUri: utl.changeCommunityKeyCompression(communityId) & "/")
(self.tempOwnerDeploymentParams, self.tempMasterDeploymentParams) = self.createOwnerAndMasterDeploymentParams(communityId)
self.tempOwnerTokenMetadata.description = ownerDescription
self.tempOwnerTokenMetadata.tokenType = TokenType.ERC721
self.tempMasterTokenMetadata.description = masterDescription
@ -250,9 +253,10 @@ method onAirdropFeesComputed*(self: Module, args: AirdropFeesArgs) =
method onBurnFeeComputed*(self: Module, ethCurrency: CurrencyAmount, fiatCurrency: CurrencyAmount, errorCode: ComputeFeeErrorCode, responseId: string) =
self.view.updateBurnFee(ethCurrency, fiatCurrency, errorCode.int, responseId)
method computeDeployFee*(self: Module, chainId: int, accountAddress: string, tokenType: TokenType, isOwnerDeployment: bool, requestId: string) =
method computeDeployFee*(self: Module, communityId: string, chainId: int, accountAddress: string, tokenType: TokenType, isOwnerDeployment: bool, requestId: string) =
if isOwnerDeployment:
self.controller.computeDeployOwnerContractsFee(chainId, accountAddress, requestId)
let (ownerDeploymentParams, masterDeploymentParams) = self.createOwnerAndMasterDeploymentParams(communityId)
self.controller.computeDeployOwnerContractsFee(chainId, accountAddress, communityId, ownerDeploymentParams, masterDeploymentParams, requestId)
else:
self.controller.computeDeployFee(chainId, accountAddress, tokenType, requestId)

View File

@ -50,8 +50,8 @@ QtObject:
proc airdropFeesUpdated*(self: View, json: string) {.signal.}
proc burnFeeUpdated*(self: View, ethCurrency: QVariant, fiatCurrency: QVariant, errorCode: int, responseId: string) {.signal.}
proc computeDeployFee*(self: View, chainId: int, accountAddress: string, tokenType: int, isOwnerDeployment: bool, requestId: string) {.slot.} =
self.communityTokensModule.computeDeployFee(chainId, accountAddress, intToEnum(tokenType, TokenType.Unknown), isOwnerDeployment, requestId)
proc computeDeployFee*(self: View, communityId: string, chainId: int, accountAddress: string, tokenType: int, isOwnerDeployment: bool, requestId: string) {.slot.} =
self.communityTokensModule.computeDeployFee(communityId, chainId, accountAddress, intToEnum(tokenType, TokenType.Unknown), isOwnerDeployment, requestId)
proc computeSelfDestructFee*(self: View, collectiblesToBurnJsonString: string, contractUniqueKey: string, addressFrom: string, requestId: string) {.slot.} =
self.communityTokensModule.computeSelfDestructFee(collectiblesToBurnJsonString, contractUniqueKey, addressFrom, requestId)

View File

@ -325,7 +325,7 @@ proc init*(self: Controller) =
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.delegate.onOwnerTokenDeployStateChanged(args.communityId, args.chainId, args.ownerContractAddress, args.masterContractAddress, args.deployState, args.transactionHash)
self.events.on(SIGNAL_COMMUNITY_TOKEN_REMOVED) do(e: Args):
let args = CommunityTokenRemovedArgs(e)

View File

@ -311,7 +311,7 @@ method onCommunityTokenOwnersFetched*(self: AccessInterface, communityId: string
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.} =
method onOwnerTokenDeployStateChanged*(self: AccessInterface, communityId: string, chainId: int, ownerContractAddress: string, masterContractAddress: string, deployState: DeployState, transactionHash: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onCommunityTokenSupplyChanged*(self: AccessInterface, communityId: string, chainId: int, contractAddress: string, supply: Uint256, remainingSupply: Uint256, destructedAmount: Uint256) {.base.} =

View File

@ -1124,11 +1124,13 @@ 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) =
method onOwnerTokenDeployStateChanged*[T](self: Module[T], communityId: string, chainId: int, ownerContractAddress: string, masterContractAddress: string, deployState: DeployState, transactionHash: string) =
let item = self.view.model().getItemById(communityId)
if item.id != "":
# update temporary master contract address first
item.updateCommunityTokenAddress(chainId, temporaryMasterContractAddress(ownerContractAddress), masterContractAddress)
if transactionHash != "":
item.updateCommunityTokenAddress(chainId, temporaryMasterContractAddress(transactionHash), masterContractAddress)
item.updateCommunityTokenAddress(chainId, temporaryOwnerContractAddress(transactionHash), ownerContractAddress)
# then update states
item.updateCommunityTokenDeployState(chainId, ownerContractAddress, deployState)
item.updateCommunityTokenDeployState(chainId, masterContractAddress, deployState)

View File

@ -22,6 +22,10 @@ type
chainId: int
addressFrom: string
requestId: string
ownerParams: JsonNode
masterParams: JsonNode
communityId: string
signerPubKey: string
const asyncGetDeployOwnerContractsFeesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[AsyncDeployOwnerContractsFeesArg](argEncoded)
@ -30,7 +34,12 @@ const asyncGetDeployOwnerContractsFeesTask: Task = proc(argEncoded: string) {.gc
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
# get deployment signature
let signatureResponse = community_tokens.createCommunityTokenDeploymentSignature(arg.chainId, arg.addressFrom, arg.communityId)
let signature = signatureResponse.result.getStr()
let deployGas = community_tokens.deployOwnerTokenEstimate(arg.chainId, arg.addressFrom, arg.ownerParams, arg.masterParams, signature, arg.communityId, arg.signerPubKey).result.getInt
gasTable[(arg.chainId, "")] = deployGas
arg.finish(%* {
"feeTable": tableToJsonArray(feeTable),

View File

@ -251,22 +251,32 @@ QtObject:
if not receivedData.success:
warn "Owner contracts not deployed", chainId=ownerTransactionDetails.ownerToken.chainId, address=ownerTransactionDetails.ownerToken.address
var masterContractAddress = ownerTransactionDetails.masterToken.address
var ownerContractAddress = ownerTransactionDetails.ownerToken.address
try:
# get master token address from transaction logs
if receivedData.success:
let response = tokens_backend.getMasterTokenContractAddressFromHash(ownerTransactionDetails.masterToken.chainId, receivedData.transactionHash)
var response = tokens_backend.getOwnerTokenContractAddressFromHash(ownerTransactionDetails.ownerToken.chainId, receivedData.transactionHash)
ownerContractAddress = response.result.getStr()
if ownerContractAddress == "":
raise newException(RpcException, "owner contract address is empty")
response = tokens_backend.getMasterTokenContractAddressFromHash(ownerTransactionDetails.masterToken.chainId, receivedData.transactionHash)
masterContractAddress = response.result.getStr()
if masterContractAddress == "":
raise newException(RpcException, "master contract address is empty")
debug "Minted owner token contract address:", ownerContractAddress
debug "Minted master token contract address:", masterContractAddress
# update master token address
discard updateCommunityTokenAddress(ownerTransactionDetails.masterToken.chainId, ownerTransactionDetails.masterToken.address, masterContractAddress)
# update owner token address
discard updateCommunityTokenAddress(ownerTransactionDetails.ownerToken.chainId, ownerTransactionDetails.ownerToken.address, ownerContractAddress)
#update db state for owner and master token
discard updateCommunityTokenState(ownerTransactionDetails.ownerToken.chainId, ownerTransactionDetails.ownerToken.address, deployState)
discard updateCommunityTokenState(ownerTransactionDetails.ownerToken.chainId, ownerContractAddress, 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)
var response = tokens_backend.addCommunityToken(ownerTransactionDetails.communityId, ownerTransactionDetails.ownerToken.chainId, ownerContractAddress)
if response.error != nil:
let error = Json.decode($response.error, RpcError)
raise newException(RpcException, "error adding owner token: " & error.message)
@ -280,7 +290,7 @@ QtObject:
error "Error updating owner contracts state", message = getCurrentExceptionMsg()
let data = OwnerTokenDeployedStatusArgs(communityId: ownerTransactionDetails.communityId, chainId: ownerTransactionDetails.ownerToken.chainId,
ownerContractAddress: ownerTransactionDetails.ownerToken.address,
ownerContractAddress: ownerContractAddress,
masterContractAddress: masterContractAddress,
deployState: deployState,
transactionHash: receivedData.transactionHash)
@ -386,8 +396,11 @@ QtObject:
addedCommunityToken.chainId,
)
proc temporaryMasterContractAddress*(ownerContractAddress: string): string =
return ownerContractAddress & "-master"
proc temporaryMasterContractAddress*(ownerContractTransactionHash: string): string =
return ownerContractTransactionHash & "-master"
proc temporaryOwnerContractAddress*(ownerContractTransactionHash: string): string =
return ownerContractTransactionHash & "-owner"
proc deployOwnerContracts*(self: Service, communityId: string, addressFrom: string, password: string,
ownerDeploymentParams: DeploymentParameters, ownerTokenMetadata: CommunityTokensMetadataDto,
@ -398,14 +411,21 @@ QtObject:
if txData.source == parseAddress(ZERO_ADDRESS):
return
let response = tokens_backend.deployOwnerToken(chainId, %ownerDeploymentParams, %masterDeploymentParams, %txData, common_utils.hashPassword(password))
let ownerContractAddress = response.result["contractAddress"].getStr()
# set my pub key as signer
let signerPubKey = singletonInstance.userProfile.getPubKey()
# get deployment signature
let signatureResponse = tokens_backend.createCommunityTokenDeploymentSignature(chainId, addressFrom, communityId)
let signature = signatureResponse.result.getStr()
# deploy contract
let response = tokens_backend.deployOwnerToken(chainId, %ownerDeploymentParams, %masterDeploymentParams,
signature, communityId, signerPubKey, %txData, common_utils.hashPassword(password))
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.TokenMaster)
var ownerToken = self.createCommunityToken(ownerDeploymentParams, ownerTokenMetadata, chainId, temporaryOwnerContractAddress(transactionHash), communityId, addressFrom, PrivilegesLevel.Owner)
var masterToken = self.createCommunityToken(masterDeploymentParams, masterTokenMetadata, chainId, temporaryMasterContractAddress(transactionHash), communityId, addressFrom, PrivilegesLevel.TokenMaster)
var croppedImage = croppedImageJson.parseJson
ownerToken.image = croppedImage{"imagePath"}.getStr
@ -672,7 +692,7 @@ QtObject:
#TODO: handle error - emit error signal
error "Error loading fees", msg = e.msg
proc computeDeployOwnerContractsFee*(self: Service, chainId: int, accountAddress: string, requestId: string) =
proc computeDeployOwnerContractsFee*(self: Service, chainId: int, accountAddress: string, communityId: string, ownerDeploymentParams: DeploymentParameters, masterDeploymentParams: DeploymentParameters, requestId: string) =
try:
let arg = AsyncDeployOwnerContractsFeesArg(
tptr: cast[ByteAddress](asyncGetDeployOwnerContractsFeesTask),
@ -680,7 +700,11 @@ QtObject:
slot: "onDeployOwnerContractsFees",
chainId: chainId,
addressFrom: accountAddress,
requestId: requestId
requestId: requestId,
signerPubKey: singletonInstance.userProfile.getPubKey(),
communityId: communityId,
ownerParams: %ownerDeploymentParams,
masterParams: %masterDeploymentParams
)
self.threadpool.start(arg)
except Exception as e:

View File

@ -88,14 +88,22 @@ proc remoteDestructedAmount*(chainId: int, contractAddress: string): RpcResponse
let payload = %*[chainId, contractAddress]
return core.callPrivateRPC("communitytokens_remoteDestructedAmount", payload)
proc deployOwnerTokenEstimate*(): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %*[]
proc deployOwnerTokenEstimate*(chainId: int, addressFrom: string, ownerParams: JsonNode, masterParams: JsonNode, signature: string, communityId: string, signerPubKey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %*[chainId, addressFrom, ownerParams, masterParams, signature, communityId, signerPubKey]
return core.callPrivateRPC("communitytokens_deployOwnerTokenEstimate", payload)
proc deployOwnerToken*(chainId: int, ownerParams: JsonNode, masterParams: JsonNode, txData: JsonNode, hashedPassword: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %*[chainId, ownerParams, masterParams, txData, hashedPassword]
proc deployOwnerToken*(chainId: int, ownerParams: JsonNode, masterParams: JsonNode, signature: string, communityId: string, signerPubKey: string, txData: JsonNode, hashedPassword: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %*[chainId, ownerParams, masterParams, signature, communityId, signerPubKey, txData, hashedPassword]
return core.callPrivateRPC("communitytokens_deployOwnerToken", payload)
proc getMasterTokenContractAddressFromHash*(chainId: int, transactionHash: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %*[chainId, transactionHash]
return core.callPrivateRPC("communitytokens_getMasterTokenContractAddressFromHash", payload)
return core.callPrivateRPC("communitytokens_getMasterTokenContractAddressFromHash", payload)
proc getOwnerTokenContractAddressFromHash*(chainId: int, transactionHash: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %*[chainId, transactionHash]
return core.callPrivateRPC("communitytokens_getOwnerTokenContractAddressFromHash", payload)
proc createCommunityTokenDeploymentSignature*(chainId: int, addressFrom: string, signerAddress: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %*[chainId, addressFrom, signerAddress]
return core.callPrivateRPC("wakuext_createCommunityTokenDeploymentSignature", payload)

View File

@ -94,6 +94,7 @@ SplitView {
communityLogo: ModelsData.collectibles.doodles
communityColor: "#FFC4E9"
communityName: "Doodles" // It cannot be changed since owner token and tMaster token in tokenModel used are related to the `Doodles` community
communityId: ""
// Profile type:
isAdmin: adminChecked.checked

View File

@ -8,6 +8,7 @@ import QtQuick 2.15
SingleFeeSubscriber {
id: root
required property string communityId
required property int chainId
required property int tokenType
required property bool isOwnerDeployment

View File

@ -46,6 +46,7 @@ QtObject {
required property DeployFeesSubscriber subscriber
readonly property var requestArgs: ({
type: TransactionFeesBroker.FeeType.Deploy,
communityId: subscriber.communityId,
chainId: subscriber.chainId,
accountAddress: subscriber.accountAddress,
tokenType: subscriber.tokenType,
@ -156,7 +157,7 @@ QtObject {
}
function computeDeployFee(args, topic) {
communityTokensStore.computeDeployFee(args.chainId, args.accountAddress, args.tokenType, args.isOwnerDeployment, topic)
communityTokensStore.computeDeployFee(args.communityId, args.chainId, args.accountAddress, args.tokenType, args.isOwnerDeployment, topic)
}
function computeSelfDestructFee(args, topic) {

View File

@ -26,6 +26,7 @@ StackView {
// General properties:
property int viewWidth: 560 // by design
property string previousPageName: depth > 1 ? qsTr("Back") : ""
required property string communityId
required property string communityName
required property string communityLogo
required property color communityColor
@ -242,6 +243,7 @@ StackView {
DeployFeesSubscriber {
id: feeSubscriber
communityId: root.communityId
chainId: editOwnerTokenView.ownerToken.chainId
tokenType: editOwnerTokenView.ownerToken.type
isOwnerDeployment: editOwnerTokenView.ownerToken.isPrivilegedToken
@ -394,6 +396,7 @@ StackView {
DeployFeesSubscriber {
id: deployFeeSubscriber
communityId: root.communityId
chainId: editView.token.chainId
tokenType: editView.token.type
isOwnerDeployment: editView.token.isPrivilegedToken
@ -442,6 +445,7 @@ StackView {
DeployFeesSubscriber {
id: feeSubscriber
communityId: root.communityId
chainId: preview.token.chainId
tokenType: preview.token.type
isOwnerDeployment: preview.token.isPrivilegedToken

View File

@ -320,6 +320,7 @@ StatusSectionLayout {
rootStore.communityTokensStore
// General community props
communityId: root.community.id
communityName: root.community.name
communityLogo: root.community.image
communityColor: root.community.color

View File

@ -120,8 +120,8 @@ QtObject {
JSON.stringify(addresses), feeAccountAddress, requestId)
}
function computeDeployFee(chainId, accountAddress, tokenType, isOwnerDeployment, requestId) {
communityTokensModuleInst.computeDeployFee(chainId, accountAddress, tokenType, isOwnerDeployment, requestId)
function computeDeployFee(communityId, chainId, accountAddress, tokenType, isOwnerDeployment, requestId) {
communityTokensModuleInst.computeDeployFee(communityId, chainId, accountAddress, tokenType, isOwnerDeployment, requestId)
}
/**