From 688fece264caad9433b2ead7ed7c672d97a11df3 Mon Sep 17 00:00:00 2001 From: Stacey Korbit Date: Thu, 25 Aug 2022 12:04:12 +0300 Subject: [PATCH 1/2] refactor(@casimir/team-service): refactor service --- .../casimir/services/Team/lib/TeamService.js | 614 +++++++++++------- packages/casimir/services/Team/package.json | 1 + 2 files changed, 375 insertions(+), 240 deletions(-) diff --git a/packages/casimir/services/Team/lib/TeamService.js b/packages/casimir/services/Team/lib/TeamService.js index 3bf5ca687..4610bd231 100644 --- a/packages/casimir/services/Team/lib/TeamService.js +++ b/packages/casimir/services/Team/lib/TeamService.js @@ -20,11 +20,194 @@ import { } from '@casimir/commands'; import { ChainService } from '@casimir/chain-service'; import { WebSocketService } from '@casimir/web-socket-service'; +import { walletSignTx } from '@casimir/platform-util'; import { TeamHttp } from './TeamHttp'; const proposalDefaultLifetime = new Date(new Date().getTime() + 86400000 * 365 * 3).getTime(); +/** + * Add proposal commands for adding members + * @param {BaseTxBuilder} txBuilder + * @param {string} batchWeight + * @param {Array} proposalBatch + * @param {string} creator + * @returns {BaseTxBuilder} + */ +const addProposalCommandsForAddingMembers = async ( + txBuilder, + batchWeight, + proposalBatch, + creator +) => { + const createProposalCmd = new CreateProposalCmd({ + creator, + type: APP_PROPOSAL.ADD_DAO_MEMBER_PROPOSAL, + expirationTime: proposalDefaultLifetime, + proposedCmds: proposalBatch, + batchWeight + }); + + txBuilder.addCmd(createProposalCmd); + + const joinTeamProposalId = createProposalCmd.getProtocolEntityId(); + const updateProposalCmd = new AcceptProposalCmd({ + entityId: joinTeamProposalId, + account: creator, + batchWeight + }); + + txBuilder.addCmd(updateProposalCmd); + return txBuilder; +}; + +/** + * Pack transaction for creation + * @param {BaseTxBuilder} chainTxBuilder + * @param {string} creator + * @param {Object} data + * @param {CreateDaoCmd} createDaoCmd + * @param {TransferFTCmd} transferFTCmd + * @param {string} entityId + * @returns {FinalizedTx} + */ +const packTxForCreation = async ( + chainTxBuilder, + creator, + data, + createDaoCmd, + transferFTCmd, + entityId +) => { + const txBuilder = await chainTxBuilder.begin(); + + txBuilder.addCmd(createDaoCmd); + + if (transferFTCmd) { + txBuilder.addCmd(transferFTCmd); + } + + let updatedTxBuilder; + + const members = data.members.filter((m) => m !== creator); + if (members.length > 0) { + const invites = members.map((invitee) => { + const addTeamMemberCmd = new AddDaoMemberCmd({ + member: invitee, + teamId: entityId, + isThresholdPreserved: true + }); + + return addTeamMemberCmd; + }); + + const proposalBatch = [ + ...invites + ]; + const batchWeight = await chainTxBuilder.getBatchWeight(proposalBatch); + updatedTxBuilder = await addProposalCommandsForAddingMembers( + txBuilder, + batchWeight, + proposalBatch, + creator + ); + } + return updatedTxBuilder ? updatedTxBuilder.end() : txBuilder.end(); +}; + +/** + * Add proposal commands for team update + * @param {BaseTxBuilder} txBuilder + * @param {string} batchWeight + * @param {Array} proposalBatch + * @param {string} creator + * @param {number} proposalLifetime + * @param {boolean} isProposalApproved + * @returns {BaseTxBuilder} + */ +const addProposalCommandsForTeamUpdate = async ( + txBuilder, + batchWeight, + proposalBatch, + creator, + proposalLifetime, + isProposalApproved +) => { + const createProposalCmd = new CreateProposalCmd({ + creator, + type: APP_PROPOSAL.TEAM_UPDATE_PROPOSAL, + expirationTime: proposalLifetime, + proposedCmds: proposalBatch, + batchWeight + }); + + txBuilder.addCmd(createProposalCmd); + + if (isProposalApproved) { + const teamUpdateProposalId = createProposalCmd.getProtocolEntityId(); + const updateProposalCmd = new AcceptProposalCmd({ + entityId: teamUpdateProposalId, + account: creator, + batchWeight + }); + + txBuilder.addCmd(updateProposalCmd); + } + return txBuilder; +}; + +/** + * Pack transaction for team update + * @param {BaseTxBuilder} chainTxBuilder + * @param {Array} attributes + * @param {string} description + * @param {string} entityId + * @param {boolean} isProposal + * @param {string} creator + * @param {number} proposalLifetime + * @param {boolean} isProposalApproved + * @returns {FinalizedTx} + */ +const packTxForUpdate = async ( + chainTxBuilder, + attributes, + description, + entityId, + isProposal, + creator, + proposalLifetime, + isProposalApproved +) => { + const txBuilder = await chainTxBuilder.begin(); + + const updateDaoCmd = new UpdateDaoCmd({ + entityId, + isTeamAccount: true, + attributes, // need clarification + description + }); + + let updatedTxBuilder; + + if (isProposal) { + const proposalBatch = [ + updateDaoCmd + ]; + + const batchWeight = await chainTxBuilder.getBatchWeight(proposalBatch); + + updatedTxBuilder = await addProposalCommandsForTeamUpdate( + txBuilder, + batchWeight, + proposalBatch, + creator, + proposalLifetime, + isProposalApproved + ); + } + txBuilder.addCmd(updateDaoCmd); + return (updatedTxBuilder) ? updatedTxBuilder.end() : txBuilder.end(); +}; export class TeamService { proxydi = proxydi; teamHttp = TeamHttp.getInstance(); @@ -65,88 +248,58 @@ export class TeamService { const attributes = replaceFileWithName(data.attributes); const description = genSha256Hash(attributes); - const response = await ChainService.getInstanceAsync(env) - .then((chainService) => { - let entityId; - const chainNodeClient = chainService.getChainNodeClient(); - const chainTxBuilder = chainService.getChainTxBuilder(); - return chainTxBuilder.begin() - .then((txBuilder) => { - const createDaoCmd = new CreateDaoCmd({ - isTeamAccount: true, - fee: { ...CORE_ASSET, amount: 0 }, - authority: { - owner: authority - }, - creator, - description, - attributes - }); - - txBuilder.addCmd(createDaoCmd); - entityId = createDaoCmd.getProtocolEntityId(); - - if (ACCOUNT_DEFAULT_FUNDING_AMOUNT) { - const transferFTCmd = new TransferFTCmd({ - from: creator, - to: entityId, - tokenId: CORE_ASSET.id, - amount: ACCOUNT_DEFAULT_FUNDING_AMOUNT - }); - txBuilder.addCmd(transferFTCmd); - } - - const members = data.members.filter((m) => m !== creator); - if (members.length > 0) { - const invites = members.map((invitee) => { - const addTeamMemberCmd = new AddDaoMemberCmd({ - member: invitee, - teamId: entityId, - isThresholdPreserved: true - }); - - return addTeamMemberCmd; - }); - - const proposalBatch = [ - ...invites - ]; - - return chainTxBuilder.getBatchWeight(proposalBatch) - .then((batchWeight) => { - const createProposalCmd = new CreateProposalCmd({ - creator, - type: APP_PROPOSAL.ADD_DAO_MEMBER_PROPOSAL, - expirationTime: proposalDefaultLifetime, - proposedCmds: proposalBatch, - batchWeight - }); - - txBuilder.addCmd(createProposalCmd); - - const joinTeamProposalId = createProposalCmd.getProtocolEntityId(); - const updateProposalCmd = new AcceptProposalCmd({ - entityId: joinTeamProposalId, - account: creator, - batchWeight - }); - - txBuilder.addCmd(updateProposalCmd); - return txBuilder.end(); - }); - } - return txBuilder.end(); - }) - .then((packedTx) => packedTx.signAsync(privKey, chainNodeClient)) - .then((packedTx) => { - // eslint-disable-next-line max-len - const msg = new MultFormDataMsg(formData, packedTx.getPayload(), { 'entity-id': entityId }); - if (RETURN_MSG && RETURN_MSG === true) { - return msg; - } - return this.teamHttp.create(msg); - }); + const chainService = await ChainService.getInstanceAsync(env); + + const chainNodeClient = chainService.getChainNodeClient(); + const chainTxBuilder = chainService.getChainTxBuilder(); + + const createDaoCmd = new CreateDaoCmd({ + isTeamAccount: true, + fee: { ...CORE_ASSET, amount: 0 }, + authority: { + owner: authority + }, + creator, + description, + attributes + }); + + const entityId = createDaoCmd.getProtocolEntityId(); + let transferFTCmd; + + if (ACCOUNT_DEFAULT_FUNDING_AMOUNT) { + transferFTCmd = new TransferFTCmd({ + from: creator, + to: entityId, + tokenId: CORE_ASSET.id, + amount: ACCOUNT_DEFAULT_FUNDING_AMOUNT }); + } + + const packedTx = await packTxForCreation( + chainTxBuilder, + creator, + data, + createDaoCmd, + transferFTCmd, + entityId + ); + + const chainInfo = chainService.getChainInfo(); + let signedTx; + + if (env.WALLET_URL) { + signedTx = await walletSignTx(packedTx, chainInfo); + } else { + signedTx = await packedTx.signAsync(privKey, chainNodeClient); + } + + const msg = new MultFormDataMsg(formData, signedTx.getPayload(), { 'entity-id': entityId }); + if (RETURN_MSG && RETURN_MSG === true) { + return msg; + } + + const response = await this.teamHttp.create(msg); await this.webSocketService.waitForMessage((message) => { const [, eventBody] = message; @@ -192,70 +345,45 @@ export class TeamService { const attributes = replaceFileWithName(data.attributes); const description = genSha256Hash(attributes); - const response = await ChainService.getInstanceAsync(env) - .then((chainService) => { - const chainNodeClient = chainService.getChainNodeClient(); - const chainTxBuilder = chainService.getChainTxBuilder(); - return chainTxBuilder.begin() - .then((txBuilder) => { - const updateDaoCmd = new UpdateDaoCmd({ - entityId, - isTeamAccount: true, - attributes, // need clarification - description - }); - - if (isProposal) { - const proposalBatch = [ - updateDaoCmd - ]; - - return chainTxBuilder.getBatchWeight(proposalBatch) - .then((batchWeight) => { - const createProposalCmd = new CreateProposalCmd({ - creator, - type: APP_PROPOSAL.TEAM_UPDATE_PROPOSAL, - expirationTime: proposalLifetime, - proposedCmds: proposalBatch, - batchWeight - }); - - txBuilder.addCmd(createProposalCmd); - - if (isProposalApproved) { - const teamUpdateProposalId = createProposalCmd.getProtocolEntityId(); - const updateProposalCmd = new AcceptProposalCmd({ - entityId: teamUpdateProposalId, - account: creator, - batchWeight - }); - - txBuilder.addCmd(updateProposalCmd); - } - return txBuilder.end(); - }); - } - txBuilder.addCmd(updateDaoCmd); - return txBuilder.end(); - }) - .then((packedTx) => packedTx.signAsync(privKey, chainNodeClient)) - .then((packedTx) => { - // eslint-disable-next-line max-len - const msg = new MultFormDataMsg(formData, packedTx.getPayload(), { 'entity-id': entityId }); - - if (env.RETURN_MSG === true) { - return msg; - } - - return this.teamHttp.update(msg); - }); - }); + const chainService = await ChainService.getInstanceAsync(env); + + const chainNodeClient = chainService.getChainNodeClient(); + const chainTxBuilder = chainService.getChainTxBuilder(); + + const packedTx = await packTxForUpdate( + chainTxBuilder, + attributes, + description, + entityId, + isProposal, + creator, + proposalLifetime, + isProposalApproved + ); + + const chainInfo = chainService.getChainInfo(); + let signedTx; + + if (env.WALLET_URL) { + signedTx = await walletSignTx(packedTx, chainInfo); + } else { + signedTx = await packedTx.signAsync(privKey, chainNodeClient); + } + + // eslint-disable-next-line max-len + const msg = new MultFormDataMsg(formData, signedTx.getPayload(), { 'entity-id': entityId }); + + if (env.RETURN_MSG === true) { + return msg; + } + + const response = await this.teamHttp.update(msg); await this.webSocketService.waitForMessage((message) => { const [, eventBody] = message; return eventBody.event.eventNum === APP_EVENT.DAO_UPDATED - && eventBody.event.eventPayload.daoId === response.data._id; + && eventBody.event.eventPayload.daoId === response.data._id; }); return response; @@ -284,55 +412,58 @@ export class TeamService { isThresholdPreserved } = payload; - return ChainService.getInstanceAsync(env) - .then((chainService) => { - const chainNodeClient = chainService.getChainNodeClient(); - const chainTxBuilder = chainService.getChainTxBuilder(); - return chainTxBuilder.begin() - .then((txBuilder) => { - const addTeamMemberCmd = new AddDaoMemberCmd({ - member, - teamId, - isThresholdPreserved: isBoolean(isThresholdPreserved) ? isThresholdPreserved : true - }); - - const proposalBatch = [ - addTeamMemberCmd - ]; - - return chainTxBuilder.getBatchWeight(proposalBatch) - .then((batchWeight) => { - const createProposalCmd = new CreateProposalCmd({ - creator, - type: APP_PROPOSAL.ADD_DAO_MEMBER_PROPOSAL, - expirationTime: proposalDefaultLifetime, - proposedCmds: proposalBatch, - batchWeight - }); - txBuilder.addCmd(createProposalCmd); - - const joinTeamProposalId = createProposalCmd.getProtocolEntityId(); - const updateProposalCmd = new AcceptProposalCmd({ - entityId: joinTeamProposalId, - account: creator, - batchWeight - }); - txBuilder.addCmd(updateProposalCmd); - - return txBuilder.end(); - }); - }) - .then((packedTx) => packedTx.signAsync(privKey, chainNodeClient)) - .then((packedTx) => { - const msg = new JsonDataMsg(packedTx.getPayload(), { 'entity-id': teamId }); - - if (env.RETURN_MSG === true) { - return msg; - } - - return this.teamHttp.addTeamMember(msg); - }); - }); + const chainService = await ChainService.getInstanceAsync(env); + + const chainNodeClient = chainService.getChainNodeClient(); + const chainTxBuilder = chainService.getChainTxBuilder(); + const txBuilder = await chainTxBuilder.begin(); + + const addTeamMemberCmd = new AddDaoMemberCmd({ + member, + teamId, + isThresholdPreserved: isBoolean(isThresholdPreserved) ? isThresholdPreserved : true + }); + + const proposalBatch = [ + addTeamMemberCmd + ]; + + const batchWeight = await chainTxBuilder.getBatchWeight(proposalBatch); + const createProposalCmd = new CreateProposalCmd({ + creator, + type: APP_PROPOSAL.ADD_DAO_MEMBER_PROPOSAL, + expirationTime: proposalDefaultLifetime, + proposedCmds: proposalBatch, + batchWeight + }); + txBuilder.addCmd(createProposalCmd); + + const joinTeamProposalId = createProposalCmd.getProtocolEntityId(); + const updateProposalCmd = new AcceptProposalCmd({ + entityId: joinTeamProposalId, + account: creator, + batchWeight + }); + txBuilder.addCmd(updateProposalCmd); + + const packedTx = await txBuilder.end(); + + const chainInfo = chainService.getChainInfo(); + let signedTx; + + if (env.WALLET_URL) { + signedTx = await walletSignTx(packedTx, chainInfo); + } else { + signedTx = await packedTx.signAsync(privKey, chainNodeClient); + } + + const msg = new JsonDataMsg(signedTx.getPayload(), { 'entity-id': teamId }); + + if (env.RETURN_MSG === true) { + return msg; + } + + return this.teamHttp.addTeamMember(msg); } /** @@ -358,57 +489,60 @@ export class TeamService { isThresholdPreserved } = payload; - return ChainService.getInstanceAsync(env) - .then((chainService) => { - const chainNodeClient = chainService.getChainNodeClient(); - const chainTxBuilder = chainService.getChainTxBuilder(); - return chainTxBuilder.begin() - .then((txBuilder) => { - const removeDaoMemberCmd = new RemoveDaoMemberCmd({ - member, - teamId, - isThresholdPreserved: isBoolean(isThresholdPreserved) ? isThresholdPreserved : true - }); - - const proposalBatch = [ - removeDaoMemberCmd - ]; - - return chainTxBuilder.getBatchWeight(proposalBatch) - .then((batchWeight) => { - const createProposalCmd = new CreateProposalCmd({ - creator, - type: APP_PROPOSAL.REMOVE_DAO_MEMBER_PROPOSAL, - expirationTime: proposalDefaultLifetime, - proposedCmds: proposalBatch, - batchWeight - }); - - txBuilder.addCmd(createProposalCmd); - - const leaveTeamProposalId = createProposalCmd.getProtocolEntityId(); - const updateProposalCmd = new AcceptProposalCmd({ - entityId: leaveTeamProposalId, - account: creator, - batchWeight - }); - - txBuilder.addCmd(updateProposalCmd); - - return txBuilder.end(); - }); - }) - .then((packedTx) => packedTx.signAsync(privKey, chainNodeClient)) - .then((packedTx) => { - const msg = new JsonDataMsg(packedTx.getPayload(), { 'entity-id': teamId }); - - if (env.RETURN_MSG === true) { - return msg; - } - - return this.teamHttp.removeTeamMember(msg); - }); - }); + const chainService = await ChainService.getInstanceAsync(env); + + const chainNodeClient = chainService.getChainNodeClient(); + const chainTxBuilder = chainService.getChainTxBuilder(); + const txBuilder = await chainTxBuilder.begin(); + + const removeDaoMemberCmd = new RemoveDaoMemberCmd({ + member, + teamId, + isThresholdPreserved: isBoolean(isThresholdPreserved) ? isThresholdPreserved : true + }); + + const proposalBatch = [ + removeDaoMemberCmd + ]; + + const batchWeight = await chainTxBuilder.getBatchWeight(proposalBatch); + const createProposalCmd = new CreateProposalCmd({ + creator, + type: APP_PROPOSAL.REMOVE_DAO_MEMBER_PROPOSAL, + expirationTime: proposalDefaultLifetime, + proposedCmds: proposalBatch, + batchWeight + }); + + txBuilder.addCmd(createProposalCmd); + + const leaveTeamProposalId = createProposalCmd.getProtocolEntityId(); + const updateProposalCmd = new AcceptProposalCmd({ + entityId: leaveTeamProposalId, + account: creator, + batchWeight + }); + + txBuilder.addCmd(updateProposalCmd); + + const packedTx = await txBuilder.end(); + + const chainInfo = chainService.getChainInfo(); + let signedTx; + + if (env.WALLET_URL) { + signedTx = await walletSignTx(packedTx, chainInfo); + } else { + signedTx = await packedTx.signAsync(privKey, chainNodeClient); + } + + const msg = new JsonDataMsg(signedTx.getPayload(), { 'entity-id': teamId }); + + if (env.RETURN_MSG === true) { + return msg; + } + + return this.teamHttp.removeTeamMember(msg); } /** diff --git a/packages/casimir/services/Team/package.json b/packages/casimir/services/Team/package.json index 435657306..ab16280c6 100644 --- a/packages/casimir/services/Team/package.json +++ b/packages/casimir/services/Team/package.json @@ -28,6 +28,7 @@ "@casimir/lib-crypto": "1.394.0", "@casimir/messages": "1.394.0", "@casimir/platform-core": "1.394.0", + "@casimir/platform-util": "^1.394.0", "@casimir/proxydi": "1.394.0", "@casimir/toolbox": "1.394.0", "@casimir/user-service": "1.394.0", From bd4a48fb1bb7da1a87ba2b057e0f5e640cde8e9b Mon Sep 17 00:00:00 2001 From: Stacey Korbit Date: Tue, 30 Aug 2022 13:25:18 +0300 Subject: [PATCH 2/2] refactor(@casimir/team-service): fix updatedtxbuilder --- .../casimir/services/Team/lib/TeamService.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/packages/casimir/services/Team/lib/TeamService.js b/packages/casimir/services/Team/lib/TeamService.js index 4610bd231..fb652b64a 100644 --- a/packages/casimir/services/Team/lib/TeamService.js +++ b/packages/casimir/services/Team/lib/TeamService.js @@ -87,8 +87,6 @@ const packTxForCreation = async ( txBuilder.addCmd(transferFTCmd); } - let updatedTxBuilder; - const members = data.members.filter((m) => m !== creator); if (members.length > 0) { const invites = members.map((invitee) => { @@ -101,18 +99,17 @@ const packTxForCreation = async ( return addTeamMemberCmd; }); - const proposalBatch = [ - ...invites - ]; + const proposalBatch = invites; const batchWeight = await chainTxBuilder.getBatchWeight(proposalBatch); - updatedTxBuilder = await addProposalCommandsForAddingMembers( + const updatedTxBuilder = await addProposalCommandsForAddingMembers( txBuilder, batchWeight, proposalBatch, creator ); + return updatedTxBuilder.end(); } - return updatedTxBuilder ? updatedTxBuilder.end() : txBuilder.end(); + return txBuilder.end(); }; /** @@ -187,8 +184,6 @@ const packTxForUpdate = async ( description }); - let updatedTxBuilder; - if (isProposal) { const proposalBatch = [ updateDaoCmd @@ -196,7 +191,7 @@ const packTxForUpdate = async ( const batchWeight = await chainTxBuilder.getBatchWeight(proposalBatch); - updatedTxBuilder = await addProposalCommandsForTeamUpdate( + const updatedTxBuilder = await addProposalCommandsForTeamUpdate( txBuilder, batchWeight, proposalBatch, @@ -204,9 +199,11 @@ const packTxForUpdate = async ( proposalLifetime, isProposalApproved ); + + return updatedTxBuilder.end(); } txBuilder.addCmd(updateDaoCmd); - return (updatedTxBuilder) ? updatedTxBuilder.end() : txBuilder.end(); + return txBuilder.end(); }; export class TeamService { proxydi = proxydi;