From c411af946e41f5e5eb5c2ac8946481676aaae5e6 Mon Sep 17 00:00:00 2001 From: Boldizsar Mezei Date: Mon, 25 Sep 2023 10:41:02 +0200 Subject: [PATCH] Set project on records Fixes Fixes Fixes Fixes Fixes Fixes Fixes Fixes --- packages/functions/jest.config.js | 1 + packages/functions/package.json | 2 +- packages/functions/scripts/manualRefund.ts | 2 + .../functions/src/controls/address.control.ts | 4 +- .../award/award.approve.participant.ts | 4 +- .../src/controls/award/award.create.ts | 7 ++- .../src/controls/award/award.fund.ts | 9 +-- .../src/controls/award/award.owner.ts | 7 ++- .../src/controls/award/award.participate.ts | 5 +- .../collection/collection-mint.control.ts | 5 +- .../collection/collection.create.control.ts | 5 ++ .../src/controls/credit/credit.controller.ts | 10 +++- .../src/controls/nft/nft.bid.control.ts | 9 +-- .../functions/src/controls/nft/nft.create.ts | 12 ++-- .../functions/src/controls/nft/nft.deposit.ts | 8 +-- .../src/controls/nft/nft.puchase.control.ts | 12 +++- .../functions/src/controls/nft/nft.stake.ts | 8 +-- .../src/controls/nft/nft.withdraw.ts | 3 +- .../src/controls/project/init.soon.project.ts | 2 + .../project/project.create.control.ts | 2 + .../src/controls/proposal/create.proposal.ts | 7 ++- .../src/controls/proposal/vote.on.proposal.ts | 8 +-- .../controls/space/member.accept.control.ts | 4 +- .../controls/space/member.block.control.ts | 12 +++- .../src/controls/space/space.claim.control.ts | 8 ++- .../controls/space/space.create.control.ts | 6 +- .../space/space.guardian.edit.control.ts | 3 +- .../src/controls/space/space.join.control.ts | 8 ++- .../controls/space/space.update.control.ts | 18 ++++-- .../src/controls/stake/stake.deposit.ts | 8 ++- .../src/controls/stake/stake.reward.revoke.ts | 26 ++++++--- .../src/controls/stake/stake.reward.ts | 8 ++- .../token-minting/airdrop-minted-token.ts | 9 ++- .../claim-minted-token.control.ts | 4 +- .../token-minting/import-minted-token.ts | 6 +- .../token-minting/token-mint.control.ts | 7 ++- .../token-trading/token-trade.controller.ts | 8 ++- .../src/controls/token/token.airdrop.claim.ts | 10 ++-- .../src/controls/token/token.airdrop.ts | 10 +++- .../src/controls/token/token.create.ts | 3 + .../src/controls/token/token.credit.ts | 5 +- .../src/controls/token/token.order.ts | 10 +++- .../functions/src/cron/stakeReward.cron.ts | 5 ++ .../payment/address/address.space.service.ts | 11 +++- .../services/payment/award/award-service.ts | 7 ++- .../functions/src/services/payment/base.ts | 2 + .../src/services/payment/credit-service.ts | 5 +- .../services/payment/metadataNft-service.ts | 28 +++++----- .../src/services/payment/nft/common.ts | 2 + .../payment/nft/nft-deposit.service.ts | 18 ++++-- .../services/payment/nft/nft-stake.service.ts | 7 ++- .../services/payment/payment-processing.ts | 10 ++-- .../services/payment/space/space-service.ts | 5 +- .../src/services/payment/stake-service.ts | 9 ++- .../address/address-validation.service.ts | 7 ++- .../award.approve.participant.service.ts | 16 +++++- .../award/award.create.service.ts | 23 ++++++-- .../award/award.fund.service.ts | 17 +++++- .../metadataNft/mint-metadata-nft.service.ts | 7 ++- .../tangle-service/nft/nft-bid.service.ts | 8 ++- .../tangle-service/nft/nft-deposit.service.ts | 5 +- .../nft/nft-purchase.service.ts | 24 ++++++-- .../proposal/ProposalCreateService.ts | 46 ++++++++++------ .../proposal/voting/ProposalVoteService.ts | 26 +++++++-- .../proposal/voting/simple.voting.ts | 3 +- .../proposal/voting/staked.token.voting.ts | 2 + .../proposal/voting/token.voting.ts | 4 ++ .../space/SpaceAcceptMemberService.ts | 37 +++++++++++-- .../space/SpaceBlockMemberService.ts | 29 ++++++++-- .../space/SpaceCreateService.ts | 15 ++++- .../space/SpaceGuardianService.ts | 21 +++++-- .../tangle-service/space/SpaceJoinService.ts | 17 +++++- .../tangle-service/token/stake.service.ts | 7 ++- .../token/token-claim.service.ts | 14 ++++- .../token/token-trade.service.ts | 12 +++- .../token/import-minted-token.service.ts | 3 + .../payment/token/token-trade.service.ts | 19 +++++-- .../services/payment/transaction-service.ts | 27 +++++++-- .../src/services/payment/voting-service.ts | 3 + .../functions/src/triggers/award.trigger.ts | 11 +++- .../src/triggers/collection.trigger.ts | 23 +++++--- .../token-trading/match-base-token.ts | 55 ++++++++++++------- .../token-trading/match-minted-token.ts | 54 ++++++++++++------ .../token-trading/match-simple-token.ts | 30 ++++++---- .../functions/src/triggers/token.trigger.ts | 26 ++++++--- .../transaction-trigger/airdrop.claim.ts | 13 ++++- .../award.transaction.update.ts | 5 +- .../transaction-trigger/collection-minting.ts | 36 +++++++----- .../transaction-trigger/matadatNft-minting.ts | 14 +++-- .../transaction-trigger/token-minting.ts | 9 ++- .../transaction.trigger.ts | 7 ++- packages/functions/src/utils/common.utils.ts | 6 ++ .../functions/src/utils/token-trade.utils.ts | 15 +++-- packages/functions/test-tangle/common.ts | 5 +- .../test/controls/collection.spec.ts | 20 +++++-- .../functions/test/controls/member.spec.ts | 21 ++++++- .../functions/test/controls/order.spec.ts | 5 ++ .../controls/project/project.create.spec.ts | 4 ++ .../functions/test/controls/proposal.spec.ts | 17 ++++-- .../test/controls/stake.reward.spec.ts | 11 +++- .../token-distribution-auto-trigger.spec.ts | 3 + .../test/controls/token-distribution.spec.ts | 3 + .../test/controls/token-trade.trigger.spec.ts | 5 ++ .../controls/token.expired.sale.cron.spec.ts | 3 + .../test/cron/floor-price.cron.only.spec.ts | 16 +++++- .../test/cron/nft-stake.cron.spec.ts | 14 ++++- .../functions/test/cron/proposal.cron.spec.ts | 4 +- packages/functions/test/set-up.ts | 9 ++- .../test/stake/delete.stake.reward.spec.ts | 14 ++++- .../test/stake/stake.reward.cron.spec.ts | 13 ++++- packages/functions/test/teardown.ts | 39 +++++++++++++ packages/functions/workflow.build.js | 1 + packages/interfaces/src/models/award.ts | 2 +- packages/interfaces/src/models/base.ts | 12 ++-- .../src/models/transaction/payload.ts | 5 ++ 115 files changed, 998 insertions(+), 338 deletions(-) create mode 100644 packages/functions/test/teardown.ts diff --git a/packages/functions/jest.config.js b/packages/functions/jest.config.js index 135a2bcb13..c32f80d2bf 100644 --- a/packages/functions/jest.config.js +++ b/packages/functions/jest.config.js @@ -3,5 +3,6 @@ module.exports = { testEnvironment: 'node', testTimeout: 900000, globalSetup: './test/set-up.ts', + globalTeardown: './test/teardown.ts', reporters: ['default', 'github-actions'], }; diff --git a/packages/functions/package.json b/packages/functions/package.json index 6eb09621e8..09d46483be 100644 --- a/packages/functions/package.json +++ b/packages/functions/package.json @@ -23,7 +23,7 @@ "shell": "npm run build && firebase functions:shell", "start": "npm run shell", "export-online-test-credentials": "export GOOGLE_APPLICATION_CREDENTIALS=\"./test-service-account-key.json\"", - "test": "export LOCAL_TEST=true && jest packages/functions/test/auth.spec.ts --runInBand", + "test": "export LOCAL_TEST=true && jest --runInBand", "test-online": "npm run export-online-test-credentials && jest test/ --runInBand", "test-tangle": "export LOCAL_TEST=true && jest test-tangle/ --runInBand ", "test-tangle-online": "npm run export-online-test-credentials && jest test-tangle/ --runInBand", diff --git a/packages/functions/scripts/manualRefund.ts b/packages/functions/scripts/manualRefund.ts index 6a25d0df3f..118e31a050 100644 --- a/packages/functions/scripts/manualRefund.ts +++ b/packages/functions/scripts/manualRefund.ts @@ -31,6 +31,8 @@ db.collection(COL.MEMBER) .collection(COL.TRANSACTION) .doc(tranId) .set({ + project: '', + projects: {}, type: TransactionType.CREDIT, uid: tranId, space: '', diff --git a/packages/functions/src/controls/address.control.ts b/packages/functions/src/controls/address.control.ts index 1d4866b3d9..001856a1d8 100644 --- a/packages/functions/src/controls/address.control.ts +++ b/packages/functions/src/controls/address.control.ts @@ -12,7 +12,7 @@ import { createAddressValidationOrder } from '../services/payment/tangle-service import { invalidArgument } from '../utils/error.utils'; export const validateAddressControl = async ( - { owner }: Context, + { project, owner }: Context, params: AddressValidationRequest, ) => { const network = (params.network as Network) || DEFAULT_NETWORK; @@ -22,7 +22,7 @@ export const validateAddressControl = async ( throw invalidArgument(WenError.member_does_not_exists); } - const order = await createAddressValidationOrder(member.uid, network, params.space); + const order = await createAddressValidationOrder(project, member.uid, network, params.space); await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); return order; diff --git a/packages/functions/src/controls/award/award.approve.participant.ts b/packages/functions/src/controls/award/award.approve.participant.ts index 28e5c69472..471b83abed 100644 --- a/packages/functions/src/controls/award/award.approve.participant.ts +++ b/packages/functions/src/controls/award/award.approve.participant.ts @@ -10,7 +10,7 @@ import { Context } from '../../runtime/firebase/common'; import { approveAwardParticipant } from '../../services/payment/tangle-service/award/award.approve.participant.service'; export const approveAwardParticipantControl = async ( - { owner }: Context, + { project, owner }: Context, params: AwardApproveParticipantRequest, ): Promise => { const members = params.members.map((m) => m.toLowerCase()); @@ -21,7 +21,7 @@ export const approveAwardParticipantControl = async ( for (const member of members) { try { const badge = await build5Db().runTransaction( - approveAwardParticipant(owner, awardId, member), + approveAwardParticipant(project, owner, awardId, member), ); badges[badge.uid] = badge; // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/packages/functions/src/controls/award/award.create.ts b/packages/functions/src/controls/award/award.create.ts index b5aa86f312..cac0bccbd6 100644 --- a/packages/functions/src/controls/award/award.create.ts +++ b/packages/functions/src/controls/award/award.create.ts @@ -3,8 +3,11 @@ import { Award, AwardCreateRequest, COL, SUB_COL } from '@build-5/interfaces'; import { Context } from '../../runtime/firebase/common'; import { createAward } from '../../services/payment/tangle-service/award/award.create.service'; -export const createAwardControl = async ({ owner }: Context, params: AwardCreateRequest) => { - const { owner: awardOwner, award } = await createAward(owner, params); +export const createAwardControl = async ( + { project, owner }: Context, + params: AwardCreateRequest, +) => { + const { owner: awardOwner, award } = await createAward(project, owner, params); const batch = build5Db().batch(); diff --git a/packages/functions/src/controls/award/award.fund.ts b/packages/functions/src/controls/award/award.fund.ts index 736ca1803b..67f7dbd55b 100644 --- a/packages/functions/src/controls/award/award.fund.ts +++ b/packages/functions/src/controls/award/award.fund.ts @@ -1,17 +1,14 @@ import { build5Db } from '@build-5/database'; -import { AwardFundRequest, COL, Transaction } from '@build-5/interfaces'; +import { AwardFundRequest, COL } from '@build-5/interfaces'; import { Context } from '../../runtime/firebase/common'; import { createAwardFundOrder, getAwardForFunding, } from '../../services/payment/tangle-service/award/award.fund.service'; -export const fundAwardControl = async ( - { owner }: Context, - params: AwardFundRequest, -): Promise => { +export const fundAwardControl = async ({ project, owner }: Context, params: AwardFundRequest) => { const award = await getAwardForFunding(owner, params.uid); - const order = await createAwardFundOrder(owner, award); + const order = await createAwardFundOrder(project, owner, award); await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); diff --git a/packages/functions/src/controls/award/award.owner.ts b/packages/functions/src/controls/award/award.owner.ts index dd6fe57c87..3f64be9352 100644 --- a/packages/functions/src/controls/award/award.owner.ts +++ b/packages/functions/src/controls/award/award.owner.ts @@ -1,3 +1,4 @@ +import { build5Db } from '@build-5/database'; import { Award, AwardAddOwnerRequest, @@ -8,12 +9,12 @@ import { } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { Context } from '../../runtime/firebase/common'; +import { getProjects } from '../../utils/common.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; -import { build5Db } from '@build-5/database'; export const addOwnerControl = async ( - { owner }: Context, + { project, owner }: Context, params: AwardAddOwnerRequest, ): Promise => { const awardDocRef = build5Db().doc(`${COL.AWARD}/${params.uid}`); @@ -33,6 +34,8 @@ export const addOwnerControl = async ( } const newOwner: AwardOwner = { + project, + projects: getProjects([award], project), uid: params.member, parentId: award.uid, parentCol: COL.AWARD, diff --git a/packages/functions/src/controls/award/award.participate.ts b/packages/functions/src/controls/award/award.participate.ts index 75319ad703..bb5504fc12 100644 --- a/packages/functions/src/controls/award/award.participate.ts +++ b/packages/functions/src/controls/award/award.participate.ts @@ -9,11 +9,12 @@ import { } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { Context } from '../../runtime/firebase/common'; +import { getProjects } from '../../utils/common.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; export const awardParticipateControl = async ( - { owner }: Context, + { project, owner }: Context, params: AwardParticpateRequest, ): Promise => { const awardDocRef = build5Db().doc(`${COL.AWARD}/${params.uid}`); @@ -41,6 +42,8 @@ export const awardParticipateControl = async ( const participant: AwardParticipant = { uid: owner, + project, + projects: getProjects([award], project), comment: params.comment || null, parentId: award.uid, completed: false, diff --git a/packages/functions/src/controls/collection/collection-mint.control.ts b/packages/functions/src/controls/collection/collection-mint.control.ts index dcbdd1abb5..aa997237eb 100644 --- a/packages/functions/src/controls/collection/collection-mint.control.ts +++ b/packages/functions/src/controls/collection/collection-mint.control.ts @@ -30,6 +30,7 @@ import { createNftOutput, nftToMetadata, } from '../../utils/collection-minting-utils/nft.utils'; +import { getProjects } from '../../utils/common.utils'; import { isProdEnv } from '../../utils/config.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; @@ -38,7 +39,7 @@ import { assertIsGuardian } from '../../utils/token.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; export const mintCollectionOrderControl = async ( - { owner }: Context, + { project, owner }: Context, params: CollectionMintRequest, ) => { const network = params.network as Network; @@ -106,6 +107,8 @@ export const mintCollectionOrderControl = async ( const aliasStorageDeposit = Number(createAliasOutput(targetAddress, wallet.info).amount); const order: Transaction = { + project, + projects: getProjects([collection], project), type: TransactionType.ORDER, uid: getRandomEthAddress(), member: owner, diff --git a/packages/functions/src/controls/collection/collection.create.control.ts b/packages/functions/src/controls/collection/collection.create.control.ts index a07c41bb2b..5a8a0ce080 100644 --- a/packages/functions/src/controls/collection/collection.create.control.ts +++ b/packages/functions/src/controls/collection/collection.create.control.ts @@ -16,6 +16,7 @@ import { import { Context } from '../../runtime/firebase/common'; import { hasStakedTokens } from '../../services/stake.service'; import { assertSpaceHasValidAddress } from '../../utils/address.utils'; +import { getProjects } from '../../utils/common.utils'; import { dateToTimestamp, serverTime } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; @@ -57,6 +58,8 @@ export const createCollectionControl = async ( const placeholderNftId = params.type !== CollectionType.CLASSIC ? getRandomEthAddress() : null; const collection = { ...params, + project, + projects: getProjects([], project), discounts: await populateTokenUidOnDiscounts(discounts), uid: getRandomEthAddress(), total: 0, @@ -75,6 +78,8 @@ export const createCollectionControl = async ( if (placeholderNftId) { const placeholderNft = { + project, + projects: getProjects([collection], project), uid: placeholderNftId, name: params.name, description: params.description, diff --git a/packages/functions/src/controls/credit/credit.controller.ts b/packages/functions/src/controls/credit/credit.controller.ts index 8e3fb23937..d6826413aa 100644 --- a/packages/functions/src/controls/credit/credit.controller.ts +++ b/packages/functions/src/controls/credit/credit.controller.ts @@ -15,14 +15,15 @@ import { import dayjs from 'dayjs'; import { Context } from '../../runtime/firebase/common'; import { WalletService } from '../../services/wallet/wallet'; +import { getProjects } from '../../utils/common.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; export const creditUnrefundableControl = ( - { owner }: Context, + { project, owner }: Context, params: CreditUnrefundableRequest, -): Promise => +) => build5Db().runTransaction(async (transaction) => { const transactionDocRef = build5Db().doc(`${COL.TRANSACTION}/${params.transaction}`); const creditTransaction = await transaction.get(transactionDocRef); @@ -41,7 +42,7 @@ export const creditUnrefundableControl = ( const wallet = await WalletService.newWallet(creditTransaction.network); const targetAddress = await wallet.getNewIotaAddressDetails(); - const creditOrder = createCreditOrder(creditTransaction, owner, targetAddress.bech32); + const creditOrder = createCreditOrder(project, creditTransaction, owner, targetAddress.bech32); const creditDocRef = build5Db().doc(`${COL.TRANSACTION}/${creditOrder.uid}`); transaction.create(creditDocRef, creditOrder); @@ -49,10 +50,13 @@ export const creditUnrefundableControl = ( }); const createCreditOrder = ( + project: string, creditTtransaction: Transaction, owner: string, targetAddress: NetworkAddress, ): Transaction => ({ + project: project, + projects: getProjects([creditTtransaction], project), type: TransactionType.ORDER, uid: getRandomEthAddress(), member: owner, diff --git a/packages/functions/src/controls/nft/nft.bid.control.ts b/packages/functions/src/controls/nft/nft.bid.control.ts index 570c1d719f..ed15df4158 100644 --- a/packages/functions/src/controls/nft/nft.bid.control.ts +++ b/packages/functions/src/controls/nft/nft.bid.control.ts @@ -4,20 +4,17 @@ import { Context } from '../../runtime/firebase/common'; import { createNftBidOrder } from '../../services/payment/tangle-service/nft/nft-bid.service'; import { invalidArgument } from '../../utils/error.utils'; -export const nftBidControl = async ( - { owner, ip }: Context, - params: NftBidRequest, -): Promise => { +export const nftBidControl = async ({ project, owner, ip }: Context, params: NftBidRequest) => { const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); const member = await memberDocRef.get(); if (!member) { throw invalidArgument(WenError.member_does_not_exists); } - const bidTransaction = await createNftBidOrder(params.nft, owner, ip || ''); + const bidTransaction = await createNftBidOrder(project, params.nft, owner, ip || ''); const transactionDocRef = build5Db().doc(`${COL.TRANSACTION}/${bidTransaction.uid}`); await transactionDocRef.create(bidTransaction); - return (await transactionDocRef.get())!; + return (await transactionDocRef.get())!; }; diff --git a/packages/functions/src/controls/nft/nft.create.ts b/packages/functions/src/controls/nft/nft.create.ts index 1fcd63555b..d331cb5bd7 100644 --- a/packages/functions/src/controls/nft/nft.create.ts +++ b/packages/functions/src/controls/nft/nft.create.ts @@ -13,25 +13,26 @@ import { import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; import { Context } from '../../runtime/firebase/common'; +import { getProjects } from '../../utils/common.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; export const createNftControl = async ( - { owner }: Context, + { project, owner }: Context, params: NftCreateRequest, ): Promise => { const collection = await getCollection(owner, params.collection as string); - return await processOneCreateNft(params, collection, collection.total + 1); + return await processOneCreateNft(project, params, collection, collection.total + 1); }; export const createBatchNftControl = async ( - { owner }: Context, + { project, owner }: Context, params: NftCreateRequest[], ): Promise => { const collection = await getCollection(owner, params[0].collection); const promises = params.map((param, i) => - processOneCreateNft(param, collection, collection.total + i + 1), + processOneCreateNft(project, param, collection, collection.total + i + 1), ); return (await Promise.all(promises)).map((n) => n.uid); }; @@ -63,6 +64,7 @@ const getCollection = async (owner: string, collectionId: string) => { }; const processOneCreateNft = async ( + project: string, params: NftCreateRequest, collection: Collection, position: number, @@ -100,6 +102,8 @@ const processOneCreateNft = async ( const price = Math.max(Number(params.price) || 0, MIN_IOTA_AMOUNT); const nft = { ...params, + project, + projects: getProjects([], project), uid: getRandomEthAddress(), locked: false, price, diff --git a/packages/functions/src/controls/nft/nft.deposit.ts b/packages/functions/src/controls/nft/nft.deposit.ts index 4bcea0e4c9..142f7881f9 100644 --- a/packages/functions/src/controls/nft/nft.deposit.ts +++ b/packages/functions/src/controls/nft/nft.deposit.ts @@ -12,18 +12,18 @@ import { import dayjs from 'dayjs'; import { Context } from '../../runtime/firebase/common'; import { WalletService } from '../../services/wallet/wallet'; +import { getProjects } from '../../utils/common.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; -export const depositNftControl = async ( - { owner }: Context, - params: NftDepositRequest, -): Promise => { +export const depositNftControl = async ({ project, owner }: Context, params: NftDepositRequest) => { const network = params.network as Network; const wallet = await WalletService.newWallet(network); const targetAddress = await wallet.getNewIotaAddressDetails(); const order: Transaction = { + project, + projects: getProjects([], project), type: TransactionType.ORDER, uid: getRandomEthAddress(), member: owner, diff --git a/packages/functions/src/controls/nft/nft.puchase.control.ts b/packages/functions/src/controls/nft/nft.puchase.control.ts index a41ea71eef..3e945f5228 100644 --- a/packages/functions/src/controls/nft/nft.puchase.control.ts +++ b/packages/functions/src/controls/nft/nft.puchase.control.ts @@ -4,10 +4,16 @@ import { Context } from '../../runtime/firebase/common'; import { createNftPuchaseOrder } from '../../services/payment/tangle-service/nft/nft-purchase.service'; export const orderNftControl = async ( - { owner, ip }: Context, + { project, owner, ip }: Context, params: NftPurchaseRequest, -): Promise => { - const order = await createNftPuchaseOrder(params.collection, params.nft, owner, ip || ''); +) => { + const order = await createNftPuchaseOrder( + project, + params.collection, + params.nft, + owner, + ip || '', + ); const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); await orderDocRef.create(order); diff --git a/packages/functions/src/controls/nft/nft.stake.ts b/packages/functions/src/controls/nft/nft.stake.ts index 13c9c11a60..d1e33e5ea7 100644 --- a/packages/functions/src/controls/nft/nft.stake.ts +++ b/packages/functions/src/controls/nft/nft.stake.ts @@ -1,13 +1,11 @@ import { build5Db } from '@build-5/database'; -import { COL, Network, NftStakeRequest, StakeType, Transaction } from '@build-5/interfaces'; +import { COL, Network, NftStakeRequest, StakeType } from '@build-5/interfaces'; import { Context } from '../../runtime/firebase/common'; import { createNftStakeOrder } from '../../services/payment/nft/nft-stake.service'; -export const nftStakeControl = async ( - { owner }: Context, - params: NftStakeRequest, -): Promise => { +export const nftStakeControl = async ({ project, owner }: Context, params: NftStakeRequest) => { const order = await createNftStakeOrder( + project, owner, params.network as Network, params.weeks, diff --git a/packages/functions/src/controls/nft/nft.withdraw.ts b/packages/functions/src/controls/nft/nft.withdraw.ts index 3f45922e04..0f9ad7d898 100644 --- a/packages/functions/src/controls/nft/nft.withdraw.ts +++ b/packages/functions/src/controls/nft/nft.withdraw.ts @@ -14,7 +14,7 @@ import { createNftWithdrawOrder } from '../../services/payment/tangle-service/nf import { assertMemberHasValidAddress, getAddress } from '../../utils/address.utils'; import { invalidArgument } from '../../utils/error.utils'; -export const withdrawNftControl = async ({ owner }: Context, params: NftWithdrawRequest) => +export const withdrawNftControl = async ({ project, owner }: Context, params: NftWithdrawRequest) => build5Db().runTransaction(async (transaction) => { const nftDocRef = build5Db().doc(`${COL.NFT}/${params.nft}`); const nft = await transaction.get(nftDocRef); @@ -49,6 +49,7 @@ export const withdrawNftControl = async ({ owner }: Context, params: NftWithdraw assertMemberHasValidAddress(member, nft.mintingData?.network!); const { order, nftUpdateData } = createNftWithdrawOrder( + project, nft, member!.uid, getAddress(member, nft.mintingData?.network!), diff --git a/packages/functions/src/controls/project/init.soon.project.ts b/packages/functions/src/controls/project/init.soon.project.ts index c040647446..a56acd5d87 100644 --- a/packages/functions/src/controls/project/init.soon.project.ts +++ b/packages/functions/src/controls/project/init.soon.project.ts @@ -30,6 +30,8 @@ export const initSoonProject = functions.https.onRequest(async () => { const guardianDocRef = projectDocRef.collection(SUB_COL.GUARDIANS).doc(GUARDIAN_ID); const guardian: ProjectGuardian = { + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, uid: GUARDIAN_ID, createdOn: dateToTimestamp(dayjs()), parentCol: COL.PROJECT, diff --git a/packages/functions/src/controls/project/project.create.control.ts b/packages/functions/src/controls/project/project.create.control.ts index 39a9473e75..6f1b163fca 100644 --- a/packages/functions/src/controls/project/project.create.control.ts +++ b/packages/functions/src/controls/project/project.create.control.ts @@ -45,6 +45,8 @@ export const createProjectControl = async ({ owner }: Context, params: ProjectCr const guardianDocRef = projectDocRef.collection(SUB_COL.GUARDIANS).doc(owner); const guardian: ProjectGuardian = { + project: projectData.uid, + projects: { [projectData.uid]: true }, uid: owner, createdOn: dateToTimestamp(dayjs()), parentCol: COL.PROJECT, diff --git a/packages/functions/src/controls/proposal/create.proposal.ts b/packages/functions/src/controls/proposal/create.proposal.ts index 519e77cff7..88abd4aac3 100644 --- a/packages/functions/src/controls/proposal/create.proposal.ts +++ b/packages/functions/src/controls/proposal/create.proposal.ts @@ -3,8 +3,11 @@ import { COL, Proposal, ProposalCreateRequest, SUB_COL } from '@build-5/interfac import { Context } from '../../runtime/firebase/common'; import { createProposal } from '../../services/payment/tangle-service/proposal/ProposalCreateService'; -export const createProposalControl = async ({ owner }: Context, params: ProposalCreateRequest) => { - const { proposal, proposalOwner } = await createProposal(owner, { ...params }); +export const createProposalControl = async ( + { project, owner }: Context, + params: ProposalCreateRequest, +) => { + const { proposal, proposalOwner } = await createProposal(project, owner, { ...params }); const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); await proposalDocRef.create(proposal); diff --git a/packages/functions/src/controls/proposal/vote.on.proposal.ts b/packages/functions/src/controls/proposal/vote.on.proposal.ts index b58f082148..2f5bab2d4d 100644 --- a/packages/functions/src/controls/proposal/vote.on.proposal.ts +++ b/packages/functions/src/controls/proposal/vote.on.proposal.ts @@ -20,7 +20,7 @@ import { invalidArgument } from '../../utils/error.utils'; import { getTokenForSpace } from '../../utils/token.utils'; export const voteOnProposalControl = async ( - { owner }: Context, + { project, owner }: Context, params: ProposalVoteRequest, ): Promise => { const proposal = await getProposal(params.uid); @@ -34,19 +34,19 @@ export const voteOnProposalControl = async ( if (params.voteWithStakedTokes) { const voteTransaction = await build5Db().runTransaction(async (transaction) => - voteWithStakedTokens(transaction, owner, proposal, [params.value]), + voteWithStakedTokens(project, transaction, owner, proposal, [params.value]), ); return voteTransaction; } - const order = await createVoteTransactionOrder(owner, proposal, [params.value], token); + const order = await createVoteTransactionOrder(project, owner, proposal, [params.value], token); const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); await orderDocRef.create(order); return (await orderDocRef.get())!; } - const voteData = await executeSimpleVoting(proposalMember, proposal, [params.value]); + const voteData = await executeSimpleVoting(project, proposalMember, proposal, [params.value]); const batch = build5Db().batch(); const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); diff --git a/packages/functions/src/controls/space/member.accept.control.ts b/packages/functions/src/controls/space/member.accept.control.ts index 72cd5eaa2e..49c0d19be7 100644 --- a/packages/functions/src/controls/space/member.accept.control.ts +++ b/packages/functions/src/controls/space/member.accept.control.ts @@ -4,10 +4,10 @@ import { Context } from '../../runtime/firebase/common'; import { acceptSpaceMember } from '../../services/payment/tangle-service/space/SpaceAcceptMemberService'; export const acceptSpaceMemberControl = async ( - { owner }: Context, + { project, owner }: Context, params: SpaceMemberUpsertRequest, ) => { - const { spaceMember, space } = await acceptSpaceMember(owner, params.uid, params.member); + const { spaceMember, space } = await acceptSpaceMember(project, owner, params.uid, params.member); const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); const memberDocRef = spaceDocRef.collection(SUB_COL.MEMBERS).doc(spaceMember.uid); diff --git a/packages/functions/src/controls/space/member.block.control.ts b/packages/functions/src/controls/space/member.block.control.ts index 3dce564113..b2a96b373b 100644 --- a/packages/functions/src/controls/space/member.block.control.ts +++ b/packages/functions/src/controls/space/member.block.control.ts @@ -3,9 +3,17 @@ import { COL, SpaceMember, SpaceMemberUpsertRequest, SUB_COL } from '@build-5/in import { Context } from '../../runtime/firebase/common'; import { getBlockMemberUpdateData } from '../../services/payment/tangle-service/space/SpaceBlockMemberService'; -export const blockMemberControl = async ({ owner }: Context, params: SpaceMemberUpsertRequest) => { +export const blockMemberControl = async ( + { project, owner }: Context, + params: SpaceMemberUpsertRequest, +) => { const member = params.member; - const { space, blockedMember } = await getBlockMemberUpdateData(owner, params.uid, member); + const { space, blockedMember } = await getBlockMemberUpdateData( + project, + owner, + params.uid, + member, + ); const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); const blockedMemberDocRef = spaceDocRef.collection(SUB_COL.BLOCKED_MEMBERS).doc(member); diff --git a/packages/functions/src/controls/space/space.claim.control.ts b/packages/functions/src/controls/space/space.claim.control.ts index 2b458d39ad..593b095289 100644 --- a/packages/functions/src/controls/space/space.claim.control.ts +++ b/packages/functions/src/controls/space/space.claim.control.ts @@ -1,3 +1,4 @@ +import { build5Db } from '@build-5/database'; import { COL, Collection, @@ -13,13 +14,12 @@ import { import dayjs from 'dayjs'; import { Context } from '../../runtime/firebase/common'; import { WalletService } from '../../services/wallet/wallet'; -import { generateRandomAmount } from '../../utils/common.utils'; +import { generateRandomAmount, getProjects } from '../../utils/common.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; -import { build5Db } from '@build-5/database'; -export const claimSpaceControl = async ({ owner }: Context, params: SpaceClaimRequest) => { +export const claimSpaceControl = async ({ project, owner }: Context, params: SpaceClaimRequest) => { const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); const space = await spaceDocRef.get(); if (!space) { @@ -37,6 +37,8 @@ export const claimSpaceControl = async ({ owner }: Context, params: SpaceClaimRe const wallet = await WalletService.newWallet(collection?.mintingData?.network); const targetAddress = await wallet.getNewIotaAddressDetails(); const order: Transaction = { + project, + projects: getProjects([space], project), type: TransactionType.ORDER, uid: getRandomEthAddress(), member: owner, diff --git a/packages/functions/src/controls/space/space.create.control.ts b/packages/functions/src/controls/space/space.create.control.ts index 49f3d8c4cc..31a930e688 100644 --- a/packages/functions/src/controls/space/space.create.control.ts +++ b/packages/functions/src/controls/space/space.create.control.ts @@ -1,13 +1,13 @@ +import { build5Db } from '@build-5/database'; import { COL, SUB_COL, Space, SpaceCreateRequest } from '@build-5/interfaces'; import { Context } from '../../runtime/firebase/common'; import { getCreateSpaceData } from '../../services/payment/tangle-service/space/SpaceCreateService'; -import { build5Db } from '@build-5/database'; export const createSpaceControl = async ( - { owner }: Context, + { project, owner }: Context, params: SpaceCreateRequest, ): Promise => { - const { space, guardian, member } = await getCreateSpaceData(owner, { ...params }); + const { space, guardian, member } = await getCreateSpaceData(project, owner, { ...params }); const batch = build5Db().batch(); diff --git a/packages/functions/src/controls/space/space.guardian.edit.control.ts b/packages/functions/src/controls/space/space.guardian.edit.control.ts index 5c2a3634a6..58d1e2a74b 100644 --- a/packages/functions/src/controls/space/space.guardian.edit.control.ts +++ b/packages/functions/src/controls/space/space.guardian.edit.control.ts @@ -11,8 +11,9 @@ import { addRemoveGuardian } from '../../services/payment/tangle-service/space/S export const editGuardianControl = (type: ProposalType) => - async ({ owner }: Context, params: SpaceMemberUpsertRequest) => { + async ({ project, owner }: Context, params: SpaceMemberUpsertRequest) => { const { proposal, voteTransaction, members } = await addRemoveGuardian( + project, owner, { ...params }, type, diff --git a/packages/functions/src/controls/space/space.join.control.ts b/packages/functions/src/controls/space/space.join.control.ts index e1b85ac6d8..04e9e6cda2 100644 --- a/packages/functions/src/controls/space/space.join.control.ts +++ b/packages/functions/src/controls/space/space.join.control.ts @@ -4,13 +4,17 @@ import { Context } from '../../runtime/firebase/common'; import { getJoinSpaceData } from '../../services/payment/tangle-service/space/SpaceJoinService'; import { invalidArgument } from '../../utils/error.utils'; -export const joinSpaceControl = async ({ owner }: Context, params: SpaceJoinRequest) => { +export const joinSpaceControl = async ({ project, owner }: Context, params: SpaceJoinRequest) => { const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); const space = await spaceDocRef.get(); if (!space) { throw invalidArgument(WenError.space_does_not_exists); } - const { space: spaceUpdateData, spaceMember, member } = await getJoinSpaceData(owner, space); + const { + space: spaceUpdateData, + spaceMember, + member, + } = await getJoinSpaceData(project, owner, space); const batch = build5Db().batch(); diff --git a/packages/functions/src/controls/space/space.update.control.ts b/packages/functions/src/controls/space/space.update.control.ts index 53a3c16fbf..8912f04d2b 100644 --- a/packages/functions/src/controls/space/space.update.control.ts +++ b/packages/functions/src/controls/space/space.update.control.ts @@ -1,3 +1,4 @@ +import { build5Db } from '@build-5/database'; import { BaseProposalAnswerValue, COL, @@ -18,15 +19,18 @@ import { import dayjs from 'dayjs'; import { get, startCase } from 'lodash'; import { Context } from '../../runtime/firebase/common'; +import { getProjects } from '../../utils/common.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; import { cleanupParams } from '../../utils/schema.utils'; import { hasActiveEditProposal } from '../../utils/space.utils'; import { assertIsGuardian, getTokenForSpace } from '../../utils/token.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; -import { build5Db } from '@build-5/database'; -export const updateSpaceControl = async ({ owner }: Context, params: SpaceUpdateRequest) => { +export const updateSpaceControl = async ( + { project, owner }: Context, + params: SpaceUpdateRequest, +) => { const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); const space = await spaceDocRef.get(); @@ -56,6 +60,7 @@ export const updateSpaceControl = async ({ owner }: Context, params: SpaceUpdate const guardians = await spaceDocRef.collection(SUB_COL.GUARDIANS).get(); const proposal = createUpdateSpaceProposal( + project, space, guardian!, space.uid, @@ -64,6 +69,8 @@ export const updateSpaceControl = async ({ owner }: Context, params: SpaceUpdate ); const voteTransaction: Transaction = { + project, + projects: getProjects([space], project), type: TransactionType.VOTE, uid: getRandomEthAddress(), member: owner, @@ -103,17 +110,20 @@ export const updateSpaceControl = async ({ owner }: Context, params: SpaceUpdate }; const createUpdateSpaceProposal = ( + project: string, prevSpace: Space, owner: Member, space: string, guardiansCount: number, spaceUpdateData: Space, -) => { +): Proposal => { const additionalInfo = `${owner.name || owner.uid} wants to edit the space. ` + `Request created on ${dayjs().format('MM/DD/YYYY')}. ` + `${UPDATE_SPACE_THRESHOLD_PERCENTAGE} % must agree for this action to proceed`; - return { + return { + project, + projects: getProjects([prevSpace], project), createdBy: owner.uid, uid: getRandomEthAddress(), name: 'Edit space', diff --git a/packages/functions/src/controls/stake/stake.deposit.ts b/packages/functions/src/controls/stake/stake.deposit.ts index 2aa7367a7a..f938df5bc0 100644 --- a/packages/functions/src/controls/stake/stake.deposit.ts +++ b/packages/functions/src/controls/stake/stake.deposit.ts @@ -1,10 +1,14 @@ +import { build5Db } from '@build-5/database'; import { COL, StakeType, TokenStakeRequest } from '@build-5/interfaces'; import { Context } from '../../runtime/firebase/common'; import { createStakeOrder } from '../../services/payment/tangle-service/token/stake.service'; -import { build5Db } from '@build-5/database'; -export const depositStakeControl = async ({ owner }: Context, params: TokenStakeRequest) => { +export const depositStakeControl = async ( + { project, owner }: Context, + params: TokenStakeRequest, +) => { const order = await createStakeOrder( + project, owner, params.symbol, params.weeks, diff --git a/packages/functions/src/controls/stake/stake.reward.revoke.ts b/packages/functions/src/controls/stake/stake.reward.revoke.ts index 6bb058d545..cf04ae02cb 100644 --- a/packages/functions/src/controls/stake/stake.reward.revoke.ts +++ b/packages/functions/src/controls/stake/stake.reward.revoke.ts @@ -7,6 +7,7 @@ import { Proposal, ProposalType, REMOVE_STAKE_REWARDS_THRESHOLD_PERCENTAGE, + Space, SpaceGuardian, StakeReward, SUB_COL, @@ -20,13 +21,14 @@ import { import dayjs from 'dayjs'; import { uniq } from 'lodash'; import { Context } from '../../runtime/firebase/common'; +import { getProjects } from '../../utils/common.utils'; import { dateToTimestamp, serverTime } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; import { assertIsGuardian } from '../../utils/token.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; export const removeStakeRewardControl = async ( - { owner }: Context, + { project, owner }: Context, params: TokenStakeRewardsRemoveRequest, ) => { const stakeRewardIds = params.stakeRewardIds as string[]; @@ -72,15 +74,21 @@ export const removeStakeRewardControl = async ( .doc(token.space) .collection(SUB_COL.GUARDIANS) .get(); + + const spaceDocRef = build5Db().doc(`${COL.SPACE}/${token.space}`); + const space = await spaceDocRef.get(); const proposal = createUpdateSpaceProposal( + project, guardian, - token.space, + space!, guardians.length, stakeRewards as StakeReward[], proposalEndDate, ); const voteTransaction: Transaction = { + project, + projects: getProjects([proposal], project), type: TransactionType.VOTE, uid: getRandomEthAddress(), member: owner, @@ -101,6 +109,8 @@ export const removeStakeRewardControl = async ( .collection(SUB_COL.MEMBERS) .doc(guardian.uid) .set({ + project, + projects: getProjects([proposal], project), uid: guardian.uid, weight: 1, voted: guardian.uid === owner, @@ -120,23 +130,26 @@ export const removeStakeRewardControl = async ( }; const createUpdateSpaceProposal = ( + project: string, owner: Member, - space: string, + space: Space, guardiansCount: number, stakeRewards: StakeReward[], endDate: Timestamp, -) => { +): Proposal => { const additionalInfo = `${owner.name || owner.uid} wants to remove stake rewards. ` + `Request created on ${dayjs().format('MM/DD/YYYY')}.` + `${REMOVE_STAKE_REWARDS_THRESHOLD_PERCENTAGE} % must agree for this action to proceed

`; - return { + return { + project, + projects: getProjects([space], project), createdBy: owner.uid, description: '', uid: getRandomEthAddress(), name: 'Remove stake rewards', additionalInfo: additionalInfo + getDescription(stakeRewards), - space, + space: space.uid, type: ProposalType.REMOVE_STAKE_REWARD, approved: true, rejected: false, @@ -157,7 +170,6 @@ const createUpdateSpaceProposal = ( additionalInfo: '', }, { - uid: getRandomEthAddress(), text: 'Yes', value: BaseProposalAnswerValue.YES, additionalInfo: '', diff --git a/packages/functions/src/controls/stake/stake.reward.ts b/packages/functions/src/controls/stake/stake.reward.ts index d311ba0b5d..f88333fd93 100644 --- a/packages/functions/src/controls/stake/stake.reward.ts +++ b/packages/functions/src/controls/stake/stake.reward.ts @@ -9,12 +9,16 @@ import { } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { Context } from '../../runtime/firebase/common'; +import { getProjects } from '../../utils/common.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; import { assertIsGuardian } from '../../utils/token.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; -export const stakeRewardControl = async ({ owner }: Context, params: TokenStakeRewardsRequest) => { +export const stakeRewardControl = async ( + { project, owner }: Context, + params: TokenStakeRewardsRequest, +) => { const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${params.token}`); const token = await tokenDocRef.get(); if (!token) { @@ -23,6 +27,8 @@ export const stakeRewardControl = async ({ owner }: Context, params: TokenStakeR await assertIsGuardian(token.space, owner); const stakeRewards = (params.items || []).map((item) => ({ + project, + projects: getProjects([], project), uid: getRandomEthAddress(), startDate: dateToTimestamp(dayjs(item.startDate)), endDate: dateToTimestamp(dayjs(item.endDate)), diff --git a/packages/functions/src/controls/token-minting/airdrop-minted-token.ts b/packages/functions/src/controls/token-minting/airdrop-minted-token.ts index 4718a67d5d..743c9caca8 100644 --- a/packages/functions/src/controls/token-minting/airdrop-minted-token.ts +++ b/packages/functions/src/controls/token-minting/airdrop-minted-token.ts @@ -1,4 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import { build5Db } from '@build-5/database'; import { COL, StakeType, @@ -26,10 +27,10 @@ import { dateToTimestamp } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; import { assertIsGuardian, assertTokenApproved, assertTokenStatus } from '../../utils/token.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; -import { build5Db } from '@build-5/database'; +import { getProjects } from '../../utils/common.utils'; export const airdropMintedTokenControl = async ( - { owner }: Context, + { project, owner }: Context, params: CreateAirdropsRequest, ) => { const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${params.token}`); @@ -56,6 +57,8 @@ export const airdropMintedTokenControl = async ( }; const output = packBasicOutput(targetAddress.bech32, 0, [nativeToken], wallet.info); const order: Transaction = { + project, + projects: getProjects([], project), type: TransactionType.ORDER, uid: getRandomEthAddress(), member: owner, @@ -76,6 +79,8 @@ export const airdropMintedTokenControl = async ( }; const airdrops: TokenDrop[] = drops.map((drop) => ({ + project, + projects: getProjects([], project), createdBy: owner, uid: getRandomEthAddress(), member: drop.recipient.toLowerCase(), diff --git a/packages/functions/src/controls/token-minting/claim-minted-token.control.ts b/packages/functions/src/controls/token-minting/claim-minted-token.control.ts index 87635d2972..b3df177ad1 100644 --- a/packages/functions/src/controls/token-minting/claim-minted-token.control.ts +++ b/packages/functions/src/controls/token-minting/claim-minted-token.control.ts @@ -4,10 +4,10 @@ import { Context } from '../../runtime/firebase/common'; import { createMintedTokenAirdropCalimOrder } from '../../services/payment/tangle-service/token/token-claim.service'; export const claimMintedTokenControl = async ( - { owner }: Context, + { project, owner }: Context, params: ClaimAirdroppedTokensRequest, ) => { - const order = await createMintedTokenAirdropCalimOrder(owner, params.symbol); + const order = await createMintedTokenAirdropCalimOrder(project, owner, params.symbol); await build5Db().doc(`${COL.TRANSACTION}/${order.uid}`).create(order); return order; }; diff --git a/packages/functions/src/controls/token-minting/import-minted-token.ts b/packages/functions/src/controls/token-minting/import-minted-token.ts index 500dd12500..c5a02090c2 100644 --- a/packages/functions/src/controls/token-minting/import-minted-token.ts +++ b/packages/functions/src/controls/token-minting/import-minted-token.ts @@ -16,14 +16,14 @@ import { isEmpty } from 'lodash'; import { Context } from '../../runtime/firebase/common'; import { SmrWallet } from '../../services/wallet/SmrWalletService'; import { WalletService } from '../../services/wallet/wallet'; -import { generateRandomAmount } from '../../utils/common.utils'; +import { generateRandomAmount, getProjects } from '../../utils/common.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; import { assertIsGuardian } from '../../utils/token.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; export const importMintedTokenControl = async ( - { owner }: Context, + { project, owner }: Context, params: ImportMintedTokenRequest, ) => build5Db().runTransaction(async (transaction) => { @@ -45,6 +45,8 @@ export const importMintedTokenControl = async ( const targetAddress = await wallet.getNewIotaAddressDetails(); const order: Transaction = { + project, + projects: getProjects([], project), type: TransactionType.ORDER, uid: getRandomEthAddress(), member: owner, diff --git a/packages/functions/src/controls/token-minting/token-mint.control.ts b/packages/functions/src/controls/token-minting/token-mint.control.ts index 564329621f..c6ccc25e21 100644 --- a/packages/functions/src/controls/token-minting/token-mint.control.ts +++ b/packages/functions/src/controls/token-minting/token-mint.control.ts @@ -1,3 +1,4 @@ +import { build5Db } from '@build-5/database'; import { COL, Member, @@ -33,9 +34,9 @@ import { getUnclaimedAirdropTotalValue, } from '../../utils/token.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; -import { build5Db } from '@build-5/database'; +import { getProjects } from '../../utils/common.utils'; -export const mintTokenControl = ({ owner }: Context, params: TokenMintRequest) => +export const mintTokenControl = ({ project, owner }: Context, params: TokenMintRequest) => build5Db().runTransaction(async (transaction) => { const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${params.token}`); const token = await transaction.get(tokenDocRef); @@ -66,6 +67,8 @@ export const mintTokenControl = ({ owner }: Context, params: TokenMintRequest) = ); const order: Transaction = { + project, + projects: getProjects([token], project), type: TransactionType.ORDER, uid: getRandomEthAddress(), member: owner, diff --git a/packages/functions/src/controls/token-trading/token-trade.controller.ts b/packages/functions/src/controls/token-trading/token-trade.controller.ts index 124581629c..8e657bfad7 100644 --- a/packages/functions/src/controls/token-trading/token-trade.controller.ts +++ b/packages/functions/src/controls/token-trading/token-trade.controller.ts @@ -1,3 +1,4 @@ +import { build5Db } from '@build-5/database'; import { COL, SUB_COL, @@ -10,9 +11,11 @@ import { Context } from '../../runtime/firebase/common'; import { createTokenTradeOrder } from '../../services/payment/tangle-service/token/token-trade.service'; import { invalidArgument } from '../../utils/error.utils'; import { getTokenBySymbol } from '../../utils/token.utils'; -import { build5Db } from '@build-5/database'; -export const tradeTokenControl = async ({ owner, ip }: Context, params: TradeTokenRequest) => { +export const tradeTokenControl = async ( + { project, owner, ip }: Context, + params: TradeTokenRequest, +) => { let token = await getTokenBySymbol(params.symbol); return await build5Db().runTransaction(async (transaction) => { @@ -26,6 +29,7 @@ export const tradeTokenControl = async ({ owner, ip }: Context, params: TradeTok } const { tradeOrderTransaction, tradeOrder, distribution } = await createTokenTradeOrder( + project, transaction, owner, token, diff --git a/packages/functions/src/controls/token/token.airdrop.claim.ts b/packages/functions/src/controls/token/token.airdrop.claim.ts index 1313ca57d4..7b8e94778c 100644 --- a/packages/functions/src/controls/token/token.airdrop.claim.ts +++ b/packages/functions/src/controls/token/token.airdrop.claim.ts @@ -1,3 +1,4 @@ +import { build5Db } from '@build-5/database'; import { COL, ClaimPreMintedAirdroppedTokensRequest, @@ -15,17 +16,16 @@ import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; import { Context } from '../../runtime/firebase/common'; import { WalletService } from '../../services/wallet/wallet'; -import { generateRandomAmount } from '../../utils/common.utils'; +import { generateRandomAmount, getProjects } from '../../utils/common.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; import { assertTokenStatus, getUnclaimedDrops } from '../../utils/token.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; -import { build5Db } from '@build-5/database'; export const claimAirdroppedTokenControl = async ( - { owner }: Context, + { project, owner }: Context, params: ClaimPreMintedAirdroppedTokensRequest, -): Promise => { +) => { const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${params.token}`); const token = await tokenDocRef.get(); if (!token) { @@ -48,6 +48,8 @@ export const claimAirdroppedTokenControl = async ( const quantity = claimableDrops.reduce((sum, act) => sum + act.count, 0); const order: Transaction = { + project, + projects: getProjects([], project), type: TransactionType.ORDER, uid: tranId, member: owner, diff --git a/packages/functions/src/controls/token/token.airdrop.ts b/packages/functions/src/controls/token/token.airdrop.ts index ec0accf433..58d6574c88 100644 --- a/packages/functions/src/controls/token/token.airdrop.ts +++ b/packages/functions/src/controls/token/token.airdrop.ts @@ -1,3 +1,4 @@ +import { build5Db } from '@build-5/database'; import { COL, StakeType, @@ -11,11 +12,11 @@ import { import { chunk } from 'lodash'; import { Context } from '../../runtime/firebase/common'; import { CreateAirdropsRequest } from '../../runtime/firebase/token/base/TokenAirdropRequestSchema'; +import { getProjects } from '../../utils/common.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; import { assertIsGuardian, assertTokenApproved, assertTokenStatus } from '../../utils/token.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; -import { build5Db } from '@build-5/database'; export interface TokenDropRequest { readonly vestingAt: Date; @@ -30,7 +31,10 @@ const hasAvailableTokenToAirdrop = (token: Token, count: number) => { return token.totalSupply - totalPublicSupply - token.totalAirdropped >= count; }; -export const airdropTokenControl = async ({ owner }: Context, params: CreateAirdropsRequest) => { +export const airdropTokenControl = async ( + { project, owner }: Context, + params: CreateAirdropsRequest, +) => { const chunks = chunk(params.drops, 200); for (const chunk of chunks) { await build5Db().runTransaction(async (transaction) => { @@ -55,6 +59,8 @@ export const airdropTokenControl = async ({ owner }: Context, params: CreateAird for (const drop of chunk) { const airdrop: TokenDrop = { + project, + projects: getProjects([], project), createdBy: owner, uid: getRandomEthAddress(), member: drop.recipient.toLowerCase(), diff --git a/packages/functions/src/controls/token/token.create.ts b/packages/functions/src/controls/token/token.create.ts index 3481de67fc..e72cc5387f 100644 --- a/packages/functions/src/controls/token/token.create.ts +++ b/packages/functions/src/controls/token/token.create.ts @@ -12,6 +12,7 @@ import { merge } from 'lodash'; import { Context } from '../../runtime/firebase/common'; import { hasStakedTokens } from '../../services/stake.service'; import { assertSpaceHasValidAddress } from '../../utils/address.utils'; +import { getProjects } from '../../utils/common.utils'; import { isProdEnv } from '../../utils/config.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; @@ -64,6 +65,8 @@ export const createTokenControl = async ( const tokenUid = getRandomEthAddress(); const extraData = { + project, + projects: getProjects([], project), uid: tokenUid, createdBy: owner, approved: !isProdEnv(), diff --git a/packages/functions/src/controls/token/token.credit.ts b/packages/functions/src/controls/token/token.credit.ts index 05a789e1ea..874c9f8179 100644 --- a/packages/functions/src/controls/token/token.credit.ts +++ b/packages/functions/src/controls/token/token.credit.ts @@ -16,6 +16,7 @@ import { } from '@build-5/interfaces'; import { Context } from '../../runtime/firebase/common'; import { getAddress } from '../../utils/address.utils'; +import { getProjects } from '../../utils/common.utils'; import { invalidArgument } from '../../utils/error.utils'; import { getBoughtByMemberDiff, @@ -26,7 +27,7 @@ import { import { getRandomEthAddress } from '../../utils/wallet.utils'; export const creditTokenControl = async ( - { owner }: Context, + { project, owner }: Context, params: CreditTokenRequest, ): Promise => { const tranId = getRandomEthAddress(); @@ -69,6 +70,8 @@ export const creditTokenControl = async ( }); const creditTransaction: Transaction = { + project, + projects: getProjects([], project), type: TransactionType.CREDIT, uid: tranId, space: token.space, diff --git a/packages/functions/src/controls/token/token.order.ts b/packages/functions/src/controls/token/token.order.ts index f3ef0dd996..951ea0013d 100644 --- a/packages/functions/src/controls/token/token.order.ts +++ b/packages/functions/src/controls/token/token.order.ts @@ -1,3 +1,4 @@ +import { build5Db } from '@build-5/database'; import { COL, DEFAULT_NETWORK, @@ -23,9 +24,12 @@ import { dateToTimestamp } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; import { assertIpNotBlocked } from '../../utils/ip.utils'; import { tokenIsInPublicSalePeriod, tokenOrderTransactionDocId } from '../../utils/token.utils'; -import { build5Db } from '@build-5/database'; +import { getProjects } from '../../utils/common.utils'; -export const orderTokenControl = async ({ owner, ip }: Context, params: OrderTokenRequest) => { +export const orderTokenControl = async ( + { project, owner, ip }: Context, + params: OrderTokenRequest, +) => { const memberDocRef = build5Db().doc(`${COL.MEMBER}/${owner}`); const member = await memberDocRef.get(); assertMemberHasValidAddress(member, DEFAULT_NETWORK); @@ -62,6 +66,8 @@ export const orderTokenControl = async ({ owner, ip }: Context, params: OrderTok const order = await transaction.get(orderDoc); if (!order) { const data: Transaction = { + project, + projects: getProjects([token], project), type: TransactionType.ORDER, uid: tranId, member: owner, diff --git a/packages/functions/src/cron/stakeReward.cron.ts b/packages/functions/src/cron/stakeReward.cron.ts index 8f56c7b601..0bd392a0f6 100644 --- a/packages/functions/src/cron/stakeReward.cron.ts +++ b/packages/functions/src/cron/stakeReward.cron.ts @@ -19,6 +19,7 @@ import { import dayjs from 'dayjs'; import * as functions from 'firebase-functions/v2'; import { isEmpty, last } from 'lodash'; +import { getProject, getProjects } from '../utils/common.utils'; import { serverTime } from '../utils/dateTime.utils'; import { getRandomEthAddress } from '../utils/wallet.utils'; export const stakeRewardCronTask = async () => { @@ -127,6 +128,8 @@ const createAirdrops = async ( await distributionDocRef.update({ extraStakeRewards: build5Db().inc(-reward.value) }); const billPayment: Transaction = { + project: getProject(stakeReward), + projects: getProjects([stakeReward]), type: TransactionType.BILL_PAYMENT, uid: getRandomEthAddress(), member: reward.member, @@ -158,6 +161,8 @@ const createAirdrops = async ( const batch = build5Db().batch(); const airdrop: TokenDrop = { + project: getProject(stakeReward), + projects: getProjects([stakeReward]), uid: getRandomEthAddress(), createdBy: 'system', member: reward.member, diff --git a/packages/functions/src/services/payment/address/address.space.service.ts b/packages/functions/src/services/payment/address/address.space.service.ts index 0bedd1833b..7620410512 100644 --- a/packages/functions/src/services/payment/address/address.space.service.ts +++ b/packages/functions/src/services/payment/address/address.space.service.ts @@ -16,12 +16,13 @@ import { } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { getAddress } from '../../../utils/address.utils'; +import { getProjects } from '../../../utils/common.utils'; import { dateToTimestamp } from '../../../utils/dateTime.utils'; import { getRandomEthAddress } from '../../../utils/wallet.utils'; import { BaseService, HandlerParams } from '../base'; export class SpaceAddressService extends BaseService { - public handleRequest = async ({ order, match }: HandlerParams) => { + public handleRequest = async ({ project, order, match }: HandlerParams) => { const payment = await this.transactionService.createPayment(order, match); await this.transactionService.createCredit( TransactionPayloadType.ADDRESS_VALIDATION, @@ -38,6 +39,7 @@ export class SpaceAddressService extends BaseService { const guardians = await spaceDocRef.collection(SUB_COL.GUARDIANS).get(); const proposal = createUpdateSpaceValidatedAddressProposal( + project, order, match.from.address, owner, @@ -93,17 +95,20 @@ export class SpaceAddressService extends BaseService { } const createUpdateSpaceValidatedAddressProposal = ( + project: string, order: Transaction, validatedAddress: string, owner: Member, space: Space, guardiansCount: number, -) => { +): Proposal => { const additionalInfo = `${owner.name || owner.uid} wants to update the space's validated address. ` + `Request created on ${dayjs().format('MM/DD/YYYY')}. ` + `${UPDATE_SPACE_THRESHOLD_PERCENTAGE} % must agree for this action to proceed`; - return { + return { + project, + projects: getProjects([order], project), createdBy: owner.uid, uid: getRandomEthAddress(), name: 'Update validated address', diff --git a/packages/functions/src/services/payment/award/award-service.ts b/packages/functions/src/services/payment/award/award-service.ts index e6deb14e4f..6b2817cacb 100644 --- a/packages/functions/src/services/payment/award/award-service.ts +++ b/packages/functions/src/services/payment/award/award-service.ts @@ -25,13 +25,14 @@ import { set } from 'lodash'; import { packBasicOutput } from '../../../utils/basic-output.utils'; import { PLACEHOLDER_CID } from '../../../utils/car.utils'; import { createNftOutput } from '../../../utils/collection-minting-utils/nft.utils'; +import { getProject, getProjects } from '../../../utils/common.utils'; import { getContentType } from '../../../utils/storage.utils'; import { createAliasOutput } from '../../../utils/token-minting-utils/alias.utils'; import { getRandomEthAddress } from '../../../utils/wallet.utils'; import { SmrWallet } from '../../wallet/SmrWalletService'; import { BaseService, HandlerParams } from '../base'; -export class AwardService extends BaseService { +export class AwardFundService extends BaseService { public handleRequest = async ({ order, match }: HandlerParams) => { const payment = await this.transactionService.createPayment(order, match); @@ -75,7 +76,9 @@ export class AwardService extends BaseService { action: 'update', }); - const mintAliasOrder = { + const mintAliasOrder: Transaction = { + project: getProject(order), + projects: getProjects([order]), type: TransactionType.AWARD, uid: getRandomEthAddress(), member: order.member, diff --git a/packages/functions/src/services/payment/base.ts b/packages/functions/src/services/payment/base.ts index f0ae3586ed..df6295ef31 100644 --- a/packages/functions/src/services/payment/base.ts +++ b/packages/functions/src/services/payment/base.ts @@ -14,6 +14,8 @@ export interface HandlerParams { order: Transaction; build5Tran: Transaction | undefined; + project: string; + request: Record; } diff --git a/packages/functions/src/services/payment/credit-service.ts b/packages/functions/src/services/payment/credit-service.ts index 3b08537c82..b4cb23b386 100644 --- a/packages/functions/src/services/payment/credit-service.ts +++ b/packages/functions/src/services/payment/credit-service.ts @@ -1,6 +1,7 @@ import { build5Db } from '@build-5/database'; import { COL, Transaction, TransactionPayloadType, TransactionType } from '@build-5/interfaces'; import { get, isEmpty } from 'lodash'; +import { getProject, getProjects } from '../../utils/common.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; import { BaseService, HandlerParams } from './base'; @@ -23,7 +24,9 @@ export class CreditService extends BaseService { } this.transactionService.markAsReconciled(order, match.msgId); - const credit = { + const credit: Transaction = { + project: getProject(order), + projects: getProjects([order]), type: TransactionType.CREDIT_STORAGE_DEPOSIT_LOCKED, uid: getRandomEthAddress(), space: order.space, diff --git a/packages/functions/src/services/payment/metadataNft-service.ts b/packages/functions/src/services/payment/metadataNft-service.ts index 53639834ee..8f470d2bee 100644 --- a/packages/functions/src/services/payment/metadataNft-service.ts +++ b/packages/functions/src/services/payment/metadataNft-service.ts @@ -4,7 +4,6 @@ import { COL, CollectionStatus, CollectionType, - Network, NetworkAddress, Nft, NftAccess, @@ -20,11 +19,12 @@ import { getCollectionByMintingId, getNftByMintingId, } from '../../utils/collection-minting-utils/nft.utils'; +import { getProject, getProjects } from '../../utils/common.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; import { BaseService, HandlerParams } from './base'; export class MetadataNftService extends BaseService { - public handleRequest = async ({ order, match }: HandlerParams) => { + public handleRequest = async ({ project, order, match }: HandlerParams) => { const payment = await this.transactionService.createPayment(order, match); this.transactionService.markAsReconciled(order, match.msgId); @@ -34,6 +34,8 @@ export class MetadataNftService extends BaseService { if (!aliasId) { const mintAlias: Transaction = { + project, + projects: getProjects([], project), type: TransactionType.METADATA_NFT, uid: getRandomEthAddress(), space: order.space, @@ -94,12 +96,9 @@ export class MetadataNftService extends BaseService { const space = await build5Db().doc(`${COL.SPACE}/${order.space}`).get(); const mintNftOrder = createMintMetadataNftOrder( + order, nft, - order.network!, - order.payload.targetAddress!, space?.alias?.address!, - order.payload.targetAddress!, - get(order, 'payload.aliasId', ''), get(order, 'payload.collectionId', ''), order.uid, ); @@ -159,6 +158,8 @@ export const createMintMetadataCollectionOrder = ( aliasGovAddress: NetworkAddress, aliasBlockId = '', ): Transaction => ({ + project: getProject(transaction), + projects: getProjects([transaction]), type: TransactionType.METADATA_NFT, uid: getRandomEthAddress(), member: transaction.member, @@ -177,28 +178,27 @@ export const createMintMetadataCollectionOrder = ( }); export const createMintMetadataNftOrder = ( + transaction: Transaction, nft: Nft, - network: Network, - sourceAddress: NetworkAddress, aliasGovAddress: NetworkAddress, - targetAddress: NetworkAddress, - aliasId: string, collectionId: string, baseOrderId: string, ): Transaction => ({ + project: getProject(transaction), + projects: getProjects([transaction]), type: TransactionType.METADATA_NFT, uid: getRandomEthAddress(), member: nft.owner, space: nft.space, - network: network, + network: transaction.network, payload: { type: nft.mintingData?.nftId ? TransactionPayloadType.UPDATE_MINTED_NFT : TransactionPayloadType.MINT_NFT, - sourceAddress, + sourceAddress: transaction.payload.targetAddress, aliasGovAddress, - targetAddress, - aliasId, + targetAddress: transaction.payload.targetAddress, + aliasId: get(transaction, 'payload.aliasId', ''), collectionId, orderId: baseOrderId, nft: nft.uid, diff --git a/packages/functions/src/services/payment/nft/common.ts b/packages/functions/src/services/payment/nft/common.ts index 8851ad9149..bd3a6c82d7 100644 --- a/packages/functions/src/services/payment/nft/common.ts +++ b/packages/functions/src/services/payment/nft/common.ts @@ -11,6 +11,7 @@ import { import dayjs from 'dayjs'; import { last, set } from 'lodash'; import { getAddress } from '../../../utils/address.utils'; +import { getProject } from '../../../utils/common.utils'; import { dateToTimestamp, serverTime } from '../../../utils/dateTime.utils'; import { NotificationService } from '../../notification/notification'; import { BaseService } from '../base'; @@ -30,6 +31,7 @@ export abstract class BaseNftService extends BaseService { const membderDocRef = build5Db().doc(`${COL.MEMBER}/${order.member}`); const member = await membderDocRef.get(); const { order: withdrawOrder, nftUpdateData } = createNftWithdrawOrder( + getProject(order), nft, member.uid, getAddress(member, order.network!), diff --git a/packages/functions/src/services/payment/nft/nft-deposit.service.ts b/packages/functions/src/services/payment/nft/nft-deposit.service.ts index 9ae8de9fe6..be0f643c48 100644 --- a/packages/functions/src/services/payment/nft/nft-deposit.service.ts +++ b/packages/functions/src/services/payment/nft/nft-deposit.service.ts @@ -9,7 +9,6 @@ import { CollectionType, MediaStatus, MilestoneTransactionEntry, - Network, Nft, NftAccess, NftAvailable, @@ -23,6 +22,7 @@ import { INftOutput } from '@iota/iota.js-next'; import * as functions from 'firebase-functions/v2'; import { head, isEmpty, set } from 'lodash'; import { getNftByMintingId } from '../../../utils/collection-minting-utils/nft.utils'; +import { getProject, getProjects } from '../../../utils/common.utils'; import { getBucket } from '../../../utils/config.utils'; import { serverTime } from '../../../utils/dateTime.utils'; import { migrateUriToSotrage, uriToUrl } from '../../../utils/media.utils'; @@ -139,7 +139,7 @@ export class NftDepositService extends BaseService { metadata.nft.collectionId as string, ); const migratedCollection = getMigratedCollection( - order.network!, + order, existingCollection, space, metadata.nft, @@ -148,6 +148,8 @@ export class NftDepositService extends BaseService { ); const nft: Nft = { + project: getProject(order), + projects: getProjects([order]), uid: nftOutput.nftId, ipfsMedia: '', name: metadata.nft.name, @@ -325,7 +327,9 @@ const getSpace = async ( return { space, isNewSpace: false }; } - const space = { + const space = { + project: getProject(collection), + projects: getProjects([collection]), uid: getRandomEthAddress(), name: collectionName, about: @@ -334,12 +338,12 @@ const getSpace = async ( '". Don’t forget to claim this space if you are the original author.', collectionId, claimed: false, - }; + } as Space; return { space, isNewSpace: true }; }; const getMigratedCollection = ( - network: Network, + order: Transaction, collection: Collection | undefined, space: Space, nftMetadata: Record, @@ -353,13 +357,15 @@ const getMigratedCollection = ( const royaltyFee = head(Object.values(collectionMetadata.royalties || {})); const mintedCollection: Collection = { + project: getProject(order), + projects: getProjects([order]), space: space.uid, uid: nftMetadata.collectionId as string, name: collectionMetadata.name as string, description: collectionMetadata.description as string, status: CollectionStatus.MINTED, mintingData: { - network: network, + network: order.network, nftId: nftMetadata.collectionId as string, aliasId, }, diff --git a/packages/functions/src/services/payment/nft/nft-stake.service.ts b/packages/functions/src/services/payment/nft/nft-stake.service.ts index f90c0e3f60..519acb51d7 100644 --- a/packages/functions/src/services/payment/nft/nft-stake.service.ts +++ b/packages/functions/src/services/payment/nft/nft-stake.service.ts @@ -20,6 +20,7 @@ import { import dayjs from 'dayjs'; import * as functions from 'firebase-functions/v2'; import { cloneDeep, get } from 'lodash'; +import { getProjects } from '../../../utils/common.utils'; import { dateToTimestamp } from '../../../utils/dateTime.utils'; import { getRandomEthAddress } from '../../../utils/wallet.utils'; import { SmrWallet } from '../../wallet/SmrWalletService'; @@ -29,7 +30,7 @@ import { createNftWithdrawOrder } from '../tangle-service/nft/nft-purchase.servi import { NftDepositService } from './nft-deposit.service'; export class NftStakeService extends BaseService { - public handleRequest = async ({ order, match, tranEntry }: HandlerParams) => { + public handleRequest = async ({ project, order, match, tranEntry }: HandlerParams) => { let customErrorParams = {}; try { if (!tranEntry.nftOutput) { @@ -45,6 +46,7 @@ export class NftStakeService extends BaseService { const nft = await nftDepositService.depositNft(order, tranEntry, match); const { order: withdrawOrder, nftUpdateData } = createNftWithdrawOrder( + project, nft, order.member!, match.from.address, @@ -99,6 +101,7 @@ export class NftStakeService extends BaseService { } export const createNftStakeOrder = async ( + project: string, member: string, network: Network, weeks: number, @@ -107,6 +110,8 @@ export const createNftStakeOrder = async ( const wallet = await WalletService.newWallet(network); const targetAddress = await wallet.getNewIotaAddressDetails(); return { + project, + projects: getProjects([], project), type: TransactionType.ORDER, uid: getRandomEthAddress(), member, diff --git a/packages/functions/src/services/payment/payment-processing.ts b/packages/functions/src/services/payment/payment-processing.ts index cc09a1603d..f4a26a23bb 100644 --- a/packages/functions/src/services/payment/payment-processing.ts +++ b/packages/functions/src/services/payment/payment-processing.ts @@ -11,11 +11,12 @@ import { } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { head, isEmpty } from 'lodash'; +import { getProject } from '../../utils/common.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { invalidArgument } from '../../utils/error.utils'; import { MemberAddressService } from './address/address-member.service'; import { SpaceAddressService } from './address/address.space.service'; -import { AwardService } from './award/award-service'; +import { AwardFundService } from './award/award-service'; import { HandlerParams } from './base'; import { CreditService } from './credit-service'; import { MetadataNftService } from './metadataNft-service'; @@ -24,7 +25,7 @@ import { NftBidService } from './nft/nft-bid.service'; import { NftDepositService } from './nft/nft-deposit.service'; import { NftPurchaseService } from './nft/nft-purchase.service'; import { NftStakeService } from './nft/nft-stake.service'; -import { SpaceService } from './space/space-service'; +import { SpaceClaimService } from './space/space-service'; import { StakeService } from './stake-service'; import { TangleRequestService } from './tangle-service/TangleRequestService'; import { ImportMintedTokenService } from './token/import-minted-token.service'; @@ -111,6 +112,7 @@ export class ProcessingService { payment: undefined, match, order, + project: getProject(order), owner: order.member || '', tran, tranEntry, @@ -172,11 +174,11 @@ export class ProcessingService { case TransactionPayloadType.PROPOSAL_VOTE: return new VotingService(tranService); case TransactionPayloadType.CLAIM_SPACE: - return new SpaceService(tranService); + return new SpaceClaimService(tranService); case TransactionPayloadType.STAKE_NFT: return new NftStakeService(tranService); case TransactionPayloadType.FUND_AWARD: - return new AwardService(tranService); + return new AwardFundService(tranService); case TransactionPayloadType.IMPORT_TOKEN: return new ImportMintedTokenService(tranService); case TransactionPayloadType.MINT_METADATA_NFT: diff --git a/packages/functions/src/services/payment/space/space-service.ts b/packages/functions/src/services/payment/space/space-service.ts index 636dfe64aa..b81ec7460b 100644 --- a/packages/functions/src/services/payment/space/space-service.ts +++ b/packages/functions/src/services/payment/space/space-service.ts @@ -18,12 +18,13 @@ import { IndexerPluginClient, } from '@iota/iota.js-next'; import { Bech32AddressHelper } from '../../../utils/bech32-address.helper'; +import { getProject, getProjects } from '../../../utils/common.utils'; import { serverTime } from '../../../utils/dateTime.utils'; import { SmrWallet } from '../../wallet/SmrWalletService'; import { WalletService } from '../../wallet/wallet'; import { BaseService, HandlerParams } from '../base'; -export class SpaceService extends BaseService { +export class SpaceClaimService extends BaseService { public handleRequest = async ({ order, match }: HandlerParams) => { const payment = await this.transactionService.createPayment(order, match); await this.transactionService.createCredit( @@ -51,6 +52,8 @@ export class SpaceService extends BaseService { } const spaceMember: SpaceMember = { + project: getProject(order), + projects: getProjects([space, order]), uid: order.member!, parentId: space.uid, parentCol: COL.SPACE, diff --git a/packages/functions/src/services/payment/stake-service.ts b/packages/functions/src/services/payment/stake-service.ts index 37ed7c4f30..c579bff9a7 100644 --- a/packages/functions/src/services/payment/stake-service.ts +++ b/packages/functions/src/services/payment/stake-service.ts @@ -1,3 +1,4 @@ +import { build5Db } from '@build-5/database'; import { COL, Entity, @@ -11,13 +12,13 @@ import { } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { get } from 'lodash'; +import { getProject, getProjects } from '../../utils/common.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; import { BaseService, HandlerParams } from './base'; -import { build5Db } from '@build-5/database'; export class StakeService extends BaseService { - public handleRequest = async ({ order, match }: HandlerParams) => { + public handleRequest = async ({ project, order, match }: HandlerParams) => { const payment = await this.transactionService.createPayment(order, match); const matchAmount = match.to.amount; @@ -44,6 +45,8 @@ export class StakeService extends BaseService { const token = await tokenDocRef.get(); const billPayment: Transaction = { + project: getProject(order), + projects: getProjects([order]), type: TransactionType.BILL_PAYMENT, uid: getRandomEthAddress(), member: order.member, @@ -70,6 +73,8 @@ export class StakeService extends BaseService { }; const stake: Stake = { + project, + projects: getProjects([order]), uid: getRandomEthAddress(), member: order.member!, token: order.payload.token!, diff --git a/packages/functions/src/services/payment/tangle-service/address/address-validation.service.ts b/packages/functions/src/services/payment/tangle-service/address/address-validation.service.ts index 77dc1b9244..5eb8735a81 100644 --- a/packages/functions/src/services/payment/tangle-service/address/address-validation.service.ts +++ b/packages/functions/src/services/payment/tangle-service/address/address-validation.service.ts @@ -13,7 +13,7 @@ import { } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { set } from 'lodash'; -import { generateRandomAmount } from '../../../../utils/common.utils'; +import { generateRandomAmount, getProjects } from '../../../../utils/common.utils'; import { dateToTimestamp } from '../../../../utils/dateTime.utils'; import { invalidArgument } from '../../../../utils/error.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; @@ -25,6 +25,7 @@ import { validateAddressSchemaObject } from './AddressValidationTangleRequestSch export class TangleAddressValidationService extends BaseService { public handleRequest = async ({ + project, tran, order: tangleOrder, tranEntry, @@ -33,6 +34,7 @@ export class TangleAddressValidationService extends BaseService { }: HandlerParams): Promise => { const params = await assertValidationAsync(validateAddressSchemaObject, request); const order = await createAddressValidationOrder( + project, owner, (params.network as Network) || tangleOrder.network, params.space, @@ -61,6 +63,7 @@ export class TangleAddressValidationService extends BaseService { } export const createAddressValidationOrder = async ( + project: string, owner: string, network: Network, spaceId?: string, @@ -81,6 +84,8 @@ export const createAddressValidationOrder = async ( const targetAddress = await wallet.getNewIotaAddressDetails(); const order: Transaction = { + project, + projects: getProjects([], project), type: TransactionType.ORDER, uid: getRandomEthAddress(), member: owner, diff --git a/packages/functions/src/services/payment/tangle-service/award/award.approve.participant.service.ts b/packages/functions/src/services/payment/tangle-service/award/award.approve.participant.service.ts index 10f17b16df..0472f016f3 100644 --- a/packages/functions/src/services/payment/tangle-service/award/award.approve.participant.service.ts +++ b/packages/functions/src/services/payment/tangle-service/award/award.approve.participant.service.ts @@ -19,8 +19,9 @@ import { WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; -import { get, head, isEmpty } from 'lodash'; +import { get, head, isEmpty, set } from 'lodash'; import { getAddress } from '../../../../utils/address.utils'; +import { getProjects } from '../../../../utils/common.utils'; import { serverTime } from '../../../../utils/dateTime.utils'; import { invalidArgument } from '../../../../utils/error.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; @@ -31,6 +32,7 @@ import { approveAwardParticipantSchemaObject } from './AwardAppParticipantTangle export class AwardApproveParticipantService extends BaseService { public handleRequest = async ({ + project, owner, request, }: HandlerParams): Promise => { @@ -42,7 +44,7 @@ export class AwardApproveParticipantService extends BaseService { for (const member of params.members.map((m) => m.toLowerCase())) { try { const badge = await build5Db().runTransaction( - approveAwardParticipant(owner, params.award, member), + approveAwardParticipant(project, owner, params.award, member), ); badges[badge.uid] = member; } catch (error) { @@ -58,7 +60,7 @@ export class AwardApproveParticipantService extends BaseService { } export const approveAwardParticipant = - (owner: string, awardId: string, uidOrAddress: NetworkAddress) => + (project: string, owner: string, awardId: string, uidOrAddress: NetworkAddress) => async (transaction: ITransaction) => { const awardDocRef = build5Db().doc(`${COL.AWARD}/${awardId}`); const award = await transaction.get(awardDocRef); @@ -100,9 +102,15 @@ export const approveAwardParticipant = createdOn: participant?.createdOn || serverTime(), tokenReward: build5Db().inc(award.badge.tokenReward), }; + if (!participant) { + set(participantUpdateData, 'project', project); + set(participantUpdateData, 'projects', { [project]: true }); + } transaction.set(participantDocRef, participantUpdateData, true); const badgeTransaction: Transaction = { + project, + projects: getProjects([], project), type: TransactionType.AWARD, uid: getRandomEthAddress(), member: memberId, @@ -157,6 +165,8 @@ export const approveAwardParticipant = if (award.badge.tokenReward) { const airdrop: TokenDrop = { + project, + projects: getProjects([], project), createdBy: owner, uid: getRandomEthAddress(), member: memberId, diff --git a/packages/functions/src/services/payment/tangle-service/award/award.create.service.ts b/packages/functions/src/services/payment/tangle-service/award/award.create.service.ts index 6ebdba9406..c258f383dc 100644 --- a/packages/functions/src/services/payment/tangle-service/award/award.create.service.ts +++ b/packages/functions/src/services/payment/tangle-service/award/award.create.service.ts @@ -6,6 +6,7 @@ import { AwardCreateRequest, AwardCreateTangleRequest, AwardCreateTangleResponse, + AwardOwner, COL, Network, SUB_COL, @@ -15,6 +16,7 @@ import { } from '@build-5/interfaces'; import { isEmpty, set } from 'lodash'; import { downloadMediaAndPackCar } from '../../../../utils/car.utils'; +import { getProjects } from '../../../../utils/common.utils'; import { getBucket } from '../../../../utils/config.utils'; import { dateToTimestamp } from '../../../../utils/dateTime.utils'; import { invalidArgument } from '../../../../utils/error.utils'; @@ -33,11 +35,12 @@ import { createAwardFundOrder } from './award.fund.service'; export class AwardCreateService extends BaseService { public handleRequest = async ({ + project, owner, request, }: HandlerParams): Promise => { const params = await assertValidationAsync(awardCreateSchema, request); - const { award, owner: awardOwner } = await createAward(owner, { ...params }); + const { award, owner: awardOwner } = await createAward(project, owner, { ...params }); const awardDocRef = build5Db().doc(`${COL.AWARD}/${award.uid}`); this.transactionService.push({ @@ -52,7 +55,7 @@ export class AwardCreateService extends BaseService { action: 'set', }); - const order = await createAwardFundOrder(owner, award); + const order = await createAwardFundOrder(project, owner, award); const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); this.transactionService.push({ ref: orderDocRef, data: order, action: 'set' }); @@ -70,9 +73,13 @@ export class AwardCreateService extends BaseService { } export const createAward = async ( + project: string, owner: string, params: AwardCreateRequest | AwardCreateTangleRequest, -) => { +): Promise<{ + owner: AwardOwner; + award: Award; +}> => { await assertIsSpaceMember(params.space as string, owner); const awardId = getRandomEthAddress(); @@ -111,6 +118,8 @@ export const createAward = async ( set(awardBadge, 'tokenId', token.mintingData?.tokenId); } const award: Award = { + project, + projects: getProjects([], project), createdBy: owner, uid: awardUid, name: params.name as string, @@ -133,7 +142,13 @@ export const createAward = async ( const wallet = (await WalletService.newWallet(award.network)) as SmrWallet; const storageDeposits = await getAwardgStorageDeposits(award, token, wallet); - const awardOwner = { uid: owner, parentId: award.uid, parentCol: COL.AWARD }; + const awardOwner: AwardOwner = { + uid: owner, + project, + projects: getProjects([], project), + parentId: award.uid, + parentCol: COL.AWARD, + }; return { owner: awardOwner, award: { ...award, ...storageDeposits } }; }; diff --git a/packages/functions/src/services/payment/tangle-service/award/award.fund.service.ts b/packages/functions/src/services/payment/tangle-service/award/award.fund.service.ts index 46f0d7cbbd..e1569a8508 100644 --- a/packages/functions/src/services/payment/tangle-service/award/award.fund.service.ts +++ b/packages/functions/src/services/payment/tangle-service/award/award.fund.service.ts @@ -13,6 +13,7 @@ import { } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { isEmpty, set } from 'lodash'; +import { getProjects } from '../../../../utils/common.utils'; import { dateToTimestamp } from '../../../../utils/dateTime.utils'; import { invalidArgument } from '../../../../utils/error.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; @@ -23,11 +24,15 @@ import { BaseService, HandlerParams } from '../../base'; import { awardFundSchema } from './AwardFundTangleRequestSchema'; export class AwardFundService extends BaseService { - public handleRequest = async ({ owner, request }: HandlerParams): Promise => { + public handleRequest = async ({ + project, + owner, + request, + }: HandlerParams): Promise => { const params = await assertValidationAsync(awardFundSchema, request); const award = await getAwardForFunding(owner, params.uid); - const order = await createAwardFundOrder(owner, award); + const order = await createAwardFundOrder(project, owner, award); const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); this.transactionService.push({ ref: orderDocRef, data: order, action: 'set' }); @@ -43,7 +48,11 @@ export class AwardFundService extends BaseService { }; } -export const createAwardFundOrder = async (owner: string, award: Award): Promise => { +export const createAwardFundOrder = async ( + project: string, + owner: string, + award: Award, +): Promise => { const isNativeBadge = award.badge.type === AwardBadgeType.NATIVE; const amount = award.aliasStorageDeposit + @@ -57,6 +66,8 @@ export const createAwardFundOrder = async (owner: string, award: Award): Promise const nativeTokens = [{ id: award.badge.tokenId!, amount: totalReward.toString() }]; return { + project, + projects: getProjects([], project), type: TransactionType.ORDER, uid: getRandomEthAddress(), member: owner, diff --git a/packages/functions/src/services/payment/tangle-service/metadataNft/mint-metadata-nft.service.ts b/packages/functions/src/services/payment/tangle-service/metadataNft/mint-metadata-nft.service.ts index dfb2879ca7..bd0f4c8214 100644 --- a/packages/functions/src/services/payment/tangle-service/metadataNft/mint-metadata-nft.service.ts +++ b/packages/functions/src/services/payment/tangle-service/metadataNft/mint-metadata-nft.service.ts @@ -29,6 +29,7 @@ import { createNftOutput, getNftByMintingId, } from '../../../../utils/collection-minting-utils/nft.utils'; +import { getProject, getProjects } from '../../../../utils/common.utils'; import { dateToTimestamp } from '../../../../utils/dateTime.utils'; import { invalidArgument } from '../../../../utils/error.utils'; import { getAliasId, getIssuerNftId } from '../../../../utils/nft.output.utils'; @@ -101,7 +102,9 @@ export class MintMetadataNftService extends BaseService { this.transactionService.push({ ref: memberDocRef, data: guardian, action: 'set' }); } - const order = { + const order: Transaction = { + project: getProject(tangleOrder), + projects: getProjects([tangleOrder]), type: TransactionType.ORDER, uid: getRandomEthAddress(), member: owner, @@ -121,7 +124,7 @@ export class MintMetadataNftService extends BaseService { collectionOutputAmount, nftId: nftId === EMPTY_NFT_ID ? '' : nftId, nftOutputAmount, - metadata: request.metadata, + metadata: request.metadata as { [key: string]: unknown }, tag: match.msgId, }, }; diff --git a/packages/functions/src/services/payment/tangle-service/nft/nft-bid.service.ts b/packages/functions/src/services/payment/tangle-service/nft/nft-bid.service.ts index a714411aad..21df1b3786 100644 --- a/packages/functions/src/services/payment/tangle-service/nft/nft-bid.service.ts +++ b/packages/functions/src/services/payment/tangle-service/nft/nft-bid.service.ts @@ -19,7 +19,7 @@ import { } from '@build-5/interfaces'; import { AVAILABLE_NETWORKS } from '../../../../controls/common'; import { assertMemberHasValidAddress, getAddress } from '../../../../utils/address.utils'; -import { getRestrictions } from '../../../../utils/common.utils'; +import { getProjects, getRestrictions } from '../../../../utils/common.utils'; import { isProdEnv } from '../../../../utils/config.utils'; import { invalidArgument } from '../../../../utils/error.utils'; import { assertIpNotBlocked } from '../../../../utils/ip.utils'; @@ -32,6 +32,7 @@ import { nftBidSchema } from './NftBidTangleRequestSchema'; export class TangleNftBidService extends BaseService { public handleRequest = async ({ + project, owner, request, tran, @@ -39,7 +40,7 @@ export class TangleNftBidService extends BaseService { }: HandlerParams): Promise => { const params = await assertValidationAsync(nftBidSchema, request); - const order = await createNftBidOrder(params.nft, owner, ''); + const order = await createNftBidOrder(project, params.nft, owner, ''); order.payload.tanglePuchase = true; order.payload.disableWithdraw = params.disableWithdraw || false; @@ -70,6 +71,7 @@ export class TangleNftBidService extends BaseService { } export const createNftBidOrder = async ( + project: string, nftId: string, owner: string, ip = '', @@ -129,6 +131,8 @@ export const createNftBidOrder = async ( const finalPrice = Number(Math.max(auctionFloorPrice, MIN_AMOUNT_TO_TRANSFER).toPrecision(2)); return { + project, + projects: getProjects([], project), type: TransactionType.ORDER, uid: getRandomEthAddress(), member: owner, diff --git a/packages/functions/src/services/payment/tangle-service/nft/nft-deposit.service.ts b/packages/functions/src/services/payment/tangle-service/nft/nft-deposit.service.ts index a5798c4b7e..4d8fe5ba9c 100644 --- a/packages/functions/src/services/payment/tangle-service/nft/nft-deposit.service.ts +++ b/packages/functions/src/services/payment/tangle-service/nft/nft-deposit.service.ts @@ -8,6 +8,7 @@ import { TransactionValidationType, } from '@build-5/interfaces'; import dayjs from 'dayjs'; +import { getProject, getProjects } from '../../../../utils/common.utils'; import { dateToTimestamp } from '../../../../utils/dateTime.utils'; import { getRandomEthAddress } from '../../../../utils/wallet.utils'; import { WalletService } from '../../../wallet/wallet'; @@ -18,7 +19,9 @@ export class NftDepositService extends BaseService { const wallet = await WalletService.newWallet(params.order.network); const targetAddress = await wallet.getNewIotaAddressDetails(); - const order = { + const order: Transaction = { + project: getProject(params.order), + projects: getProjects([params.order]), type: TransactionType.ORDER, uid: getRandomEthAddress(), member: owner, diff --git a/packages/functions/src/services/payment/tangle-service/nft/nft-purchase.service.ts b/packages/functions/src/services/payment/tangle-service/nft/nft-purchase.service.ts index 0d138ba0f1..4810128b43 100644 --- a/packages/functions/src/services/payment/tangle-service/nft/nft-purchase.service.ts +++ b/packages/functions/src/services/payment/tangle-service/nft/nft-purchase.service.ts @@ -28,7 +28,7 @@ import { isEmpty } from 'lodash'; import { AVAILABLE_NETWORKS } from '../../../../controls/common'; import { getAddress } from '../../../../utils/address.utils'; import { getNftByMintingId } from '../../../../utils/collection-minting-utils/nft.utils'; -import { getRestrictions } from '../../../../utils/common.utils'; +import { getProject, getProjects, getRestrictions } from '../../../../utils/common.utils'; import { isProdEnv } from '../../../../utils/config.utils'; import { dateToTimestamp } from '../../../../utils/dateTime.utils'; import { invalidArgument } from '../../../../utils/error.utils'; @@ -43,6 +43,7 @@ import { nftPurchaseSchema } from './NftPurchaseTangleRequestSchema'; export class TangleNftPurchaseService extends BaseService { public handleRequest = async ({ + order: tangleOrder, request, owner, tran, @@ -50,7 +51,14 @@ export class TangleNftPurchaseService extends BaseService { }: HandlerParams): Promise => { const params = await assertValidationAsync(nftPurchaseSchema, request); - const order = await createNftPuchaseOrder(params.collection, params.nft, owner, '', true); + const order = await createNftPuchaseOrder( + getProject(tangleOrder), + params.collection, + params.nft, + owner, + '', + true, + ); order.payload.tanglePuchase = true; order.payload.disableWithdraw = params.disableWithdraw || false; @@ -92,6 +100,7 @@ export class TangleNftPurchaseService extends BaseService { } export const createNftPuchaseOrder = async ( + project: string, collectionId: string, nftId: string | undefined, owner: string, @@ -127,6 +136,8 @@ export const createNftPuchaseOrder = async ( const finalPrice = getNftFinalPrice(nft, discount); return { + project, + projects: getProjects([], project), type: TransactionType.ORDER, uid: nftPurchaseOrderId, member: owner, @@ -364,18 +375,21 @@ const getNftFinalPrice = (nft: Nft, discount: number) => { }; export const createNftWithdrawOrder = ( + project: string, nft: Nft, member: string, targetAddress: NetworkAddress, weeks = 0, stakeType?: StakeType, ) => { - const order = { + const order: Transaction = { + project, + projects: getProjects([], project), type: TransactionType.WITHDRAW_NFT, uid: getRandomEthAddress(), member, space: nft.space, - network: nft.mintingData?.network, + network: nft.mintingData?.network!, payload: { amount: nft.depositData?.storageDeposit || nft.mintingData?.storageDeposit || 0, sourceAddress: nft.depositData?.address || nft.mintingData?.address, @@ -383,7 +397,7 @@ export const createNftWithdrawOrder = ( collection: nft.collection, nft: nft.uid, vestingAt: dateToTimestamp(dayjs().add(weeks, 'weeks')), - stakeType: stakeType || null, + stakeType: (stakeType || null) as StakeType, weeks, nftId: nft.mintingData?.nftId || '', }, diff --git a/packages/functions/src/services/payment/tangle-service/proposal/ProposalCreateService.ts b/packages/functions/src/services/payment/tangle-service/proposal/ProposalCreateService.ts index 5c30b6a34d..9d1a8808b2 100644 --- a/packages/functions/src/services/payment/tangle-service/proposal/ProposalCreateService.ts +++ b/packages/functions/src/services/payment/tangle-service/proposal/ProposalCreateService.ts @@ -10,6 +10,7 @@ import { TokenStatus, WenError, } from '@build-5/interfaces'; +import { getProjects } from '../../../../utils/common.utils'; import { dateToTimestamp } from '../../../../utils/dateTime.utils'; import { invalidArgument } from '../../../../utils/error.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; @@ -20,12 +21,13 @@ import { proposalCreateSchemaObject } from './ProposalCreateTangleRequestSchema' export class ProposalCreateService extends BaseService { public handleRequest = async ({ + project, owner, request, }: HandlerParams): Promise => { const params = await assertValidationAsync(proposalCreateSchemaObject, request); - const { proposal, proposalOwner } = await createProposal(owner, { ...params }); + const { proposal, proposalOwner } = await createProposal(project, owner, { ...params }); const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); this.transactionService.push({ ref: proposalDocRef, data: proposal, action: 'set' }); @@ -41,7 +43,11 @@ export class ProposalCreateService extends BaseService { }; } -export const createProposal = async (owner: string, params: Record) => { +export const createProposal = async ( + project: string, + owner: string, + params: Record, +) => { const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.space}`); const spaceMemberDocRef = spaceDocRef.collection(SUB_COL.MEMBERS).doc(owner); const spaceMember = await spaceMemberDocRef.get(); @@ -58,22 +64,24 @@ export const createProposal = async (owner: string, params: Record; - const proposal = { + const proposal = { ...params, settings: { ...settings, startDate: dateToTimestamp(settings.startDate as Date, true), endDate: dateToTimestamp(settings.endDate as Date, true), }, + project, + projects: getProjects([], project), uid: getRandomEthAddress(), rank: 1, createdBy: owner, approved: false, rejected: false, completed: false, - }; + } as Proposal; - const totalWeight = await createProposalMembersAndGetTotalWeight(proposal); + const totalWeight = await createProposalMembersAndGetTotalWeight(project, proposal); const results = { total: totalWeight * proposal.questions.length, voted: 0, @@ -82,6 +90,8 @@ export const createProposal = async (owner: string, params: Record { +const createProposalMembersAndGetTotalWeight = async (project: string, proposal: Proposal) => { const subCol = proposal.settings.onlyGuardians ? SUB_COL.GUARDIANS : SUB_COL.MEMBERS; const spaceDocRef = build5Db().doc(`${COL.SPACE}/${proposal.space}`); const spaceMembers = await spaceDocRef.collection(subCol).get(); const promises = spaceMembers.map(async (spaceMember) => { - const proposalMember = await createProposalMember(proposal, spaceMember); + const proposalMember = createProposalMember(project, proposal, spaceMember); if (proposalMember.weight || proposal.type === ProposalType.NATIVE) { const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); await proposalDocRef @@ -110,12 +120,16 @@ const createProposalMembersAndGetTotalWeight = async (proposal: Proposal) => { return proposalMemberWeights.reduce((acc, act) => acc + act, 0); }; -const createProposalMember = async (proposal: Proposal, spaceMember: SpaceMember) => { - return { - uid: spaceMember.uid, - weight: proposal.type === ProposalType.NATIVE ? 0 : 1, - voted: false, - parentId: proposal.uid, - parentCol: COL.PROPOSAL, - }; -}; +const createProposalMember = ( + project: string, + proposal: Proposal, + spaceMember: SpaceMember, +): ProposalMember => ({ + project, + projects: getProjects([proposal], project), + uid: spaceMember.uid, + weight: proposal.type === ProposalType.NATIVE ? 0 : 1, + voted: false, + parentId: proposal.uid, + parentCol: COL.PROPOSAL, +}); diff --git a/packages/functions/src/services/payment/tangle-service/proposal/voting/ProposalVoteService.ts b/packages/functions/src/services/payment/tangle-service/proposal/voting/ProposalVoteService.ts index 05d8041cee..c315a08e8c 100644 --- a/packages/functions/src/services/payment/tangle-service/proposal/voting/ProposalVoteService.ts +++ b/packages/functions/src/services/payment/tangle-service/proposal/voting/ProposalVoteService.ts @@ -18,6 +18,7 @@ import { WenError, } from '@build-5/interfaces'; import dayjs from 'dayjs'; +import { getProject, getProjects } from '../../../../../utils/common.utils'; import { invalidArgument } from '../../../../../utils/error.utils'; import { assertValidationAsync } from '../../../../../utils/schema.utils'; import { getTokenForSpace } from '../../../../../utils/token.utils'; @@ -30,6 +31,7 @@ import { createVoteTransactionOrder } from './token.voting'; export class ProposalVoteService extends BaseService { public handleRequest = async ({ + order, owner, request, tran, @@ -48,6 +50,7 @@ export class ProposalVoteService extends BaseService { if (request.voteWithStakedTokes) { const voteTransaction = await voteWithStakedTokens( + getProject(order), this.transactionService.transaction, owner, proposal, @@ -56,14 +59,25 @@ export class ProposalVoteService extends BaseService { return { status: 'success', voteTransaction: voteTransaction.uid }; } - await this.handleTokenVoteRequest(owner, proposal, [params.value], token, tran, tranEntry); + await this.handleTokenVoteRequest( + getProject(order), + owner, + proposal, + [params.value], + token, + tran, + tranEntry, + ); return; } - return await this.handleSimpleVoteRequest(proposal, proposalMember, [params.value]); + return await this.handleSimpleVoteRequest(getProject(order), proposal, proposalMember, [ + params.value, + ]); }; private handleTokenVoteRequest = async ( + project: string, owner: string, proposal: Proposal, values: number[], @@ -71,7 +85,7 @@ export class ProposalVoteService extends BaseService { milestoneTran: MilestoneTransaction, milestoneTranEntry: MilestoneTransactionEntry, ) => { - const order = await createVoteTransactionOrder(owner, proposal, values, token); + const order = await createVoteTransactionOrder(project, owner, proposal, values, token); const orderDocRef = build5Db().doc(`${COL.TRANSACTION}/${order.uid}`); this.transactionService.push({ @@ -90,6 +104,7 @@ export class ProposalVoteService extends BaseService { }; private handleSimpleVoteRequest = async ( + project: string, proposal: Proposal, proposalMember: ProposalMember, values: number[], @@ -97,7 +112,7 @@ export class ProposalVoteService extends BaseService { const proposalDocRef = build5Db().doc(`${COL.PROPOSAL}/${proposal.uid}`); const proposalMemberDocRef = proposalDocRef.collection(SUB_COL.MEMBERS).doc(proposalMember.uid); - const voteData = await executeSimpleVoting(proposalMember, proposal, values); + const voteData = await executeSimpleVoting(project, proposalMember, proposal, values); this.transactionService.push({ ref: proposalDocRef, @@ -181,12 +196,15 @@ const assertAnswerIsValid = (proposal: Proposal, answerSent: number) => { }; export const createVoteTransaction = ( + project: string, proposal: Proposal, owner: string, weight: number, values: number[], stakes: string[] = [], ): Transaction => ({ + project, + projects: getProjects([proposal], project), type: TransactionType.VOTE, uid: getRandomEthAddress(), member: owner, diff --git a/packages/functions/src/services/payment/tangle-service/proposal/voting/simple.voting.ts b/packages/functions/src/services/payment/tangle-service/proposal/voting/simple.voting.ts index e093586bb2..beca61924b 100644 --- a/packages/functions/src/services/payment/tangle-service/proposal/voting/simple.voting.ts +++ b/packages/functions/src/services/payment/tangle-service/proposal/voting/simple.voting.ts @@ -4,12 +4,13 @@ import { head } from 'lodash'; import { createVoteTransaction } from './ProposalVoteService'; export const executeSimpleVoting = async ( + project: string, member: ProposalMember, proposal: Proposal, values: number[], ) => { const weight = member.weight || 0; - const voteTransaction = createVoteTransaction(proposal, member.uid, weight, values); + const voteTransaction = createVoteTransaction(project, proposal, member.uid, weight, values); const proposalUpdateData = getProposalUpdateDataAfterVote(member, weight, values); const proposalMember = { uid: member.uid, diff --git a/packages/functions/src/services/payment/tangle-service/proposal/voting/staked.token.voting.ts b/packages/functions/src/services/payment/tangle-service/proposal/voting/staked.token.voting.ts index 26a794cc7a..796d9585dc 100644 --- a/packages/functions/src/services/payment/tangle-service/proposal/voting/staked.token.voting.ts +++ b/packages/functions/src/services/payment/tangle-service/proposal/voting/staked.token.voting.ts @@ -14,6 +14,7 @@ import { getTokenVoteMultiplier } from '../../../voting-service'; import { createVoteTransaction } from './ProposalVoteService'; export const voteWithStakedTokens = async ( + project: string, transaction: ITransaction, member: string, proposal: Proposal, @@ -42,6 +43,7 @@ export const voteWithStakedTokens = async ( } const voteTransaction = createVoteTransaction( + project, proposal, member, weight, diff --git a/packages/functions/src/services/payment/tangle-service/proposal/voting/token.voting.ts b/packages/functions/src/services/payment/tangle-service/proposal/voting/token.voting.ts index e5390c24b8..ed34fce9ce 100644 --- a/packages/functions/src/services/payment/tangle-service/proposal/voting/token.voting.ts +++ b/packages/functions/src/services/payment/tangle-service/proposal/voting/token.voting.ts @@ -12,6 +12,7 @@ import { HexHelper } from '@iota/util.js-next'; import bigInt from 'big-integer'; import dayjs from 'dayjs'; import { packBasicOutput } from '../../../../../utils/basic-output.utils'; +import { getProjects } from '../../../../../utils/common.utils'; import { isProdEnv } from '../../../../../utils/config.utils'; import { dateToTimestamp } from '../../../../../utils/dateTime.utils'; import { getRandomEthAddress } from '../../../../../utils/wallet.utils'; @@ -19,6 +20,7 @@ import { SmrWallet } from '../../../../wallet/SmrWalletService'; import { WalletService } from '../../../../wallet/wallet'; export const createVoteTransactionOrder = async ( + project: string, owner: string, proposal: Proposal, voteValues: number[], @@ -41,6 +43,8 @@ export const createVoteTransactionOrder = async ( ); return { + project, + projects: getProjects([], project), type: TransactionType.ORDER, uid: getRandomEthAddress(), member: owner, diff --git a/packages/functions/src/services/payment/tangle-service/space/SpaceAcceptMemberService.ts b/packages/functions/src/services/payment/tangle-service/space/SpaceAcceptMemberService.ts index eb99c8e307..d4e7ddf1c0 100644 --- a/packages/functions/src/services/payment/tangle-service/space/SpaceAcceptMemberService.ts +++ b/packages/functions/src/services/payment/tangle-service/space/SpaceAcceptMemberService.ts @@ -1,5 +1,13 @@ import { build5Db } from '@build-5/database'; -import { BaseTangleResponse, COL, SpaceMember, SUB_COL, WenError } from '@build-5/interfaces'; +import { + BaseTangleResponse, + COL, + Space, + SpaceMember, + SUB_COL, + WenError, +} from '@build-5/interfaces'; +import { getProject, getProjects } from '../../../../utils/common.utils'; import { invalidArgument } from '../../../../utils/error.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; import { assertIsGuardian } from '../../../../utils/token.utils'; @@ -7,10 +15,19 @@ import { BaseService, HandlerParams } from '../../base'; import { editSpaceMemberSchemaObject } from './SpaceEditMemberTangleRequestSchema'; export class SpaceAcceptMemberService extends BaseService { - public handleRequest = async ({ owner, request }: HandlerParams): Promise => { + public handleRequest = async ({ + order, + owner, + request, + }: HandlerParams): Promise => { const params = await assertValidationAsync(editSpaceMemberSchemaObject, request); - const { spaceMember, space } = await acceptSpaceMember(owner, params.uid, params.member); + const { spaceMember, space } = await acceptSpaceMember( + getProject(order), + owner, + params.uid, + params.member, + ); const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); const spaceMemberDocRef = spaceDocRef.collection(SUB_COL.MEMBERS).doc(spaceMember.uid); @@ -34,10 +51,15 @@ export class SpaceAcceptMemberService extends BaseService { }; } -export const acceptSpaceMember = async (owner: string, space: string, member: string) => { - await assertIsGuardian(space, owner); +export const acceptSpaceMember = async ( + project: string, + owner: string, + spaceId: string, + member: string, +) => { + await assertIsGuardian(spaceId, owner); - const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space}`); + const spaceDocRef = build5Db().doc(`${COL.SPACE}/${spaceId}`); const knockingMember = await spaceDocRef .collection(SUB_COL.KNOCKING_MEMBERS) .doc(member) @@ -46,7 +68,10 @@ export const acceptSpaceMember = async (owner: string, space: string, member: st throw invalidArgument(WenError.member_did_not_request_to_join); } + const space = await spaceDocRef.get(); const spaceMember = { + project, + projects: getProjects([space], project), uid: member, parentId: space, parentCol: COL.SPACE, diff --git a/packages/functions/src/services/payment/tangle-service/space/SpaceBlockMemberService.ts b/packages/functions/src/services/payment/tangle-service/space/SpaceBlockMemberService.ts index b4a14a84f5..862154a412 100644 --- a/packages/functions/src/services/payment/tangle-service/space/SpaceBlockMemberService.ts +++ b/packages/functions/src/services/payment/tangle-service/space/SpaceBlockMemberService.ts @@ -1,5 +1,6 @@ import { build5Db } from '@build-5/database'; import { BaseTangleResponse, COL, Space, SUB_COL, WenError } from '@build-5/interfaces'; +import { getProject, getProjects } from '../../../../utils/common.utils'; import { invalidArgument } from '../../../../utils/error.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; import { assertIsGuardian } from '../../../../utils/token.utils'; @@ -7,11 +8,20 @@ import { BaseService, HandlerParams } from '../../base'; import { editSpaceMemberSchemaObject } from './SpaceEditMemberTangleRequestSchema'; export class SpaceBlockMemberService extends BaseService { - public handleRequest = async ({ owner, request }: HandlerParams): Promise => { + public handleRequest = async ({ + order, + owner, + request, + }: HandlerParams): Promise => { const params = await assertValidationAsync(editSpaceMemberSchemaObject, request); const member = params.member; - const { space, blockedMember } = await getBlockMemberUpdateData(owner, params.uid, member); + const { space, blockedMember } = await getBlockMemberUpdateData( + getProject(order), + owner, + params.uid, + member, + ); const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); const blockedMemberDocRef = spaceDocRef.collection(SUB_COL.BLOCKED_MEMBERS).doc(member); @@ -44,7 +54,12 @@ export class SpaceBlockMemberService extends BaseService { }; } -export const getBlockMemberUpdateData = async (owner: string, spaceId: string, member: string) => { +export const getBlockMemberUpdateData = async ( + project: string, + owner: string, + spaceId: string, + member: string, +) => { const spaceDocRef = build5Db().doc(`${COL.SPACE}/${spaceId}`); await assertIsGuardian(spaceId, owner); @@ -70,7 +85,13 @@ export const getBlockMemberUpdateData = async (owner: string, spaceId: string, m throw invalidArgument(WenError.can_not_block_guardian); } - const blockedMember = { uid: member, parentId: spaceId, parentCol: COL.SPACE }; + const blockedMember = { + project, + projects: getProjects([space]), + uid: member, + parentId: spaceId, + parentCol: COL.SPACE, + }; const spaceUpdateData = { totalMembers: build5Db().inc(spaceMember ? -1 : 0), totalPendingMembers: build5Db().inc(knockingMember ? -1 : 0), diff --git a/packages/functions/src/services/payment/tangle-service/space/SpaceCreateService.ts b/packages/functions/src/services/payment/tangle-service/space/SpaceCreateService.ts index d4cfe0eaba..7441537a63 100644 --- a/packages/functions/src/services/payment/tangle-service/space/SpaceCreateService.ts +++ b/packages/functions/src/services/payment/tangle-service/space/SpaceCreateService.ts @@ -2,6 +2,7 @@ import { build5Db, build5Storage } from '@build-5/database'; import { COL, MediaStatus, Network, SUB_COL } from '@build-5/interfaces'; import { get, set } from 'lodash'; import { downloadMediaAndPackCar } from '../../../../utils/car.utils'; +import { getProjects } from '../../../../utils/common.utils'; import { getBucket, isProdEnv } from '../../../../utils/config.utils'; import { migrateUriToSotrage, uriToUrl } from '../../../../utils/media.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; @@ -13,10 +14,10 @@ import { BaseService, HandlerParams } from '../../base'; import { createSpaceSchemaObject } from './SpaceCreateTangleRequestSchema'; export class SpaceCreateService extends BaseService { - public handleRequest = async ({ owner, request }: HandlerParams) => { + public handleRequest = async ({ project, owner, request }: HandlerParams) => { await assertValidationAsync(createSpaceSchemaObject, request); - const { space, guardian, member } = await getCreateSpaceData(owner, request); + const { space, guardian, member } = await getCreateSpaceData(project, owner, request); const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); this.transactionService.push({ ref: spaceDocRef, data: space, action: 'set' }); @@ -46,12 +47,18 @@ export class SpaceCreateService extends BaseService { }; } -export const getCreateSpaceData = async (owner: string, params: Record) => { +export const getCreateSpaceData = async ( + project: string, + owner: string, + params: Record, +) => { const wallet = await WalletService.newWallet(isProdEnv() ? Network.SMR : Network.RMS); const vaultAddress = await wallet.getNewIotaAddressDetails(); const space = { uid: getRandomEthAddress(), + project, + projects: getProjects([], project), ...params, createdBy: owner, open: params.open === false ? false : true, @@ -87,6 +94,8 @@ export const getCreateSpaceData = async (owner: string, params: Record => { @@ -38,6 +40,7 @@ export class SpaceGuardianService extends BaseService { const params = await assertValidationAsync(editSpaceMemberSchemaObject, request); const { proposal, voteTransaction, members } = await addRemoveGuardian( + getProject(order), owner, { ...params }, type, @@ -66,6 +69,7 @@ export class SpaceGuardianService extends BaseService { } export const addRemoveGuardian = async ( + project: string, owner: string, params: Record, type: ProposalType, @@ -117,15 +121,19 @@ export const addRemoveGuardian = async ( .doc(`${COL.SPACE}/${params.uid}`) .collection(SUB_COL.GUARDIANS) .get(); + const space = await spaceDocRef.get(); const proposal = getProposalData( + project, guardian, - params.uid as string, + space!, member, isAddGuardian, guardians.length, ); const voteTransaction: Transaction = { + project, + projects: getProjects([space], project), type: TransactionType.VOTE, uid: getRandomEthAddress(), member: owner, @@ -154,24 +162,27 @@ export const addRemoveGuardian = async ( }; const getProposalData = ( + project: string, owner: Member, - space: string, + space: Space, member: Member, isAddGuardian: boolean, guardiansCount: number, -) => { +): Proposal => { const additionalInfo = `${owner.name || owner.uid} wants to ${isAddGuardian ? 'add' : 'remove'} ${ member.name } as guardian. ` + `Request created on ${dayjs().format('MM/DD/YYYY')}. ` + `${ADD_REMOVE_GUARDIAN_THRESHOLD_PERCENTAGE} % must agree for this action to proceed`; - return { + return { + project, + projects: getProjects([space], project), createdBy: owner.uid, uid: getRandomEthAddress(), name: `${isAddGuardian ? 'Add' : 'Remove'} guardian`, additionalInfo: additionalInfo, - space, + space: space.uid, description: '', type: isAddGuardian ? ProposalType.ADD_GUARDIAN : ProposalType.REMOVE_GUARDIAN, approved: true, diff --git a/packages/functions/src/services/payment/tangle-service/space/SpaceJoinService.ts b/packages/functions/src/services/payment/tangle-service/space/SpaceJoinService.ts index f4b40593e8..24369992f1 100644 --- a/packages/functions/src/services/payment/tangle-service/space/SpaceJoinService.ts +++ b/packages/functions/src/services/payment/tangle-service/space/SpaceJoinService.ts @@ -9,6 +9,7 @@ import { TokenDistribution, WenError, } from '@build-5/interfaces'; +import { getProject, getProjects } from '../../../../utils/common.utils'; import { serverTime } from '../../../../utils/dateTime.utils'; import { invalidArgument } from '../../../../utils/error.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; @@ -18,7 +19,11 @@ import { BaseService, HandlerParams } from '../../base'; import { joinSpaceSchema } from './SpaceJoinTangleRequestSchema'; export class SpaceJoinService extends BaseService { - public handleRequest = async ({ owner, request }: HandlerParams): Promise => { + public handleRequest = async ({ + order, + owner, + request, + }: HandlerParams): Promise => { const params = await assertValidationAsync(joinSpaceSchema, request); const spaceDocRef = build5Db().doc(`${COL.SPACE}/${params.uid}`); @@ -27,7 +32,11 @@ export class SpaceJoinService extends BaseService { throw invalidArgument(WenError.space_does_not_exists); } - const { space: spaceUpdateData, spaceMember, member } = await getJoinSpaceData(owner, space); + const { + space: spaceUpdateData, + spaceMember, + member, + } = await getJoinSpaceData(getProject(order), owner, space); const joiningMemberDocRef = spaceDocRef .collection(space.open || space.tokenBased ? SUB_COL.MEMBERS : SUB_COL.KNOCKING_MEMBERS) @@ -56,7 +65,7 @@ export class SpaceJoinService extends BaseService { }; } -export const getJoinSpaceData = async (owner: string, space: Space) => { +export const getJoinSpaceData = async (project: string, owner: string, space: Space) => { const spaceDocRef = build5Db().doc(`${COL.SPACE}/${space.uid}`); const joinedMemberSnap = await spaceDocRef.collection(SUB_COL.MEMBERS).doc(owner).get(); @@ -82,6 +91,8 @@ export const getJoinSpaceData = async (owner: string, space: Space) => { } const spaceMember: SpaceMember = { + project, + projects: getProjects([space], project), uid: owner, parentId: space.uid, parentCol: COL.SPACE, diff --git a/packages/functions/src/services/payment/tangle-service/token/stake.service.ts b/packages/functions/src/services/payment/tangle-service/token/stake.service.ts index 9c131f095f..7eb1211174 100644 --- a/packages/functions/src/services/payment/tangle-service/token/stake.service.ts +++ b/packages/functions/src/services/payment/tangle-service/token/stake.service.ts @@ -14,6 +14,7 @@ import bigInt from 'big-integer'; import dayjs from 'dayjs'; import { set } from 'lodash'; import { packBasicOutput } from '../../../../utils/basic-output.utils'; +import { getProjects } from '../../../../utils/common.utils'; import { dateToTimestamp, serverTime } from '../../../../utils/dateTime.utils'; import { invalidArgument } from '../../../../utils/error.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; @@ -25,10 +26,11 @@ import { BaseService, HandlerParams } from '../../base'; import { depositStakeSchemaObject } from './TokenStakeTangleRequestSchema'; export class TangleStakeService extends BaseService { - public handleRequest = async ({ owner, request, tran, tranEntry }: HandlerParams) => { + public handleRequest = async ({ owner, request, tran, tranEntry, project }: HandlerParams) => { const params = await assertValidationAsync(depositStakeSchemaObject, request); const order = await createStakeOrder( + project, owner, params.symbol, params.weeks, @@ -55,6 +57,7 @@ export class TangleStakeService extends BaseService { } export const createStakeOrder = async ( + project: string, owner: string, symbol: string, weeks: number, @@ -90,6 +93,8 @@ export const createStakeOrder = async ( customMetadata, ); return { + project, + projects: getProjects([], project), type: TransactionType.ORDER, uid: getRandomEthAddress(), member: owner, diff --git a/packages/functions/src/services/payment/tangle-service/token/token-claim.service.ts b/packages/functions/src/services/payment/tangle-service/token/token-claim.service.ts index a2c8ee870a..ba92aa23f1 100644 --- a/packages/functions/src/services/payment/tangle-service/token/token-claim.service.ts +++ b/packages/functions/src/services/payment/tangle-service/token/token-claim.service.ts @@ -18,6 +18,7 @@ import { import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; import { assertMemberHasValidAddress } from '../../../../utils/address.utils'; +import { getProjects } from '../../../../utils/common.utils'; import { dateToTimestamp, serverTime } from '../../../../utils/dateTime.utils'; import { invalidArgument } from '../../../../utils/error.utils'; import { assertValidationAsync } from '../../../../utils/schema.utils'; @@ -30,9 +31,13 @@ import { BaseService, HandlerParams } from '../../base'; import { tokenClaimSchema } from './TokenClaimTangleRequestSchema'; export class TangleTokenClaimService extends BaseService { - public handleRequest = async ({ owner, request }: HandlerParams): Promise => { + public handleRequest = async ({ + project, + owner, + request, + }: HandlerParams): Promise => { const params = await assertValidationAsync(tokenClaimSchema, request); - const order = await createMintedTokenAirdropCalimOrder(owner, params.symbol); + const order = await createMintedTokenAirdropCalimOrder(project, owner, params.symbol); this.transactionService.push({ ref: build5Db().doc(`${COL.TRANSACTION}/${order.uid}`), data: order, @@ -43,6 +48,7 @@ export class TangleTokenClaimService extends BaseService { } export const createMintedTokenAirdropCalimOrder = async ( + project: string, owner: string, symbol: string, ): Promise => { @@ -71,6 +77,8 @@ export const createMintedTokenAirdropCalimOrder = async ( }, 0); return { + project, + projects: getProjects([], project), type: TransactionType.ORDER, uid: getRandomEthAddress(), member: owner, @@ -100,6 +108,8 @@ const getClaimableDrops = async (token: string, member: string) => { return airdops; } const drop: TokenDrop = { + project: '', + projects: {}, uid: getRandomEthAddress(), member, token, diff --git a/packages/functions/src/services/payment/tangle-service/token/token-trade.service.ts b/packages/functions/src/services/payment/tangle-service/token/token-trade.service.ts index afe88d73ea..0bfb0a01fd 100644 --- a/packages/functions/src/services/payment/tangle-service/token/token-trade.service.ts +++ b/packages/functions/src/services/payment/tangle-service/token/token-trade.service.ts @@ -26,6 +26,7 @@ import bigDecimal from 'js-big-decimal'; import { set } from 'lodash'; import { assertMemberHasValidAddress } from '../../../../utils/address.utils'; import { packBasicOutput } from '../../../../utils/basic-output.utils'; +import { getProject, getProjects } from '../../../../utils/common.utils'; import { isProdEnv } from '../../../../utils/config.utils'; import { dateToTimestamp } from '../../../../utils/dateTime.utils'; import { invalidArgument } from '../../../../utils/error.utils'; @@ -44,6 +45,7 @@ import { tradeMintedTokenSchema } from './TokenTradeTangleRequestSchema'; export class TangleTokenTradeService extends BaseService { public handleRequest = async ({ + order, match, payment, tran, @@ -69,6 +71,7 @@ export class TangleTokenTradeService extends BaseService { } const { tradeOrderTransaction } = await createTokenTradeOrder( + getProject(order), this.transactionService.transaction, owner, token, @@ -124,6 +127,7 @@ const ACCEPTED_TOKEN_STATUSES = [ TokenStatus.BASE, ]; export const createTokenTradeOrder = async ( + project: string, transaction: ITransaction, owner: string, token: Token, @@ -147,6 +151,7 @@ export const createTokenTradeOrder = async ( if ([TokenStatus.BASE, TokenStatus.MINTED].includes(token.status) || !isSell) { const tradeOrderTransaction = await createTradeOrderTransaction( + project, token, owner, sourceNetwork, @@ -168,7 +173,9 @@ export const createTokenTradeOrder = async ( if (Number(count) > tokensLeftForSale) { throw invalidArgument(WenError.no_available_tokens_for_sale); } - const tradeOrder = { + const tradeOrder: TokenTradeOrder = { + project, + projects: getProjects([token], project), uid: getRandomEthAddress(), owner, token: token.uid, @@ -209,6 +216,7 @@ const getSourceAndTargetNetwork = (token: Token, isSell: boolean) => { }; const createTradeOrderTransaction = async ( + project: string, token: Token, member: string, network: Network, @@ -220,6 +228,8 @@ const createTradeOrderTransaction = async ( const targetAddress = await wallet.getNewIotaAddressDetails(); const isMinted = token.status === TokenStatus.MINTED; return { + project, + projects: getProjects([token], project), type: TransactionType.ORDER, uid: getRandomEthAddress(), member, diff --git a/packages/functions/src/services/payment/token/import-minted-token.service.ts b/packages/functions/src/services/payment/token/import-minted-token.service.ts index 0ed840fb37..2f33363ed4 100644 --- a/packages/functions/src/services/payment/token/import-minted-token.service.ts +++ b/packages/functions/src/services/payment/token/import-minted-token.service.ts @@ -22,6 +22,7 @@ import { import { Converter } from '@iota/util.js-next'; import Joi from 'joi'; import { get, isEmpty } from 'lodash'; +import { getProject, getProjects } from '../../../utils/common.utils'; import { getBucket } from '../../../utils/config.utils'; import { migrateUriToSotrage, uriToUrl } from '../../../utils/media.utils'; import { isAliasGovernor } from '../../../utils/token-minting-utils/alias.utils'; @@ -59,6 +60,8 @@ export class ImportMintedTokenService extends BaseService { const vaultAddress = await wallet.getNewIotaAddressDetails(); const totalSupply = Number(foundry.tokenScheme.maximumSupply); const token: Token = { + project: getProject(order), + projects: getProjects([order]), createdBy: order.member || '', uid: tokenId, name: metadata.name, diff --git a/packages/functions/src/services/payment/token/token-trade.service.ts b/packages/functions/src/services/payment/token/token-trade.service.ts index 188d8e4a18..763cc56a33 100644 --- a/packages/functions/src/services/payment/token/token-trade.service.ts +++ b/packages/functions/src/services/payment/token/token-trade.service.ts @@ -15,12 +15,19 @@ import { } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { get, head } from 'lodash'; +import { getProjects } from '../../../utils/common.utils'; import { dateToTimestamp } from '../../../utils/dateTime.utils'; import { getRandomEthAddress } from '../../../utils/wallet.utils'; import { BaseService, HandlerParams } from '../base'; export class TokenTradeService extends BaseService { - public handleRequest = async ({ order, match, tranEntry, build5Tran }: HandlerParams) => { + public handleRequest = async ({ + project, + order, + match, + tranEntry, + build5Tran, + }: HandlerParams) => { const payment = await this.transactionService.createPayment(order, match); const nativeTokenId = head(order.payload.nativeTokens as NativeToken[])?.id; @@ -40,9 +47,11 @@ export class TokenTradeService extends BaseService { await this.createDistributionDocRef(order.payload.token!, order.member!); const token = await build5Db().doc(`${COL.TOKEN}/${order.payload.token}`).get(); const network = order.network || DEFAULT_NETWORK; - const data = { + const data: TokenTradeOrder = { + project, + projects: getProjects([order], project), uid: getRandomEthAddress(), - owner: order.member, + owner: order.member!, token: token.uid, tokenStatus: token.status, type: @@ -51,8 +60,8 @@ export class TokenTradeService extends BaseService { : TokenTradeOrderType.BUY, count: nativeTokens || get(order, 'payload.count', 0), price: get(order, 'payload.price', 0), - totalDeposit: nativeTokens || order.payload.amount, - balance: nativeTokens || order.payload.amount, + totalDeposit: nativeTokens || order.payload.amount || 0, + balance: nativeTokens || order.payload.amount || 0, fulfilled: 0, status: TokenTradeOrderStatus.ACTIVE, orderTransactionId: order.uid, diff --git a/packages/functions/src/services/payment/transaction-service.ts b/packages/functions/src/services/payment/transaction-service.ts index eb5cecc3b2..0298f3f120 100644 --- a/packages/functions/src/services/payment/transaction-service.ts +++ b/packages/functions/src/services/payment/transaction-service.ts @@ -29,6 +29,7 @@ import * as functions from 'firebase-functions/v2'; import { get, isEmpty, set } from 'lodash'; import { SmrMilestoneTransactionAdapter } from '../../triggers/milestone-transactions-triggers/SmrMilestoneTransactionAdapter'; import { getOutputMetadata } from '../../utils/basic-output.utils'; +import { getProject, getProjects } from '../../utils/common.utils'; import { dateToTimestamp, serverTime } from '../../utils/dateTime.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; export interface TransactionMatch { @@ -78,6 +79,8 @@ export class TransactionService { throw new Error('Order was not provided as transaction.'); } const data: Transaction = { + project: getProject(order), + projects: getProjects([order]), type: TransactionType.PAYMENT, uid: getRandomEthAddress(), member: order.member || tran.from.address, @@ -137,10 +140,12 @@ export class TransactionService { } if (finalAmt > 0) { - const data = { + const data: Transaction = { + project: getProject(payment), + projects: getProjects([payment]), type: TransactionType.BILL_PAYMENT, uid: getRandomEthAddress(), - space: order.payload.beneficiary !== 'member' ? order.space : null, + space: (order.payload.beneficiary !== 'member' ? order.space : null) as string, member: order.member || payment.member || '', network: order.network || DEFAULT_NETWORK, payload: { @@ -157,7 +162,7 @@ export class TransactionService { royalty: false, void: false, collection: order.payload.collection || null, - quantity: order.payload.quantity || null, + quantity: (order.payload.quantity || null) as number, restrictions: get(order, 'payload.restrictions', {}), }, }; @@ -171,7 +176,9 @@ export class TransactionService { } if (royaltyAmt > 0) { - const data = { + const data: Transaction = { + project: getProject(payment), + projects: getProjects([payment]), type: TransactionType.BILL_PAYMENT, uid: getRandomEthAddress(), member: order.member, @@ -189,7 +196,7 @@ export class TransactionService { void: false, nft: order.payload.nft || null, collection: order.payload.collection || null, - quantity: order.payload.quantity || null, + quantity: (order.payload.quantity || null) as number, restrictions: get(order, 'payload.restrictions', {}), }, }; @@ -218,6 +225,8 @@ export class TransactionService { ): Promise { if (payment.payload.amount! > 0) { const data: Transaction = { + project: getProject(payment), + projects: getProjects([payment]), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: payment.space, @@ -276,6 +285,8 @@ export class TransactionService { ) { if (payment.payload.amount! > 0) { const data: Transaction = { + project: getProject(payment), + projects: getProjects([payment]), type: TransactionType.CREDIT_TANGLE_REQUEST, uid: getRandomEthAddress(), space: payment.space, @@ -320,7 +331,9 @@ export class TransactionService { if (!isEmpty(error) && !get(error, 'code')) { functions.logger.error(payment.uid, tran.to.nftOutput?.nftId, error); } - const transaction = { + const transaction: Transaction = { + project: getProject(payment), + projects: getProjects([payment]), type: TransactionType.CREDIT_NFT, uid: getRandomEthAddress(), space: payment.space || '', @@ -482,6 +495,8 @@ export class TransactionService { ) => { const network = order.network || DEFAULT_NETWORK; const data: Transaction = { + project: getProject(order), + projects: getProjects([order]), type: TransactionType.UNLOCK, uid: getRandomEthAddress(), space: order.space || '', diff --git a/packages/functions/src/services/payment/voting-service.ts b/packages/functions/src/services/payment/voting-service.ts index a2eefe45e9..7320e96a7c 100644 --- a/packages/functions/src/services/payment/voting-service.ts +++ b/packages/functions/src/services/payment/voting-service.ts @@ -9,6 +9,7 @@ import { } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { get, head } from 'lodash'; +import { getProject, getProjects } from '../../utils/common.utils'; import { getTokenForSpace } from '../../utils/token.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; import { BaseService, HandlerParams } from './base'; @@ -104,6 +105,8 @@ export class VotingService extends BaseService { values: number[], ) => { const voteTransaction: Transaction = { + project: getProject(order), + projects: getProjects([order]), type: TransactionType.VOTE, uid: getRandomEthAddress(), member: order.member, diff --git a/packages/functions/src/triggers/award.trigger.ts b/packages/functions/src/triggers/award.trigger.ts index cbb6d47f82..e838913fb6 100644 --- a/packages/functions/src/triggers/award.trigger.ts +++ b/packages/functions/src/triggers/award.trigger.ts @@ -11,6 +11,7 @@ import { } from '@build-5/interfaces'; import * as functions from 'firebase-functions/v2'; import { getAddress } from '../utils/address.utils'; +import { getProject, getProjects } from '../utils/common.utils'; import { getRandomEthAddress } from '../utils/wallet.utils'; export const awardUpdateTrigger = functions.firestore.onDocumentUpdated( @@ -31,7 +32,9 @@ export const awardUpdateTrigger = functions.firestore.onDocumentUpdated( const member = await memberDocRef.get(); const targetAddress = getAddress(member, curr.network); - const burnAlias = { + const burnAlias: Transaction = { + project: getProject(curr), + projects: getProjects([curr]), type: TransactionType.AWARD, uid: getRandomEthAddress(), space: curr.space, @@ -52,7 +55,9 @@ export const awardUpdateTrigger = functions.firestore.onDocumentUpdated( if (curr.badge.type === AwardBadgeType.BASE && remainingBadges) { const tokenDocRef = build5Db().doc(`${COL.TOKEN}/${curr.badge.tokenUid}`); const token = (await tokenDocRef.get())!; - const baseTokenCredit = { + const baseTokenCredit: Transaction = { + project: getProject(curr), + projects: getProjects([curr]), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: curr.space, @@ -90,6 +95,8 @@ export const awardUpdateTrigger = functions.firestore.onDocumentUpdated( const token = (await tokenDocRef.get())!; const nativeTokensCredit: Transaction = { + project: getProject(curr), + projects: getProjects([curr]), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: curr.space, diff --git a/packages/functions/src/triggers/collection.trigger.ts b/packages/functions/src/triggers/collection.trigger.ts index ec5b3db0e2..9118c59cd0 100644 --- a/packages/functions/src/triggers/collection.trigger.ts +++ b/packages/functions/src/triggers/collection.trigger.ts @@ -18,6 +18,7 @@ import { last } from 'lodash'; import { scale } from '../scale.settings'; import { getAddress } from '../utils/address.utils'; import { collectionToIpfsMetadata, downloadMediaAndPackCar } from '../utils/car.utils'; +import { getProject, getProjects } from '../utils/common.utils'; import { getRandomEthAddress } from '../utils/wallet.utils'; export const collectionWrite = functions.firestore.onDocumentUpdated( @@ -96,12 +97,14 @@ const hidePlaceholderNft = async (collection: Collection) => { const onCollectionMinted = async (collection: Collection) => { if (collection.limitedEdition) { - const order = { + const order: Transaction = { + project: getProject(collection), + projects: getProjects([collection]), type: TransactionType.MINT_COLLECTION, uid: getRandomEthAddress(), member: collection.mintingData?.mintedBy, space: collection.space, - network: collection.mintingData?.network, + network: collection.mintingData?.network!, payload: { type: TransactionPayloadType.LOCK_COLLECTION, amount: 0, @@ -115,12 +118,14 @@ const onCollectionMinted = async (collection: Collection) => { } const memberDocRef = build5Db().doc(`${COL.MEMBER}/${collection.mintingData?.mintedBy}`); const member = (await memberDocRef.get())!; - const order = { + const order: Transaction = { + project: getProject(collection), + projects: getProjects([collection]), type: TransactionType.MINT_COLLECTION, uid: getRandomEthAddress(), member: collection.mintingData?.mintedBy, space: collection.space, - network: collection.mintingData?.network, + network: collection.mintingData?.network!, payload: { type: TransactionPayloadType.SEND_ALIAS_TO_GUARDIAN, amount: collection.mintingData?.aliasStorageDeposit, @@ -153,12 +158,14 @@ const onCollectionMinting = async (collection: Collection) => { }; const onNftMediaPrepared = async (collection: Collection) => { - const order = { + const order: Transaction = { + project: getProject(collection), + projects: getProjects([collection]), type: TransactionType.MINT_COLLECTION, uid: getRandomEthAddress(), member: collection.mintingData?.mintedBy!, space: collection.space, - network: collection.mintingData?.network, + network: collection.mintingData?.network!, payload: { type: TransactionPayloadType.MINT_ALIAS, amount: collection.mintingData?.aliasStorageDeposit || 0, @@ -299,7 +306,9 @@ const setNftForMinting = async (nftId: string, collection: Collection): Promise< const member = ( await build5Db().doc(`${COL.MEMBER}/${nft.auctionHighestBidder}`).get() ); - const credit = { + const credit: Transaction = { + project: getProject(highestTransaction), + projects: getProjects([highestTransaction]), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: highestTransaction.space, diff --git a/packages/functions/src/triggers/token-trading/match-base-token.ts b/packages/functions/src/triggers/token-trading/match-base-token.ts index 4e9713f121..b86c7b2d39 100644 --- a/packages/functions/src/triggers/token-trading/match-base-token.ts +++ b/packages/functions/src/triggers/token-trading/match-base-token.ts @@ -8,7 +8,6 @@ import { Member, Space, Token, - TokenPurchase, TokenTradeOrder, TokenTradeOrderType, Transaction, @@ -21,7 +20,7 @@ import { SmrWallet } from '../../services/wallet/SmrWalletService'; import { WalletService } from '../../services/wallet/wallet'; import { getAddress } from '../../utils/address.utils'; import { packBasicOutput } from '../../utils/basic-output.utils'; -import { getProject } from '../../utils/common.utils'; +import { getProject, getProjects } from '../../utils/common.utils'; import { getRoyaltyFees } from '../../utils/royalty.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; import { Match } from './match-token'; @@ -30,6 +29,7 @@ import { getMemberTier, getTokenTradingFee } from './token-trade-order.trigger'; const createIotaPayments = async ( token: Token, sell: TokenTradeOrder, + buy: TokenTradeOrder, seller: Member, buyer: Member, count: number, @@ -44,7 +44,9 @@ const createIotaPayments = async ( const sellOrder = await build5Db() .doc(`${COL.TRANSACTION}/${sell.orderTransactionId}`) .get(); - const billPayment = { + const billPayment: Transaction = { + project: getProject(sell), + projects: getProjects([sell, buy]), type: TransactionType.BILL_PAYMENT, uid: getRandomEthAddress(), member: sell.owner, @@ -59,7 +61,7 @@ const createIotaPayments = async ( previousOwner: seller.uid, ownerEntity: Entity.MEMBER, owner: buyer.uid, - sourceTransaction: [sell.paymentTransactionId], + sourceTransaction: [sell.paymentTransactionId || ''], royalty: false, void: false, token: token.uid, @@ -69,11 +71,13 @@ const createIotaPayments = async ( if (sell.fulfilled + count < sell.count || !balance) { return [billPayment]; } - const credit = { + const credit: Transaction = { + project: getProject(sell), + projects: getProjects([sell, buy]), type: TransactionType.CREDIT, uid: getRandomEthAddress(), member: sell.owner, - network: sell.sourceNetwork, + network: sell.sourceNetwork!, space: token.space, payload: { type: TransactionPayloadType.TOKEN_TRADE_FULLFILLMENT, @@ -85,7 +89,7 @@ const createIotaPayments = async ( previousOwner: seller.uid, ownerEntity: Entity.MEMBER, owner: seller.uid, - sourceTransaction: [sell.paymentTransactionId], + sourceTransaction: [sell.paymentTransactionId || ''], royalty: false, void: false, token: token.uid, @@ -97,23 +101,26 @@ const createIotaPayments = async ( const createRoyaltyPayment = async ( token: Token, + sell: TokenTradeOrder, buy: TokenTradeOrder, buyOrder: Transaction, seller: Member, spaceId: string, fee: number, info: INodeInfo, -) => { +): Promise => { const space = (await build5Db().doc(`${COL.SPACE}/${spaceId}`).get())!; const spaceAddress = getAddress(space, buy.sourceNetwork!); const sellerAddress = getAddress(seller, buy.sourceNetwork!); const output = packBasicOutput(spaceAddress, 0, undefined, info, sellerAddress); - return { + return { + project: getProject(sell), + projects: getProjects([sell, buy]), type: TransactionType.BILL_PAYMENT, uid: getRandomEthAddress(), space: spaceId, member: buy.owner, - network: buy.sourceNetwork, + network: buy.sourceNetwork!, payload: { type: TransactionPayloadType.BASE_TOKEN_TRADE, amount: Number(output.amount) + fee, @@ -127,7 +134,7 @@ const createRoyaltyPayment = async ( previousOwner: buy.owner, ownerEntity: Entity.SPACE, owner: spaceId, - sourceTransaction: [buy.paymentTransactionId], + sourceTransaction: [buy.paymentTransactionId || ''], royalty: true, void: false, token: token.uid, @@ -173,7 +180,7 @@ const createSmrPayments = async ( const royaltyPaymentPromises = Object.entries(royaltyFees) .filter((entry) => entry[1] > 0) .map(([space, fee]) => - createRoyaltyPayment(token, buy, buyOrder!, seller, space, fee, wallet.info), + createRoyaltyPayment(token, sell, buy, buyOrder!, seller, space, fee, wallet.info), ); const royaltyPayments = await Promise.all(royaltyPaymentPromises); royaltyPayments.forEach((rp) => { @@ -185,7 +192,9 @@ const createSmrPayments = async ( return []; } - const billPayment = { + const billPayment: Transaction = { + project: getProject(sell), + projects: getProjects([sell, buy]), type: TransactionType.BILL_PAYMENT, uid: getRandomEthAddress(), member: buy.owner, @@ -200,7 +209,7 @@ const createSmrPayments = async ( previousOwner: buy.owner, ownerEntity: Entity.MEMBER, owner: sell.owner, - sourceTransaction: [buy.paymentTransactionId], + sourceTransaction: [buy.paymentTransactionId || ''], royalty: false, void: false, token: token.uid, @@ -211,11 +220,13 @@ const createSmrPayments = async ( if (!fulfilled || !balanceLeft) { return [...royaltyPayments, billPayment]; } - const credit = { + const credit: Transaction = { + project: getProject(buy), + projects: getProjects([sell, buy]), type: TransactionType.CREDIT, uid: getRandomEthAddress(), member: buy.owner, - network: buy.sourceNetwork, + network: buy.sourceNetwork!, space: token.space, payload: { type: TransactionPayloadType.TOKEN_TRADE_FULLFILLMENT, @@ -227,7 +238,7 @@ const createSmrPayments = async ( previousOwner: buy.owner, ownerEntity: Entity.MEMBER, owner: buy.owner, - sourceTransaction: [buy.paymentTransactionId], + sourceTransaction: [buy.paymentTransactionId || ''], royalty: false, void: false, token: token.uid, @@ -249,7 +260,7 @@ export const matchBaseToken = async ( const seller = await build5Db().doc(`${COL.MEMBER}/${sell.owner}`).get(); const buyer = await build5Db().doc(`${COL.MEMBER}/${buy.owner}`).get(); - const iotaPayments = await createIotaPayments(token, sell, seller!, buyer!, tokensToTrade); + const iotaPayments = await createIotaPayments(token, sell, buy, seller!, buyer!, tokensToTrade); const smrPayments = await createSmrPayments( token, sell, @@ -273,7 +284,9 @@ export const matchBaseToken = async ( return { sellerCreditId: iotaPayments.find((o) => o.type === TransactionType.CREDIT)?.uid, buyerCreditId: smrPayments.find((o) => o.type === TransactionType.CREDIT)?.uid, - purchase: { + purchase: { + project: getProject(triggeredBy === TokenTradeOrderType.SELL ? sell : buy), + projects: getProjects([sell, buy]), uid: getRandomEthAddress(), token: buy.token, tokenStatus: token.status, @@ -293,7 +306,9 @@ export const matchBaseToken = async ( .map((o) => o.uid), sellerTier: await getMemberTier(getProject(sell), seller!), - sellerTokenTradingFeePercentage: getTokenTradingFee(seller!), + sellerTokenTradingFeePercentage: getTokenTradingFee(seller!) as number, + + age: {}, }, }; }; diff --git a/packages/functions/src/triggers/token-trading/match-minted-token.ts b/packages/functions/src/triggers/token-trading/match-minted-token.ts index c582046c88..4da74dae34 100644 --- a/packages/functions/src/triggers/token-trading/match-minted-token.ts +++ b/packages/functions/src/triggers/token-trading/match-minted-token.ts @@ -5,7 +5,6 @@ import { Member, Space, Token, - TokenPurchase, TokenTradeOrder, TokenTradeOrderType, Transaction, @@ -20,7 +19,7 @@ import { SmrWallet } from '../../services/wallet/SmrWalletService'; import { WalletService } from '../../services/wallet/wallet'; import { getAddress } from '../../utils/address.utils'; import { packBasicOutput } from '../../utils/basic-output.utils'; -import { getProject } from '../../utils/common.utils'; +import { getProject, getProjects } from '../../utils/common.utils'; import { getRoyaltyFees } from '../../utils/royalty.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; import { Match } from './match-token'; @@ -28,6 +27,7 @@ import { getMemberTier, getTokenTradingFee } from './token-trade-order.trigger'; const createRoyaltyBillPayments = async ( token: Token, + sell: TokenTradeOrder, buy: TokenTradeOrder, seller: Member, buyer: Member, @@ -41,12 +41,14 @@ const createRoyaltyBillPayments = async ( const promises = Object.entries(royaltyFees) .filter((entry) => entry[1] > 0) - .map(async ([spaceId, fee]) => { + .map(async ([spaceId, fee]): Promise => { const space = await build5Db().doc(`${COL.SPACE}/${spaceId}`).get(); const spaceAddress = getAddress(space, token.mintingData?.network!); const sellerAddress = getAddress(seller, token.mintingData?.network!); const output = packBasicOutput(spaceAddress, 0, undefined, info, sellerAddress); - return { + return { + project: getProject(buy), + projects: getProjects([sell, buy]), type: TransactionType.BILL_PAYMENT, uid: getRandomEthAddress(), space: spaceId, @@ -65,7 +67,7 @@ const createRoyaltyBillPayments = async ( previousOwner: buyer.uid, ownerEntity: Entity.SPACE, owner: spaceId, - sourceTransaction: [buy.paymentTransactionId], + sourceTransaction: [buy.paymentTransactionId || ''], royalty: true, void: false, token: token.uid, @@ -82,13 +84,16 @@ const createBillPaymentToSeller = ( buyer: Member, seller: Member, buyOrderTran: Transaction, + sell: TokenTradeOrder, buy: TokenTradeOrder, salePrice: number, info: INodeInfo, -) => { +): Transaction => { const sellerAddress = getAddress(seller, token.mintingData?.network!); const output = packBasicOutput(sellerAddress, salePrice, undefined, info); - return { + return { + project: getProject(sell), + projects: getProjects([sell, buy]), type: TransactionType.BILL_PAYMENT, uid: getRandomEthAddress(), space: token.space, @@ -103,7 +108,7 @@ const createBillPaymentToSeller = ( previousOwner: buyer.uid, ownerEntity: Entity.MEMBER, owner: seller.uid, - sourceTransaction: [buy.paymentTransactionId], + sourceTransaction: [buy.paymentTransactionId || ''], royalty: false, void: false, token: token.uid, @@ -133,6 +138,8 @@ const createBillPaymentWithNativeTokens = ( sellerAddress, ); return { + project: getProject(sell), + projects: getProjects([sell, buy]), type: TransactionType.BILL_PAYMENT, uid: getRandomEthAddress(), space: token.space, @@ -166,10 +173,13 @@ const createCreditToSeller = ( token: Token, seller: Member, sell: TokenTradeOrder, + buy: TokenTradeOrder, sellOrderTran: Transaction, -) => { +): Transaction => { const sellerAddress = getAddress(seller, token.mintingData?.network!); - return { + return { + project: getProject(sell), + projects: getProjects([sell, buy]), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: token.space, @@ -185,7 +195,7 @@ const createCreditToSeller = ( previousOwner: seller.uid, ownerEntity: Entity.MEMBER, owner: seller.uid, - sourceTransaction: [sell.paymentTransactionId], + sourceTransaction: [sell.paymentTransactionId || ''], royalty: false, void: false, token: token.uid, @@ -197,12 +207,15 @@ const createCreditToSeller = ( const createCreditToBuyer = ( token: Token, buyer: Member, + sell: TokenTradeOrder, buy: TokenTradeOrder, buyOrderTran: Transaction, amount: number, -) => { +): Transaction => { const buyerAddress = getAddress(buyer, token.mintingData?.network!); - return { + return { + project: getProject(buy), + projects: getProjects([sell, buy]), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: token.space, @@ -218,7 +231,7 @@ const createCreditToBuyer = ( previousOwner: buyer.uid, ownerEntity: Entity.MEMBER, owner: buyer.uid, - sourceTransaction: [buy.paymentTransactionId], + sourceTransaction: [buy.paymentTransactionId || ''], royalty: false, void: false, token: token.uid, @@ -270,6 +283,7 @@ export const matchMintedToken = async ( const royaltyBillPayments = await createRoyaltyBillPayments( token, + sell, buy, seller, buyer, @@ -300,6 +314,7 @@ export const matchMintedToken = async ( buyer, seller, buyOrderTran, + sell, buy, salePrice, wallet.info, @@ -312,12 +327,12 @@ export const matchMintedToken = async ( const creditToSeller = sell.fulfilled + tokensToTrade === sell.count - ? createCreditToSeller(token, seller, sell, sellOrderTran) + ? createCreditToSeller(token, seller, sell, buy, sellOrderTran) : undefined; const creditToBuyer = buyIsFulfilled && balanceLeft - ? createCreditToBuyer(token, buyer, buy, buyOrderTran, balanceLeft) + ? createCreditToBuyer(token, buyer, sell, buy, buyOrderTran, balanceLeft) : undefined; [ @@ -334,7 +349,9 @@ export const matchMintedToken = async ( }); return { - purchase: { + purchase: { + project: getProject(triggeredBy === TokenTradeOrderType.SELL ? sell : buy), + projects: getProjects([sell, buy]), uid: getRandomEthAddress(), token: buy.token, tokenStatus: token.status, @@ -348,7 +365,8 @@ export const matchMintedToken = async ( royaltyBillPayments: royaltyBillPayments.map((o) => o.uid), sellerTier: await getMemberTier(getProject(sell), seller), - sellerTokenTradingFeePercentage: getTokenTradingFee(seller), + sellerTokenTradingFeePercentage: getTokenTradingFee(seller) as number, + age: {}, }, sellerCreditId: creditToSeller?.uid, buyerCreditId: creditToBuyer?.uid, diff --git a/packages/functions/src/triggers/token-trading/match-simple-token.ts b/packages/functions/src/triggers/token-trading/match-simple-token.ts index 2f7b957c5a..8c1961ff19 100644 --- a/packages/functions/src/triggers/token-trading/match-simple-token.ts +++ b/packages/functions/src/triggers/token-trading/match-simple-token.ts @@ -8,7 +8,6 @@ import { SUB_COL, Space, Token, - TokenPurchase, TokenTradeOrder, TokenTradeOrderType, Transaction, @@ -18,7 +17,7 @@ import { import bigDecimal from 'js-big-decimal'; import { isEmpty, tail } from 'lodash'; import { getAddress } from '../../utils/address.utils'; -import { getProject } from '../../utils/common.utils'; +import { getProject, getProjects } from '../../utils/common.utils'; import { getRoyaltyFees } from '../../utils/royalty.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; import { Match } from './match-token'; @@ -56,9 +55,11 @@ const createBuyPayments = async ( const royaltyPaymentPromises = Object.entries(royaltyFees) .filter((entry) => entry[1] > 0) - .map(async ([space, fee]) => { + .map(async ([space, fee]): Promise => { const spaceData = await build5Db().doc(`${COL.SPACE}/${space}`).get(); - return { + return { + project: getProject(buy), + projects: getProjects([sell, buy]), type: TransactionType.BILL_PAYMENT, uid: getRandomEthAddress(), space: token.space, @@ -73,7 +74,7 @@ const createBuyPayments = async ( previousOwner: buy.owner, owner: space, ownerEntity: Entity.SPACE, - sourceTransaction: [buy.paymentTransactionId], + sourceTransaction: [buy.paymentTransactionId || ''], royalty: true, void: false, quantity: tokensToTrade, @@ -90,7 +91,9 @@ const createBuyPayments = async ( if (salePrice < MIN_IOTA_AMOUNT) { return []; } - const billPayment = { + const billPayment: Transaction = { + project: getProject(buy), + projects: getProjects([sell, buy]), type: TransactionType.BILL_PAYMENT, uid: getRandomEthAddress(), space: token.space, @@ -105,7 +108,7 @@ const createBuyPayments = async ( previousOwner: buy.owner, owner: sell.owner, ownerEntity: Entity.MEMBER, - sourceTransaction: [buy.paymentTransactionId], + sourceTransaction: [buy.paymentTransactionId || ''], royalty: false, void: false, quantity: tokensToTrade, @@ -116,7 +119,9 @@ const createBuyPayments = async ( if (!fulfilled || !balanceLeft) { return [billPayment, ...royaltyPayments]; } - const credit = { + const credit: Transaction = { + project: getProject(buy), + projects: getProjects([sell, buy]), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: token.space, @@ -132,7 +137,7 @@ const createBuyPayments = async ( previousOwner: buy.owner, ownerEntity: Entity.MEMBER, owner: buy.owner, - sourceTransaction: [buy.paymentTransactionId], + sourceTransaction: [buy.paymentTransactionId || ''], royalty: false, void: false, token: token.uid, @@ -202,7 +207,9 @@ export const matchSimpleToken = async ( }); return { - purchase: { + purchase: { + project: getProject(triggeredBy === TokenTradeOrderType.SELL ? sell : buy), + projects: getProjects([sell, buy]), uid: getRandomEthAddress(), token: buy.token, tokenStatus: token.status, @@ -217,7 +224,8 @@ export const matchSimpleToken = async ( triggeredBy, sellerTier: await getMemberTier(getProject(sell), seller), - sellerTokenTradingFeePercentage: getTokenTradingFee(seller), + sellerTokenTradingFeePercentage: getTokenTradingFee(seller) as number, + age: {}, }, buyerCreditId: buyerPayments.filter((p) => p.type === TransactionType.CREDIT)[0]?.uid || '', sellerCreditId: undefined, diff --git a/packages/functions/src/triggers/token.trigger.ts b/packages/functions/src/triggers/token.trigger.ts index 82e515d749..b99890c0a9 100644 --- a/packages/functions/src/triggers/token.trigger.ts +++ b/packages/functions/src/triggers/token.trigger.ts @@ -25,7 +25,7 @@ import { scale } from '../scale.settings'; import { WalletService } from '../services/wallet/wallet'; import { getAddress } from '../utils/address.utils'; import { downloadMediaAndPackCar, tokenToIpfsMetadata } from '../utils/car.utils'; -import { guardedRerun } from '../utils/common.utils'; +import { getProject, getProjects, guardedRerun } from '../utils/common.utils'; import { getRoyaltyFees } from '../utils/royalty.utils'; import { cancelTradeOrderUtil } from '../utils/token-trade.utils'; import { @@ -146,7 +146,9 @@ const createBillAndRoyaltyPayment = async ( if (fee >= MIN_IOTA_AMOUNT && balance - fee >= MIN_IOTA_AMOUNT) { const royaltySpace = await build5Db().doc(`${COL.SPACE}/${royaltySpaceId}`).get(); const network = order.network || DEFAULT_NETWORK; - royaltyPayment = { + royaltyPayment = { + project: getProject(order), + projects: getProjects([order, token]), type: TransactionType.BILL_PAYMENT, uid: getRandomEthAddress(), space: token.space, @@ -174,7 +176,9 @@ const createBillAndRoyaltyPayment = async ( balance -= fee; } const network = order.network || DEFAULT_NETWORK; - const billPayment = { + const billPayment: Transaction = { + project: getProject(order), + projects: getProjects([order, token]), type: TransactionType.BILL_PAYMENT, uid: getRandomEthAddress(), space: token.space, @@ -217,7 +221,9 @@ const createCredit = async ( const tranId = getRandomEthAddress(); const docRef = build5Db().doc(`${COL.TRANSACTION}/${tranId}`); const network = order.network || DEFAULT_NETWORK; - const data = { + const data: Transaction = { + project: getProject(order), + projects: getProjects([order, token]), type: TransactionType.CREDIT, uid: tranId, space: token.space, @@ -383,12 +389,14 @@ const mintToken = async (token: Token) => { await cancelAllActiveSales(token!.uid); await setIpfsData(token); - const order = { + const order: Transaction = { + project: getProject(token), + projects: getProjects([token]), type: TransactionType.MINT_TOKEN, uid: getRandomEthAddress(), member: token.mintingData?.mintedBy, space: token!.space, - network: token.mintingData?.network, + network: token.mintingData?.network!, payload: { type: TransactionPayloadType.MINT_ALIAS, amount: token.mintingData?.aliasStorageDeposit, @@ -440,12 +448,14 @@ const onTokenVaultEmptied = async (token: Token) => { .where('type', '==', TransactionType.PAYMENT) .where('payload.sourceTransaction', 'array-contains', token.mintingData?.vaultAddress!) .get(); - const credit = { + const credit: Transaction = { + project: getProject(token), + projects: getProjects([token]), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: token.space, member: minter!.uid, - network: token.mintingData?.network, + network: token.mintingData?.network!, payload: { type: TransactionPayloadType.TOKEN_VAULT_EMPTIED, dependsOnBillPayment: true, diff --git a/packages/functions/src/triggers/transaction-trigger/airdrop.claim.ts b/packages/functions/src/triggers/transaction-trigger/airdrop.claim.ts index c8cfeae591..e6ab84ce34 100644 --- a/packages/functions/src/triggers/transaction-trigger/airdrop.claim.ts +++ b/packages/functions/src/triggers/transaction-trigger/airdrop.claim.ts @@ -22,6 +22,7 @@ import { head } from 'lodash'; import { SmrWallet } from '../../services/wallet/SmrWalletService'; import { WalletService } from '../../services/wallet/wallet'; import { getAddress } from '../../utils/address.utils'; +import { getProject, getProjects } from '../../utils/common.utils'; import { dateToTimestamp, serverTime } from '../../utils/dateTime.utils'; import { dropToOutput } from '../../utils/token-minting-utils/member.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; @@ -50,6 +51,8 @@ const onPreMintedAirdropClaim = async (order: Transaction, token: Token) => { const airdropDocRef = build5Db().doc(`${COL.AIRDROP}/${airdrop.uid}`); const billPayment: Transaction = { + project: getProject(order), + projects: getProjects([order]), type: TransactionType.BILL_PAYMENT, uid: getRandomEthAddress(), space: order.space, @@ -159,7 +162,9 @@ const onMintedAirdropClaim = async (order: Transaction, token: Token) => { }); if (storageDepositUsed < order.payload.amount!) { - const credit = { + const credit: Transaction = { + project: getProject(order), + projects: getProjects([order]), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: token.space, @@ -195,6 +200,8 @@ const claimOwnedMintedTokens = ( } const airdrop: TokenDrop = { + project: getProject(order), + projects: getProjects([order]), uid: getRandomEthAddress(), member: member.uid, token: token.uid, @@ -239,6 +246,8 @@ const mintedDropToBillPayment = ( const output = dropToOutput(token, drop, memberAddress, wallet.info); const nativeTokens = [{ id: head(output.nativeTokens)?.id!, amount: drop.count.toString() }]; return { + project: getProject(order), + projects: getProjects([order]), type: TransactionType.BILL_PAYMENT, uid: getRandomEthAddress(), space: token.space, @@ -274,6 +283,8 @@ const mintedDropToStake = (order: Transaction, drop: TokenDrop, billPayment: Tra return undefined; } const stake: Stake = { + project: getProject(order), + projects: getProjects([order]), uid: getRandomEthAddress(), member: order.member!, token: order.payload.token!, diff --git a/packages/functions/src/triggers/transaction-trigger/award.transaction.update.ts b/packages/functions/src/triggers/transaction-trigger/award.transaction.update.ts index d46f719b95..4e37327e56 100644 --- a/packages/functions/src/triggers/transaction-trigger/award.transaction.update.ts +++ b/packages/functions/src/triggers/transaction-trigger/award.transaction.update.ts @@ -2,6 +2,7 @@ import { build5Db } from '@build-5/database'; import { COL, Transaction, TransactionPayloadType, TransactionType } from '@build-5/interfaces'; import { ITransactionPayload, TransactionHelper } from '@iota/iota.js-next'; import { indexToString } from '../../utils/block.utils'; +import { getProject, getProjects } from '../../utils/common.utils'; import { getTransactionPayloadHex } from '../../utils/smr.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; @@ -35,7 +36,9 @@ const onAliasMinted = async (transaction: Transaction) => { aliasId: TransactionHelper.resolveIdFromOutputId(aliasOutputId), }); - const order = { + const order: Transaction = { + project: getProject(transaction), + projects: getProjects([transaction]), type: TransactionType.AWARD, uid: getRandomEthAddress(), member: transaction.member, diff --git a/packages/functions/src/triggers/transaction-trigger/collection-minting.ts b/packages/functions/src/triggers/transaction-trigger/collection-minting.ts index e2cca42781..9c6dc3bd84 100644 --- a/packages/functions/src/triggers/transaction-trigger/collection-minting.ts +++ b/packages/functions/src/triggers/transaction-trigger/collection-minting.ts @@ -15,6 +15,7 @@ import * as functions from 'firebase-functions/v2'; import { get } from 'lodash'; import { getAddress } from '../../utils/address.utils'; import { indexToString } from '../../utils/block.utils'; +import { getProject, getProjects } from '../../utils/common.utils'; import { getTransactionPayloadHex } from '../../utils/smr.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; @@ -62,7 +63,9 @@ const onCollectionAliasMinted = async (transaction: Transaction) => { 'mintingData.aliasStorageDeposit': transaction.payload.amount, }); - const order = { + const order: Transaction = { + project: getProject(transaction), + projects: getProjects([transaction]), type: TransactionType.MINT_COLLECTION, uid: getRandomEthAddress(), member: transaction.member, @@ -143,23 +146,26 @@ const onNftMintSuccess = async (transaction: Transaction) => { } }; -const createMintNftsTransaction = (transaction: Transaction) => - { - type: TransactionType.MINT_COLLECTION, - uid: getRandomEthAddress(), - member: transaction.member, - space: transaction.space, - network: transaction.network, - payload: { - type: TransactionPayloadType.MINT_NFTS, - sourceAddress: transaction.payload.sourceAddress, - collection: transaction.payload.collection, - }, - }; +const createMintNftsTransaction = (transaction: Transaction): Transaction => ({ + project: getProject(transaction), + projects: getProjects([transaction]), + type: TransactionType.MINT_COLLECTION, + uid: getRandomEthAddress(), + member: transaction.member, + space: transaction.space, + network: transaction.network, + payload: { + type: TransactionPayloadType.MINT_NFTS, + sourceAddress: transaction.payload.sourceAddress, + collection: transaction.payload.collection, + }, +}); const onCollectionLocked = async (transaction: Transaction) => { const member = (await build5Db().doc(`${COL.MEMBER}/${transaction.member}`).get())!; - const order = { + const order: Transaction = { + project: getProject(transaction), + projects: getProjects([transaction]), type: TransactionType.MINT_COLLECTION, uid: getRandomEthAddress(), member: transaction.member, diff --git a/packages/functions/src/triggers/transaction-trigger/matadatNft-minting.ts b/packages/functions/src/triggers/transaction-trigger/matadatNft-minting.ts index 4ada549c53..5056b40a45 100644 --- a/packages/functions/src/triggers/transaction-trigger/matadatNft-minting.ts +++ b/packages/functions/src/triggers/transaction-trigger/matadatNft-minting.ts @@ -23,6 +23,7 @@ import { import { WalletService } from '../../services/wallet/wallet'; import { getAddress } from '../../utils/address.utils'; import { indexToString } from '../../utils/block.utils'; +import { getProject, getProjects } from '../../utils/common.utils'; import { dateToTimestamp } from '../../utils/dateTime.utils'; import { getTransactionPayloadHex } from '../../utils/smr.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; @@ -128,12 +129,9 @@ const onCollectionMinted = async (transaction: Transaction) => { const space = await build5Db().doc(`${COL.SPACE}/${transaction.space}`).get(); const nftMintOrder = createMintMetadataNftOrder( + transaction, nft, - transaction.network!, - transaction.payload.targetAddress!, space?.alias?.address!, - transaction.payload.targetAddress!, - get(transaction, 'payload.aliasId', ''), collectionId, get(transaction, 'payload.orderId', ''), ); @@ -179,7 +177,9 @@ const onNftMinted = async (transaction: Transaction) => { const collection = await build5Db().doc(`${COL.COLLECTION}/${nft?.collection}`).get(); const space = await build5Db().doc(`${COL.SPACE}/${collection?.space}`).get(); - const creditTransaction = { + const creditTransaction: Transaction = { + project: getProject(order), + projects: getProjects([order]), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: transaction.space, @@ -225,7 +225,9 @@ const onNftUpdated = async (transaction: Transaction) => { const collection = await build5Db().doc(`${COL.COLLECTION}/${nft?.collection}`).get(); const space = await build5Db().doc(`${COL.SPACE}/${collection?.space}`).get(); - const creditTransaction = { + const creditTransaction: Transaction = { + project: getProject(order), + projects: getProjects([order]), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: transaction.space, diff --git a/packages/functions/src/triggers/transaction-trigger/token-minting.ts b/packages/functions/src/triggers/transaction-trigger/token-minting.ts index f977fe11ab..8f8b91c92b 100644 --- a/packages/functions/src/triggers/transaction-trigger/token-minting.ts +++ b/packages/functions/src/triggers/transaction-trigger/token-minting.ts @@ -21,6 +21,7 @@ import dayjs from 'dayjs'; import * as functions from 'firebase-functions/v2'; import { getAddress } from '../../utils/address.utils'; import { indexToString } from '../../utils/block.utils'; +import { getProject, getProjects } from '../../utils/common.utils'; import { getTransactionPayloadHex } from '../../utils/smr.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; export const onTokenMintingUpdate = async (transaction: Transaction) => { @@ -59,7 +60,9 @@ const onAliasMinted = async (transaction: Transaction) => { }); const token = await build5Db().doc(`${COL.TOKEN}/${transaction.payload.token}`).get(); - const order = { + const order: Transaction = { + project: getProject(transaction), + projects: getProjects([transaction]), type: TransactionType.MINT_TOKEN, uid: getRandomEthAddress(), member: transaction.member, @@ -112,7 +115,9 @@ const onFoundryMinted = async (transaction: Transaction) => { const token = await build5Db().doc(`${COL.TOKEN}/${transaction.payload.token}`).get(); const member = await build5Db().doc(`${COL.MEMBER}/${token.mintingData?.mintedBy}`).get(); - const order = { + const order: Transaction = { + project: getProject(transaction), + projects: getProjects([transaction]), type: TransactionType.MINT_TOKEN, uid: getRandomEthAddress(), member: transaction.member, diff --git a/packages/functions/src/triggers/transaction-trigger/transaction.trigger.ts b/packages/functions/src/triggers/transaction-trigger/transaction.trigger.ts index ee0a8985dc..e8c373b140 100644 --- a/packages/functions/src/triggers/transaction-trigger/transaction.trigger.ts +++ b/packages/functions/src/triggers/transaction-trigger/transaction.trigger.ts @@ -24,6 +24,7 @@ import { SmrParams, SmrWallet } from '../../services/wallet/SmrWalletService'; import { AliasWallet } from '../../services/wallet/smr-wallets/AliasWallet'; import { WalletService } from '../../services/wallet/wallet'; import { getAddress } from '../../utils/address.utils'; +import { getProject, getProjects } from '../../utils/common.utils'; import { isEmulatorEnv } from '../../utils/config.utils'; import { serverTime } from '../../utils/dateTime.utils'; import { getRandomEthAddress } from '../../utils/wallet.utils'; @@ -193,7 +194,7 @@ const executeTransaction = async (transactionId: string) => { } const docRef = build5Db().doc(`${COL.TRANSACTION}/${transactionId}`); - const transaction = await docRef.get(); + const transaction = (await docRef.get())!; const payload = transaction.payload; const params = await getWalletParams(transaction, transaction.network || DEFAULT_NETWORK); @@ -517,7 +518,9 @@ const isConfirmed = (prev: Transaction | undefined, curr: Transaction | undefine const onMintedAirdropCleared = async (curr: Transaction) => { const member = await build5Db().doc(`${COL.MEMBER}/${curr.member}`).get(); - const credit = { + const credit: Transaction = { + project: getProject(curr), + projects: getProjects([curr]), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: curr.space, diff --git a/packages/functions/src/utils/common.utils.ts b/packages/functions/src/utils/common.utils.ts index 6955583f7f..5d8f54a1e1 100644 --- a/packages/functions/src/utils/common.utils.ts +++ b/packages/functions/src/utils/common.utils.ts @@ -67,3 +67,9 @@ export const assertIsProjectGuardian = async (project: string, member: string) = }; export const getProject = (data: BaseRecord | undefined) => data?.project || SOON_PROJECT_ID; + +export const getProjects = (data: (BaseRecord | undefined)[], project?: string) => + data.reduce( + (acc, act) => ({ ...acc, ...(act?.projects || {}) }), + project ? { [project]: true } : {}, + ); diff --git a/packages/functions/src/utils/token-trade.utils.ts b/packages/functions/src/utils/token-trade.utils.ts index 729df0e9fc..718c6f3a31 100644 --- a/packages/functions/src/utils/token-trade.utils.ts +++ b/packages/functions/src/utils/token-trade.utils.ts @@ -16,6 +16,7 @@ import { } from '@build-5/interfaces'; import bigDecimal from 'js-big-decimal'; import { getAddress } from './address.utils'; +import { getProject, getProjects } from './common.utils'; import { getRandomEthAddress } from './wallet.utils'; export const creditBuyer = async (transaction: ITransaction, buy: TokenTradeOrder) => { @@ -29,7 +30,9 @@ export const creditBuyer = async (transaction: ITransaction, buy: TokenTradeOrde const order = (await orderDocRef.get())!; const network = order.network || DEFAULT_NETWORK; - const credit = { + const credit: Transaction = { + project: getProject(buy), + projects: getProjects([buy]), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: token.space, @@ -41,7 +44,7 @@ export const creditBuyer = async (transaction: ITransaction, buy: TokenTradeOrde amount: buy.balance, sourceAddress: order.payload.targetAddress, targetAddress: getAddress(member, network), - sourceTransaction: [buy.paymentTransactionId], + sourceTransaction: [buy.paymentTransactionId || ''], reconciled: true, void: false, token: token.uid, @@ -66,7 +69,9 @@ const creditBaseTokenSale = async ( const memberDocRef = build5Db().doc(`${COL.MEMBER}/${sale.owner}`); const member = await memberDocRef.get(); const network = order.network || DEFAULT_NETWORK; - const data = { + const data: Transaction = { + project: getProject(sale), + projects: getProjects([sale]), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: '', @@ -78,7 +83,7 @@ const creditBaseTokenSale = async ( amount: sale.balance, sourceAddress: order.payload.targetAddress, targetAddress: getAddress(member, network), - sourceTransaction: [sale.paymentTransactionId], + sourceTransaction: [sale.paymentTransactionId || ''], reconciled: true, void: false, token: token.uid, @@ -138,6 +143,8 @@ const cancelMintedSell = async (transaction: ITransaction, sell: TokenTradeOrder const tokensLeft = sell.count - sell.fulfilled; const network = order.network || DEFAULT_NETWORK; const data: Transaction = { + project: getProject(sell), + projects: getProjects([sell]), type: TransactionType.CREDIT, uid: getRandomEthAddress(), space: token.space, diff --git a/packages/functions/test-tangle/common.ts b/packages/functions/test-tangle/common.ts index 8c5a888887..d83669e82a 100644 --- a/packages/functions/test-tangle/common.ts +++ b/packages/functions/test-tangle/common.ts @@ -3,6 +3,7 @@ import { COL, MAX_WALLET_RETRY, Network, + SOON_PROJECT_ID, Transaction, TransactionPayloadType, TransactionType, @@ -13,7 +14,7 @@ import { Converter } from '@iota/util.js-next'; import dayjs from 'dayjs'; import { isEmpty } from 'lodash'; import { SmrWallet } from '../src/services/wallet/SmrWalletService'; -import { generateRandomAmount } from '../src/utils/common.utils'; +import { generateRandomAmount, getProjects } from '../src/utils/common.utils'; import { dateToTimestamp, serverTime } from '../src/utils/dateTime.utils'; import { getRandomEthAddress } from '../src/utils/wallet.utils'; import { wait } from '../test/controls/common'; @@ -66,6 +67,8 @@ export const getTangleOrder = async () => { const walletService = await getWallet(Network.RMS); const targetAddress = await walletService.getNewIotaAddressDetails(); const order = { + project: SOON_PROJECT_ID, + projects: getProjects([], SOON_PROJECT_ID), type: TransactionType.ORDER, uid: getRandomEthAddress(), network: Network.RMS, diff --git a/packages/functions/test/controls/collection.spec.ts b/packages/functions/test/controls/collection.spec.ts index 7393773551..43b4a77783 100644 --- a/packages/functions/test/controls/collection.spec.ts +++ b/packages/functions/test/controls/collection.spec.ts @@ -13,6 +13,7 @@ import { NetworkAddress, Nft, RANKING_TEST, + SOON_PROJECT_ID, SUB_COL, Space, StakeType, @@ -25,6 +26,7 @@ import { chunk } from 'lodash'; import { createNft } from '../../src/runtime/firebase/nft'; import { rankController } from '../../src/runtime/firebase/rank'; import { voteController } from '../../src/runtime/firebase/vote'; +import { getProjects } from '../../src/utils/common.utils'; import * as wallet from '../../src/utils/wallet.utils'; import { soonTokenId, testEnv } from '../set-up'; import { @@ -381,7 +383,12 @@ describe('CollectionController: ' + WEN_FUNC.createCollection, () => { describe('Collection trigger test', () => { it('Should set approved&reject properly on nfts', async () => { - const collection = { ...dummyCollection('', 0.1), uid: wallet.getRandomEthAddress() }; + const collection = { + ...dummyCollection('', 0.1), + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, + uid: wallet.getRandomEthAddress(), + }; await build5Db().doc(`${COL.COLLECTION}/${collection.uid}`).create(collection); const nftIds = Array.from(Array(1000)); @@ -390,10 +397,11 @@ describe('Collection trigger test', () => { const batch = build5Db().batch(); chunks[chunkIndex].forEach((_, index) => { const id = wallet.getRandomEthAddress(); - batch.create( - build5Db().doc(`${COL.NFT}/${id}`), - dummyNft(chunkIndex * 500 + index, id, collection.uid), - ); + batch.create(build5Db().doc(`${COL.NFT}/${id}`), { + ...dummyNft(chunkIndex * 500 + index, id, collection.uid), + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, + }); }); await batch.commit(); } @@ -668,6 +676,8 @@ describe('Collection rank test', () => { const saveToken = async (space: string) => { const token = { + project: SOON_PROJECT_ID, + projects: getProjects([], SOON_PROJECT_ID), uid: wallet.getRandomEthAddress(), symbol: getRandomSymbol(), approved: true, diff --git a/packages/functions/test/controls/member.spec.ts b/packages/functions/test/controls/member.spec.ts index f09c60fe7d..3cc9bab3f9 100644 --- a/packages/functions/test/controls/member.spec.ts +++ b/packages/functions/test/controls/member.spec.ts @@ -1,5 +1,13 @@ import { build5Db } from '@build-5/database'; -import { COL, Nft, NftAvailable, NftStatus, WEN_FUNC, WenError } from '@build-5/interfaces'; +import { + COL, + Nft, + NftAvailable, + NftStatus, + SOON_PROJECT_ID, + WEN_FUNC, + WenError, +} from '@build-5/interfaces'; import { createMember, updateMember } from '../../src/runtime/firebase/member'; import * as wallet from '../../src/utils/wallet.utils'; import { MEDIA, testEnv } from '../../test/set-up'; @@ -72,6 +80,8 @@ describe('MemberController: ' + WEN_FUNC.updateMember, () => { it('Should set nft as avatar, then unset', async () => { const nft = { + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, uid: wallet.getRandomEthAddress(), media: MEDIA, owner: dummyAddress, @@ -100,6 +110,8 @@ describe('MemberController: ' + WEN_FUNC.updateMember, () => { it('Should set nft as avatar, when available field is missing', async () => { const nft = { + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, uid: wallet.getRandomEthAddress(), media: MEDIA, owner: dummyAddress, @@ -118,7 +130,12 @@ describe('MemberController: ' + WEN_FUNC.updateMember, () => { mockWalletReturnValue(walletSpy, dummyAddress, { avatarNft: wallet.getRandomEthAddress() }); await expectThrow(testEnv.wrap(updateMember)({}), WenError.nft_does_not_exists.key); - const nft = { uid: wallet.getRandomEthAddress(), media: MEDIA }; + const nft = { + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, + uid: wallet.getRandomEthAddress(), + media: MEDIA, + }; const nftDocRef = build5Db().doc(`${COL.NFT}/${nft.uid}`); await nftDocRef.create(nft); diff --git a/packages/functions/test/controls/order.spec.ts b/packages/functions/test/controls/order.spec.ts index ce0b7425d4..8c49b297c8 100644 --- a/packages/functions/test/controls/order.spec.ts +++ b/packages/functions/test/controls/order.spec.ts @@ -9,6 +9,7 @@ import { NetworkAddress, Nft, NftAccess, + SOON_PROJECT_ID, Space, Transaction, TransactionPayloadType, @@ -494,6 +495,8 @@ describe('Ordering flows', () => { ); let badge = { + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, member, type: TransactionType.AWARD, uid: wallet.getRandomEthAddress(), @@ -506,6 +509,8 @@ describe('Ordering flows', () => { ); badge = { + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, member, type: TransactionType.AWARD, uid: wallet.getRandomEthAddress(), diff --git a/packages/functions/test/controls/project/project.create.spec.ts b/packages/functions/test/controls/project/project.create.spec.ts index cb889c0dce..c4f16c4b28 100644 --- a/packages/functions/test/controls/project/project.create.spec.ts +++ b/packages/functions/test/controls/project/project.create.spec.ts @@ -4,12 +4,14 @@ import { Project, ProjectBilling, ProjectGuardian, + SOON_PROJECT_ID, SUB_COL, Token, TokenStatus, WenError, } from '@build-5/interfaces'; import { createProject } from '../../../src/runtime/firebase/project/index'; +import { getProjects } from '../../../src/utils/common.utils'; import * as wallet from '../../../src/utils/wallet.utils'; import { testEnv } from '../../set-up'; import { createMember, expectThrow, getRandomSymbol, mockWalletReturnValue } from '../common'; @@ -27,6 +29,8 @@ describe('Project create', () => { guardian = await createMember(walletSpy); const tokenId = wallet.getRandomEthAddress(); token = { + project: SOON_PROJECT_ID, + projects: getProjects([], SOON_PROJECT_ID), uid: tokenId, symbol: getRandomSymbol(), name: 'MyToken', diff --git a/packages/functions/test/controls/proposal.spec.ts b/packages/functions/test/controls/proposal.spec.ts index 217e9d3229..1166675ec7 100644 --- a/packages/functions/test/controls/proposal.spec.ts +++ b/packages/functions/test/controls/proposal.spec.ts @@ -7,6 +7,7 @@ import { ProposalStartDateMin, ProposalType, RelatedRecordsResponse, + SOON_PROJECT_ID, Space, Token, TokenStatus, @@ -76,12 +77,16 @@ describe('ProposalController: ' + WEN_FUNC.rejectProposal + ' NATIVE', () => { body = dummyBody(space.uid); const tokenId = wallet.getRandomEthAddress(); - await build5Db().doc(`${COL.TOKEN}/${tokenId}`).create({ - uid: tokenId, - space: space.uid, - status: TokenStatus.MINTED, - approved: true, - }); + await build5Db() + .doc(`${COL.TOKEN}/${tokenId}`) + .create({ + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, + uid: tokenId, + space: space.uid, + status: TokenStatus.MINTED, + approved: true, + }); }); it('successfully create proposal with name', async () => { diff --git a/packages/functions/test/controls/stake.reward.spec.ts b/packages/functions/test/controls/stake.reward.spec.ts index 737a6fc2ae..7928cc3469 100644 --- a/packages/functions/test/controls/stake.reward.spec.ts +++ b/packages/functions/test/controls/stake.reward.spec.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { COL, Space, StakeReward, WenError } from '@build-5/interfaces'; +import { COL, SOON_PROJECT_ID, Space, StakeReward, WenError } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { stakeReward } from '../../src/runtime/firebase/stake'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; @@ -19,7 +19,14 @@ describe('Stake reward controller', () => { space = await createSpace(walletSpy, guardian); token = wallet.getRandomEthAddress(); - await build5Db().doc(`${COL.TOKEN}/${token}`).create({ uid: token, space: space.uid }); + await build5Db() + .doc(`${COL.TOKEN}/${token}`) + .create({ + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, + uid: token, + space: space.uid, + }); }); it('Should throw, token does not exist', async () => { diff --git a/packages/functions/test/controls/token-distribution-auto-trigger.spec.ts b/packages/functions/test/controls/token-distribution-auto-trigger.spec.ts index 0fa31503b9..0f3f0aeaa9 100644 --- a/packages/functions/test/controls/token-distribution-auto-trigger.spec.ts +++ b/packages/functions/test/controls/token-distribution-auto-trigger.spec.ts @@ -5,6 +5,7 @@ import { MIN_IOTA_AMOUNT, Network, NetworkAddress, + SOON_PROJECT_ID, Space, SUB_COL, Token, @@ -93,6 +94,8 @@ const dummyToken = ( publicPercentageSale: number, guardian: string, ) => ({ + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, symbol: getRandomSymbol(), totalSupply, updatedOn: serverTime(), diff --git a/packages/functions/test/controls/token-distribution.spec.ts b/packages/functions/test/controls/token-distribution.spec.ts index b61ca0ebc9..88eba4a833 100644 --- a/packages/functions/test/controls/token-distribution.spec.ts +++ b/packages/functions/test/controls/token-distribution.spec.ts @@ -5,6 +5,7 @@ import { Member, Network, NetworkAddress, + SOON_PROJECT_ID, SUB_COL, SYSTEM_CONFIG_DOC_ID, Space, @@ -310,6 +311,8 @@ const dummyToken = ( publicPercentageSale: number, guardian: string, ) => ({ + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, symbol: getRandomSymbol(), totalSupply, updatedOn: serverTime(), diff --git a/packages/functions/test/controls/token-trade.trigger.spec.ts b/packages/functions/test/controls/token-trade.trigger.spec.ts index e88399d8c4..682f226d87 100644 --- a/packages/functions/test/controls/token-trade.trigger.spec.ts +++ b/packages/functions/test/controls/token-trade.trigger.spec.ts @@ -7,6 +7,7 @@ import { Member, Network, NetworkAddress, + SOON_PROJECT_ID, SUB_COL, SYSTEM_CONFIG_DOC_ID, StakeType, @@ -89,6 +90,8 @@ describe('Trade trigger', () => { const saveSellToDb = async (count: number, price: number) => { const data = { + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, createdOn: serverTime(), uid: wallet.getRandomEthAddress(), owner: seller, @@ -473,6 +476,8 @@ describe('Trade trigger', () => { const sellTokenFunc = async (count: number, price: number) => { const sellDocId = wallet.getRandomEthAddress(); const data = { + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, uid: sellDocId, owner: seller, token: token.uid, diff --git a/packages/functions/test/controls/token.expired.sale.cron.spec.ts b/packages/functions/test/controls/token.expired.sale.cron.spec.ts index a1b3a64021..aa1517ffae 100644 --- a/packages/functions/test/controls/token.expired.sale.cron.spec.ts +++ b/packages/functions/test/controls/token.expired.sale.cron.spec.ts @@ -2,6 +2,7 @@ import { build5Db } from '@build-5/database'; import { COL, MIN_IOTA_AMOUNT, + SOON_PROJECT_ID, SUB_COL, Token, TokenDistribution, @@ -49,6 +50,8 @@ describe('Expired sales cron', () => { status: TokenTradeOrderStatus, type: TokenTradeOrderType, ): TokenTradeOrder => ({ + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, uid: wallet.getRandomEthAddress(), owner: seller, token: token.uid, diff --git a/packages/functions/test/cron/floor-price.cron.only.spec.ts b/packages/functions/test/cron/floor-price.cron.only.spec.ts index e51c3a56dd..5d1b6f873f 100644 --- a/packages/functions/test/cron/floor-price.cron.only.spec.ts +++ b/packages/functions/test/cron/floor-price.cron.only.spec.ts @@ -1,5 +1,12 @@ import { build5Db } from '@build-5/database'; -import { COL, Collection, MIN_IOTA_AMOUNT, NftAccess, NftAvailable } from '@build-5/interfaces'; +import { + COL, + Collection, + MIN_IOTA_AMOUNT, + NftAccess, + NftAvailable, + SOON_PROJECT_ID, +} from '@build-5/interfaces'; import { updateFloorPriceOnCollections } from '../../src/cron/collection.floor.price.cron'; import { getRandomEthAddress } from '../../src/utils/wallet.utils'; @@ -7,7 +14,12 @@ describe('Collection floor price', () => { it('Should set collection floor price', async () => { const collection = getRandomEthAddress(); const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${collection}`); - await collectionDocRef.create({ uid: collection, name: 'asd' }); + await collectionDocRef.create({ + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, + uid: collection, + name: 'asd', + }); const promises = [ NftAvailable.AUCTION, diff --git a/packages/functions/test/cron/nft-stake.cron.spec.ts b/packages/functions/test/cron/nft-stake.cron.spec.ts index 26b54e5cda..38872c74a4 100644 --- a/packages/functions/test/cron/nft-stake.cron.spec.ts +++ b/packages/functions/test/cron/nft-stake.cron.spec.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { COL, Collection, NftStake, StakeType } from '@build-5/interfaces'; +import { COL, Collection, NftStake, SOON_PROJECT_ID, StakeType } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { processExpiredNftStakes } from '../../src/cron/nftStake.cron'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; @@ -9,9 +9,17 @@ describe('Expired nft stake cron', () => { it('Should process expired nft stake', async () => { const collection = getRandomEthAddress(); const collectionDocRef = build5Db().doc(`${COL.COLLECTION}/${collection}`); - await collectionDocRef.create({ uid: collection, name: 'asd', stakedNft: 2 }); + await collectionDocRef.create({ + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, + uid: collection, + name: 'asd', + stakedNft: 2, + }); - let nftStake = { + let nftStake: NftStake = { + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, uid: getRandomEthAddress(), member: getRandomEthAddress(), space: getRandomEthAddress(), diff --git a/packages/functions/test/cron/proposal.cron.spec.ts b/packages/functions/test/cron/proposal.cron.spec.ts index b2a93bcd68..98695d58de 100644 --- a/packages/functions/test/cron/proposal.cron.spec.ts +++ b/packages/functions/test/cron/proposal.cron.spec.ts @@ -1,5 +1,5 @@ import { build5Db } from '@build-5/database'; -import { COL } from '@build-5/interfaces'; +import { COL, SOON_PROJECT_ID } from '@build-5/interfaces'; import dayjs from 'dayjs'; import { markExpiredProposalCompleted } from '../../src/cron/proposal.cron'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; @@ -14,6 +14,8 @@ describe('Set proposal completed', () => { let batch = build5Db().batch(); for (let i = 0; i < count; ++i) { const proposal = { + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, uid: ids[i], settings: { startDate: dateToTimestamp(dayjs().subtract(10, 'd')), diff --git a/packages/functions/test/set-up.ts b/packages/functions/test/set-up.ts index 88599b4242..2644d27672 100644 --- a/packages/functions/test/set-up.ts +++ b/packages/functions/test/set-up.ts @@ -88,7 +88,14 @@ export const SOON_PROJ_GUARDIAN = '0x3d5d0b3f40c9438871b1c43d6b70117eeff77ad8'; export const soonTokenId = '0xa381bfccaf121e38e31362d85b5ad30cd7fc0d06'; const setup = async () => { - await build5Db().doc(`${COL.TOKEN}/${soonTokenId}`).set({ uid: soonTokenId, symbol: 'SOON' }); + await build5Db() + .doc(`${COL.TOKEN}/${soonTokenId}`) + .set({ + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, + uid: soonTokenId, + symbol: 'SOON', + }); const soonProject = { uid: SOON_PROJECT_ID, diff --git a/packages/functions/test/stake/delete.stake.reward.spec.ts b/packages/functions/test/stake/delete.stake.reward.spec.ts index a9314415ef..f98ad30f3e 100644 --- a/packages/functions/test/stake/delete.stake.reward.spec.ts +++ b/packages/functions/test/stake/delete.stake.reward.spec.ts @@ -3,6 +3,7 @@ import { COL, Proposal, ProposalType, + SOON_PROJECT_ID, Space, StakeReward, StakeRewardStatus, @@ -40,13 +41,22 @@ describe('Delete stake reward', () => { await addGuardianToSpace(space.uid, member); token = wallet.getRandomEthAddress(); - await build5Db().doc(`${COL.TOKEN}/${token}`).create({ uid: token, space: space.uid }); + await build5Db() + .doc(`${COL.TOKEN}/${token}`) + .create({ + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, + uid: token, + space: space.uid, + }); }); const createStakeRewards = async () => { const now = dayjs(); const stakeRewards = [ { + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, uid: wallet.getRandomEthAddress(), startDate: dateToTimestamp(now.add(2, 'd')), endDate: dateToTimestamp(now.add(3, 'd')), @@ -56,6 +66,8 @@ describe('Delete stake reward', () => { status: StakeRewardStatus.UNPROCESSED, }, { + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, uid: wallet.getRandomEthAddress(), startDate: dateToTimestamp(now.add(1, 'd')), endDate: dateToTimestamp(now.add(2, 'd')), diff --git a/packages/functions/test/stake/stake.reward.cron.spec.ts b/packages/functions/test/stake/stake.reward.cron.spec.ts index 33f94c3c1b..fd721c732f 100644 --- a/packages/functions/test/stake/stake.reward.cron.spec.ts +++ b/packages/functions/test/stake/stake.reward.cron.spec.ts @@ -1,5 +1,12 @@ import { build5Db } from '@build-5/database'; -import { COL, Stake, StakeReward, StakeRewardStatus, StakeType } from '@build-5/interfaces'; +import { + COL, + SOON_PROJECT_ID, + Stake, + StakeReward, + StakeRewardStatus, + StakeType, +} from '@build-5/interfaces'; import dayjs from 'dayjs'; import { getStakedPerMember } from '../../src/cron/stakeReward.cron'; import { dateToTimestamp } from '../../src/utils/dateTime.utils'; @@ -123,6 +130,8 @@ describe('Stake reward cron: getStakedPerMember', () => { const createStake = async (createdOn: dayjs.Dayjs, expiresAt: dayjs.Dayjs) => { const stake: Stake = { + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, uid: getRandomEthAddress(), member, space, @@ -143,6 +152,8 @@ describe('Stake reward cron: getStakedPerMember', () => { const createReward = async (start: dayjs.Dayjs, end: dayjs.Dayjs) => { const stakeReward = { + project: SOON_PROJECT_ID, + projects: { [SOON_PROJECT_ID]: true }, uid: getRandomEthAddress(), startDate: dateToTimestamp(start.toDate()), endDate: dateToTimestamp(end.toDate()), diff --git a/packages/functions/test/teardown.ts b/packages/functions/test/teardown.ts new file mode 100644 index 0000000000..d2b7e0bc2c --- /dev/null +++ b/packages/functions/test/teardown.ts @@ -0,0 +1,39 @@ +import { build5Db } from '@build-5/database'; +import { BaseRecord, COL, SOON_PROJECT_ID } from '@build-5/interfaces'; +import { isEqual } from 'lodash'; +import { getProjects } from '../src/utils/common.utils'; + +const collections = [ + COL.AWARD, + COL.COLLECTION, + COL.NFT, + COL.SPACE, + COL.PROPOSAL, + COL.TRANSACTION, + COL.BADGES, + COL.TOKEN, + COL.TOKEN_MARKET, + COL.TOKEN_PURCHASE, + COL.STAKE, + COL.STAKE_REWARD, + COL.NFT_STAKE, + COL.AIRDROP, +]; + +const teardown = async () => { + for (const collection of collections) { + const snap = await build5Db().collection(collection).get(); + for (const data of snap) { + if (data.project !== SOON_PROJECT_ID) { + console.log(collection, data); + throw Error('Project not defined'); + } + if (!isEqual(data.projects, getProjects([], SOON_PROJECT_ID))) { + console.log(collection, data); + throw Error('Projects not set'); + } + } + } +}; + +export default teardown; diff --git a/packages/functions/workflow.build.js b/packages/functions/workflow.build.js index 20469a9445..d4a97e6715 100644 --- a/packages/functions/workflow.build.js +++ b/packages/functions/workflow.build.js @@ -194,6 +194,7 @@ function createEmulatedOnlineTest() { init(emulatedOnlineTestFile); const files = glob .sync(`./test/**/*.spec.ts`) + .filter((f) => !f.includes('exclude')) .filter((f) => !f.includes('only.spec.ts')) .filter((f) => !f.includes('dbRoll')); chunk(files, emulatorChunkSize).forEach((chunk, i) => diff --git a/packages/interfaces/src/models/award.ts b/packages/interfaces/src/models/award.ts index 7090b46611..f68f87fe4a 100644 --- a/packages/interfaces/src/models/award.ts +++ b/packages/interfaces/src/models/award.ts @@ -42,7 +42,7 @@ export interface AwardOwner extends BaseSubCollection { /** * Added on. */ - createdOn: Timestamp; + createdOn?: Timestamp; } /** diff --git a/packages/interfaces/src/models/base.ts b/packages/interfaces/src/models/base.ts index 03effaf30a..ee18bd4522 100644 --- a/packages/interfaces/src/models/base.ts +++ b/packages/interfaces/src/models/base.ts @@ -102,6 +102,8 @@ export interface Base { } export interface BaseSubCollection { + project?: string; + projects?: { [key: string]: boolean }; parentId: string; parentCol: string; } @@ -112,13 +114,7 @@ export interface BaseSubCollection { * Every object will have these basic fields. */ export interface BaseRecord extends Base { - /** - * The project to which this record belongs to. - */ project?: string; - /** - * The project to which this record belongs to. - */ projects?: { [key: string]: boolean }; /** * Date/time it was created on. @@ -207,7 +203,7 @@ export interface NftMintingData { readonly nftsStorageDeposit?: number; } -export interface Vote extends BaseSubCollection, BaseRecord { +export interface Vote extends BaseSubCollection { readonly direction: -1 | 1; } @@ -217,7 +213,7 @@ export interface VoteStats { readonly voteDiff: number; } -export interface Rank extends BaseSubCollection, BaseRecord { +export interface Rank extends BaseSubCollection { readonly rank: number; } diff --git a/packages/interfaces/src/models/transaction/payload.ts b/packages/interfaces/src/models/transaction/payload.ts index caa108025d..f72c75b9c5 100644 --- a/packages/interfaces/src/models/transaction/payload.ts +++ b/packages/interfaces/src/models/transaction/payload.ts @@ -70,6 +70,9 @@ export interface TransactionPayload { orderId?: NetworkAddress; collectionOutputAmount?: number; + aliasOutputAmount?: number; + nftOutputAmount?: number; + // TransactionPayloadType.MINT_COLLECTION - METADATA_NFT, aliasId?: NetworkAddress; aliasBlockId?: NetworkAddress; @@ -145,4 +148,6 @@ export interface TransactionPayload { tanglePuchase?: boolean; disableWithdraw?: boolean; + + lockCollectionNft?: boolean; }